그래프
개론
일반적으로 알고 있는 그래프와는 조금 다름
노드와 에지
노드 : 중간 지점
에지 : 노드끼리를 연결하는 길
광범위한 의미
하나의 네트워크의 기호적인 표현
전화
www
전자 회로
인공 신경망
좀 더 형식적인 기술
G = {N, E}
N : 0 ~ (N-1)
E : 3-5 / 19-7
가중치 존재
거리
길의 특성(오르막, 늪 등)
트리
비순환인 모든 그래프를 포함하는 그래프의 부분집합
그래프 밀도
밀집하거나
성기거나
다이그래프
에지의 방향 존재
16-6 : 16->6 ( ! 6->16 )
16 : 근원 노드(source node)
6 : 목적 노드(destination node)
무방향 그래프 == 쌍방향 다이그래프
게임 AI에서의 그래프
항해 그래프(navgraph)
게임 에이전트가 방문할 수 있는 게임 환경의 모든 장소와 그 지점들 사이의 모든 연결의 추상화
종속 그래프(dependency graph)
여러 빌딩, 물자, 유닛과 선우에 적용될 수 있는 기술들 사이의 종속성을 표현하기 위해 사용
상태 그래프(state graph)
시스템이 존재할 수 있는 모든 가능한 상태와 그 상태들 사이의 전환을 표현
루트 노드
부모 상태 - 자식 상태
분기율(branching factor)
각 부모 노드에서 퍼져 나가는 자식 노드의 평균 개수
대부분 분기율이 높기 때문에 목표 상태 쪽으로 탐색을 지시해 한 번에 몇 개의 노드만 생성되고 탐색
그래프 클래스 구현하기
개론
표현 자료구조
인접 행렬(adjacency matrix)
직관적
용량 비효율
N의 제곱
인접 리스트(adjacency list)
성긴 그래프에 효율적
공간 낭비 x
N+E
GraphNode Class
노드가 필요로 하는 최소 정보를 캡슐화
template< class extra_info = void* > class NavGraphNode : public GraphNode
GraphEdge Class
두 개의 노드 사이의 연결을 나타내기 위해 필요한 기본 정보를 캡슐화
가중치
가중치가 동일하다면 그 필드를 생략함으로써 메모리 절약
가중치가 두 노드 사이의 거리라면 Distance 함수 사용
SparseGraph Class
노드와 에지에 접근할 수 있게끔
인텍스 사용
컨테이너
vector<node_type> NodeVector
list<edge_type> EdgeList
vector<EdgeList> EdgeListVector
그래프 탐색 알고리즘
개론
탐색 알고리즘이 하는 일
그래프의 모든 노드 방문
두 노드 사이의 어떠한 경로를 찾음
두 노드 사이의 최적 경로를 찾음
무정보 그래프 탐색
에지 비용에 대한 언급 없이 그래프 탐색
깊이 우선 탐색
모든 노드와 에지가 방문될 것임을 보장
알고리즘 구현
멤버
m_Visited : unvisited
방문된 모든 노드들의 인덱스 기록
m_Route : no_parent_assigned
목표까지의 경로 보유
std::Stack 사용
순서
생성자 -> Search()
std::stack<const Edge*> stack;
Edge Dummy();
stack.push(&Dummy);
while(!stack.empty())
const Edge* Next = stack.top()
stack.pop()
m_Route[Next->To] = Next->From()
m_Visited[Next->To()] = visited
if(Next->To() == m_iTarget) return true;
for( ConstEdgeItr )
if(m_Visited[pE->To()] == unvisited) stack.push(pE);
GetPathToTarget() 에서 목표까지의 경로 반환
너비 우선 탐색
가장 적은 에지를 방문하는 경로를 보장
멤버
m_Visited : unvisited
방문된 모든 노드들의 인덱스 기록
m_Route : no_parent_assigned
목표까지의 경로 보유
std::queue 사용
알고리즘 구현
std::queue<const Edge*> Q
const Edge Dummy()
Q.push(&Dummy)
m_Visited[m_iSource] = visited;
while(!Q.empty())
const Edge* Next = Q.front();
Q.pop();
m_Route[Next->To()] = Next->From();
if(Next->To() == m_iTarget) return true;
for(ConstEdgeItr)
if(m_Visited[pE->To()] = visited)
Q.push(pE);
m_Visited[pE->To()] = visited;
비용 기반 그래프 탐색