manhattan distance works better than manhattan distance + linear conflict - c++

I try to implement A* algorithm with both manhattan distance and manhattan distance + linear conflict heuristic.
but my manhattan distance works much better and I can't understand why!
manhattan distance + linear conflict in my algorithm expands much more node and i found that it's answer it not even optimal.
#include <iostream>
#include <time.h>
#include <fstream>
#include <set>
#include <vector>
#include <queue>
#include <map>
#include "node.h"
using namespace std;
const int n = 4;
const int hash_base = 23;
const long long hash_mod = 9827870924701019;
set<long long> explored;
set<pair<int , node*> > frontier;
map<string,int> database[3];
void check(int* state){
for(int j = 0 ; j < n ; j++){
for(int i = 0 ; i < n ; i++)
cerr << state[j * n + i] << " ";
cerr << endl;
}
cerr << endl;
}
bool goal_test(int* state){
if(state[n * n - 1] != 0) return 0;
for(int i = 0 ; i < (n * n - 1) ; i++){
if(state[i] != i + 1)
return 0;
}
return 1;
}
vector<node> solution(node* v){
vector<node> ans;
while((v->parent)->hash != v->hash){
ans.push_back(*v);
v = v->parent;
}
return ans;
}
//first heuristic
int manhattanDistance(int* state){
int md = 0;
for(int i = 0 ; i < (n * n) ; i++){
if(state[i] == 0) continue;
//what is the goal row and column of this tile
int gr = (state[i] - 1) / n , gc = (state[i] - 1) % n;
//what is the row and column of this tile
int r = i / n , c = i % n;
md += (max(gr - r , r - gr) + max(gc - c , c - gc));
}
return md;
}
//second heuristic
int linearConflict(int* state){
int lc = 0;
for(int i = 0 ; i < n ; i++){
for(int j = 0 ; j < n ; j++){
//jth tile in ith row = (i * n + j)th in state
int la = i * n + j;
if(state[la] == 0 || (state[la] / n) != i)
continue;
for(int k = j + 1 ; k < n ; k++){
//kth tile in ith row = (i * n + k)th in state
int lb = i * n + k;
if(state[lb] == 0 || (state[lb] / n) != i)
continue;
if(state[la] > state[lb])
lc++;
}
}
}
for(int i = 0 ; i < n ; i++){
for(int j = 0 ; j < n ; j++){
//j the tile of i th column
int la = j * 4 + i;
if(state[la] == 0 || (state[la] % n) != i)
continue;
for(int k = j + 1 ; k < n ; k++){
int lb = k * 4 + i;
if(state[lb] == 0 || (state[lb] % n) != i)
continue;
if(state[la] > state[lb])
lc++;
}
}
}
return lc * 2;
}
long long make_hash(int* v){
long long power = 1LL;
long long hash = 0 * 1LL;
for(int i = 0 ; i < (n * n) ; i++){
hash += (power * v[i] * 1LL) % hash_mod;
hash %= hash_mod;
power = (hash_base * power * 1LL) % hash_mod;
}
return hash;
}
vector<node> successor(node* parent){
vector<node> child;
int parent_empty = parent->empty_cell;
//the row and column of empty cell
int r = parent_empty / n , c = parent_empty % n;
//empty cell go down
if(r + 1 < n){
struct node down;
for(int i = 0 ; i < (n*n) ; i++)
down.state[i] = parent->state[i];
down.state[parent_empty] = parent->state[parent_empty + n];
down.state[parent_empty + n] = 0;
down.hash = make_hash(down.state);
down.empty_cell = parent_empty + n;
down.cost = parent->cost + 1;
down.parent = parent;
//first heuristic -> manhattan Distance
// down.heuristic = manhattanDistance(down.state);
//second heuristic -> manhattan distance + linear conflict
down.heuristic = linearConflict(down.state) + manhattanDistance(down.state);
//third heuristic -> disjoint pattern database
// down.heuristic = DisjointPatternDB(down.state);
child.push_back(down);
}
//empty cell go up
if(r - 1 >= 0){
struct node up;
for(int i = 0 ; i < n * n ; i++)
up.state[i] = parent->state[i];
up.state[parent_empty] = parent->state[parent_empty - n];
up.state[parent_empty - n] = 0;
up.empty_cell = parent_empty - n;
up.hash = make_hash(up.state);
up.cost = parent->cost + 1;
up.parent = parent;
//first heuristic -> manhattan Distance
// up.heuristic = manhattanDistance(up.state);
//second heuristic -> manhattan distance + linear conflict
up.heuristic = linearConflict(up.state) + manhattanDistance(up.state);
//third heuristic -> disjoint pattern database
// up.heuristic = DisjointPatternDB(up.state);
child.push_back(up);
}
//empty cell going right
if(c + 1 < n){
struct node right;
for(int i = 0 ; i < (n * n) ; i++)
right.state[i] = parent->state[i];
right.state[parent_empty] = parent->state[parent_empty + 1];
right.state[parent_empty + 1] = 0;
right.empty_cell = parent_empty + 1;
right.hash = make_hash(right.state);
right.cost = parent->cost + 1;
right.parent = parent;
//first heuristic -> manhattan Distance
// right.heuristic = manhattanDistance(right.state);
//second heuristic -> manhattan distance + linear conflict
right.heuristic = linearConflict(right.state) + manhattanDistance(right.state);
//third heuristic -> disjoint pattern database
// right.heuristic = DisjointPatternDB(right.state);
child.push_back(right);
}
//empty cell going left
if(c - 1 >= 0){
struct node left;
for (int i = 0; i < (n * n) ; i++)
left.state[i] = parent->state[i];
left.state[parent_empty] = parent->state[parent_empty - 1];
left.state[parent_empty - 1] = 0;
left.empty_cell = parent_empty - 1;
left.hash = make_hash(left.state);
left.cost = parent->cost + 1;
left.parent = parent;
//first heuristic -> manhattan Distance
// left.heuristic = manhattanDistance(left.state);
//second heuristic -> manhattan distance + linear conflict
left.heuristic = linearConflict(left.state) + manhattanDistance(left.state);
//third heuristic -> disjoint pattern database
// left.heuristic = DisjointPatternDB(left.state);
child.push_back(left);
}
return child;
}
node* nodeCopy(node child){
node* tmp = new node;
for(int i = 0 ; i < n * n; i++)
tmp->state[i] = child.state[i];
tmp->hash = child.hash;
tmp->empty_cell = child.empty_cell;
tmp->cost = child.cost;
tmp->parent = child.parent;
tmp->heuristic = child.heuristic;
return tmp;
}
vector<node> Astar(node* initNode){
if(goal_test(initNode->state)) return solution(initNode);
frontier.insert(make_pair(initNode->cost + initNode-> heuristic ,initNode));
explored.insert(initNode->hash);
while(!frontier.empty()){
node* v = (*frontier.begin()).second;
if(goal_test(v->state)) return solution(v);
frontier.erase(frontier.begin());
vector<node> childs = successor(v);
for(node child: childs){
if(explored.find(child.hash) == explored.end()){
node* tmp = nodeCopy(child);
frontier.insert(make_pair((child.cost + child.heuristic) , tmp));
explored.insert(child.hash);
}
}
}
return solution(initNode);
}
int main(){
clock_t tStart = clock();
printf("Time taken: %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);
struct node init;// {{1 , 2 , 3 , 4 , 5, 6, 7, 8, 0} , 1 , 9 , 0 , &init , 0};
for(int i = 0 ; i < (n * n) ; i++){
cin >> init.state[i];
if(init.state[i] == 0)
init.empty_cell = i;
}
init.hash = make_hash(init.state);
init.cost = 0;
init.parent = &init;
init.heuristic = manhattanDistance(init.state) ;//+ linearConflict(init.state);
vector <node> ans = Astar(&init);
//cout << 1 << " ";
for(int j = 0 ; j < n * n ; j++){
if(j == n * n - 1) cout << init.state[j];
else cout << init.state[j] << ",";
}
cout << endl;
for(int i = (ans.size() - 1) ; i >= 0 ; i--){
//cout << (ans.size() - i + 1) << " ";
cerr << linearConflict(ans[i].state) << endl;
for(int j = 0 ; j < n * n ; j++){
if(j == n * n - 1) cout << ans[i].state[j];
else cout << ans[i].state[j] << ",";
}
cout << endl;
}
cout << "path size : " << ans.size() << endl;
cout << "number of node expanded : " << explored.size() << endl;
printf("Time taken: %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);
}
#include <vector>
using namespace std;
struct node{
int state[16];
long long hash;
int empty_cell;
long cost;
node* parent;
int heuristic;
};

If its answer is not optimal it is because your heuristic is not admissible.
This means that sometimes it is overestimating the cost to reach a node in your graph.
linear conflicts heuristic should always be coupled with a distance estimated heuristic like Manhattan and it is not as simple as giving twice the number of linear conflicts in each row / column.
See Linear Conflict violating admissibility and driving me insane
and
https://cse.sc.edu/~mgv/csce580sp15/gradPres/HanssonMayerYung1992.pdf

Related

Reason for Segmentation Fault During Depth First Search on Tree of Large Size C++

I'm trying to solve https://open.kattis.com/problems/rootedsubtrees and part of the solution requires finding the minimum distance between any 2 nodes on the tree. To do this, I'm using Lowest Common Ancestor as a subroutine. Part of my LCA code uses a DFS to traverse the tree. Somehow, running this code on a line graph of size 200000 leads to a segmentation fault during the DFS section of the code.
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,fma")
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vi;
#define fast_cin() \
ios_base::sync_with_stdio(false); \
cin.tie(NULL); \
cout.tie(NULL);
int n, q, idx;
vector<int> adjlist[200009];
vector<int> L, E,
H; // depth at traversal index, node at traversal index, first traversal index of node
void dfs(int cur, int depth) {
cout << "dfs " << cur << " " << idx << endl;
H[cur] = idx;
E[idx] = cur;
L[idx++] = depth;
for (int &nxt : adjlist[cur]) {
if (H[nxt] != -1) continue;
dfs(nxt, depth + 1);
E[idx] = cur; // backtrack to current node
L[idx++] = depth;
}
}
class SparseTable { // OOP style
private:
vi A, P2, L2;
vector<vi> SpT; // the Sparse Table
public:
SparseTable() {} // default constructor
SparseTable(vi &initialA) { // pre-processing routine
A = initialA;
int n = (int)A.size();
int L2_n = (int)log2(n) + 1;
P2.assign(L2_n, 0);
L2.assign(1 << L2_n, 0);
for (int i = 0; i <= L2_n; ++i) {
P2[i] = (1 << i); // to speed up 2^i
L2[(1 << i)] = i; // to speed up log_2(i)
}
for (int i = 2; i < P2[L2_n]; ++i)
if (L2[i] == 0) L2[i] = L2[i - 1]; // to fill in the blanks
// the initialization phase
SpT = vector<vi>(L2[n] + 1, vi(n));
for (int j = 0; j < n; ++j) SpT[0][j] = j; // RMQ of sub array [j..j]
// the two nested loops below have overall time complexity = O(n log n)
for (int i = 1; P2[i] <= n; ++i) // for all i s.t. 2^i <= n
for (int j = 0; j + P2[i] - 1 < n; ++j) { // for all valid j
int x = SpT[i - 1][j]; // [j..j+2^(i-1)-1]
int y = SpT[i - 1][j + P2[i - 1]]; // [j+2^(i-1)..j+2^i-1]
SpT[i][j] = A[x] <= A[y] ? x : y;
}
}
int RMQ(int i, int j) {
int k = L2[j - i + 1]; // 2^k <= (j-i+1)
int x = SpT[k][i]; // covers [i..i+2^k-1]
int y = SpT[k][j - P2[k] + 1]; // covers [j-2^k+1..j]
return A[x] <= A[y] ? x : y;
}
};
int LCA(int u, int v, SparseTable &SpT) {
if (H[u] > H[v]) swap(u, v);
return E[SpT.RMQ(H[u], H[v])];
}
int APSP(int u, int v, SparseTable &SpT) {
int ancestor = LCA(u, v, SpT);
return L[H[u]] + L[H[v]] - 2 * L[H[ancestor]];
}
int main() {
fast_cin();
cin >> n >> q;
L.assign(2 * (n + 9), 0);
E.assign(2 * (n + 9), 0);
H.assign(n + 9, -1);
idx = 0;
int u, v;
for (int i = 0; i < n - 1; i++) {
cin >> u >> v;
u--;
v--;
adjlist[u].emplace_back(v);
adjlist[v].emplace_back(u);
}
dfs(0, 0);
SparseTable SpT(L);
ll d;
while (q--) {
cin >> u >> v;
u--;
v--;
d = (ll) APSP(u, v, SpT) + 1;
cout << (ll) n - d + (d) * (d + 1) / 2 << endl;
}
return 0;
}
Using the following Python Code to generate the input of a large line graph
n = 200000
q = 1
print(n, q)
for i in range(1, n):
print(i, i+1)
print(1, 200000)
I get the following last few lines of output before my program crashes.
.
.
.
dfs 174494 174494
dfs 174495 174495
dfs 174496 174496
dfs 174497 174497
dfs 174498 174498
Segmentation fault (core dumped)
Is the problem an issue of exhausting stack space with the recursion or something else?
You posted a lot of code, but here is one obvious error in the SparseMatrix class:
std::vector<int> P2;
//...
P2.assign(L2_n, 0);
for (int i = 0; i <= L2_n; ++i)
{
P2[i] = (1 << i); // <-- Out of bounds access when i == L2_n
To show you the error, change that line of code to this:
P2.at(i) = (1 << i); // <-- Out of bounds access when i == L2_n
You will now get a std::out_of_range exception thrown.
If you write a loop using <=, that loop will be considered suspicious, since a lot of off-by-one and buffer overrun errors occur with loop conditions written this way.
I believe stack exhaustion was the main problem in running the code on my machine. I re-implemented the DFS in an iterative fashion.
stack<tuple<int, int, bool>> st; // cur, depth, first_time
st.push ({0, 0, 1});
while (!st.empty()) {
auto [cur, depth, first_time] = st.top();
st.pop();
if (first_time){
H[cur] = idx;
}
E[idx] = cur;
L[idx++] = depth;
for (int &nxt : adjlist[cur]) {
if (H[nxt] != -1) continue;
st.push({cur, depth, 0});
st.push({nxt, depth+1, 1});
break;
}
}
and my code was able to run the large testcase on my machine.
I'm not sure is this is relevant to the original question, but after this change, the code still flagged a run-time error on the online judge and I eventually realized that the issue was that the sparse table was using too much memory, so I fixed that by avoiding wasted declared but not used memory spaces in rows of the sparse table. Then the online judge deemed it as being too slow. So I reverted the DFS code back to the recursive version, and it was accepted. Note that the accepted solution actually crashes on my machine when running the large testcase... I guess my machine has a more limited stack space than the online grader.
The accepted solution is here
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,fma")
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vi;
#define fast_cin() \
ios_base::sync_with_stdio(false); \
cin.tie(NULL); \
cout.tie(NULL);
int n, q, idx;
vector<int> adjlist[(int)2e5 + 9];
vector<int> L, E,
H; // depth at traversal index, node at traversal index, first traversal index of node
void dfs(int cur, int depth) {
H[cur] = idx;
E[idx] = cur;
L[idx++] = depth;
for (int &nxt : adjlist[cur]) {
if (H[nxt] != -1) continue;
dfs(nxt, depth + 1);
E[idx] = cur; // backtrack to current node
L[idx++] = depth;
}
}
class SparseTable { // OOP style
private:
vi A, P2, L2;
vector<vi> SpT; // the Sparse Table
public:
SparseTable() {} // default constructor
SparseTable(vi &initialA) { // pre-processing routine
A = initialA;
int n = (int)A.size();
int L2_n = (int)log2(n) + 1;
P2.assign(L2_n + 1, 0);
L2.assign((1 << L2_n) + 1, 0);
for (int i = 0; i <= L2_n; ++i) {
P2[i] = (1 << i); // to speed up 2^i
L2[(1 << i)] = i; // to speed up log_2(i)
}
for (int i = 2; i < P2[L2_n]; ++i)
if (L2[i] == 0) L2[i] = L2[i - 1]; // to fill in the blanks
// the initialization phase
SpT = vector<vi>(L2[n] + 1, vi());
SpT[0] = vi(n, 0);
for (int j = 0; j < n; ++j) SpT[0][j] = j; // RMQ of sub array [j..j]
// the two nested loops below have overall time complexity = O(n log n)
for (int i = 1; P2[i] <= n; ++i) { // for all i s.t. 2^i <= n
SpT[i] = vi(n + 1 - P2[i]); // initialize SpT[i]
for (int j = 0; j + P2[i] - 1 < n; ++j) { // for all valid j
int x = SpT[i - 1][j]; // [j..j+2^(i-1)-1]
int y = SpT[i - 1][j + P2[i - 1]]; // [j+2^(i-1)..j+2^i-1]
SpT[i][j] = A[x] <= A[y] ? x : y;
}
}
}
int RMQ(int i, int j) {
int k = L2[j - i + 1]; // 2^k <= (j-i+1)
int x = SpT[k][i]; // covers [i..i+2^k-1]
int y = SpT[k][j - P2[k] + 1]; // covers [j-2^k+1..j]
return A[x] <= A[y] ? x : y;
}
};
int LCA(int u, int v, SparseTable &SpT) {
if (H[u] > H[v]) swap(u, v);
return E[SpT.RMQ(H[u], H[v])];
}
int APSP(int u, int v, SparseTable &SpT) {
int ancestor = LCA(u, v, SpT);
return L[H[u]] + L[H[v]] - 2 * L[H[ancestor]];
}
int main() {
fast_cin();
cin >> n >> q;
L.assign(2 * (n), 0);
E.assign(2 * (n), 0);
H.assign(n, -1);
idx = 0;
int u, v;
for (int i = 0; i < n - 1; i++) {
cin >> u >> v;
u--;
v--;
adjlist[u].emplace_back(v);
adjlist[v].emplace_back(u);
}
dfs(n - 1, 0);
SparseTable SpT(L);
ll d;
while (q--) {
cin >> u >> v;
u--;
v--;
d = (ll)APSP(u, v, SpT) + 1LL;
cout << (ll)n - d + (d) * (d + 1) / (ll)2 << endl;
}
return 0;
}

Low Accuracy of DNN

I've been implementing NN recently based on http://neuralnetworksanddeeplearning.com/. I've made whole algorithm for backprop and SGD almost the same way as author of this book. The problem is that while he gets accuracy around 90 % after one epoch i get 30% after 5 epochs even though i have the same hiperparameters. Do you have any idea what might be the cause ?
Here s my respository.
https://github.com/PiPower/Deep-Neural-Network
Here is part with algorithm for backprop and SGD implemented in Network.cpp:
void Network::Train(MatrixD_Array& TrainingData, MatrixD_Array& TrainingLabels, int BatchSize,int epochs, double LearningRate)
{
assert(TrainingData.size() == TrainingLabels.size() && CostFunc != nullptr && CostFuncDer != nullptr && LearningRate > 0);
std::vector<long unsigned int > indexes;
for (int i = 0; i < TrainingData.size(); i++) indexes.push_back(i);
std::random_device rd;
std::mt19937 g(rd());
std::vector<Matrix<double>> NablaWeights;
std::vector<Matrix<double>> NablaBiases;
NablaWeights.resize(Layers.size());
NablaBiases.resize(Layers.size());
for (int i = 0; i < Layers.size(); i++)
{
NablaWeights[i] = Matrix<double>(Layers[i].GetInDim(), Layers[i].GetOutDim());
NablaBiases[i] = Matrix<double>(1, Layers[i].GetOutDim());
}
//---- Epoch iterating
for (int i = 0; i < epochs; i++)
{
cout << "Epoch number: " << i << endl;
shuffle(indexes.begin(), indexes.end(), g);
// Batch iterating
for (int batch = 0; batch < TrainingData.size(); batch = batch + BatchSize)
{
for (int i = 0; i < Layers.size(); i++)
{
NablaWeights[i].Clear();
NablaBiases[i].Clear();
}
int i = 0;
while( i < BatchSize && (i+batch)< TrainingData.size())
{
std::vector<Matrix<double>> ActivationOutput;
std::vector<Matrix<double>> Z_Output;
ActivationOutput.resize(Layers.size() + 1);
Z_Output.resize(Layers.size());
ActivationOutput[0] = TrainingData[indexes[i + batch]];
int index = 0;
// Pushing values through
for (auto layer : Layers)
{
Z_Output[index] = layer.Mul(ActivationOutput[index]);
ActivationOutput[index + 1] = layer.ApplyActivation(Z_Output[index]);
index++;
}
// ---- Calculating Nabla that will be later devided by batch size element wise
auto DeltaNabla = BackPropagation(ActivationOutput, Z_Output, TrainingLabels[indexes[i + batch]]);
for (int i = 0; i < Layers.size(); i++)
{
NablaWeights[i] = NablaWeights[i] + DeltaNabla.first[i];
NablaBiases[i] = NablaBiases[i] + DeltaNabla.second[i];
}
i++;
}
for (int g = 0; g < Layers.size(); g++)
{
Layers[g].Weights = Layers[g].Weights - NablaWeights[g] * LearningRate;
Layers[g].Biases = Layers[g].Biases - NablaBiases[g] * LearningRate;
}
// std::transform(NablaWeights.begin(), NablaWeights.end(), NablaWeights.begin(),[BatchSize, LearningRate](Matrix<double>& Weight) {return Weight * (LearningRate / BatchSize);});
//std::transform(NablaBiases.begin(), NablaBiases.end(), NablaBiases.begin(), [BatchSize, LearningRate](Matrix<double>& Bias) {return Bias * (LearningRate / BatchSize); });
}
}
}
std::pair<MatrixD_Array, MatrixD_Array> Network::BackPropagation( MatrixD_Array& ActivationOutput, MatrixD_Array& Z_Output,Matrix<double>& label)
{
MatrixD_Array NablaWeight;
MatrixD_Array NablaBias;
NablaWeight.resize(Layers.size());
NablaBias.resize(Layers.size());
auto zs = Layers[Layers.size() - 1].ActivationPrime(Z_Output[Z_Output.size() - 1]);
Matrix<double> Delta_L = Hadamard(CostFuncDer(ActivationOutput[ActivationOutput.size() - 1],label), zs);
NablaWeight[Layers.size() - 1] = Delta_L * ActivationOutput[ActivationOutput.size() - 2].Transpose();
NablaBias[Layers.size() - 1] = Delta_L;
for (int j = 2; j <= Layers.size() ; j++)
{
auto sp = Layers[Layers.size() - j].ActivationPrime(Z_Output[Layers.size() -j]);
Delta_L = Hadamard(Layers[Layers.size() - j+1 ].Weights.Transpose() * Delta_L, sp);
NablaWeight[Layers.size() - j] = Delta_L * ActivationOutput[ActivationOutput.size() -j-1].Transpose();
NablaBias[Layers.size() - j] = Delta_L;
}
return make_pair(NablaWeight, NablaBias);
}
It turned out that mnist loader didnt work correctly.

How to count moves in BFS algorithm? (Shortest path in a maze)

So I try implementing a BFS algorithm and really understand how it works (creating some kind of "my version", out of scratch, just looking at graphs and some pseudocodes) and here is what I ended up with:
#include<iostream>
#include<string>
#include<fstream>
#include<queue>
using namespace std;
void main(int argc, char *argv[])
{
// Deklaracja uchwytu do pliku (tylko do odczytu pliku)
ifstream plik(argv[1]);
// Tablica stringow - przechowujaca wartosci pol 12x12
string labirynt[12];
pair <int, int> start;
pair <int, int> koniec;
// Wektor par - działa jak tablica, przechowuje pary współrzędnych pól
queue <pair<int, int>> kolejka;
// Tablica odwiedzin - sprawdza czy pole zostalo odwiedzone, 0 jesli nie, 1 jesli tak
bool odwiedzone[12][12] = { 0 };
// Zmienna pomocnicza - bo getline sluzy do umieszczania danych w stringu, nie w tablicy znakow
int i = 0;
// Pętla wczytująca tekst z pliku do tablicy labirynt
while (getline(plik, labirynt[i]))
{
i++;
}
// Wyszukanie początku i końca w labiryncie (A i B)
for (int i = 0; i < 12; i++)
{
for (int j = 0; j < 12; j++)
{
if (labirynt[i][j] == 'A')
{
start.first = i;
start.second = j;
}
if (labirynt[i][j] == 'B')
{
koniec.first = i;
koniec.second = j;
}
}
}
// Ustawiamy pole startowe jako odwiedzone - żadne pole nie może być odwiedzone więcej niż 1 raz
odwiedzone[start.first][start.second] = true;
// Wiersz i kolumna bieżącego wierzchołka
int w, k;
kolejka.push(start);
// Dopóki kolejka nie jest pusta
while (!kolejka.empty())
{
// Pobieramy z kolejki wiersz i kolumnę bieżącego wierzchołka
w = kolejka.front().first;
k = kolejka.front().second;
// Usuwamy parę z kolejki
kolejka.pop();
// Sprawdzamy czy dotarliśmy do wyjścia
if (w == koniec.first && k == koniec.second)
break;
// Przeglądamy sąsiadów bieżącego wierzchołka
for (i = -1; i <= 1; i++)
for (int j = -1; j <= 1; j++)
{
if ((i != j) && (!i || !j))
if (labirynt[w + i][k + j] == ' ' && !odwiedzone[w + i][k + j])
{
odwiedzone[w + i][k + j] = true;
pair <int, int> para;
para.first = w + i;
para.second = k + j;
kolejka.push(para);
cout << kolejka.front().first << endl;
cout << kolejka.front().second << endl;
}
}
}
system("PAUSE");
}
Here is the example maze I use (program reads from file that is dropped on .exe)
xxxxxxxxxxxx
xxA xxxxxxx
xx x xxxxxx
x x xxxxxx
xx x xxxx
xx xxx xxxxx
x xxxxxxxx
x x xxxxxxx
x xxx xxxxxx
x xxxxxxx
xxx Bxxx
xxxxxxxxxxxx
It works (shows coordinates of every field in a maze it goes through and finds B), but I don't know how to count moves needed to go through shortest path.
instead of using odwiedzone[w + i][k + j] = true; for checking the coordinate have been stepped before, use something like odwiedzone[w + i][k + j] = now + 1 to count the number of step from start to that position:
// first, declare all odwiedzone[][]=-1
...
odwiedzone[start.first][start.second] = 0;
// first position needs 0 step
...
for (i = -1; i <= 1; i++)
for (int j = -1; j <= 1; j++)
{
if ((i != j) && (!i || !j))
if (labirynt[w + i][k + j] == ' ' && odwiedzone[w + i][k + j]==-1)
{
odwiedzone[w + i][k + j] = odwiedzone[w][k]+1;
//next position = now position + 1
pair <int, int> para;
para.first = w + i;
para.second = k + j;
kolejka.push(para);
cout << kolejka.front().first << endl;
cout << kolejka.front().second << endl;
}
}
I see 2 ways of achieving what you want:
Use a separate queue for storing the associated distance with each cell, e.g. start will have 0, each neighbour of start will have 1 and so on. Each time you add a new neighbor, his value will be distance to current cell + 1. The value for destination in the second queue will give you the path length.
When adding a neighbor in the queue, record his parent. So when you find the source you can reconstruct the path and count the number of steps.

Runtime Error signal 11 on simple C++ code

I am getting a runtime error with this code and I have no idea why.
I am creating a grid and then running a BFS over it. The objective here is to read in the rows and columns of the grid, then determine the maximum number of stars you can pass over before reaching the end.
The start is the top left corner and the end is the bottom right corner.
You can only move down and right. Any ideas?
#include <iostream>
#include <queue>
using namespace std;
int main() {
int r, c, stars[1001][1001], grid[1001][1001], ns[1001][1001];
pair<int, int> cr, nx;
char tmp;
queue<pair<int, int> > q;
cin >> r >> c;
for(int i = 0; i < r; i++) {
for(int j = 0; j < c; j++) {
cin >> tmp;
if(tmp == '.') {
grid[i][j] = 1000000000;
ns[i][j] = 0;
stars[i][j] = 0;
}
else if(tmp == '*') {
grid[i][j] = 1000000000;
ns[i][j] = 1;
stars[i][j] = 1;
}
else
grid[i][j] = -1;
}
}
grid[0][0] = 0;
cr.first = 0;
cr.second = 0;
q.push(cr);
while(!q.empty()) {
cr = q.front();
q.pop();
if(cr.first < r - 1 && grid[cr.first + 1][cr.second] != -1 && ns[cr.first][cr.second] + stars[cr.first + 1][cr.second] > ns[cr.first + 1][cr.second]) {
nx.first = cr.first + 1; nx.second = cr.second;
grid[nx.first][nx.second] = grid[cr.first][cr.second] + 1;
ns[nx.first][nx.second] = ns[cr.first][cr.second] + stars[cr.first + 1][cr.second];
q.push(nx);
}
if(cr.second < c - 1 && grid[cr.first][cr.second + 1] != -1 && ns[cr.first][cr.second] + stars[cr.first][cr.second + 1] > ns[cr.first][cr.second + 1]) {
nx.first = cr.first; nx.second = cr.second + 1;
grid[nx.first][nx.second] = grid[cr.first][cr.second] + 1;
ns[nx.first][nx.second] = ns[cr.first][cr.second] + stars[cr.first][cr.second + 1];
q.push(nx);
}
}
if(grid[r - 1][c - 1] == 1000000000)
cout << "Impossible" << endl;
else
cout << ns[r - 1][c - 1] << endl;
}
Sample input :
6 7
.#*..#.
..*#...
#.....#
..###..
..##..*
*#.....
I'm guessing your stack is not big enough for
int stars[1001][1001], grid[1001][1001], ns[1001][1001];
which is 3 * 1001 * 1001 * sizeof(int) bytes. That's ~12MB if the size of int is 4 bytes.
Either increase the stack size with a compiler option, or go with dynamic allocation i.e. std::vector.
To avoid the large stack you should allocate on the heap
Since you seem to have three parallel 2 - dimension arrays you could
maybe create struct that contains all three values for a x,y position.
That would make it easier to maintain:
struct Area
{
int grid;
int ns;
int stars;
};
std::vector<std::array<Area,1001>> dim2(1001);
dim2[x][y].grid = 100001;
...

Laguerre interpolation algorithm, something's wrong with my implementation

This is a problem I have been struggling for a week, coming back just to give up after wasted hours...
I am supposed to find coefficents for the following Laguerre polynomial:
P0(x) = 1
P1(x) = 1 - x
Pn(x) = ((2n - 1 - x) / n) * P(n-1) - ((n - 1) / n) * P(n-2)
I believe there is an error in my implementation, because for some reason the coefficents I get seem way too big. This is the output this program generates:
a1 = -190.234
a2 = -295.833
a3 = 378.283
a4 = -939.537
a5 = 774.861
a6 = -400.612
Description of code (given below):
If you scroll the code down a little to the part where I declare array, you'll find given x's and y's.
The function polynomial just fills an array with values of said polynomial for certain x. It's a recursive function. I believe it works well, because I have checked the output values.
The gauss function finds coefficents by performing Gaussian elimination on output array. I think this is where the problems begin. I am wondering, if there's a mistake in this code or perhaps my method of veryfying results is bad? I am trying to verify them like that:
-190.234 * 1.5 ^ 5 - 295.833 * 1.5 ^ 4 ... - 400.612 = -3017,817625 =/= 2
Code:
#include "stdafx.h"
#include <conio.h>
#include <iostream>
#include <iomanip>
#include <math.h>
using namespace std;
double polynomial(int i, int j, double **tab)
{
double n = i;
double **array = tab;
double x = array[j][0];
if (i == 0) {
return 1;
} else if (i == 1) {
return 1 - x;
} else {
double minusone = polynomial(i - 1, j, array);
double minustwo = polynomial(i - 2, j, array);
double result = (((2.0 * n) - 1 - x) / n) * minusone - ((n - 1.0) / n) * minustwo;
return result;
}
}
int gauss(int n, double tab[6][7], double results[7])
{
double multiplier, divider;
for (int m = 0; m <= n; m++)
{
for (int i = m + 1; i <= n; i++)
{
multiplier = tab[i][m];
divider = tab[m][m];
if (divider == 0) {
return 1;
}
for (int j = m; j <= n; j++)
{
if (i == n) {
break;
}
tab[i][j] = (tab[m][j] * multiplier / divider) - tab[i][j];
}
for (int j = m; j <= n; j++) {
tab[i - 1][j] = tab[i - 1][j] / divider;
}
}
}
double s = 0;
results[n - 1] = tab[n - 1][n];
int y = 0;
for (int i = n-2; i >= 0; i--)
{
s = 0;
y++;
for (int x = 0; x < n; x++)
{
s = s + (tab[i][n - 1 - x] * results[n-(x + 1)]);
if (y == x + 1) {
break;
}
}
results[i] = tab[i][n] - s;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int num;
double **array;
array = new double*[5];
for (int i = 0; i <= 5; i++)
{
array[i] = new double[2];
}
//i 0 1 2 3 4 5
array[0][0] = 1.5; //xi 1.5 2 2.5 3.5 3.8 4.1
array[0][1] = 2; //yi 2 5 -1 0.5 3 7
array[1][0] = 2;
array[1][1] = 5;
array[2][0] = 2.5;
array[2][1] = -1;
array[3][0] = 3.5;
array[3][1] = 0.5;
array[4][0] = 3.8;
array[4][1] = 3;
array[5][0] = 4.1;
array[5][1] = 7;
double W[6][7]; //n + 1
for (int i = 0; i <= 5; i++)
{
for (int j = 0; j <= 5; j++)
{
W[i][j] = polynomial(j, i, array);
}
W[i][6] = array[i][1];
}
for (int i = 0; i <= 5; i++)
{
for (int j = 0; j <= 6; j++)
{
cout << W[i][j] << "\t";
}
cout << endl;
}
double results[6];
gauss(6, W, results);
for (int i = 0; i < 6; i++) {
cout << "a" << i + 1 << " = " << results[i] << endl;
}
_getch();
return 0;
}
I believe your interpretation of the recursive polynomial generation either needs revising or is a bit too clever for me.
given P[0][5] = {1,0,0,0,0,...}; P[1][5]={1,-1,0,0,0,...};
then P[2] is a*P[0] + convolution(P[1], { c, d });
where a = -((n - 1) / n)
c = (2n - 1)/n and d= - 1/n
This can be generalized: P[n] == a*P[n-2] + conv(P[n-1], { c,d });
In every step there is involved a polynomial multiplication with (c + d*x), which increases the degree by one (just by one...) and adding to P[n-1] multiplied with a scalar a.
Then most likely the interpolation factor x is in range [0..1].
(convolution means, that you should implement polynomial multiplication, which luckily is easy...)
[a,b,c,d]
* [e,f]
------------------
af,bf,cf,df +
ae,be,ce,de, 0 +
--------------------------
(= coefficients of the final polynomial)
The definition of P1(x) = x - 1 is not implemented as stated. You have 1 - x in the computation.
I did not look any further.