In my project, I had an error with a vector that I solved by including this line in the header file:
std::vector<std::vector<int, int>, int> cells;
However, this produced 181 errors, all of them found either in the 'vector' file or the 'xmemory' file. How do I fix these errors?
The first of these errors is: '_Alloc': must be a class or namespace when followed by '::'
My two files:
Cells.cpp
#include "Cells.h"
#include <vector>
vector<vector<int, int>, int> cells; // [[x, y], state]
// initiates the list of cells
void Cells::init(int w, int h, int s) {
cells.clear();
for (int y = s; y <= h; y += s) {
for (int x = s; x <= w; x += s) {
cells.push_back({ x, y }, 0);
}
}
}
// finds the index of a cell given its coordinates
int find(int x, int y) {
for (int i = 0; i < cells.size(); i++) {
if (cells[i][0] == { x, y }) {
return i
}
}
}
void Cells::setState(int x, int y, int s) {
cells[find(x, y)][1] = s;
}
// the logic of the game
int Cells::brain(int x, int y, int s) { // 1 alive 0 dead, s = size + space
vector<int, int, int, int> around;
int tAlive;
// getting the states of all the cells in a 1 cell radius around the focused one
around.push_back(cells[find(x - s, y - s)][1]);
around.push_back(cells[find(x, y - s)][1]);
around.push_back(cells[find(x + s, y - s)][1]);
around.push_back(cells[find(x - s, y)][1]);
around.push_back(cells[find(x + s, y)][1]);
around.push_back(cells[find(x - s, y + s)][1]);
around.push_back(cells[find(x, y + s)][1]);
around.push_back(cells[find(x + s, y + s)][1]);
for (int i = 0; i < 8; i++) {
if (around[i] == 1) {
tAlive++;
}
}
if (cells[find(x, y)][1] == 1) {
if (tAlive <= 1 || tAlive >= 4) {
cells[find(x, y)][1] = 0;
} else {
cells[find(x, y)][1] = 1;
}
} else {
if (tAlive == 3) {
cells[find(x, y)][1] = 1;
}
}
return cells[find(x, y)][1];
}
Cells.h
#pragma once
#include <vector>
class Cells {
public:
std::vector<std::vector<int, int>, int> cells;
void init(int w, int h, int s);
int brain(int x, int y, int s);
void setState(int x, int y, int s);
};
Firstly, vector> isn’t allowed before C++11 standard. So, you could select Properties->Configuration Properties->C/C++->Language->C++ Language Standard and set ISO C++17 Standard (/std:c++17).
Secondly, you could add std:: before vector and ; after return i.
Finally , if you use vector,int>>, you could change cells.push_back({ x, y }, 0); to cells.push_back(make_pair(make_pair(x, y), 0)); and change cells[i][0] == { x, y } to cells.at[i].first.first == x&& cells.at[i].first.second==y.
i am doing a standard problem to calculate min moves to reach target by a knight but i also want to keep track of path but its showing error.it dispalys
prog.cpp: In function
'int minStepToReachTarget(int*, int*, int)':
prog.cpp:76:42: error: no match for 'operator[]' (operand types are
'std::vector<cell>' and 'cell')
{q.push(cell(x, y, t.dis + 1));parent[cell(x, y, t.dis + 1)]=t;}
I have commented down the line 76 in my code.
struct cell {
int x, y;
int dis;
cell() {}
cell(int x, int y, int dis): x(x), y(y), dis(dis) {}
};
//cell parent[10000];
typedef cell c;
vector<c> parent(10000);
bool isInside(int x, int y, int N) {
if (x >= 1 && x <= N && y >= 1 && y <= N)
return true;
return false;
}
int minStepToReachTarget(int knightPos[], int targetPos[], int N) {
// x and y direction, where a knight can move
int dx[] = {-2, -1, 1, 2, -2, -1, 1, 2};
int dy[] = {-1, -2, -2, -1, 1, 2, 2, 1};
// queue for storing states of knight in board
queue<cell> q;
// push starting position of knight with 0 distance
q.push(cell(knightPos[0], knightPos[1], 0));
cell t;
int x, y;
bool visit[N + 1][N + 1];
// make all cell unvisited
for (int i = 1; i <= N; i++)
for (int j = 1; j <= N; j++)
visit[i][j] = false;
visit[knightPos[0]][knightPos[1]] = true;
// parent[cell(knightPos[0], knightPos[1], 0)]=t;
// loop untill we have one element in queue
while (!q.empty()) {
t = q.front();
//parent[t]=t;
q.pop();
visit[t.x][t.y] = true;
// if current cell is equal to target cell,
// return its distance
if (t.x == targetPos[0] && t.y == targetPos[1])
return t.dis;
// loop for all reahable states
for (int i = 0; i < 8; i++) {
x = t.x + dx[i];
y = t.y + dy[i];
// If rechable state is not yet visited and
// inside board, push that state into queue
if (isInside(x, y, N) && !visit[x][y]) {
q.push(cell(x, y, t.dis + 1));
//76 ERROR: parent[cell(x, y, t.dis + 1)]=t;}
}
}
}
int main() {
// size of square board
int N = 6;
int knightPos[] = {4, 5};
int targetPos[] = {1, 1};
int m= minStepToReachTarget(knightPos, targetPos, N);
cout<<m<<endl;
return 0;
}
#Code
int dx[8] = {-1,-2, 1 ,2 ,-1, -2, 1, 2};
int dy[8] = {-2,-1, -2,-1, 2, 1, 2, 1};
q.push(ppi(pi(kx, ky), 0));
while(!q.empty()){
pi cur = q.front().first; int d = q.front().second; q.pop();
int x = cur.first;
int y = cur.second;
// printf("%d %d %d\n", x,y, visited[x][y]);
if(visited[x][y]) continue;
visited[x][y] = true;
if (x == tx && y == ty){
printf("%d", d);
return 0;
}
for(int i = 0; i<8; i++){
int nx = x+dx[i];
int ny = y+dy[i];
if(nx <= 0 || nx > n || ny <= 0 || ny > n) continue;
q.push(ppi(pi(nx, ny), d+1));
}
}
printf("-1");
Explanation
Here, this is the bfs which I implemented. I am storing the grid as a boolean value, I can keep track of which squares I have traveled too. If I am unable to reach the square, I output -1. I would also recommend not using function calls unless really necessary, as this is a simple BFS question.
Extension
Just in case you want to find out more, I took the following chunk from my code for a harder problem, where there exists a grid with forbidden squares where the knight cannot travel. In that case, forbidden squares are initially marked as 'true' instead of 'false' to signify that is traveled so I will not go on it.
I hope my above solution helps.
I implemented A* and JPS(Jump Point Search) using VS2008.
Then i tried comparing time cost of these code.
On debug mode, (my) JPS is faster than A* about 2.0~50 times .
But on release mode, JPS is faster than A* about 0.6~3.0 times.
Especially, almost cases of test on release mode, JPS slower than A*.
Why results are so different?
In the paper( "Online Graph Pruning for Pathfinding on Grid Maps", 2011 ),
JPS is faster than A* about 20~30 times.
If i want to get a similar results in the paper, what should i do?
I just call map1.A_star() and map2.JPS() in main.cpp.
and I used prioiry_queue(STL) for A* and JPS.
↓ pathfinding.cpp
#include "util.h"
using namespace std;
int DIR_X[8] = { 0, 1, 1, 1, 0, -1, -1, -1 };
int DIR_Y[8] = { -1, -1, 0, 1, 1, 1, 0, -1 };
// diagonal index {1, 3, 5, 7}
template<class T>
void vector_clear(vector<T>& vecObj)
{
vector<T> tempObj;
tempObj.swap(vecObj);
}
bool operator<(const Node& a, const Node& b)
{
return a.getPriority() > b.getPriority();
}
void read_scenario(char* path, char(*scenarios)[256], int& total) {
ifstream scen_file(path);
char buffer[256];
int num = 0;
scen_file.getline(buffer, 256);
while (!scen_file.eof()) {
scen_file.getline(buffer, 256);
num++;
int index1;
int index2;
int count = 0;
for (int i = 0; i<256; i++) {
if (buffer[i] == ' ')
count++;
if (buffer[i] == ' ' && count == 4)
index1 = i;
if (buffer[i] == ' ' && count == 8)
index2 = i;
}
for (int i = index1 + 1; i <= index2 - 1; i++) {
scenarios[num][i - (index1 + 1)] = buffer[i];
}
scenarios[num][index2] = NULL;
}
std::cout << num << " 개의 시나리오가 있습니다." << endl;
total = num;
scen_file.close();
}
Map::Map(int* START_GOAL, char* IN_PATH, char* OUT_PATH, string MODE) {
sx = START_GOAL[0];
sy = START_GOAL[1];
gx = START_GOAL[2];
gy = START_GOAL[3];
mode = MODE;
in_path = IN_PATH;
out_path = OUT_PATH;
ifstream map_file(in_path);
if (!map_file.is_open()) {
std::cout << "there is no map_file" << endl;
}
char buffer[128];
char ch[4];
char cw[4];
map_file.getline(buffer, 128);
map_file.getline(buffer, 128);
for (int i = 7; i < strlen(buffer); i++) {
ch[i - 7] = buffer[i];
}
h = atoi(ch);
std::cout << "height = " << h << endl;;
map_file.getline(buffer, 128);
for (int i = 6; i < strlen(buffer); i++) {
cw[i - 6] = buffer[i];
}
w = atoi(cw);
std::cout << "width = " << w << endl;;
map_file.getline(buffer, 128);
std::cout << "Start at (" << sx << " " << sy << ")" << endl;
std::cout << "Goal is (" << gx << " " << gy << ")" << endl;
std::cout << endl;
in_map = new char*[h];
direction_map = new int*[h];
visit_map = new bool*[h];
out_map = new char*[h];
parent_map = new int*[h];
open_node_map = new double*[h];
for (int j = 0; j<h; j++) {
in_map[j] = new char[w];
direction_map[j] = new int[w];
visit_map[j] = new bool[w];
out_map[j] = new char[w];
parent_map[j] = new int[w];
open_node_map[j] = new double[w];
for (int i = 0; i <= w; i++) {
char tmp;
map_file.get(tmp);
if (w == i)
continue;
in_map[j][i] = tmp;
direction_map[j][i] = -1;
visit_map[j][i] = false;
out_map[j][i] = tmp;
open_node_map[j][i] = 0.0;
}
}
map_file.close();
}
Map::~Map() {
for (int i = 0; i<h; i++) {
delete[] parent_map[i];
delete[] in_map[i];
delete[] direction_map[i];
delete[] visit_map[i];
delete[] out_map[i];
delete[] open_node_map[i];
}
delete[] parent_map;
delete[] in_map;
delete[] direction_map;
delete[] visit_map;
delete[] out_map;
delete[] open_node_map;
}
int Map::getGx() const { return gx; }
int Map::getGy() const { return gy; }
int Map::getSx() const { return sx; }
int Map::getSy() const { return sy; }
int Map::getHeight() const { return h; }
int Map::getWidth() const { return w; }
double Map::getOptimalLength() const { return optimal_length; }
char Map::getInMapData(int x, int y) { return in_map[y][x]; }
int Map::getDirectionData(int x, int y) { return direction_map[y][x]; }
bool Map::getVisitMapData(int x, int y) { return visit_map[y][x]; }
int Map::getParentMapData(int x, int y) { return parent_map[y][x]; }
double Map::getOpen_NodeData(int x, int y) { return open_node_map[y][x]; }
char Map::getOutMapData(int x, int y) const { return out_map[y][x]; }
void Map::setVisitMap(int x, int y, bool data) { visit_map[y][x] = data; }
void Map::setDirectionMap(int x, int y, int data) { direction_map[y][x] = data; }
void Map::setOutMap(int x, int y, char data) { out_map[y][x] = data; }
void Map::setParentMap(int x, int y, int data) { parent_map[y][x] = data; }
void Map::setOpen_NodeMap(int x, int y, double data) { open_node_map[y][x] = data; }
void Map::initialize() {}
void Map::draw_map() {
ofstream out_file(out_path);
for (int j = 0; j<h; j++) {
for (int i = 0; i<w; i++) {
if (j == sy && i == sx)
out_map[j][i] = 'S';
if (j == gy && i == gx)
out_map[j][i] = 'G';
out_file << out_map[j][i];
}
out_file << "\r\n";
}
out_file.close();
}
void Map::A_star() {
priority_queue<Node> search_q[2];
Node startPoint(sx, sy, gx, gy, -1, 0, mode);
int pqi = 0;
search_q[pqi].push(startPoint);
Map::setOpen_NodeMap(sx, sy, startPoint.getPriority());
while (!search_q[pqi].empty()) {
int cx = search_q[pqi].top().getX(); // current x, y
int cy = search_q[pqi].top().getY();
double passedLength_c = search_q[pqi].top().getPassedLength();
Map::setVisitMap(cx, cy, true);
Map::setOpen_NodeMap(cx, cy, search_q[pqi].top().getPriority());
search_q[pqi].pop();
if (cx == gx && cy == gy) {
double shortestLength = 0;
while (1) {
if ((cx == sx) && (cy == sy)) break;
int tmp_x, tmp_y, tmp_dir;
tmp_x = cx;
tmp_y = cy;
tmp_dir = getDirectionData(tmp_x, tmp_y);
cx -= DIR_X[tmp_dir];
cy -= DIR_Y[tmp_dir];
setOutMap(cx, cy, '#');
if (tmp_dir % 2 == 1)
shortestLength += sqrt(2.0);
else
shortestLength += 1.0;
}
cout << "A_star find!" << endl;
cout << "Path Length = " << shortestLength << endl;
optimal_length = shortestLength;
while (!search_q[pqi].empty()) {
search_q[pqi].pop();
}
return;
}
for (int dir = 0; dir<8; dir++) {
// next_node
int nx = cx + DIR_X[dir];
int ny = cy + DIR_Y[dir];
if (!(nx >(w - 1) || nx < 0 || ny >(h - 1) || ny < 0 || getInMapData(nx, ny) == '#' || getVisitMapData(nx, ny) == true)) {
Node next_node(nx, ny, gx, gy, passedLength_c, dir, mode, 1);
if (Map::getOpen_NodeData(nx, ny) == 0) {
Map::setOutMap(nx, ny, 'I');
Map::setOpen_NodeMap(nx, ny, next_node.getPriority());
search_q[pqi].push(next_node);
Map::setDirectionMap(nx, ny, dir);
}
else if (Map::getOpen_NodeData(nx, ny) > next_node.getPriority()) {
Map::setOpen_NodeMap(nx, ny, next_node.getPriority());
Map::setDirectionMap(nx, ny, dir);
search_q[pqi].push(next_node);
/*
while (!(search_q[pqi].top().getX() == nx && search_q[pqi].top().getY() == ny))
search_q[1 - pqi].push(search_q[pqi].top());
search_q[pqi].pop();
}
search_q[pqi].pop();
if (search_q[pqi].size() > search_q[1 - pqi].size()) {
pqi = 1 - pqi;
}
while (!search_q[pqi].empty()) {
search_q[1 - pqi].push(search_q[pqi].top());
search_q[pqi].pop();
}
pqi = 1 - pqi;
search_q[pqi].push(next_node);
*/
}
}
}
}
}
void Map::JPS() {
priority_queue <Node> JumpPoints;
Node startPoint(sx, sy, gx, gy, 0, -1, mode, 1);
startPoint.calculateDistanceToGoal();
startPoint.updatePriority();
JumpPoints.push(startPoint);
while (!JumpPoints.empty()) {
int x = JumpPoints.top().getX();
int y = JumpPoints.top().getY();
if (x == gx && y == gy) {
cout << "JPS find!!!" << endl;
double shortestLength = 0;
while (!(x == Map::getSx() && y == Map::getSy())) {
int fix_x = x;
int fix_y = y;
int tmp_dir = getDirectionData(fix_x, fix_y);
int px = Map::getParentMapData(fix_x, fix_y) % 512;
int py = Map::getParentMapData(fix_x, fix_y) / 512;
//while(!(Map::getOutMapData(x, y) == 'J')){
while (!(px == x && py == y)) {
if (Map::getParentMapData(fix_x, fix_y) == (y * Map::getWidth() + x)) break;
//if(!(Map::getOutMapData(x, y) == 'J')){
if (!(Map::getOutMapData(x, y) == 'J')) {
setOutMap(x, y, '#');
}
x -= DIR_X[tmp_dir];
y -= DIR_Y[tmp_dir];
if (tmp_dir % 2 == 1)
shortestLength += sqrt(2.0);
else
shortestLength += 1.0;
}
}
optimal_length = shortestLength;
cout << "Path Length = " << shortestLength << endl;
//cout<<"Path Length = "<< passedLength_c << endl;
return;
}
else
Map::identifySuccessors(JumpPoints);
}
while (!JumpPoints.empty()) {
JumpPoints.pop();
}
cout << "not found" << endl;
}
/*
Node Map::jump(Node const node, int dir, int& off) {
int nx = node.getX() + DIR_X[dir];
int ny = node.getY() + DIR_Y[dir];
if (nx > (w - 1) || nx < 0 || ny >(h - 1) || ny < 0) {
// Map::setOutMap(nx, ny, 'B');
Node NULL_node(-100, -100, 0, 0, 0, 0, "OCTILE", 1);
return NULL_node;
}
char n_MapData = Map::getOutMapData(nx, ny);
if (n_MapData == '#') {
Node NULL_node(-100, -100, 0, 0, 0, 0, "OCTILE", 1);
return NULL_node;
}
Node n_node(nx, ny, gx, gy, node.getPassedLength(), dir);
if (n_MapData == 'I')
Map::setOutMap(nx, ny, 'X');
if (nx == gx && ny == gy) {
off = 1;
return n_node;
}
int forced_neighbours_bits = Map::forced_neighbours(nx, ny, dir);
if (forced_neighbours_bits > 0) {
//Map::setOutMap(nx, ny, 'F');
return n_node;
}
if (dir % 2 == 1) {
// Algorithm 2 function jump 8th line)
if (Map::jump(n_node, (dir + 7) % 8, off).getX() != -100)
return n_node;
if (Map::jump(n_node, (dir + 1) % 8, off).getX() != -100)
return n_node;
}
if (n_MapData != 'S' && n_MapData != 'I' && n_MapData != 'G' && n_MapData != '#' && n_MapData != 'J')
Map::setOutMap(nx, ny, 'I');
//draw_map();
return Map::jump(n_node, dir, off);
}
*/
int Map::jump(int index, int dir, int& off) {
int x = index % w;
int y = index / w;
int nx = x + DIR_X[dir];
int ny = y + DIR_Y[dir];
int n_index = ny * w + nx;
if (nx > (w - 1) || nx < 0 || ny >(h - 1) || ny < 0) {
// Map::setOutMap(nx, ny, 'B');
return -1;
}
char n_MapData = Map::getOutMapData(nx, ny);
if (n_MapData == '#') {
return -1;
}
if (n_MapData == 'I')
Map::setOutMap(nx, ny, 'X');
if (nx == gx && ny == gy) {
off = 1;
return n_index;
}
int forced_neighbours_bits = Map::forced_neighbours(nx, ny, dir);
if (forced_neighbours_bits > 0) {
//Map::setOutMap(nx, ny, 'F');
return n_index;
}
if (dir % 2 == 1) {
// Algorithm 2 function jump 8th line)
if (Map::jump(n_index, (dir + 7) % 8, off) != -1)
return n_index;
if (Map::jump(n_index, (dir + 1) % 8, off) != -1)
return n_index;
}
if (n_MapData != 'S' && n_MapData != 'I' && n_MapData != 'G' && n_MapData != '#' && n_MapData != 'J')
Map::setOutMap(nx, ny, 'I');
//draw_map();
return Map::jump(n_index, dir, off);
}
void Map::identifySuccessors(priority_queue <Node>& successors) {
int x = successors.top().getX();
int y = successors.top().getY();
if (x == gx && y == gy)
return;
int index = y * Map::getWidth() + x;
int dir = successors.top().getDirection();
double passedLength = successors.top().getPassedLength();
Node start(x, y, gx, gy, passedLength, dir, mode, 1);
start.updatePassedLength();
start.calculateDistanceToGoal();
start.updatePriority();
successors.pop();
vector<int> candidate_dir;
if (dir == -1) {
for (int i = 0; i<8; i++) {
int dx = x + DIR_X[i];
int dy = y + DIR_Y[i];
if (!(dx < 0 || dx >(w - 1) || dy < 0 || dy >(h - 1) || Map::getOutMapData(dx, dy) == '#'))
candidate_dir.push_back(i);
}
}
else {
int bits = Map::forced_neighbours(x, y, dir);
for (int i = 0; i<8; i++) {
if (bits & (1 << i))
candidate_dir.push_back(i);
}
if (dir % 2 == 1) {
int dx = x + DIR_X[(dir + 1) % 8];
int dy = y + DIR_Y[(dir + 1) % 8];
if (!(dx < 0 || dx >(w - 1) || dy < 0 || dy >(h - 1) || Map::getOutMapData(dx, dy) == '#'))
candidate_dir.push_back((dir + 1) % 8);
dx = x + DIR_X[(dir + 7) % 8];
dy = y + DIR_Y[(dir + 7) % 8];
if (!(dx < 0 || dx >(w - 1) || dy < 0 || dy >(h - 1) || Map::getOutMapData(dx, dy) == '#'))
candidate_dir.push_back((dir + 7) % 8);
dx = x + DIR_X[dir];
dy = y + DIR_Y[dir];
if (!(dx < 0 || dx >(w - 1) || dy < 0 || dy >(h - 1) || Map::getOutMapData(dx, dy) == '#'))
candidate_dir.push_back(dir);
}
else {
int dx = x + DIR_X[dir];
int dy = y + DIR_Y[dir];
if (!(dx < 0 || dx >(w - 1) || dy < 0 || dy >(h - 1) || Map::getOutMapData(dx, dy) == '#'))
candidate_dir.push_back(dir);
}
}
for (int i = 0; i<candidate_dir.size(); i++) {
int nx, ny, n_index;
int n_dir = candidate_dir[i];
nx = x + DIR_X[n_dir];
ny = y + DIR_Y[n_dir];
int jx, jy;
double j_passedLength, s_dist = 0.0, d_dist = 0.0;
int off = 0;
int j_index = Map::jump(index, n_dir, off);
if (j_index == -1)
continue;
jx = j_index % w;
jy = j_index / w;
j_passedLength = passedLength + sqrt((x - jx)*(x - jx) + (y - jy)*(y - jy));
Node j_node(jx, jy, gx, gy, j_passedLength, n_dir, mode, 1);
j_node.setPassedLength(j_passedLength);
j_node.calculateDistanceToGoal();
j_node.updatePriority();
if (Map::getOpen_NodeData(jx, jy) == 0) {
Map::setOutMap(jx, jy, 'J');
Map::setParentMap(jx, jy, y * Map::getWidth() + x);
Map::setDirectionMap(jx, jy, n_dir);
Map::setOpen_NodeMap(jx, jy, j_node.getPriority());
successors.push(j_node);
}
else if (Map::getOpen_NodeData(jx, jy) > j_node.getPriority()) {
Map::setOpen_NodeMap(jx, jy, j_node.getPriority());
Map::setDirectionMap(jx, jy, n_dir);
Map::setParentMap(jx, jy, y * Map::getWidth() + x);
}
}
candidate_dir.clear();
return;
cout << "not found" << endl;
}
/*
*/
bool Map::is_obstacle(int x, int y, int dir) {
int nx = x + DIR_X[dir];
int ny = y + DIR_Y[dir];
if (nx < 0 || nx >(w - 1) || ny < 0 || ny >(h - 1))
return false;
if (Map::getInMapData(nx, ny) == '#')
return true;
else
return false;
}
int Map::forced_neighbours(int x, int y, int dir) {
int bits = 0;
if (dir == -1)
return -1;
if (dir % 2 == 0) {
// straight
int ndir1 = (dir + 2) % 8;
int ndir2 = (dir + 6) % 8;
if (Map::is_obstacle(x, y, ndir1)) {
if (!Map::is_obstacle(x, y, (dir + 1) % 8))
bits = bits | 1 << ((dir + 1) % 8);
}
if (Map::is_obstacle(x, y, ndir2))
if (!Map::is_obstacle(x, y, (dir + 7) % 8))
bits = bits | 1 << ((dir + 7) % 8);
}
else {
int ndir1 = (dir + 3) % 8;
int ndir2 = (dir + 5) % 8;
if (Map::is_obstacle(x, y, ndir1))
if (!Map::is_obstacle(x, y, (dir + 1) % 8))
bits = bits | 1 << ((dir + 1) % 8);
if (Map::is_obstacle(x, y, ndir2))
if (!Map::is_obstacle(x, y, (dir + 7) % 8))
bits = bits | 1 << ((dir + 7) % 8);
}
return bits;
}
Node::Node(int const x, int const y, int const gx, int const gy, double const passedLength, int const direction, string const mode, int const k) {
this->x = x; this->y = y;
this->direction = direction;
this->passedLength = passedLength;
this->gx = gx; this->gy = gy;
this->mode = mode;
if (k == 1) {
updatePassedLength();
calculateDistanceToGoal();
updatePriority();
}
}
Node::~Node() {}
int Node::getX() const { return x; }
int Node::getY() const { return y; }
int Node::getDirection() const { return direction; }
double Node::getPriority() const { return priority; }
double Node::getPassedLength() const { return passedLength; }
double Node::getDistanceToGoal() const { return distanceToGoal; }
void Node::calculateDistanceToGoal() {
double xd = abs(x - gx);
double yd = abs(y - gy);
if (mode.compare("MANHATTAN") == 0)
distanceToGoal = abs(xd) + abs(yd);
else if (mode.compare("EUCLIDIAN") == 0)
distanceToGoal = sqrt((xd*xd) + (yd*yd));
else if (mode.compare("CHEBYSHEV") == 0)
distanceToGoal = max(abs(xd), abs(yd));
else if (mode.compare("OCTILE") == 0)
distanceToGoal = max(xd, yd) + (sqrt(2.0) - 1) + min(xd, yd);
else
cout << "plz input mode" << endl;
}
void Node::updatePassedLength() {
if (direction == -1);
else if (direction % 2 == 1)
passedLength += (sqrt(2.0));
else
passedLength += (1);
}
void Node::updatePriority() {
priority = passedLength + distanceToGoal;
}
void Node::setPassedLength(double data) {
passedLength = data;
}
util.h
#include <iostream>
#include <string>
#include <queue>
#include <math.h>
#include <fstream>
#include <istream>
#include <cstdio>
#include <vector>
using namespace std;
class Node {
private:
int x;
int y;
int gx;
int gy;
int direction; // direction from past node
double passedLength;
double distanceToGoal;
double priority;
string mode; // mode -> "MANHATTAN", "EUCLIDIAN", CHEBYSHEV", "OCTILE"
public:
Node(int const x, int const y, int const gx, int const gy, double const passedLength, int const direction = 0, string const mode = "MANHATTAN" , int const k = 0 );
~Node();
int getX() const;
int getY() const;
int getDirection() const;
double getPriority() const;
double getPassedLength() const;
double getDistanceToGoal() const;
void setPassedLength(double data);
void calculateDistanceToGoal();
void updatePassedLength();
void updatePriority();
};
class Map {
public:
int gx, gy, sx, sy, w, h;
char* in_path, *out_path;
string mode;
char** in_map;
int** direction_map;
bool** visit_map;
char** out_map;
int** parent_map;
double** open_node_map;
double optimal_length;
public:
Map(int* START_GOAL, char* IN_PATH, char* OUT_PATH, string MODE);
~Map();
int getGx() const;
int getGy() const;
int getSx() const;
int getSy() const;
char getInMapData(int x, int y);
int getDirectionData(int x, int y);
bool getVisitMapData(int x, int y);
int getParentMapData(int x, int y);
double getOpen_NodeData(int x, int y);
int getHeight() const;
int getWidth() const;
double getOptimalLength() const;
char getOutMapData(int x, int y) const;
void setVisitMap(int x, int y, bool data);
void setDirectionMap(int x, int y, int data);
void setOutMap(int x, int y, char data);
void setParentMap(int x, int y, int data);
void setOpen_NodeMap(int x, int y, double data);
void initialize();
void draw_map();
void A_star();
void JPS();
//int identifySuccessors(int x, int y);
void identifySuccessors(priority_queue <Node>& successors);
//int jump(int node_index, int dir, double& s_distance, priority_queue <Node>& successors, double& d_distance, int& trig, int& fx_fy);
//Node Map::jump(Node node, int dir, int& off);
int Map::jump(int index, int dir, int& off);
bool is_obstacle(int x, int n, int dir);
int Map::forced_neighbours(int x, int y, int dir);
};
void read_scenario(char* path, char(*scenarios)[256], int& total);
Without an individual review of each line of code, it appears that the speed difference is due to your programming style.
To take just the first two examples: vector_clear is a poor reimplementation of std::vector::clear and operator<(Node a, Node b) makes unnecessary copies of both nodes. And glancing at the rest of the code, these do not appear to be exceptions.
Measuring the speed of a debug executable is pointless. The compiler settings used for debugging do not take speed of the resulting executable into account. And you've further complicated it by using a debug version of new. Only the speed in release mode is reasonable, and then only if you have good code to start with.
I'm currently writing a BLOB detection algorithm. When I run it I get the error
Unhandled exception at 0x00007FF70476CDA7 in blobdetector.exe: 0xC0000005:
Access violation reading location 0x0000007BDDA0347D.
This is the part of the code where it breaks.
The debugger stops at the last line before the if(val == 255)
void connectivity(BlobBurnMat temp, size_t y, size_t x){
uchar* ptr = (uchar*)temp.getTemp().data;
size_t min_y = temp.getTemp().rows, min_x = temp.getTemp().cols, max_y = 0, max_x = 0;
for (int i = 0; i < 4; i++){
int kernel[4][2] = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };
int temp_y = y + kernel[i][0];
int temp_x = x + kernel[i][1];
uchar val = ptr[temp.getTemp().step * temp_y + temp_x]; //breaks here
if (val == 255) {
temp.setValZero(x, y);
x = temp_x;
y = temp_y;
if (temp_x > max_x)
max_x = temp_x;
if(temp_x < min_x)
min_x = temp_x;
if (temp_y > max_y)
max_y = temp_y;
if (temp_y < min_y)
min_y = temp_y;
int pass_x = ((max_x - min_x) / 2);
int pass_y((max_y - min_y) / 2);
setCoordinates(pass_x, pass_y);
connectivity(temp, y, x);
}
}
}
Here is the rest of the code. The above connectivity() method is in the BLOB class.
#include "opencv2/opencv.hpp"
#include<stdio.h>
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
using namespace cv;
using namespace std;
class BlobBurnMat{
//Class used to store a copy of the source image where pixels get burned in BLOB finding.
private:
Mat temp;
public:
void initiate(Mat temp){
this -> temp = temp;
}
Mat getTemp(){
return temp;
}
void setValZero(int x, int y){
temp.at<uchar>(y, x) = 0;
}
};
class BLOB{
//BLOB class to store coordinates of the BLOBs before they are added to the vector-array-list-thingamajig
private:
int x, y;
public:
void setCoordinates(int x, int y){
this->x = x;
this->y = y;
}
int getX(){
return x;
}
int getY(){
return y;
}
void connectivity(BlobBurnMat temp){
connectivity(temp, x, y);
}
void connectivity(BlobBurnMat temp, int y, int x){
uchar* ptr = (uchar*)temp.getTemp().data;
int min_y = temp.getTemp().rows, min_x = temp.getTemp().cols, max_y = 0, max_x = 0;
for (int i = 0; i < 4; i++){
int kernel[4][2] = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };
int temp_y = y + kernel[i][0];
int temp_x = x + kernel[i][1];
uchar val = ptr[temp.getTemp().step * temp_y + temp_x];
if (val == 255) {
temp.setValZero(x, y);
x = temp_x;
y = temp_y;
if (temp_x > max_x)
max_x = temp_x;
if(temp_x < min_x)
min_x = temp_x;
if (temp_y > max_y)
max_y = temp_y;
if (temp_y < min_y)
min_y = temp_y;
int pass_x = ((max_x - min_x) / 2);
int pass_y((max_y - min_y) / 2);
setCoordinates(pass_x, pass_y);
connectivity(temp, y, x);
}
}
}
};
vector<Point2i> getBlobCoordinates(Mat src){
BlobBurnMat *temp = new BlobBurnMat();
temp->initiate(src.clone());
vector<Point2i> blobCoordinates; //Vector holding all BLOB coordinates
Point2i blobCoords; //Coordinates of a single BLOB
//Go through the binary matrix looking for white pixels.
for (size_t y = 0; y < src.rows; y++) {
for (size_t x = 0; x < src.cols; x++) {
uchar* ptr = (uchar*)temp->getTemp().data;
uchar val = ptr[temp->getTemp().step * y + x];
if (val == 255){
BLOB *blob = new BLOB();
blob->setCoordinates(x, y);
blob->connectivity(*temp);
blobCoords.x = blob->getX();
blobCoords.y = blob->getY();
blobCoordinates.push_back(blobCoords); //add a new element to the vector.
}
}
}
return blobCoordinates;
}
int main(int, char){
Mat src;
String path = "C:/Users/Runagar/Desktop/segment.jpg";
src = imread(path, 0);
if (src.data && !src.empty()){
imshow("blobie", src);
}
else cout << "You fucked up ";
vector <Point2i> blobCoordinates = getBlobCoordinates(src);
for (int k = 0; k < blobCoordinates.size(); k++)
cout << blobCoordinates[k];
waitKey(0);
return 0;
}
Thanks in advance!
When i == 2 and x == 0, temp_x == -1 so you read 1 byte before ptr outside the memory allocaded.
You have to handle the case when x == 0, y == 0, x == src.cols and y == src.rows.
Mat getTemp() returns a copy of your Mat instance.
uchar* ptr = (uchar*)temp.getTemp().data; retrieves a pointer from a temporary Mat instance. This instance is then immediately deleted, and you're left with a pointer to (presumably) properly deleted data.
Try Mat & getTemp() instead.
I am trying to a C++ implementation of this knapsack problem using branch and bounding. There is a Java version on this website here: Implementing branch and bound for knapsack
I'm trying to make my C++ version print out the 90 that it should, however it's not doing that, instead, it's printing out 5.
Does anyone know where and what the problem may be?
#include <queue>
#include <iostream>
using namespace std;
struct node
{
int level;
int profit;
int weight;
int bound;
};
int bound(node u, int n, int W, vector<int> pVa, vector<int> wVa)
{
int j = 0, k = 0;
int totweight = 0;
int result = 0;
if (u.weight >= W)
{
return 0;
}
else
{
result = u.profit;
j = u.level + 1;
totweight = u.weight;
while ((j < n) && (totweight + wVa[j] <= W))
{
totweight = totweight + wVa[j];
result = result + pVa[j];
j++;
}
k = j;
if (k < n)
{
result = result + (W - totweight) * pVa[k]/wVa[k];
}
return result;
}
}
int knapsack(int n, int p[], int w[], int W)
{
queue<node> Q;
node u, v;
vector<int> pV;
vector<int> wV;
Q.empty();
for (int i = 0; i < n; i++)
{
pV.push_back(p[i]);
wV.push_back(w[i]);
}
v.level = -1;
v.profit = 0;
v.weight = 0;
int maxProfit = 0;
//v.bound = bound(v, n, W, pV, wV);
Q.push(v);
while (!Q.empty())
{
v = Q.front();
Q.pop();
if (v.level == -1)
{
u.level = 0;
}
else if (v.level != (n - 1))
{
u.level = v.level + 1;
}
u.weight = v.weight + w[u.level];
u.profit = v.profit + p[u.level];
u.bound = bound(u, n, W, pV, wV);
if (u.weight <= W && u.profit > maxProfit)
{
maxProfit = u.profit;
}
if (u.bound > maxProfit)
{
Q.push(u);
}
u.weight = v.weight;
u.profit = v.profit;
u.bound = bound(u, n, W, pV, wV);
if (u.bound > maxProfit)
{
Q.push(u);
}
}
return maxProfit;
}
int main()
{
int maxProfit;
int n = 4;
int W = 16;
int p[4] = {2, 5, 10, 5};
int w[4] = {40, 30, 50, 10};
cout << knapsack(n, p, w, W) << endl;
system("PAUSE");
}
I think you have put the profit and weight values in the wrong vectors. Change:
int p[4] = {2, 5, 10, 5};
int w[4] = {40, 30, 50, 10};
to:
int w[4] = {2, 5, 10, 5};
int p[4] = {40, 30, 50, 10};
and your program will output 90.
I believe what you are implementing is not a branch & bound algorithm exactly. It is more like an estimation based backtracking if I have to match it with something.
The problem in your algorithm is the data structure that you are using. What you are doing is to simply first push all the first levels, and then to push all second levels, and then to push all third levels to the queue and get them back in their order of insertion. You will get your result but this is simply searching the whole search space.
Instead of poping the elements with their insertion order what you need to do is to branch always on the node which has the highest estimated bound. In other words you are always branching on every node in your way regardless of their estimated bounds. Branch & bound technique gets its speed benefit from branching on only one single node each time which is most probable to lead to the result (has the highest estimated value).
Example : In your first iteration assume that you have found 2 nodes with estimated values
node1: 110
node2: 80
You are pushing them both to your queue. Your queue became "n2-n1-head" In the second iteration you are pushing two more nodes after branching on node1:
node3: 100
node4: 95
and you are adding them to you queue as well("n4-n3-n2-head". There comes the error. In the next iteration what you are going to get will be node2 but instead it should be node3 which has the highest estimated value.
So if I don't miss something in your code both your implementation and the java implementation are wrong. You should rather use a priority queue (heap) to implement a real branch & bound.
You are setting the W to 16, so the result is 5. The only item you can take into the knapsack is item 3 with profit 5 and weight 10.
#include <bits/stdc++.h>
using namespace std;
struct Item
{
float weight;
int value;
};
struct Node
{
int level, profit, bound;
float weight;
};
bool cmp(Item a, Item b)
{
double r1 = (double)a.value / a.weight;
double r2 = (double)b.value / b.weight;
return r1 > r2;
}
int bound(Node u, int n, int W, Item arr[])
{
if (u.weight >= W)
return 0;
int profit_bound = u.profit;
int j = u.level + 1;
int totweight = u.weight;
while ((j < n) && (totweight + arr[j].weight <= W))
{
totweight = totweight + arr[j].weight;
profit_bound = profit_bound + arr[j].value;
j++;
}
if (j < n)
profit_bound = profit_bound + (W - totweight) * arr[j].value /
arr[j].weight;
return profit_bound;
}
int knapsack(int W, Item arr[], int n)
{
sort(arr, arr + n, cmp);
queue<Node> Q;
Node u, v;
u.level = -1;
u.profit = u.weight = 0;
Q.push(u);
int maxProfit = 0;
while (!Q.empty())
{
u = Q.front();
Q.pop();
if (u.level == -1)
v.level = 0;
if (u.level == n-1)
continue;
v.level = u.level + 1;
v.weight = u.weight + arr[v.level].weight;
v.profit = u.profit + arr[v.level].value;
if (v.weight <= W && v.profit > maxProfit)
maxProfit = v.profit;
v.bound = bound(v, n, W, arr);
if (v.bound > maxProfit)
Q.push(v);
v.weight = u.weight;
v.profit = u.profit;
v.bound = bound(v, n, W, arr);
if (v.bound > maxProfit)
Q.push(v);
}
return maxProfit;
}
int main()
{
int W = 55; // Weight of knapsack
Item arr[] = {{10, 60}, {20, 100}, {30, 120}};
int n = sizeof(arr) / sizeof(arr[0]);
cout << "Maximum possible profit = "
<< knapsack(W, arr, n);
return 0;
}
**SEE IF THIS HELPS**