Boost Graph Library(BGL)은 Graph를 처리하는 범용 그래픽 라이브러리 입니다.
그래프(Graph)는 정점(vertex), 선(edge)으로 이루어져 있습니다.
1차원을 구성하는 점과 선이 기본 요소이기 때문에 1차원 이상의 고차원에 존재하는 모든 표현이 가능합니다.
그래프로 할 수 있는 일이 굉장히 많습니다.
  • UML 다이어그램
  • Node 기반 그래프(퀘스트 연결 관계 등..)
  • C++ 헤더 파일 포함 관계 그래프
  • 최단거리 길 찾기
  • ...
이번에는 BGL을 이용하여 Dijkstra(다익스트라) 최단거리 알고리즘을 활용해 보겠습니다.
사용자 삽입 이미지
위와 같은 그래프를 BGL Dijkstra Shortest Path 알고리즘을 활용하여 처리한 결과는 다음과 같습니다.
사용자 삽입 이미지
#include "ShortestPath.h"

int _tmain(int argc, _TCHAR* argv[])
{
	setlocale( LC_ALL, "Korean" );

	CShortestPath ShortestPath;
	ShortestPath.BuildGraph();

	return 0;
}
main 함수에서 하는 일은 없습니다. CShortestPath 클래스가 핵심입니다.
BuildGraph()에서 하는 일은 다음과 같습니다.
  • Vertex 추가 / 이름 설정
  • Edge 추가 / 이름 / 가중치 설정
  • boost::dijkstra_shortest_paths()로 최단 거리 구하기
  • PrintShortestPath( vStartVertex )에서 시작 vertex를 지정하고 최단거리 Console로 출력하기
  • WriteGraphviz()에서 Graphviz.dot 파일로 그래프 파일 출력하기
