The graph:
and how the points are connected:
the file how points are connected are the output i have . The expected output should be 1<->216 , 23<->157 115<->157 and then 115<->216 . The order doesn't matter but those points should be connected this way
Let me ask you a question.
I have the following code:
for (int i = 0; i < values.size()-1;i++)
{
int result = 0;
double Min2 = DBL_MAX;
int x = 0;
for (int j = i+1; j < values.size(); j++)
{
/*if (visited[j] == false)*/
{
distance = sqrt(pow((values[i].x2 - values[j].x2), 2) + pow((values[i].y2 - values[j].y2), 2));
if (distance < Min2 && distance != 0)
{
Min2 = distance;
x = j;
}
}
}
If you look at the graph the left first node is 1 then goes 216 then 115 then 157 and then 23. I have the right connection except for 216-115 but instead of it connects 216-157. Why does it ignore or min distance won't help. I tried to use flag( like if visited or not)the same result. All nodes work , just this one doesn't want to be connected right.
The logic of the code seems a bit odd...
for (int i = 0; i < values.size()-1;i++) {
int result = 0;
double Min2 = DBL_MAX;
int x = 0;
for (int j = i+1; j < values.size(); j++) {
iterating till size()-1 seems like you assume that the relation "closest neighbour" is commutative, but it is not. Consider this example:
a b c
a has b as closest node and (by chance) also b has a as closest node, but c has b as closest node and this connection you would miss.
Further, starting the second loop at i+1 seems rather odd, as it assumes that the points in the vector are already ordered (if this would be the case, then whats the point of searching the closest nodes?).
If you know already, that the nodes are along a route, then I would do it like this:
1) start with the first node n0 in the route (its a bit more complicated if you dont know this node)
2) find the closest node to n0 call it n1
3) continue to find the closest node to ni among the nodes that are not yet connected to the route, call it ni+1
4) repeat 3) until you reach the end of the route.
I have the impression, that you dont understand the difference between those steps and your code. I dont like to give up, so I will try to explain again in a less pseudo way:
int currentNode = startNode; // as mentioned before, if you dont know
// this its a bit more involved
std::vector<int> route;
route.push_back(currentNode);
while (currentNode != endNode) { // also knowing the last node of the route helps...
double minDistance = std::numeric_limits<double>::max();
int nextNode = -1;
for (int i=0;i<nodes.size();i++) {
if (std::find(route.begin(), route.end(), i) == route.end()){
double distance = getDistance(currentNode,i);
if (distance < minDistance) {
minDistance = distance;
nextNode = i;
}
}
}
route.push_back(nextNode);
currentNode = nextNode;
}
Your outer loop shouldnt iterate through all nodes, if you actually want to find only that one route. Also you have to remember nodes that are already in the route (in case each node should appear only once and you dont want a closed loop).
for (int i = 0; i < values.size();i++)
{
int result = 0;
double Min2 = DBL_MAX;
int x = 0;
for (int j =0; j < values.size(); j++)
{
/*if (visited[j] == false)*/
{
distance = sqrt(pow((values[i].x2 - values[j].x2), 2) + pow((values[i].y2 - values[j].y2), 2));
if (distance < Min2 && distance != 0)
{
Min2 = distance;
x = j;
}
}
}
/*visited[i] = true;*/
Related
I'm solving some problems and I can't solve these one. I have to write a code where user enter a decimal number, and I need to count how many times that number starts with digit 1 in other numerous systems.
Here is algorithm:
for (int i = 3; i <= n; i++) {
int z = n;
while (z != 0) {
x = z % i;
z = z / i;
}
if (x == 1) {
brOsnova++;
}
}
You can accelerate it already by not checking the i's that verify
i <= n < 2*i since all of them will satisfy.
Therefore, check only for(int i = 3; i <= n/2; ++i) and then add (n+1)/2 to the final brOsnova.
I am sure it can be further accelerated and there must be some O(log(n)) algorithm, but maybe it would be far fetched... or a good candidate question for the algorithm tag.
Instead of the loop, use this:
x = x - ((x / i) * i);
if (x == 1)
{
...
}
This only works for integer maths.
I am having trouble with implementing Dijkstra algorithm.
I have the following variables initialized :
enum GraphLimit300 {MAX_NODES = 50};
typedef unsigned int Element300;
Element300 adjacencyMatrix[MAX_NODES][MAX_NODES];
Element300 distanceArray[MAX_NODES];
bool visitedSet[MAX_NODES];
int numberNodes;
Here is my current implementation of the algorithm:
int startNode;
int visited;
unsigned int smallest = UINT_MAX;
do
{
startNode = getStartNode300();
setVisitedSet300();
smallest = UINT_MAX;
visitedSet[startNode] = true;
for (int i = 0; i < numberNodes; i++)
{
distanceArray[i] = adjacencyMatrix[startNode][i];
}
for (int i = 0; i < numberNodes - 1; i++)
{
for (int v = 0; v < numberNodes; v++)
{
if (visitedSet[v] == false)
{
if (distanceArray[v] < smallest)
{
smallest = distanceArray[v];
visited = v;
}
}
}
visitedSet[visited] = true;
for (int w = 0; w < numberNodes; w++)
{
if (visitedSet[w] == false)
{
distanceArray[w] = min(distanceArray[w], distanceArray[visited] + adjacencyMatrix[visited][w]);
}
}
}
On this particular for loop where it should do the certain math to find the min between values at a certain index where the nodes are false and store the min in that index. What I found is that after it chooses the smallest value in distaceArray and set it to true(which is 3 if I start at 1 using the data file below, Which is correct.).
for (int w = 0; w < numberNodes; w++)
{
if (visitedSet[w] == false)
{
distanceArray[w] = min(distanceArray[w], distanceArray[visited] + adjacencyMatrix[visited][w]);
}
}
It uses the nodes '0' and '2' as of this particular iteration is the nodes that are false. And does the math for times and stores them in the wrong array.
I am using this data set that stores the numbers in adjacencyMatrix correctly.
0 5 10 4294967295
4294967295 0 4294967295 3
4294967295 7 0 4294967295
4294967295 4294967295 4 0
The correct output is:
Distance[0] =4294967295
Distance[1] =0 //Which is the node that I choose to start with
Distance[2] =7
Distance[3] =3
What I am getting is:
Distance[0] =3
Distance[1] =0
Distance[2] =3
Distance[3] =3
I have done this process by hand to confirm that the correct output that I should be getting is true and it IS.
Updated if:
if (visitedSet[w] == false && adjacencyMatrix[visited][w] != UINT_MAX)
{
distanceArray[w] = min(distanceArray[w], distanceArray[visited] + adjacencyMatrix[visited][w]);
}
The problem here is again, the fact that you shall only consider edges which exist, that is adjacencyMatrix[visited][w]!=UINT_MAX.
If you don't exclude these edges, distanceArray[visited] + adjacencyMatrix[visited][w] will overflow and the min() will not return the result that you expect.
You can solve this by changing this line:
if (visitedSet[w] == false && adjacencyMatrix[visited][w]!=UINT_MAX )
Edit:
There is indeed another problem hidden in your nested for loops. The first inner for loop looks each time for the shortest subpath to expland. Unfortuantely, you didn't reset smallest, so that it starts with the smalest value of the previous iteration.
Update the looping as follows and you'll get your explected result:
for (int i = 0; i < numberNodes - 1; i++)
{
smallest = UINT_MAX; // !!!!!!!!!!!!!!!!!!!!!!!
for (int v = 0; v < numberNodes; v++)
{
...
}
...
}
I'm trying to implement backtracing of the vertices visited for the lowest costing route to a vertex. I'm getting incorrect results and don't understand why. The only correct output was the last one in the image. What is causing the incorrect
Note: driverMap is a 2D 14x14 integer vector that holds the distances it takes to get to each vertex and path is a int array to hold the past path vertex taken. The beginning is a section of the code from my Main function to help out.
It's different as my previous questions were different, this time i'm asking for help on my current output against expected when attempting to backtrace.
for(int i = 0; i < allCars.size(); i++) //allCars.size()
{
int startInt = allCars[i].getStart(), loopEnder = 0;
for(int k = 0; k < driverMap.size(); k++)
{
path[k] = 0;
Distances[k] = 0;
}
for(int j = 0; j < driverMap.size(); j++)
{
Distances[j] = driverMap[startInt][j];
}
cout << "\nSTART INTERSECTION: '" << startInt << "' END INTERSECTION: '" << allCars[i].getEnd() << "'" << endl;
Dijkstra(driverMap, Distances, path, startInt);
int endInt = allCars[i].getEnd(), atInt = path[endInt];
cout << "END = " << endInt;
//allCars[i].addPath(endInt);
do
{
cout << "AT = " << atInt;
allCars[i].addPath(atInt);
atInt = path[atInt];
loopEnder++;
}while(atInt != endInt && loopEnder < 5);
cout << endl;
//allCars[i].addPath(startInt);
allCars[i].displayCar();
}
void Dijkstra(const vector< vector<int> > & driverMap, int Distances[], int path[], int startInt)
{
int Intersections[driverMap.size()];
for(int a = 0; a < driverMap.size(); a++)
{
Intersections[a] = a;
}
Intersections[startInt] = -1;
for(int l = 0; l < driverMap.size(); l++)
{
int minValue = 99999;
int minNode = 0;
for (int i = 0; i < driverMap.size(); i++)
{
if(Intersections[i] == -1)
{
continue;
}
if(Distances[i] > 0 && Distances[i] < minValue)
{
minValue = Distances[i];
minNode = i;
}
}
Intersections[minNode] = -1;
for(int i = 0; i < driverMap.size(); i++)
{
if(driverMap[minNode][i] < 0)
{
continue;
}
if(Distances[i] < 0)
{
Distances[i] = minValue + driverMap[minNode][i];
path[i] = minNode;
continue;
}
if((Distances[minNode] + driverMap[minNode][i]) < Distances[i])
{
Distances[i] = minValue + driverMap[minNode][i];
path[i] = minNode;
}
}
}
}
Doing backtracking in djikstra
Record the node that update the value of the current node with a smaller value
// Every time you update distance value with a smaller value
Distances[i] = minValue + driverMap[minNode][i];
back[i] = minNode; //Record the node with an int array, should be something like this
After you have complete all djikstra looping. Backtrack from any point except the start point.
Say, we want to trace from pt 5 to pt 0 in your graph where pt 5 is starting point. We start at 0, take back[0] (should equal to 4), then we take back[4] (should equal to 8), then we take back[8] (should equal to 5), then we should have some kinds of mechanism to stop here as pt 5 is a starting point. As a result, you get 0-4-8-5 and you reverse the order. You get the path 5-8-4-0.
In my approach, pathTaken[minNode].push_back(i); is not using. You might need to initiate the int array back[] with starting point's value for those who is connected to starting point.
Edit Part
You miss the point: "You might need to initiate the int array back[] with starting point's value for those who is connected to starting point".
path[k] = 0; is wrong. You should not initiate path with fixed index for all cases. Instead, you should initiate with startInt (for those directly connected to starting node) and non-exist node index -1 (for those not directly connected to starting node)
What back-tracking doing is
to record which node provides a new minimum Cost to current node (and keep updating in dijkstra loop). At the end, every node will get a node value (back[i] in my case) that point to a node that provides node i with its minimize Cost.
Base on the concept of dijkstra algorithm with back-tracking, back[i] is the previous node in the path from starting node to node i. That mean the path should be looks like :
(start node)->(path with zero or more nodes)->node point by back[i]-> node i
Applying this concept, we can track the path backward with back[i], back[back[i]], back[back[back[i]]],...
Any why path[k] = 0; is wrong? In your code, your starting node is not always node 0, but startint. Consider case like startint = 13 and your target destination node is 11. Obviously, the path is 13-11. For node 11, it will never encounter Distances[i] = minValue + driverMap[minNode][i]; when startint = 13 in your coding because that is first minimum cost node. And what have you set? node 11 has back[11]=0 (initialization) which state that the previous node in the path node 13 to 11 is node 0 which is obviously incorrect in concept and back[0]=0 (best path from 13 to 0 is 13-0, no update also) which will loop to itself as 0=back[back[0]]=back[back[back[0]]]=....
In djikstra if you go backwards (finnish -> start) just pick lowest cost node at each step to reach staring point. This works after you have solved graph and you have each node evaluated/costed.
I am attempting to make a maze-solver using a Breadth-first search, and mark the shortest path using a character '*'
The maze is actually just a bunch of text. The maze consists of an n x n grid, consisting of "#" symbols that are walls, and periods "." representing the walkable area/paths. An 'S' denotes start, 'F' is finish. Right now, this function does not seem to be finding the solution (it thinks it has the solution even when one is impossible). I am checking the four neighbors, and if they are 'unfound' (-1) they are added to the queue to be processed.
The maze works on several mazes, but not on this one:
...###.#....
##.#...####.
...#.#.#....
#.####.####.
#F..#..#.##.
###.#....#S.
#.#.####.##.
....#.#...#.
.####.#.#.#.
........#...
What could be missing in my logic?
int mazeSolver(char *maze, int rows, int cols)
{
int start = 0;
int finish = 0;
for (int i=0;i<rows*cols;i++) {
if (maze[i] == 'S') { start=i; }
if (maze[i] == 'F') { finish=i; }
}
if (finish==0 || start==0) { return -1; }
char* bfsq;
bfsq = new char[rows*cols]; //initialize queue array
int head = 0;
int tail = 0;
bool solved = false;
char* prd;
prd = new char[rows*cols]; //initialize predecessor array
for (int i=0;i<rows*cols;i++) {
prd[i] = -1;
}
prd[start] = -2; //set the start location
bfsq[tail] = start;
tail++;
int delta[] = {-cols,-1,cols,+1}; // North, West, South, East neighbors
while(tail>head) {
int front = bfsq[head];
head++;
for (int i=0; i<4; i++) {
int neighbor = front+delta[i];
if (neighbor/cols < 0 || neighbor/cols >= rows || neighbor%cols < 0 || neighbor%cols >= cols) {
continue;
}
if (prd[neighbor] == -1 && maze[neighbor]!='#') {
prd[neighbor] = front;
bfsq[tail] = neighbor;
tail++;
if (maze[neighbor] == 'F') { solved = true; }
}
}
}
if (solved == true) {
int previous = finish;
while (previous != start) {
maze[previous] = '*';
previous = prd[previous];
}
maze[finish] = 'F';
return 1;
}
else { return 0; }
delete [] prd;
delete [] bfsq;
}
Iterating through neighbours can be significantly simplified(I know this is somewhat similar to what kobra suggests but it can be improved further). I use a moves array defining the x and y delta of the given move like so:
int moves[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
Please note that not only tis lists all the possible moves from a given cell but it also lists them in clockwise direction which is useful for some problems.
Now to traverse the array I use a std::queue<pair<int,int> > This way the current position is defined by the pair of coordinates corresponding to it. Here is how I cycle through the neighbours of a gien cell c:
pair<int,int> c;
for (int l = 0;l < 4/*size of moves*/;++l){
int ti = c.first + moves[l][0];
int tj = c.second + moves[l][1];
if (ti < 0 || ti >= n || tj < 0 || tj >= m) {
// This move goes out of the field
continue;
}
// Do something.
}
I know this code is not really related to your code, but as I am teaching this kind of problems trust me a lot of students were really thankful when I showed them this approach.
Now back to your question - you need to start from the end position and use prd array to find its parent, then find its parent's parent and so on until you reach a cell with negative parent. What you do instead considers all the visited cells and some of them are not on the shortest path from S to F.
You can break once you set solved = true this will optimize the algorithm a bit.
I personally think you always find a solution because you have no checks for falling off the field. (the if (ti < 0 || ti >= n || tj < 0 || tj >= m) bit in my code).
Hope this helps you and gives you some tips how to improve your coding.
A few comments:
You can use queue container in c++, its much more easier in use
In this task you can write something like that:
int delta[] = {-1, cols, 1 -cols};
And then you simple can iterate through all four sides, you shouldn't copy-paste the same code.
You will have problems with boundaries of your array. Because you are not checking it.
When you have founded finish you should break from cycle
And in last cycle you have an error. It will print * in all cells in which you have been (not only in the optimal way). It should look:
while (finish != start)
{
maze[finish] = '*';
finish = prd[finish];
}
maze[start] = '*';
And of course this cycle should in the last if, because you don't know at that moment have you reach end or not
PS And its better to clear memory which you have allocate in function
I have some C++ code I wrote to find an A* path, but it's behaving strangely. There's quite a bit of code here, so I'll split it into chunks and try to explain what I'm doing. I'm not gonna explain how A* pathing works. I assume if you're trying to help you already know the algorithm.
First off, here's my function for calculating the h value of a node:
int
calculateH(int cX, int cY, int eX, int eY, int horiCost = 10, int diagCost = 14) {
int h;
int xDist = abs(eX - cX);
int yDist = abs(eY - cY);
if (xDist > yDist)
h = (diagCost * yDist) + (horiCost * (xDist - yDist));
else
h = (diagCost * xDist) + (horiCost * (yDist - xDist));
return h;
}
I'm pretty sure there's no problem here; pretty simple stuff.
Next my Node class. And I know, I know, make those variables private and use getters; I just did it this way for testing purposes.
class Node {
public:
Node(int x_, int y_, int g_, int h_, int pX_, int pY_, bool list_) {
x = x_;
y = y_;
g = g_;
h = h_;
pX = pX_;
pY = pY_;
list = list_;
};
int x, y, g, h, pX, pY;
bool list;
};
Each Node has an X and Y variable. I only store G and H, not F, and calculate F when I need it (which is only once in my code). Then there's the Parent X and Y values. List is a boolean: fale = open list, true = closed list.
I also have a Object class. The only variables that matter here are X, Y, and Passable, all accessed through getters.
Now here's the start of my actual pathfinding code. It returns a string of numbers corresponding to directions as shown below:
432
501
678
So 1 means move right, 8 means go down and right, 0 means don't go anywhere.
string
findPath(int startX, int startY, int finishX, int finishY) {
// Check if we're already there.
if (startX == finishX && startY == finishY)
return "0";
// Check if the space is occupied.
for (int k = 0; k < objects.size(); k ++)
if ((objects[k] -> getX() == finishX) &&
(objects[k] -> getY() == finishY) &&
(!objects[k] -> canPass()))
return "0";
// The string that contains our path.
string path = "";
// The identifier of the current node.
int currentNode = 0;
// The list of nodes.
vector<Node> nodes;
// Add the starting node to the closed list.
nodes.push_back(Node(startX, startY, 0,
calculateH(startX, startY, finishX, finishY),
startX, startY, true));
Now we loop through until we find the destination. Note that sizeLimit is just to make sure we don't loop forever (it WONT if I can fix this code. As of right now it's very necessary). Everything from this point on, until I mark otherwise, is inside the i j loops.
int sizeLimit = 0;
while ((nodes[currentNode].x != finishX) | (nodes[currentNode].y != finishY)) {
// Check the surrounding spaces.
for (int i = -1; i <= 1; i ++) {
for (int j = -1; j <= 1; j ++) {
bool isEmpty = true;
// Check if there's a wall there.
for (int k = 0; k < objects.size(); k ++) {
if ((objects[k] -> getX() == (nodes[currentNode].x + i)) &&
(objects[k] -> getY() == (nodes[currentNode].y + j)) &&
(!objects[k] -> canPass())) {
isEmpty = false;
}
}
Next part:
// Check if it's on the closed list.
for (int k = 0; k < nodes.size(); k ++) {
if ((nodes[k].x == (nodes[currentNode].x + i)) &&
(nodes[k].y == (nodes[currentNode].y + j)) &&
(nodes[k].list)) {
isEmpty = false;
}
}
Continuing on:
// Check if it's on the open list.
for (int k = 0; k < nodes.size(); k ++) {
if ((nodes[k].x == (nodes[currentNode].x + i)) &&
(nodes[k].y == (nodes[currentNode].y + j)) &&
(!nodes[k].list)) {
// Check if the G score is lower from here.
if (nodes[currentNode].g + 10 + (abs(i * j) * 4) <= nodes[k].g) {
nodes[k].g = nodes[currentNode].g + 10 + (abs(i * j) * 4);
nodes[k].pX = nodes[currentNode].x;
nodes[k].pY = nodes[currentNode].y;
}
isEmpty = false;
}
}
This is the last part of the i j loop:
if (isEmpty) {
nodes.push_back(Node(nodes[currentNode].x + i,
nodes[currentNode].y + j,
nodes[currentNode].g + 10 + (abs(i * j) * 4),
calculateH(nodes[currentNode].x + i, nodes[currentNode].y + j, finishX, finishY),
nodes[currentNode].x,
nodes[currentNode].y,
false));
}
}
}
Now we find the Node with the lowest F score, change it to the current node, and add it to the closed list. The protection against infinite lopping is also finished up here:
// Set the current node to the one with the lowest F score.
int lowestF = (nodes[currentNode].g + nodes[currentNode].h);
int lowestFIndex = currentNode;
for (int k = 0; k < nodes.size(); k ++) {
if (((nodes[k].g + nodes[k].h) <= lowestF) &&
(!nodes[k].list)) {
lowestF = (nodes[k].g + nodes[k].h);
lowestFIndex = k;
}
}
currentNode = lowestFIndex;
// Change it to the closed list.
nodes[currentNode].list = true;
sizeLimit ++;
if (sizeLimit > 1000)
return "";
}
The problem I'm having is that it wont find certain paths. It seems to never work if the path goes up or left at any point. Down, left, and right all work fine. Most of the time anyway. I have absolutely no idea what's causing this problem; at one point I even tried manually following my code to see where the problem was. No surprise that didn't work.
And one more thing: if you're counting my curly braces (first of all wow, you have more dedication than I thought), you'll notice I'm missing a close brace at the end. Not to mention my return statement. There's a little bit of code at the end to actually make the path that I've left out. I know that that part's not the problem however; I currently have it commented out and it still doesn't work in the same way. I added some code to tell me where it's not working, and it's at the pathfinding part, not the interpretation.
Sorry my code's so messy and inefficient. I'm new to c++, so any critical advice on my technique is welcome as well.
I think that when you are looking for the next "currentNode", you should not start with lowestF = (nodes[currentNode].g + nodes[currentNode].h); because that value, in principle, will (always) be lower-or-equal-to any other nodes in the open-set. Just start with the value of std::numeric_limits<int>::max() or some very large number, or use a priority queue instead of an std::vector to store the nodes (like std::priority_queue, or boost::d_ary_heap_indirect).
I'm pretty sure that is the problem. And since your heuristic can very often be equal to the actual path-distance obtained, there is a good chance that following nodes in the open-set turn out to have the same cost (g+h) as the currentNode. This would explain why certain paths get explored and others don't and why it gets stuck.