2011-10-23 2 views
0
)

파이썬에서 Google AI 챌린지에 대한 봇을 C++로 다시 작성하고 부스트의 그래프 라이브러리를 사용하여 경로 찾기를 처리합니다. 이전에 파이썬에서했던 것처럼 내 자신의 그래프와 검색 코드를 롤백합니다.부스트 그래프 라이브러리가있는 경로 찾기 (

지도는 가장자리를 감싸는 단순한 사각형 격자입니다.

나는 C가 꽤 잘 안다. 이전에는 부스트 나 C++을 사용하지 않았고, 부스트 그래프 문서를 찾기가 힘들어서 약간의 도움이 필요하다. 내가 함께하는 데 문제

특정 문서 : 순간 :) 여기

에서 두 개의 링크로 제한

  • http://www.boost.org/doc/libs/1_47_0/libs/graph/doc/dijkstra_shortest_paths.html
  • http://www.boost.org/doc/libs/1_47_0/libs/graph/example/dijkstra-example.cpp
  • 등의 조각이다 작업 파이썬 코드 :

    def do_turn(self, ants): 
        # update path-finding graph 
        for row in range(ants.rows): 
         for col in range(ants.cols): 
          key = (row, col) 
          self.graph[key] = [] 
    
          def append_if_unoccupied(coord): 
           if ants.passable(coord) and coord not in ants.my_hills(): 
            self.graph[key].append(coord) 
    
          if row - 1 >= 0: 
           append_if_unoccupied((row - 1, col)) 
          else: 
           append_if_unoccupied((ants.rows + (row - 1), col)) 
    
          if col - 1 >= 0: 
           append_if_unoccupied((row, col - 1)) 
          else: 
           append_if_unoccupied((row, ants.cols + (col - 1))) 
    
          if row + 1 < ants.rows: 
           append_if_unoccupied((row + 1, col)) 
          else: 
           append_if_unoccupied((row + 1 - ants.rows, col)) 
    
          if col + 1 < ants.cols: 
           append_if_unoccupied((row, col + 1)) 
          else: 
           append_if_unoccupied((row, col + 1 - ants.cols)) 
    

    그런 다음 shortest_path(self.graph, loc, dest) (맨하탄 경험적 검색을 사용한 검색)을 사용하여 다른 곳의 최단 경로가 포함 된 목록을 가져옵니다. C++에서는 비슷한 것을 원합니다 (최단 경로를 가진 벡터). 여기에 지금까지 가지고있는 코드는 (난 그냥, 내가 나머지를 할 수는 장애물없이 기본 그리드 작업지고 도움이 필요) : 당신은 ++ BGL을 악용하는 C로 전환 할 필요가 없습니다

    #include <vector> 
    
    #include <boost/config.hpp> 
    #include <boost/graph/graph_traits.hpp> 
    #include <boost/graph/adjacency_list.hpp> 
    //#include <boost/graph/astar_search.hpp> 
    #include <boost/graph/dijkstra_shortest_paths.hpp> 
    
    // struct with .row and .col 
    #include "Location.h" 
    
    // might not be necessary 
    struct Edge {}; 
    
    typedef boost::adjacency_list< 
        boost::listS,  // container for edges 
        boost::vecS,  // container for vertices 
        boost::undirectedS, // directed or undirected edges 
        Location,   // vertex type 
        Edge    // edge type 
    > Graph; 
    
    typedef Graph::vertex_descriptor VertexID; 
    typedef Graph::edge_descriptor EdgeID; 
    
    const int rows = 100; 
    const int cols = 100; 
    
    int main() { 
        Graph graph; 
    
        // this is probably useless since the graph stores everything 
        // haven't looked for a way around it yet 
        std::vector<std::vector<VertexID>> grid; 
    
        // create the grid/graph 
        for (int row = 0; row < rows; row++) { 
         grid.resize(rows); 
         for (int col = 0; col < cols; col++) { 
          grid[row].resize(cols); 
    
          VertexID vID = boost::add_vertex(graph); 
          graph[vID].row = row; 
          graph[vID].col = col; 
    
          grid[row][col] = vID; 
         } 
        } 
    
        // add the edges 
        for (int row = 0; row < rows; row++) { 
         for (int col = 0; col < cols; col++) { 
          // add edges for the squares in the grid (it wraps around) 
          // right now all the squares are traversable but that won't always 
          // be the case 
          int c_row, c_col; 
    
          if (row - 1 >= 0) { 
           c_row = row - 1; 
           c_col = col; 
          } else { 
           c_row = rows + (row - 1); 
           c_col = col; 
          } 
          boost::add_edge(grid[c_row][c_col], grid[row][col], graph); 
    
          if (col - 1 >= 0) { 
           c_row = row; 
           c_col = col - 1; 
          } else { 
           c_row = row; 
           c_col = cols + (col - 1); 
          } 
          boost::add_edge(grid[c_row][c_col], grid[row][col], graph); 
    
          if (row + 1 < rows) { 
           c_row = row + 1; 
           c_col = col; 
          } else { 
           c_row = row + 1 - rows; 
           c_col = col; 
          } 
          boost::add_edge(grid[c_row][c_col], grid[row][col], graph); 
    
          if (col + 1 < cols) { 
           c_row = row; 
           c_col = col + 1; 
          } else { 
           c_row = row; 
           c_col = col + 1 - cols; 
          } 
          boost::add_edge(grid[c_row][c_col], grid[row][col], graph); 
         } 
         // having trouble figuring out use these 
         //boost::astar_search(graph, grid[c] 
         //auto indexmap = get(vertex_index, graph); 
         //dijkstra_shortest_paths(graph, grid[0][0], &p[0], &d[0], weightmap, indexmap, 
              //std::less<int>(), closed_plus<int>(), 
              //(std::numeric_limits<int>::max)(), 0, 
              //default_dijkstra_visitor()); 
        } 
        return 0; 
    } 
    