void CShortestPath::BuildGraph()
{
	//////////////////////////////////////////////////////////////////////////
	// Vertex 추가하기
	const VertexDescriptor vA  = boost::add_vertex( m_Graph );
	const VertexDescriptor vB  = boost::add_vertex( m_Graph );
	const VertexDescriptor vC  = boost::add_vertex( m_Graph );
	const VertexDescriptor vD  = boost::add_vertex( m_Graph );
	const VertexDescriptor vE  = boost::add_vertex( m_Graph );

	// Vertex 이름 설정하기
	boost::put( boost::vertex_name, m_Graph, vA, "A" );
	boost::put( boost::vertex_name, m_Graph, vB, "B" );
	boost::put( boost::vertex_name, m_Graph, vC, "C" );
	boost::put( boost::vertex_name, m_Graph, vD, "D" );
	boost::put( boost::vertex_name, m_Graph, vE, "E" );



	//////////////////////////////////////////////////////////////////////////
	// Edge 추가하기
	const EdgeDescriptor eAC = boost::add_edge( vA, vC, m_Graph ).first;
	const EdgeDescriptor eBB = boost::add_edge( vB, vB, m_Graph ).first;
	const EdgeDescriptor eBD = boost::add_edge( vB, vD, m_Graph ).first;
	const EdgeDescriptor eBE = boost::add_edge( vB, vE, m_Graph ).first;
	const EdgeDescriptor eCB = boost::add_edge( vC, vB, m_Graph ).first;
	const EdgeDescriptor eCD = boost::add_edge( vC, vD, m_Graph ).first;
	const EdgeDescriptor eDE = boost::add_edge( vD, vE, m_Graph ).first;
	const EdgeDescriptor eEB = boost::add_edge( vE, vB, m_Graph ).first;
	const EdgeDescriptor eEA = boost::add_edge( vE, vA, m_Graph ).first;

	// Edge 이름 설정하기
	boost::put( boost::edge_name, m_Graph, eAC, "AC" );
	boost::put( boost::edge_name, m_Graph, eBB, "BB" );
	boost::put( boost::edge_name, m_Graph, eBD, "BD" );
	boost::put( boost::edge_name, m_Graph, eBE, "BE" );
	boost::put( boost::edge_name, m_Graph, eCB, "CB" );
	boost::put( boost::edge_name, m_Graph, eCD, "CD" );
	boost::put( boost::edge_name, m_Graph, eDE, "DE" );
	boost::put( boost::edge_name, m_Graph, eEB, "EB" );
	boost::put( boost::edge_name, m_Graph, eEA, "EA" );
	
	// Edge에 가중치 설정하기
	boost::put( boost::edge_weight, m_Graph, eAC, 1 );
	boost::put( boost::edge_weight, m_Graph, eBB, 2 );
	boost::put( boost::edge_weight, m_Graph, eBD, 1 );
	boost::put( boost::edge_weight, m_Graph, eBE, 2 );
	boost::put( boost::edge_weight, m_Graph, eCB, 7 );
	boost::put( boost::edge_weight, m_Graph, eCD, 3 );
	boost::put( boost::edge_weight, m_Graph, eDE, 1 );
	boost::put( boost::edge_weight, m_Graph, eEB, 1 );
	boost::put( boost::edge_weight, m_Graph, eEA, 1 );


	//////////////////////////////////////////////////////////////////////////
	// Shortest Path 구하기

	// Property Map 가져오기
	boost::property_map< Graph, boost::edge_weight_t >::type		mapEdgeWeight			= boost::get( boost::edge_weight, m_Graph );
	boost::property_map< Graph, boost::vertex_index_t >::type		mapVertexIndex			= boost::get( boost::vertex_index, m_Graph );
	boost::property_map< Graph, boost::vertex_distance_t >::type	mapVertexDistance		= boost::get( boost::vertex_distance, m_Graph );
	boost::property_map< Graph, boost::vertex_predecessor_t >::type	mapVertexPredecessor	= boost::get( boost::vertex_predecessor, m_Graph );

	// 다익스트라 최단거리 알고리즘
	const VertexDescriptor vStartVertex = vA;
	boost::dijkstra_shortest_paths(
		m_Graph, 
		vStartVertex,
		boost::weight_map( mapEdgeWeight ).vertex_index_map( mapVertexIndex ).distance_map( mapVertexDistance ).predecessor_map( mapVertexPredecessor )
		); 


	//////////////////////////////////////////////////////////////////////////
	// 최단거리 결과 출력
	PrintShortestPath( vStartVertex );

	// Dot 파일로 출력
	WriteGraphviz();
}
기존 BGL 책에 소개된 배열 기반의 예제를 탈피해서,
STL을 주로 사용하시는 분들에 맞게 코드를 작성하였습니다.
다른 기능을 추가하고자 하신다면, boost.org의 Graph 라이브러리 페이지를 참조하세요.
2011/06/11 00:49 2011/06/11 00:49

글 걸기 주소 : 이 글에는 트랙백을 보낼 수 없습니다

덧글을 달아 주세요

  1. hanstar17 2011/06/11 21:21 고유주소 고치기 답하기

    기본도 모자라, 이젠 다익스트라같은 응용 알고리즘까지 라이브러리로 제공되는군요!!ㅋㅋ 신기하네요.ㅎㅎ 좋은글 감사합니다~!

    • TTF 2011/06/14 03:00 고유주소 고치기

      네, Boost에 검증된 라이브러리를 사용하실 수록 그 매력에 빠져드실 꺼에요.

  2. actin 2011/06/12 01:33 고유주소 고치기 답하기

    이렇게 깔끔하게 정리되었군요 ^^

    • TTF 2011/06/14 03:01 고유주소 고치기

      네 ㅎㅎ.
      나중에 다시 봐도 알아볼 수는 있을까요?

  3. soomong 2011/06/13 16:40 고유주소 고치기 답하기

    와우! 다익스트라 알고리즘을 Lib 로 제공해준다니!!!
    멋집니다~