www.pudn.com > KSP.rar > QYShortestPath.cpp


// ____________________________________________________________________________ 
// 
//  General Information: 
// 
//  File Name:      QYShortetsPath.cpp 
//  Author:         Yan Qi 
//  Project:        KShortestPath 
// 
//  Description:    Implementation of class(es) CQYShortestPath 
// 
//  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
//  Revision History: 
// 
//  11/23/2006   Yan   Initial Version 
// 
//  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
//  Copyright Notice: 
// 
//  Copyright (c) 2006 Your Company Inc. 
// 
//  Warning: This computer program is protected by copyright law and  
//  international treaties.  Unauthorized reproduction or distribution 
//  of this program, or any portion of it, may result in severe civil and 
//  criminal penalties, and will be prosecuted to the maximum extent  
//  possible under the law. 
// 
// ____________________________________________________________________________ 
#pragma warning(disable: 4786) 
#include  
#include "QYShortestPath.h" 
 
namespace asu_emit_qyan 
{ 
	using namespace std; 
	using namespace boost; 
	////////////////////////////////////////////////////////////////////// 
	// Construction/Destruction 
	////////////////////////////////////////////////////////////////////// 
	 
	/************************************************************************/ 
	/* Default Constructor 
	/************************************************************************/ 
	CQYShortestPath::CQYShortestPath( const CQYDirectedGraph& rGraph ) : m_rGraph(rGraph) 
	{ 
		m_nSourceNodeId = -1; // the source node id is 0 by default. 
		_Init(); 
	} 
	 
	CQYShortestPath::~CQYShortestPath()	{} 
	 
 
	/************************************************************************/ 
	/* Initiate members 
	/************************************************************************/ 
	void CQYShortestPath::_Init() 
	{ 
		int vertices_count = m_rGraph.GetNumberOfVertices(); 
		 
		// First: edges with weights 
		for (int i=0; i!=vertices_count; ++i) 
		{ 
			for (int j=0; j!=vertices_count; ++j) 
			{ 
				if (m_rGraph.GetWeight(i,j) != CQYDirectedGraph::DISCONNECT) 
				{ 
					m_vEdges.push_back(Edge_Type(i,j)); 
					m_vWeights.push_back(m_rGraph.GetWeight(i,j)); 
				} 
			} 
		}  
	} 
 
	/************************************************************************/ 
	/* Analysis of m_vResult4Vertices and m_vResult4Distance to generate the  
	/* shortest path. 
	/************************************************************************/ 
	CQYDirectedPath* CQYShortestPath::_GetShortestPath( int nTargetNodeId ) 
	{ 
		vector vertex_list; 
		 
		// Check the input 
		if (nTargetNodeId >= m_rGraph.GetNumberOfVertices() || nTargetNodeId < 0) 
		{ 
			std::cerr << "Please enter a right terminal id!" << std::endl; 
			return new CQYDirectedPath(-1, CQYDirectedGraph::DISCONNECT, vertex_list); 
		} 
		 
		if (m_distanceMap[nTargetNodeId] == CQYDirectedGraph::DISCONNECT) 
		{ 
			std::cerr << "The path doesn't exist!" << std::endl; 
			return new CQYDirectedPath(-2, CQYDirectedGraph::DISCONNECT, vertex_list); 
		} 
		 
		// Determine the shortest path from the source to the terminal.	 
		int cur_vertex = nTargetNodeId; 
		list tmp_list; 
		tmp_list.push_front(nTargetNodeId); 
		do  
		{ 
			if (m_nextNodeMap[cur_vertex] == m_nSourceNodeId) 
			{ 
				if(cur_vertex != m_nSourceNodeId) tmp_list.push_front(m_nSourceNodeId); 
				break; 
			}else 
			{ 
				cur_vertex = m_nextNodeMap[cur_vertex]; 
				tmp_list.push_front(cur_vertex); 
			} 
		} while(1); 
		// 
		copy(tmp_list.begin(), tmp_list.end(), back_inserter(vertex_list)); 
		 
		//  
		return new CQYDirectedPath(0, m_distanceMap[nTargetNodeId], vertex_list); 
	} 
 
	/************************************************************************/ 
	/* Calculate the shortest path from a source to a target. 
	/************************************************************************/ 
	CQYDirectedPath* CQYShortestPath::GetShortestPath( int nSourceNodeId, int nTargetNodeId ) 
	{ 
		if (m_nSourceNodeId != nSourceNodeId) 
		{ 
			m_nSourceNodeId = nSourceNodeId; 
			_DijkstraShortestPathsAlg(); 
		} 
		 
		return _GetShortestPath(nTargetNodeId);	 
	} 
	 
	/************************************************************************/ 
	/* Based on the input - the source of the path, create a steiner tree. (???)  
	/************************************************************************/ 
	void CQYShortestPath::ConstructPathTree( int nSourceNodeId ) 
	{ 
		m_nSourceNodeId = nSourceNodeId; 
		_DijkstraShortestPathsAlg(); 
	} 
 
	/************************************************************************/ 
	/*  
	/************************************************************************/ 
	void CQYShortestPath::_DijkstraShortestPathsAlg() 
	{ 
		int edges_count = m_rGraph.GetNumberOfEdges(); 
		int vertices_count = m_rGraph.GetNumberOfVertices(); 
 
		////////////////////////////////////////////////////////////////////////// 
		// Initiate the boost graph 
		vector vResult4Vertices; 
		vector vResult4Distance; 
		Boost_Graph_Type g(vertices_count); 
		property_map::type weightmap = get(edge_weight, g); 
		// 
		for (std::size_t j = 0; j < edges_count; ++j)  
		{ 
			Edge_Descriptor e; bool inserted; 
			tie(e, inserted) = add_edge(m_vEdges[j].first, m_vEdges[j].second, g); 
			weightmap[e] = m_vWeights[j]; 
		}		 
		 
		// about the vertices in the boost graph 
		vResult4Vertices.resize(num_vertices(g)); 
		vResult4Distance.resize(num_vertices(g)); 
		Vertex_Descriptor s = vertex(m_nSourceNodeId, g); 
			 
		// run the algorithm 
		// VC++ has trouble with the named parameters mechanism 
		property_map::type indexmap = get(vertex_index, g); 
		dijkstra_shortest_paths(g, s, &vResult4Vertices[0], &vResult4Distance[0], weightmap, indexmap,  
			std::less(), closed_plus(),  
			CQYDirectedGraph::DISCONNECT, 0, default_dijkstra_visitor()); 
		 
		////////////////////////////////////////////////////////////////////////// 
		// Set the results 
		for (int i=0; i