C++ 如何将此代码从Dijkstra转换为Astar?
因此,我有一个项目,我想切换到阿斯塔由于速度的原因 但是C++不是我的最强点。谁能帮我一下,或者告诉我怎么做。。将算法从Dijkstra转换为Astar 我发现这个Astar实现: 但我不知道如何在现有代码中使用它 以下是获得算法的图形文件:C++ 如何将此代码从Dijkstra转换为Astar?,c++,dijkstra,a-star,C++,Dijkstra,A Star,因此,我有一个项目,我想切换到阿斯塔由于速度的原因 但是C++不是我的最强点。谁能帮我一下,或者告诉我怎么做。。将算法从Dijkstra转换为Astar 我发现这个Astar实现: 但我不知道如何在现有代码中使用它 以下是获得算法的图形文件: #include "Graph.h" #include <iostream> #include <algorithm> #include <stack> Graph::Graph(void) { } Graph::
#include "Graph.h"
#include <iostream>
#include <algorithm>
#include <stack>
Graph::Graph(void)
{
}
Graph::~Graph(void)
{
while(!mNodes.empty())
{
delete mNodes.back();
mNodes.pop_back();
}
}
void Graph::addNode(int name, bool exists, Node** NodeID )
{
Node* pStart = NULL;
mNodes.push_back(new Node(name,exists));
std::vector<Node*>::iterator itr;
itr = mNodes.begin()+mNodes.size()-1;
pStart = (*itr);
if(exists == true)pStart->DoesExist_yes();
*NodeID = pStart;
}
void Graph::connect_oneway(Node* pFirst, Node* pSecond, int moveCost)
{
if(pFirst != NULL && pSecond != NULL)
{
pFirst->createEdge(pSecond, moveCost);
}
}
#define MAX_NODES (32768)
#define MAX_CONNECTIONS (5)
#include <time.h>
int * Graph::findPath_r(Node* pStart, Node* pEnd)
{
int *arr = new int[MAX_NODES+2];
for (int i=0; i<MAX_NODES; i++)
arr[i] = -1;
arr[0] = 0;
if(pStart == pEnd)
{
return arr;
}
std::vector<Node*> openList;
openList.push_back(pStart);
Node* pCurrNode = NULL;
while(!openList.empty())
{
//Get best node from open list (lowest F value).
//Since we sort the list at the end of the previous loop we know
//the front node is the best
pCurrNode = openList.front();
//Exit if we're are the goal
if(pCurrNode == pEnd)
break;
//Remove the node from the open list and place it in the closed
openList.erase(openList.begin());
pCurrNode->setClosed(true); //We use a flag instead of a list for speed
//Test all of the edge nodes from the current node
std::vector<Edge*>* pEdges = pCurrNode->getEdges();
Node* pEdgeNode = NULL;
for(std::vector<Edge*>::iterator i = pEdges->begin(); i != pEdges->end(); ++i)
{
pEdgeNode = (*i)->pNode;
//If it's closed we've already analysed it
if(!pEdgeNode->getClosed() && pCurrNode->DoesExist() == true)
{
if(!inList(pEdgeNode,&openList))
{
openList.push_back(pEdgeNode);
pEdgeNode->setGCost(pCurrNode->getGCost()+(*i)->moveCost);
pEdgeNode->calcFCost();
pEdgeNode->setParent(pCurrNode);
}
else
{
//If this is a better node (lower G cost)
if(pEdgeNode->getGCost() > pCurrNode->getGCost()+(*i)->moveCost)
{
pEdgeNode->setGCost(pCurrNode->getGCost()+(*i)->moveCost);
pEdgeNode->calcFCost();
pEdgeNode->setParent(pCurrNode);
}
}
}
}
//Place the lowest F cost item in the open list at the top, so we can
//access it easily next iteration
std::sort(openList.begin(), openList.end(), Graph::compareNodes);
}
//Make sure we actually found a path
if(pEnd->getParent() != NULL)
{
//Output the path
//Use a stack because it is LIFO
std::stack<Node*> path;
while(pCurrNode != NULL)
{
path.push(pCurrNode);
pCurrNode = pCurrNode->getParent();
}
int counter = 0;
arr[1] = 0;
while(!path.empty())
{
arr[counter+2] = path.top()->getName();
counter++;
arr[1] += path.top()->getGCost();
path.pop();
}
arr[0] = counter;
return arr;
}
return arr;
}
bool Graph::inList(Node* pNode, std::vector<Node*>* pList)
{
for(std::vector<Node*>::iterator i = pList->begin(); i != pList->end(); ++i)
{
if((*i) == pNode)
{
return true;
}
}
return false;
}
bool Graph::compareNodes(Node* pFirst, Node* pSecond)
{
return pFirst->getFCost() < pSecond->getFCost();
}
void Graph::reset(void)
{
for(std::vector<Node*>::iterator i = mNodes.begin(); i != mNodes.end(); ++i)
{
(*i)->reset();
}
}
查找路径的函数如下所示:
图形::findPath\u r
我真正想做的是保留边缘,因为它们决定道路是双向还是单向
以下是其他文件:
图h
Node.h
#ifndef _NODE_H_
#define _NODE_H_
#include <string>
#include <vector>
//Forward declare Node so Edge can see it
class Node;
struct Edge
{
Edge(Node* node, int cost) : pNode(node), moveCost(cost){}
Node* pNode;
int moveCost;
};
class Node
{
public:
Node(void);
Node(int name, bool exists);
~Node(void);
void createEdge(Node* pTarget, int moveCost);
void setGCost(int cost);
void setClosed(bool closed);
void setParent(Node* pParent);
int getGCost(void);
int getFCost(void);
bool getClosed(void);
Node* getParent(void);
int getName(void);
bool DoesExist(void);
bool DoesExist_yes(void);
std::vector<Edge*>* getEdges(void);
void calcFCost(void);
void reset(void);
private:
int mGCost;
int mTotal;
bool mClosed;
Node* mpParent;
int mName;
bool mHeur;
std::vector<Edge*> mEdges;
};
#endif
Node.cpp
#include "Node.h"
Node::Node(void)
{
}
Node::Node(/*const std::string&*/int name, bool exists) : mGCost(0), mTotal(0), mClosed(false), mpParent(NULL), mName(name), mHeur(exists)
{
}
Node::~Node(void)
{
while(!mEdges.empty())
{
delete mEdges.back();
mEdges.pop_back();
}
}
int Node::getName(void)
{
return mName;
}
void Node::createEdge(Node* pTarget, int moveCost)
{
mEdges.push_back(new Edge(pTarget, moveCost));
}
void Node::setClosed(bool closed)
{
mClosed = closed;
}
bool Node::getClosed(void)
{
return mClosed;
}
std::vector<Edge*>* Node::getEdges(void)
{
return &mEdges;
}
int Node::getGCost(void)
{
return mGCost;
}
void Node::setGCost(int cost)
{
mGCost = cost;
}
void Node::calcFCost(void)
{
mTotal = mGCost;
}
void Node::setParent(Node* pParent)
{
mpParent = pParent;
}
int Node::getFCost(void)
{
return mTotal;
}
bool Node::DoesExist(void)
{
return mHeur;
}
bool Node::DoesExist_yes(void)
{
mHeur = true;
return true;
}
Node* Node::getParent(void)
{
return mpParent;
}
void Node::reset(void)
{
mGCost = 0;
mTotal = 0;
mClosed = false;
mpParent = NULL;
}
你提到谷歌代码上的一个库。很清楚您想要做什么,我认为最好是自己编写实现 首先,您应该知道Dijsktra是a*的一个特例。在A*中,您有一个启发式,名为h;A*=当h为空函数时,Dijsktra的可能实现 然后,关于您的实现,让我们从Node开始。它将需要以下功能:
constructor, destructor
create/get edge
set/get parent
set/is closed (for speed)
set/get GCost
set/get FCost
set/is obstacle (name way more descriptive than 'DoesExist')
set/get position
reset
// optional method:
get name
希望这部分代码不会有太大变化。启发式代码将放置在pathfinder中。边类保持不变
现在最重要的是:图表。您不需要删除任何公共方法
你需要一个启发式的方法。对于将要描述的实现,您将需要一个可接受的一致启发式:
它不能高估到目标的距离
它必须是单调一致的
一般的大小写签名是int-getHCostNode*node;。如果总是返回0,则会有一个Dijsktra算法,这不是您想要的。这里我们将采用节点和目标之间的欧几里德距离。计算速度比曼哈顿距离慢,但结果更好。您可以在以后更改此设置
int getHCost(Node* node, Note* goal);
这意味着您必须将节点放置在三维空间中。请注意,启发式是一种启发式,即对距离的估计
我不会写代码。我将根据您的情况编写一些伪代码。原始伪代码位于上。此伪代码是findPath\r函数:
function A*(start,goal)
set all nodes to not closed // The set of nodes already evaluated.
openset = {start} // The set of tentative nodes to be evaluated, initially containing the start node
start.gcost = 0 // Cost from start along best known path.
// Estimated total cost from start to goal through y.
start.fcost = start.gcost + getHCost(start, goal)
while openset is not empty
current = the node in openset having the lowest f_cost (usually the first if you use a sorted list)
if current == goal
return construct_path(goal)
remove current from openset
current.closed = true
for each neighbor in (node connected by edge in current.edges) // Here is the condition for one-way edges
if neighbor.closed or neighbor.obstacle
continue
gcost = current.gcost + dist_between(current,neighbor) // via edge distance
if neighbor not in openset
add neighbor to openset
neighbor.parent = current
neighbor.gcost = gcost
neighbor.fcost = neighbor.gcost + getHCost(neighbor, goal)
else if gcost < neighbor.gcost
neighbor.parent = current
neighbor.gcost = gcost
neighbor.fcost = neighbor.gcost + getHCost(neighbor, goal)
update neighbor position in openset
return failure
function construct_path(current_node)
std::vector<Node*> path
while current_node != 0
path.push_front(current_node)
current_node = current_node.parent
return path
上面的实现使用单向边
<>你可以在C++中编写dijsTrac算法,所以用C++编写这个伪代码应该不会有问题。
第二部分,表演。首先,衡量
我有一些可以提高性能的提示:
使用内存池进行分配-解除分配
对打开的列表使用侵入式列表,也可以使用此技术使其自动排序
我建议你阅读,这是一本很有用的书,即使你不使用tilemap。你提到谷歌代码上有一个库。很清楚您想要做什么,我认为最好是自己编写实现 首先,您应该知道Dijsktra是a*的一个特例。在A*中,您有一个启发式,名为h;A*=当h为空函数时,Dijsktra的可能实现 然后,关于您的实现,让我们从Node开始。它将需要以下功能:
constructor, destructor
create/get edge
set/get parent
set/is closed (for speed)
set/get GCost
set/get FCost
set/is obstacle (name way more descriptive than 'DoesExist')
set/get position
reset
// optional method:
get name
希望这部分代码不会有太大变化。启发式代码将放置在pathfinder中。边类保持不变
现在最重要的是:图表。您不需要删除任何公共方法
你需要一个启发式的方法。对于将要描述的实现,您将需要一个可接受的一致启发式:
它不能高估到目标的距离
它必须是单调一致的
一般的大小写签名是int-getHCostNode*node;。如果总是返回0,则会有一个Dijsktra算法,这不是您想要的。这里我们将采用节点和目标之间的欧几里德距离。计算速度比曼哈顿距离慢,但结果更好。您可以在以后更改此设置
int getHCost(Node* node, Note* goal);
这意味着您必须将节点放置在三维空间中。请注意,启发式是一种启发式,即对距离的估计
我不会写代码。我将根据您的情况编写一些伪代码。原始伪代码位于上。此伪代码是findPath\r函数:
function A*(start,goal)
set all nodes to not closed // The set of nodes already evaluated.
openset = {start} // The set of tentative nodes to be evaluated, initially containing the start node
start.gcost = 0 // Cost from start along best known path.
// Estimated total cost from start to goal through y.
start.fcost = start.gcost + getHCost(start, goal)
while openset is not empty
current = the node in openset having the lowest f_cost (usually the first if you use a sorted list)
if current == goal
return construct_path(goal)
remove current from openset
current.closed = true
for each neighbor in (node connected by edge in current.edges) // Here is the condition for one-way edges
if neighbor.closed or neighbor.obstacle
continue
gcost = current.gcost + dist_between(current,neighbor) // via edge distance
if neighbor not in openset
add neighbor to openset
neighbor.parent = current
neighbor.gcost = gcost
neighbor.fcost = neighbor.gcost + getHCost(neighbor, goal)
else if gcost < neighbor.gcost
neighbor.parent = current
neighbor.gcost = gcost
neighbor.fcost = neighbor.gcost + getHCost(neighbor, goal)
update neighbor position in openset
return failure
function construct_path(current_node)
std::vector<Node*> path
while current_node != 0
path.push_front(current_node)
current_node = current_node.parent
return path
上面的实现使用单向边
<>你可以在C++中编写dijsTrac算法,所以用C++编写这个伪代码应该不会有问题。
第二部分,表演。首先,衡量
我有一些可以提高性能的提示:
使用内存池进行分配-解除分配
对打开的列表使用侵入式列表,也可以使用此技术使其自动排序
我建议您阅读,这是一本很有用的书,即使您不使用tilemap。附带说明:您自己实现它很重要吗?对于这些东西来说,这是非常好的…我使用boost dijkstras算法重写了我的插件,但它破坏了所有东西,所以我做了回滚;/现在我想使用星型算法,因为它更快。或者
有人知道如何在这段代码中大幅提高速度吗?@GamErix你会问如何提高速度。第一步总是在代码上运行探查器。在此之前,不要麻烦优化任何东西。计算代码是线程化的,主代码在另一个线程中运行,因此它们不会相互干扰。要使用A-Star,您需要一个线程。如果您的图形表示物理点,例如道路网络,您可以使用直线距离或曼哈顿距离作为启发。另请注意:您自己实现它是否重要?对于这些东西来说,这是非常好的…我使用boost dijkstras算法重写了我的插件,但它破坏了所有东西,所以我做了回滚;/现在我想使用星型算法,因为它更快。或者有人知道如何在这段代码中大幅提高速度吗?@GamErix你会问如何提高速度。第一步总是在代码上运行探查器。在此之前,不要麻烦优化任何东西。计算代码是线程化的,主代码在另一个线程中运行,因此它们不会相互干扰。要使用A-Star,您需要一个线程。如果图形表示物理点,例如道路网络,则可以使用直线距离或曼哈顿距离作为启发。