Issue Implementing A* in C++ with Priority Queues - c++

I'm currently working on a homework assignment to implement A* for the sliding brick puzzle. I have previously implemented BFS and DFS for this puzzle, but an now having problems. I attempted to write my A* code by adapting the BFS code I already had working using a priority queue and Manhattan distance as the heuristic. In order to have the program open the node with the lowest f value (g+h), I had to override the operator for the priority queue, as it contains a defined structure. When I compile the code, no errors arise, but when I run it the program just crashed. My guess is that it is getting stuck in a loop somewhere. Maybe I implemented the operator override incorrectly. Can anyone help me figure out what is going wrong? I have pasted my code below.
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <list>
#include <queue>
#include <set>
#include <stack>
#include <map>
#include <time.h>
using namespace std;
struct move //creates structure for a move containing a pice number and direction to move
{
int piece;
char direction;
};
struct parentmove
{
vector< vector<int> > par;
move mo;
};
struct position
{
int row;
int column;
};
struct node
{
vector< vector<int> > par;
vector< vector<int> > state;
position pos;
int g;
int h;
int f;
};
bool operator<(const node& a, const node& b)
{
return a.f > b.f;
}
void SBP::Astar(vector <vector<int> > st)
{
position goalpos = getposition(st, -1);
node stnode;
stnode.state = st;
stnode.g = 0;
position stpos = getposition(st, 2);
stnode.h = abs(goalpos.row - stpos.row) + abs(goalpos.column - stpos.column);
stnode.f = stnode.g + stnode.h;
stnode.pos = stpos;
list<move> allm;
priority_queue< node > unexplored, explored;
set< vector <vector<int> > > closedset; //contains explored states in a set,
map < vector <vector<int> >, parentmove > pathdict;
allm = (*this).allmoves(st);
list<move>::iterator it = allm.begin();
for (int i = 0; i < allm.size(); i++)
{
move m;
m.piece = (*it).piece;
m.direction = (*it).direction;
vector< vector<int> > newst = (*this).applyMove(st, m);
newst = (*this).normalization(newst);
node newnode;
newnode.par = st;
newnode.state = newst;
newnode.g = 1;
position newpos = getposition(newst, 2);
newnode.h = abs(goalpos.row - newpos.row) + abs(goalpos.column - newpos.column);
newnode.f = newnode.h + newnode.g;
newnode.pos = newpos;
unexplored.push(newnode);
parentmove pm = { st,m };
pathdict[newst] = pm;
++it;
}
explored.push(stnode);
closedset.insert(st);
while (!unexplored.empty())
{
node currentnode = unexplored.top();
vector< vector<int> > currentst = currentnode.state;
unexplored.pop();
bool iscomplete = (*this).complete(currentst);
if (iscomplete)
{
explored.push(currentnode);
closedset.insert(currentst);
list<move> path = (*this).constructpath(currentst, pathdict, st);
(*this).display(currentst);
printf("A* explored %i nodes\n", explored.size());
printf("The length of the path solution is %i moves\n", path.size());
return;
}
else
{
set< vector< vector<int> > >::iterator ite = closedset.find(currentst);
if (ite == closedset.end()) //does not already exist in queue
{
list<move> possm;
possm = (*this).allmoves(currentst);
list<move>::iterator iter = possm.begin();
for (int j = 0; j < possm.size(); j++)
{
move m;
m.piece = (*iter).piece;
m.direction = (*iter).direction;
vector< vector<int> > newst = (*this).applyMove(currentst, m);
vector< vector<int> > normst = (*this).normalization(newst);;
node normnode;
normnode.state = normst;
normnode.par = currentst;
normnode.g = currentnode.g + 1;
position p = getposition(normst, 2);
normnode.h = abs(goalpos.row - p.row) + abs(goalpos.column - p.column);
normnode.f = normnode.g + normnode.h;
normnode.pos = p;
unexplored.push(normnode);
if (pathdict.find(normst) == pathdict.end())
{
parentmove pm = { currentst,m };
pathdict[normst] = pm;
}
++iter;
}
explored.push(currentnode);
closedset.insert(currentst);
}
}
}
return;
}