답변

5

는 데 도움이 될 것입니다

// visitor that terminates when we find the goal 
class astar_goal_visitor : public boost::default_astar_visitor { 
public: 
    astar_goal_visitor(TriangleDescriptor goal) : m_goal(goal) 
    {} 

    void examine_vertex(TriangleDescriptor u, const NavMeshGraph & g) 
    { 
     if (u == m_goal) 
      throw found_goal(); 
    } 

private: 
    TriangleDescriptor m_goal; 
}; 
:

// euclidean distance heuristic 
class distance_heuristic : public boost::astar_heuristic <NavMeshGraph, float> { 
public: 
    distance_heuristic(const NavMeshGraph & l, TriangleDescriptor goal) 
    : m_graph(l), m_goal(goal) 
    {} 

    float operator()(TriangleDescriptor u) { 
     const NavMeshTriangle & U = m_graph[u]; 
     const NavMeshTriangle & V = m_graph[m_goal]; 
     float dx = U.pos.x - V.pos.x; 
     float dy = U.pos.y - V.pos.y; 
     return ::sqrt(dx * dx + dy * dy); 
    } 

private: 
    const NavMeshGraph & m_graph; 
    TriangleDescriptor m_goal; 
}; 

당신은 또한 방문자가 필요합니다

boost::astar_search 
    (
     m_navmesh, start, 
     distance_heuristic(m_navmesh, goal), 
     boost::predecessor_map(&p[0]) 
     .distance_map(&d[0]) 
     .visitor(astar_goal_visitor(goal)) 
     .weight_map(get(&NavMeshConnection::dist, m_navmesh)) 
    ); 

이 기능을 사용하면 자신을 만들 필요가 펑터 인, 거리 휴리스틱 소요

found_gloal은 반환하려는 항목에 따라 간단한 구조체 일 수도 있고 더 복잡한 무언가 일 수도 있습니다. : 가장 좋은 방법은 다음에 검색되는

try { 

    boost::astar_search 
    (
     ... 
    ); 


} catch (found_goal fg) { // found a path to the goal 

: 당신이 try/catch 블록에 부스트 :: astar_search()를 포장 할 수 있도록 객체가, 방문자에 발생합니다

struct found_goal {}; 

이러한 블록을 잡으십시오 :

std::list<TriangleDescriptor> shortest_path; 
    for (TriangleDescriptor v = goal;; v = p[v]) { 
     shortest_path.push_front(v); 
     if (p[v] == v) 
      break; 
    } 

무거운 개조가 필요합니다. 그러나 적어도 이것은 부스트를 자신의 길로 나가기에 충분해야합니다.

그런데 Djikstra는 완전히 유사하지 않습니다. 다른 모든 노드에서 가능한 모든 경로를 반환합니다.이것은 속도면에서는 좋지 않지만 사전 처리에 탁월합니다. 전 세계가 정적 인 경우 O (1)에서 다음 노드를 반환하는 길 찾기 행렬을 미리 작성할 수 있습니다.

관련 문제