Related

C++ function not getting called

I have a function that takes 2d-vector and outputs a 2d-vector. For some reason, the function is not getting called.
Here is the link to reproduce the issue: Google Colab.
In the link to check for correctness, I have added another code that uses the exact same function but doesn't take a 2d-vector array as an argument instead it runs on static input.
mycode.cpp:
#include <vector>
#include "geomutils.h"
#include "mycode.h"
#include <iostream>
using namespace std;
vector< vector<double> > customComputeConvexHull(vector< vector<double> > i_matrix){
cout <<"\nDone1.1";
Polygon custompts, customhull;
for (int r = 0; r < i_matrix.size(); r++){
custompts.push_back(Point(i_matrix[r][0], i_matrix[r][1]));
}
computeConvexHull(custompts, customhull);
// vector< vector<double> > res;
vector<vector<double>> res( customhull.size() , vector<double> (2));
for(int i = 0;i < customhull.size();i ++) {
res[i][0] = customhull[i].x;
res[i][1] = customhull[i].y;
}
return res;
}
void print_polygon(Polygon &h, int name){
std::cout << "\nHull in "<< name << ": \n"<<"[";
for(int i = 0;i < h.size();i ++) {
std::cout << "("<< h[i].x<< ", "<< h[i].y<<"), ";
}
std::cout <<"]\n";
}
void get_convex_hull_custom(){
Polygon custompts;
Polygon customhull;
custompts.push_back(Point(0,0));
custompts.push_back(Point(4.58,7.14));
custompts.push_back(Point(0,7.14));
computeConvexHull(custompts, customhull);
print_polygon(customhull, -99999);
}
int main()
{
// Create an empty vector
vector< vector<double> > mat,mat2;
vector<double> myRow1(0,0);
mat.push_back(myRow1);
vector<double> myRow2(7.61,9.48);
mat.push_back(myRow2);
vector<double> myRow3(0,9.48);
mat.push_back(myRow3);
cout <<"Done1\n";
get_convex_hull_custom();
mat2 = customComputeConvexHull(mat);
cout <<"Done2";
return 0;
}
mycode.h:
#ifndef _code
#define _code
#include <vector>
std::vector< std::vector<double> > customComputeConvexHull (std::vector< std::vector<double> > i_matrix);
#endif
geomutils.cpp:
#include "geomutils.h"
#include <iostream>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/geometries/adapted/boost_tuple.hpp>
BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian)
void computeConvexHull(Polygon &pts, Polygon &chull) {
chull.clear();
if(pts.size() == 1) {
chull.push_back(pts[0]);
chull.push_back(pts[0]);
return;
} else if(pts.size() == 2) {
chull.push_back(pts[0]);
chull.push_back(pts[1]);
chull.push_back(pts[0]);
return;
}
typedef boost::tuple<double, double> point;
typedef boost::geometry::model::multi_point<point> mpoints;
typedef boost::geometry::model::polygon<point> polygon;
mpoints mpts;
for(int i = 0;i < pts.size();i ++) {
boost::geometry::append(mpts,point(pts[i].x,pts[i].y));
}
polygon hull;
// Polygon is closed
boost::geometry::convex_hull(mpts, hull);
for(auto pt : hull.outer()) {
chull.push_back(Point(pt.get<0>(), pt.get<1>()));
}
}
geomutils.h:
#ifndef GEOMUTILS_H
#define GEOMUTILS_H
#include <vector>
struct Point {
double x,y;
Point(){}
Point(double x, double y):x(x),y(y){}
};
typedef std::vector<Point> Polygon;
void computeConvexHull(Polygon &pts, Polygon &chull);
#endif // GEOMUTILS_H
When I compile the code and try to run it.
Only Done1 gets printed on the console. It neither gives any error nor any message.
Output:
Done1
Hull in -99999:
[(0, 0), (0, 7.14), (4.58, 7.14), (0, 0), ]
There's some issue on your code. First of all in main to correctly initialize the vector you have to use the {} syntax. Further in customComputeConvexHull you are setting values inside the res vector which are not yet present. You have to use push_back to populate res. Below a version of your code which works (I put everything into one cpp file for semplicity.
#include <vector>
//#include "geomutils.h"
//#include "mycode.h"
#include <iostream>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/geometries/adapted/boost_tuple.hpp>
using namespace std;
struct Point {
double x, y;
Point() {}
Point(double x, double y) :x(x), y(y) {}
};
typedef std::vector<Point> Polygon;
BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian);
void computeConvexHull(Polygon& pts, Polygon& chull) {
chull.clear();
if (pts.size() == 1) {
chull.push_back(pts[0]);
chull.push_back(pts[0]);
return;
}
else if (pts.size() == 2) {
chull.push_back(pts[0]);
chull.push_back(pts[1]);
chull.push_back(pts[0]);
return;
}
typedef boost::tuple<double, double> point;
typedef boost::geometry::model::multi_point<point> mpoints;
typedef boost::geometry::model::polygon<point> polygon;
mpoints mpts;
for (int i = 0; i < pts.size(); i++) {
boost::geometry::append(mpts, point(pts[i].x, pts[i].y));
}
polygon hull;
// Polygon is closed
boost::geometry::convex_hull(mpts, hull);
for (auto pt : hull.outer()) {
chull.push_back(Point(pt.get<0>(), pt.get<1>()));
}
}
vector< vector<double> > customComputeConvexHull(vector< vector<double> > i_matrix) {
cout << "\nDone1.1";
Polygon custompts, customhull;
for (int r = 0; r < i_matrix.size(); r++) {
custompts.push_back(Point(i_matrix[r][0], i_matrix[r][1]));
}
computeConvexHull(custompts, customhull);
vector< vector<double> > res;
for (int i = 0; i < 3; i++)
{
vector<double> v1{ customhull[i].x, customhull[i].y };
res.push_back(v1);
}
return res;
}
int main()
{
// Create an empty vector
vector< vector<double> > mat, mat2;
vector<double> myRow1{0, 0};
mat.push_back(myRow1);
vector<double> myRow2{ 7.61, 9.48 };
mat.push_back(myRow2);
vector<double> myRow3{ 0, 9.48 };
mat.push_back(myRow3);
cout << "Done1";
mat2 = customComputeConvexHull(mat);
cout << "Done2";
return 0;
}

#ifndef error : need to update includepath

My header file "broker.h" is
#ifndef _BROKER_
#define _BROKER_
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <list>
#include <iterator>
#include <vector>
#include "strategy.h"
#include "utils.h"
using namespace std;
class Broker{
private:
vector< vector<double> > buy_signals; //time X codes
vector< vector<double> > sell_signals; //time X codes
vector< vector<double> > positions; //time X codes
vector< vector<double> > cashs; //time X 1
vector< vector<double> > prices; // time X codes
vector<double> position;
fstream fs;
fstream indi;
vector<string>codes;
vector<string>time_index;
int n_cols, n_rows;
double return_mean, sharp;
Strategy strategy;
public:
double cash;
double unit;
template<typename T>
void set_data(vector<string>& _codes, const map<string, vector<T>>>& _fs, const map<string, vector<T>>>& _indi, const vector<vector<double>>& _prices, const vector<string>& _time_index){
codes = _codes;
time_index = _time_index; //2015-2020
n_cols = codes.size();
n_rows = time_index.size();
/*
I don't know which data type is better for multi-index columns
fs=_fs;
indi = _indi;
*/
buy_signals = zero_vector(buy_signals, n_rows, n_cols);
sell_signals = zero_vector(sell_signals, n_rows, n_cols);
positions = zero_vector(positions, n_rows, n_cols);
cashs = zero_vector(cashs, n_rows, 1);
prices = _prices;
vector<vector<double>> temp;
position = zero_vector(temp, 1, n_cols)[0];
};
void update_data(Strategy s, int date_index){
cash = s.cash;
position = s.position;
cashs[i] = s.cash; // times X 1 : vector< vector<int> >
positions[i] = s.position; // times X codes : vector<vector<int>>
buy_signals[i] = s.buy_signal;
sell_signals[i] = s.sell_signal;
};
void run(){
for (int i=0; i < n_rows ; i++) {
string date = time_index[i];
string year = date.substr(0,4);
string prev_year = to_string(stoi(year)-1);
// 추상적 데이터 접근 - fs 데이터 타입 정해진 후 수정 바람
prev_fs_row = fs[prev_year]; // Not exact fs data type
curr_fs_row = fs[year];
curr_indi_row = indi[date];
Strategy strat = Strategy();
strat.set_data(prev_fs_row, curr_fs_row, curr_indi_row, codes, unit, cash);
strat.run();
update_data(strat, i);
}
};
void performance(){
vector<double> last_price = prices.back(); // {vector<int>, vector<int>, ....}
vector<double> total_remain_num = position;
vector<vector<double>> total_buy_data = d2_vec_mul(prices, buy_signals);
vector<vector<double>> total_sell_data = d2_vec_mul(prices, sell_signals);
double total_buy = sum_vector(sum_vector(total_buy_data, 1))[0][0];
double total_sell = sum_vector(sum_vector(total_sell_data, 1))[0][0];
double total_remain = vec_mul(last_price, total_remain_num)[0];
double profit = total_sell + total_remain - total_buy;
if (total_buy) {
return_mean = profit/total_buy;
}
else{
cout << "No buy!" <<endl;
return;
}
int n_rows = time_index.size();
// prices : already change from na -> 0 (from python)
vector<vector<double>> posses_stock_value = sum_vector(d2_vec_mul(positions, prices), 1); // times X 1
vector<vector<double>> accumulates = sum_vectors(cashs, posses_stock_value);
vector<vector<double>> shift_accumulates = shift_vector(accumulates);
vector<vector<double>> daily_return = divide_vectors(sum_vectors(accumulates, shift_accumulates, 0), shift_accumulates);
vector<double> temp ={1}; vector<vector<double>> ones(n_rows, temp);
daily_return = sum_vectors(daily_return, ones, 0);
temp.clear();
temp.push_back(return_mean); vector<vector<double>> daily_return_mean(n_rows, temp);
vector<vector<double>> daily_Err = (sum_vectors(pop_front(daily_return), pop_front(daily_return_mean));
double SSE = sum_vector(d2_vec_mul(daily_Err, daily_Err));
double std = power_vector(SSE, 0.5);
sharp = return_mean / std;
}
};
#endif
And there is an error in #ifndef BROKER as "There is #include error. Please update includePath."
My c_cpp_properties.json is
My project folder location is
However, my includepath is correct and when I just a simple HelloWorld.cpp there is no error. Why is there an error in #ifndef??

Vector::push_back not storing values in vector

Recently I've been trying to write a neural network program. I have all a neurons connections stored in a vector in the neuron. However whenever I push back a connection into the vector it doesn't seem to store (I can tell via debug mode), and when I try to add up the activation values of the vectors in a for loop, I get an out_of_range error. Here's my code.
Main.cpp
#include <iostream>
#include "neuron.h"
void displayboard(bool board [8][8]);
using namespace std;
int main()
{
int id = 2;
int inputids [] = {3};
int outputids [] = {4};
int inputweights [] = {5};
bool new_neuron = true;
neuron test (inputids, outputids, inputweights, new_neuron, id);
test.connections.at(0).value = 6;
// here is where the error is returned
test.activation();
cout << test.activationnumber;
return 0;
}
And here's Neuron.cpp:
#include "neuron.h"
#include <vector>
#include <random>
#include <ctime>
using namespace std;
neuron::neuron(int inputids [], int outputids [], int inputweights [],
bool new_neuron, int id)
{
this->id = id;
if (new_neuron==true) {
srand (time(0));
connection tempconnection;
for (int i = 0; i <=(sizeof (inputids)/sizeof (inputids [0])); i++)
{
tempconnection.type=false;
tempconnection.tofrom = inputids [i];
tempconnection.weight = rand ();
this->connections.push_back (tempconnection);
}
// this continues on for other options
}
void neuron::activation (){
for (int i=0; i<=this->connections.size (); i++) {
this->activationnumber += ((this->connections.at(i).value)
*(this->connections.at (i).weight));
}
}
UPDATE: Reading this will help you understand why your "sizeof/sizeof" approach is not good in C++.
Original answer
The behavior of sizeof(array)/sizeof(array[0]) might not be what you expected. The following code outputs 2 but you seem to expect 4. Use array for objects in the stack or vector for objects in the heap.
#include <iostream>
using namespace std;
void foo( int array[] )
{
wcout << sizeof( array ) / sizeof( array[ 0 ] );
}
int main()
{
int test[ 4 ];
foo( test );
return 0;
}
Change
int inputids [] = {3};
int outputids [] = {4};
to
vector< int > {3};
vector< int > {4};
Also change
neuron(int inputids [],int outputids [] …
{
…
for (int i = 0; i <= …; i++)
…
tempconnection.tofrom = inputids [i];
to
neuron( vector< int > & inputids, vector< int > & outputids …
{
…
for( auto id : inputids )
…
tempconnection.tofrom = id;

Vector subscript out of range when incrementing an int?

So strange situation, I am creating a list of structs, and then I am trying to update one of the list members with new values, and then move it back into the list.
I seem to be able to copy the values of the struct at iterator just fine, but when I attempt to update the value of the struct's member (using int++;) it throws an exception in the vector class of all things.
Any kind of explanation as to what might be happening here would be helpful.
struct Blob
{
int x;
int y;
};
list<Blob> blob;
// Add a Blob to blob using .push_back(); here
for(list<Blob>::iterator iterator=blob.begin(); iterator!=blob.end(); ++iterator)
{
Blob temp;
temp.x = ((Blob)*iterator).x;
temp.y = ((Blob)*iterator).y;
if (temp.x < 10 - 1)
temp.x++; /* Exception: vector: line 932 - "Vector subscript out of range" */
((Rain)*iterator) = temp;
}
When you want to update the existing value of object then take a reference of it. I have written a sample code to explain the same
#include<list>
#include<iostream>
using namespace std;
struct Test
{
int x;
int y;
};
int main()
{
list<Test> lTest;
int i = 0;
for(i=0;i<5;i++)
{
Test t1;
t1.x = i;
t1.y = i*i;
lTest.push_back(t1);
}
list<Test>::iterator lIter = lTest.begin();
for(;lIter != lTest.end();++lIter)
{
Test &t1 = *lIter;
cout<<"1 Val is:"<<t1.x<<"|"<<t1.y<<endl;
t1.x += 2;
t1.y += 2;
cout<<"2 Val is:"<<t1.x<<"|"<<t1.y<<endl;
}
lIter = lTest.begin();
for(;lIter != lTest.end();++lIter)
{
Test t1 = *lIter;
cout<<"3 Val is:"<<t1.x<<"|"<<t1.y<<endl;
}
return 0;
}
If you're writing a loop it's likely there's another way to do it. You can use std::for_each:
#include <list>
#include <algorithm>
struct Blob
{
int x;
int y;
};
void incrementXIfLessThanNine(Blob& blob)
{
if(blob.x < 9)
{
blob.x++;
}
}
int main()
{
std::list<Blob> blobs;
std::for_each(blob.begin(), blob.end(), incrementXIfLessThanNine);
return 0;
}
If you're using C++11:
#include <list>
struct Blob
{
int x;
int y;
};
int main()
{
std::list<Blob> blobs;
for(Blob& blob: blobs)
{
if(blob.x < 9)
{
blob.x++;
}
}
return 0;
}

Debugging vector retrieval?

This is pretty much a followup from debugging a map insertion, I applied the suggestion pointed there, but now that even more pointers were needed I'm getting really puzzled by this:
#include <stdio.h>
#include <vector>
#include <stack>
#include <map>
using namespace std;
class Nodo
{
public:
vector<Nodo*> Relaciones;
int Valor;
bool Visitado;
Nodo(int V)
{
Valor = V;
Visitado = false;
}
Nodo()
{
Visitado = false;
}
};
class Grafo
{
public:
Nodo *Raiz;
map<int, Nodo*> Nodos;
Grafo(int V)
{
Raiz = new Nodo(V);
Nodos.insert(pair<int, Nodo*>(V, Raiz));
}
void Insertar(int _1, int _2)
{
Nodo *Fuente = Nodos[_1];
Nodo *Destino = new Nodo(_2);
Nodos.insert(pair<int, Nodo>(_2, Destino));
Fuente->Relaciones.push_back(Destino);
Destino->Relaciones.push_back(Fuente);
}
pair<int, Nodo> Resultado;
void DFS(Nodo Fuente)
{
stack<pair<int, Nodo>> St;
St.push(pair<int, Nodo>(0, Fuente));
Fuente.Visitado = true;
while(!St.empty())
{
pair<int, Nodo> P = St.top();
int Dist = P.first;
Nodo N = P.second;
St.pop();
if(Dist < Resultado.first)
{
Resultado.first = Dist;
Resultado.second = N;
}
for(int i = 0; i < N.Relaciones.size(); i++)
{
//Getting error C2664: 'Nodo::Nodo(int)' : cannot convert parameter 1 from 'Nodo *' to 'int' here
Nodo *I = N.Relaciones[i];
if(!I->Visitado)
{
I->Visitado = true;
St.push(pair<int, Nodo>(Dist + 1, I));
}
}
}
}
int Procesar()
{
DFS(*Raiz);
Resultado.first = 0;
DFS(Resultado.second);
return Resultado.first;
}
};
int main()
{
Grafo* G;
int Nodos = 0;
scanf("%d", &Nodos);
int _1, _2 = 0;
scanf("%d", &_1);
scanf("%d", &_2);
G = new Grafo(_1);
G->Insertar(_1, _2);
Nodos--;
while(Nodos - 1 > 0)
{
scanf("%d", &_1);
scanf("%d", &_2);
G->Insertar(_1, _2);
Nodos--;
}
printf("%d" + G->Procesar());
system("PAUSE");
}
Shouldn't it work as it is? I declare I as a pointer to Nodo, and the [] operator is meant to give me just that, a Nodo pointer.
If it is of importance, I'm using Visual Studio 2011 configured for no charset.
Since the map uses pointer, you need to insert a pair with pointer, change all
pair<int, Nodo>
to
pair<int, Nodo*>
I see a few problems with Insertar...
void Insertar(int _1, int _2)
{
Nodo *Fuente = Nodos[_1];
Nodo *Destino = new Nodo(_2);
Nodos.insert(pair<int, Nodo>(_2, Destino));
Fuente->Relaciones.push_back(Destino);
Destino->Relaciones.push_back(Fuente);
}
1) Nodos[_1] is not the way to find the entry associated with key _1 because it will create an entry in your map if one does not already exist. Please use map::find().
2) The insert of pair is being passed a Nodo*. That is incorrect.
I only looked at this function. I'm sure there are other issues.