Пример #1
0
Position stringToHypergraph(Strings const& inputTokens, IMutableHypergraph<Arc>* pHgResult,
                            StringToHypergraphOptions const& opts = StringToHypergraphOptions(),
                            TokenWeights const& inputWeights = TokenWeights()) {
  IVocabularyPtr const& pVoc = pHgResult->getVocabulary();
  if (!pVoc) SDL_THROW_LOG(Hypergraph, InvalidInputException, "pHgResult hypergraph must contain vocabulary");
  for (std::size_t i = 0, numNonlexicalStates = inputTokens.size() + 1; i < numNonlexicalStates; ++i)
    pHgResult->addState();
  pHgResult->setStart(0);
  StateId prevState = 0;

  typedef typename Arc::Weight Weight;
  typedef FeatureInsertFct<Weight> FI;
  Position i = 0, n = inputTokens.size();
  for (; i != n; ++i) {
    std::string const& token = inputTokens[i];
    SDL_TRACE(Hypergraph.StringToHypergraph, i << ": " << token);
    const Sym sym = opts.terminalMaybeUnk(pVoc.get(), token);
    const StateId nextState = prevState + 1;
    Arc* pArc = new Arc(nextState, Tails(prevState, pHgResult->addState(sym)));
    Weight& weight = pArc->weight();
    assert(opts.inputFeatures != NULL);
    for (FeatureId featureId : opts.inputFeatures->getFeaturesForInputPosition(i)) {
      FI::insertNew(&weight, featureId, 1);
      if (opts.tokens) opts.tokens->insert(sym, featureId);
    }
    inputWeights.reweight(i, weight);
    pHgResult->addArc(pArc);
    prevState = nextState;
  }
  pHgResult->setFinal(prevState);
  return n;
}
Пример #2
0
    State Dubins::getState(myFloat len) const {
        Arc path1 = getFirstArc();
        myFloat l1 = path1.getLength();
        if (len < l1) {
            return path1.getState(len);
        }

        myFloat l2;
        if (isCCC) {
            Arc ca = getCenterArc();
            l2 = ca.getLength();
            if (len < l1 + l2) {
                return ca.getState(len - l1);
            }
        } else {
            Line cl = getCenter();
            l2 = cl.getLength();
            if (len < l1 + l2) {
                return cl.getState(len - l1);
            }
        }

        Arc path3 = getSecondArc();
        return path3.getState(len - l1 - l2);
    }
Пример #3
0
	void printAllProbs(std::ostream& resStream) {
		Arc arc; arc.setFirst();
		do {
			double p = calcProb(arc);
			resStream << arc << "   " << p << std::endl;
		} while (arc.next(pof_.n));
	}
Пример #4
0
    Intersection Dubins::getClosestIntersection(const Point &p) const {
        Intersection closest;

        closest.state = start;
        closest.distance = 0;

        auto a1c = getFirstArc().getClosestIntersection(p);
        if (a1c.state.point.distance(p) < closest.state.point.distance(p)) {
            closest = a1c;
        }

        auto a2c = getSecondArc().getClosestIntersection(p);
        if (a2c.state.point.distance(p) < closest.state.point.distance(p)) {
            closest = a2c;
        }

        Intersection a3c;
        if (isCCC) {
            Arc ca = getCenterArc();
            a3c = ca.getClosestIntersection(p);
        } else {
            Line cl = getCenter();
            a3c = cl.getClosestIntersection(p);
        }

        if (a3c.state.point.distance(p) < closest.state.point.distance(p)) {
            closest = a3c;
        }

        return closest;
    }
Пример #5
0
void rotation (Arc& A)
{
	int b = A.angle_begin(), e = A.angle_end();
	if (e<360) { b+=90; e+=90; } 
	else { b=0; e=90; }
	A.set_angle(b,e);
}
Пример #6
0
void Magnusson::backtrack(Node* start, TrackingAlgorithm::Path& p, TrackingAlgorithm::VisitorFunction nodeVisitor)
{
	p.clear();
	Node* current = start;

    while(current != &(graph_->getSourceNode()))
	{
        nodeVisitor(current);
        Arc* bestArc = nullptr;
        if(current == start)
            bestArc = selectorFunction_(current);
        else
            bestArc = current->getBestInArc();

		assert(bestArc != nullptr);
        assert(bestArc->isEnabled());

        if(bestArc->getType() != Arc::Dummy)
            bestArc->markUsed();
		p.push_back(bestArc);
		current = bestArc->getSourceNode();
	}

    nodeVisitor(current);
	std::reverse(p.begin(), p.end());
}
Пример #7
0
	void MinCost<FlowType, CostType>::TestOptimality()
{
	Node* i;
	Arc* a;

	for (i=nodes; i<nodes+nodeNum; i++)
	{
		if (i->excess != 0)
		{
			assert(0);
		}
		for (a=i->firstSaturated; a; a=a->next)
		{
			if (a->r_cap != 0)
			{
				assert(0);
			}
		}
		for (a=i->firstNonsaturated; a; a=a->next)
		{
			CostType c = a->GetRCost();
			if (a->r_cap <= 0 || a->GetRCost() < -1e-5)
			{
				assert(0);
			}
		}
	}
}
Пример #8
0
void
Subdivider::addArc( int npts, TrimVertex *pts, long _nuid ) 
{
    Arc *jarc 		= new(arcpool) Arc( arc_none, _nuid );
    jarc->pwlArc	= new(pwlarcpool) PwlArc( npts, pts );        
    initialbin.addarc( jarc  );
    pjarc		= jarc->append( pjarc );
}
Пример #9
0
int Flow::createVarW()
{
	int nvars = 0;

	double coeff = 0.0;
	double lb = 0.;
	double ub = 1e20;
	VariableHash::iterator vit;
	Variable::VARTYPE varType = Variable::V_W;
	Column::COLTYPE colType = Column::COLTYPE::CONTINUOUS;

	for (int sIt = 0; sIt < g->nTerminals; ++sIt)
	{
		Vertex s = g->terminals[sIt];

		for (int i = 1; i <= g->nVertices; ++i)
		{
			for (int j = 0; j < g->adjList[i].size(); ++j)
			{
				Arc arc = g->adjList[i][j];

				Variable w(colType, coeff, lb, ub);
				w.setType(varType);
				w.setCategory('p');
				w.setVertex1(s);
				w.setArc(arc.toEdge());

				vit = vHash[varType].find(w);
				if (vit != vHash[varType].end())
					continue;

				bool isInserted = addCol(&w);
				if (isInserted)
				{
					w.setColIdx(getNCols() - 1);
					vHash[varType][w] = w.getColIdx();
					++nvars;
				}

				w.setCategory('m');

				vit = vHash[varType].find(w);
				if (vit != vHash[varType].end())
					continue;

				isInserted = addCol(&w);
				if (isInserted)
				{
					w.setColIdx(getNCols() - 1);
					vHash[varType][w] = w.getColIdx();
					++nvars;
				}
			}
		}
	}

	return nvars;
}
Пример #10
0
Kcore::Kcore(GrapheNonOriente* graphe, int k){
    std::vector<int> degresCumulatifs;
    std::vector<int> tabdegre;//tableau de degrés des sommets
    for(unsigned int i=0;i<graphe->size();i++){
       tabdegre.push_back(graphe->getDegre(i));
    }
    while(!supK(tabdegre,k)){//tant qu'il reste des degrés inférieurs à k et différents de 0
        for(unsigned int i=0;i<graphe->size();i++){
            if(tabdegre[i]<k && tabdegre[i]!=0){
                tabdegre[i] = 0;//on passe le degré du sommet à 0 vu qu'il n'appartient pas au kcore
                std::vector<Arc> arcs = graphe->getArcs(i);
                for (unsigned int j=0;j<arcs.size();j++){
                    //on récupère les voisins et on diminuent leur degré de 1
                    Arc a = arcs[j];
                    if(tabdegre[a.getNumeroSommet()] != 0)
                        tabdegre[a.getNumeroSommet()]--;
                }
            }
        }
    }
    //calcul degrés cumultatifs
    for(unsigned int i=0;i<graphe->size();i++){
        if(i == 0){
            degresCumulatifs.push_back(tabdegre[i]);
        }else{
            degresCumulatifs.push_back(tabdegre[i] + degresCumulatifs[i-1]);
        }
    }
    //construction de graphe
    std::vector<Arc> arcsG;
    std::vector<double> poids;
    unsigned int nbArcs = graphe->nbArcs();
    for(unsigned int numeroSommet=0; numeroSommet<graphe->size();numeroSommet++){
        if(tabdegre[numeroSommet] == 0){
            //On dérément le nombre d'arcs car ce sommet n'a plus d'arcs
            vector<Arc> voisins = graphe->getArcs(numeroSommet);
            for(unsigned int indiceVoisin=0; indiceVoisin < voisins.size(); indiceVoisin++){
                    if(tabdegre[(voisins[indiceVoisin]).getNumeroSommet()] != 0){
                        nbArcs--;
                    }else if(voisins[indiceVoisin].getNumeroSommet() < numeroSommet){
                        nbArcs--;
                    }
            }
        }else{
            vector<Arc> voisins = graphe->getArcs(numeroSommet);
            for(unsigned int indiceVoisin=0; indiceVoisin < voisins.size(); indiceVoisin++){
                    if(tabdegre[(voisins[indiceVoisin]).getNumeroSommet()] != 0){
                        //Si le voisin a toujours des arcs, alors on ajoute l'arc
                        arcsG.push_back(voisins[indiceVoisin]);
                    }
            }
        }
    }

    m_grapheKcore = new GrapheNonOriente(degresCumulatifs, arcsG, poids, nbArcs);
    m_tabDegre = tabdegre;
}
/* DONE */ FoliationRP2::GoodOneSidedCurve FoliationRP2::GetGoodOneSidedCurve(const SeparatrixSegment& SegmentShiftedToLeft,
                                                                    const SeparatrixSegment& SegmentShiftedToRight){
    if (AreDepthsGoodForOneSidedCurve(SegmentShiftedToRight.m_Depth, SegmentShiftedToLeft.m_Depth)) {
        Arc myArc = GetClosingArcIfGoodOneSidedCurve(SegmentShiftedToRight, SegmentShiftedToLeft);
        if (myArc.GetLeftEndpoint().GetSide() == LEFT) {
            return GoodOneSidedCurve(SegmentShiftedToLeft, SegmentShiftedToRight, myArc);
        }
    }
    throw ExceptionNoObjectFound();
}
Пример #12
0
	void MinCost<FlowType, CostType>::Dijkstra(Node* start)
{
	assert(start->excess > 0);

	Node* i;
	Node* j;
	Arc* a;
	CostType d;
	Node* permanentNodes;

	int FLAG0 = ++ counter; // permanently labeled nodes
	int FLAG1 = ++ counter; // temporarily labeled nodes

	start->parent = NULL;
	start->flag = FLAG1;
	queue.Reset();
	queue.Add(start, 0);

	permanentNodes = NULL;

	while ( (i=queue.RemoveMin(d)) )
	{
		if (i->excess < 0)
		{
			FlowType delta = Augment(start, i);
			cost += delta*(d - i->pi + start->pi);
			for (i=permanentNodes; i; i=i->next_permanent) i->pi += d;
			break;
		}

		i->pi -= d;
		i->flag = FLAG0;
		i->next_permanent = permanentNodes;
		permanentNodes = i;

		for (a=i->firstNonsaturated; a; a=a->next)
		{
			j = a->head;
			if (j->flag == FLAG0) continue;
			d = a->GetRCost();
			if (j->flag == FLAG1)
			{
				if (d >= queue.GetKey(j)) continue;
				queue.DecreaseKey(j, d);
			}
			else
			{
				queue.Add(j, d);
				j->flag = FLAG1;
			}
			j->parent = a;
		}

	}
}
int main()
{
    Simple_window win {Point{100, 100}, 600, 600, "Exercise 1"};

    Arc a {Point{200, 200}, 50, 40, 0, 70};
    a.set_color(Color::red);
    a.set_fill_color(Color::white);
    win.attach(a);

    win.wait_for_button();
}
Пример #14
0
  Node *Arcs::target_node( Label l )

  {
    Arc *arc;

    for( arc=first_arcp; arc; arc=arc->next)
      if (arc->label() == l)
	return arc->target_node();
  
    return NULL;
  }
bool ArcsAroundDivPoints::ContainsArcQ(const Arc& arc) const{
    for (int i = 0; i < m_DivPoints.size(); i++) {
        if (arc.ContainsQ(m_Arcs[i].GetLeftEndpoint()) || arc.ContainsQ(m_Arcs[i].GetRightEndpoint())) {
            return false;
        }
    }
    for (int i = 0; i < m_DivPoints.size(); i++) {
        if (m_Arcs[i].ContainsQ(arc.GetRightEndpoint())) {
            return true;
        }
    }
    return false;
}
Пример #16
0
/*---------------------------------------------------------------------------
 * addArc - add a bezier arc to a trim loop and to a bin
 *---------------------------------------------------------------------------
 */
void
Subdivider::addArc( REAL *cpts, Quilt *quilt, long _nuid )
{
    BezierArc *bezierArc = new(bezierarcpool) BezierArc;
    Arc *jarc  		= new(arcpool) Arc( arc_none, _nuid );
    jarc->pwlArc	= 0;
    jarc->bezierArc	= bezierArc;
    bezierArc->order	= quilt->qspec->order;
    bezierArc->stride	= quilt->qspec->stride;
    bezierArc->mapdesc	= quilt->mapdesc;
    bezierArc->cpts	= cpts;
    initialbin.addarc( jarc );
    pjarc		= jarc->append( pjarc );
}
Пример #17
0
void floydWarshallInit(IHypergraph<Arc> const& hg, Util::Matrix<typename ArcWtFn::Weight>* pdistances,
                       ArcWtFn arcWtFn) {
  typedef typename ArcWtFn::Weight Weight;
  Util::Matrix<Weight>& dist = *pdistances;
  dist.setDiagonal(Weight::one(), Weight::zero());
  for (StateId tail = 0, numStates = (StateId)dist.getNumRows(); tail < numStates; ++tail) {
    Weight* rowTail = dist.row(tail);
    for (ArcId aid : hg.outArcIds(tail)) {
      Arc* arc = hg.outArc(tail, aid);
      StateId head = arc->head();
      Hypergraph::plusBy(arcWtFn(arc), rowTail[head]);
    }
  }
}
Пример #18
0
void WorkspaceBound::SetArc(const Arc& a)
{
  if(a.interval.d >= Pi) {
    center = a.center();
    outerRadius = innerRadius = a.radius();
    maxAngle = a.interval.d;
  }
  else {
    Vector3 p1,p2;
    p1 = a.eval(a.interval.c);
    p2 = a.eval(a.interval.c+a.interval.d);
    center = Half*(p1+p2);
    outerRadius = Half*(p1-p2).norm();
    maxAngle = a.interval.d;
  }
}
bool ArcsAroundDivPoints::ContainsADivPoint(const Arc& arc) const{
    for (int i = 0; i < m_DivPoints.size(); i++) {
        if (arc.ContainsQ(m_DivPoints[i])) {
            return true;
        }
    }
    return false;
}
bool Polygon::intersectBool(const Arc& arc) const {
	myFloat rad = arc.getLength() / 2 + maxRadius;
	Point arcCenter = (arc.position.point + arc.getEnd().point) / 2;
	if ((arcCenter - center).length() > rad) {
		return false;
	}

	Point last = pnts.back();
	for (Point act : pnts) {
		if (!arc.intersectionPoint(Line(last, act)).position.invalid()) {
			return true;
		}
		last = act;
	}

	return false;
}
Пример #21
0
	void printAllProbs(std::ostream& resStream, int nSamples, int nStepsPerSample,
			bool printSamples = false) {
		double* samples = NULL;
		if (printSamples)
			samples = new double[nSamples];
		Arc arc; arc.setFirst();
		do {
			double p = calcProb(nSamples, nStepsPerSample, arc, samples);
			resStream << arc << "   " << p;
			if (printSamples)
				for (int i = 0; i < nSamples; ++i)
					resStream << "  " << samples[i];
			resStream << std::endl;
		} while (arc.next(pof_.n));
		if (printSamples)
			delete[] samples;
	}
Пример #22
0
void MinCost<FlowType, CostType>::Init() {
    Node* i;
    Arc* a;
    
    for (a = arcs; a < arcs + 2 * edgeNum; a++) {
        if (a->r_cap > 0 && a->GetRCost() < 0)
            PushFlow(a, a->r_cap);
    }
    
    Node** lastActivePtr = &firstActive;
    for (i = nodes; i < nodes + nodeNum; i++) {
        if (i->excess > 0) {
            *lastActivePtr = i;
            lastActivePtr = &i->next;
        } else
            i->next = NULL;
    }
    *lastActivePtr = &nodes[nodeNum];
}
Пример #23
0
Eigen::Quaterniond
AxesVisualizer::orientation(const Entity* parent, double t) const
{
    switch (m_axesType)
    {
    case BodyAxes:
        return parent->orientation(t);

    case FrameAxes:
        {
            Arc* arc = parent->chronology()->activeArc(t);
            if (arc)
            {
                return arc->bodyFrame()->orientation(t);
            }
        }

    default:
        return Quaterniond::Identity();
    }
}
Пример #24
0
void Magnusson::updateNode(Node* n)
{
    // do not try to find best in arc of source as there is none (yields -inf score otherwise)
    if(n != &graph_->getSourceNode())
	   n->updateBestInArcAndScore();

    if(motionModelScoreFunction_)
    {
        Node* predecessor = nullptr;
        double motionModelScoreDelta = 0.0;
        Arc* a = n->getBestInArc();
        if(a)
        {
            predecessor = a->getSourceNode();
        }

        for(Node::ArcIt outArc = n->getOutArcsBegin(); outArc != n->getOutArcsEnd(); ++outArc)
        {
            if((*outArc)->getType() == Arc::Move)
            {
                Node *predecessorParam = graph_->isSpecialNode(predecessor) ? nullptr : predecessor;
                Node *nParam = graph_->isSpecialNode(n) ? nullptr : n;
                Node *targetParam = graph_->isSpecialNode((*outArc)->getTargetNode()) ? nullptr : (*outArc)->getTargetNode();
                motionModelScoreDelta = motionModelScoreFunction_(predecessorParam, nParam, targetParam);
                (*outArc)->update(motionModelScoreDelta);
            }
            else
            {
                (*outArc)->update();
            }
        }
    }
    else
    {
        for(Node::ArcIt outArc = n->getOutArcsBegin(); outArc != n->getOutArcsEnd(); ++outArc)
        {
            (*outArc)->update();
        }
    }
}
Пример #25
0
void Place::produceTokens(unsigned int nbOfTokens, unsigned int colorLabel, int tokensTime)
{
	unsigned int oldNumberOfTokens = getNbOfTokens(colorLabel);

	for (unsigned int i = 0; i < nbOfTokens; ++i) {
        Token token(tokensTime);
		m_tokenByColor[colorLabel - 1].push_back(token);
	}

    if(tokensTime < 0){tokensTime = 0;}

	if ((oldNumberOfTokens < NB_OF_TOKEN_TO_ACTIVE_ARC) && (getNbOfTokens(colorLabel) >= NB_OF_TOKEN_TO_ACTIVE_ARC)) { // CB WTF : Si un token et deux arcs sortant, bug ?
		arcList outGoingArcs = outGoingArcsOf(colorLabel);
		for (unsigned int i = 0 ; i < outGoingArcs.size() ; ++i) {
			Arc* arc = outGoingArcs[i];
            
//            if (!arc->getCondition()) { // CB check if the arc can be activated
//                continue;
//            }

            Transition* transitionTo = dynamic_cast<Transition*>(arc->getTo());
            
			if (!transitionTo) {
				throw IncoherentStateException();
			}

			transitionTo->setArcAsActive(arc, tokensTime, true);

			if (transitionTo->isStatic()) {
				if(arc->getRelativeMinValue().getValue() < (int) tokensTime) {
					getPetriNet()->pushTransitionToCrossWhenAcceleration(transitionTo);
				}
			} else {
				if(arc->getRelativeMaxValue().getValue() < (int) tokensTime) {
					getPetriNet()->pushTransitionToCrossWhenAcceleration(transitionTo);
				}
			}
		}
	}
}
Пример #26
0
void Place::produceTokens(unsigned int nbOfTokens, unsigned int colorLabel, unsigned int tokensTime) {
	unsigned int oldNumberOfTokens = getNbOfTokens(colorLabel);

	for (unsigned int i = 0; i < nbOfTokens; ++i) {
		Token token;
		token.setRemainingTime(tokensTime);
		m_tokenByColor[colorLabel - 1].push_back(token);
	}

	if ((oldNumberOfTokens < NB_OF_TOKEN_TO_ACTIVE_ARC) && (getNbOfTokens(colorLabel) >= NB_OF_TOKEN_TO_ACTIVE_ARC)) {
		arcList outGoingArcs = outGoingArcsOf(colorLabel);
		for (unsigned int i = 0 ; i < outGoingArcs.size() ; ++i) {
			Arc* arc = outGoingArcs[i];

			if (!(dynamic_cast<Transition*>(arc->getTo()))) {
				throw IncoherentStateException();
			}

			Transition* transitionTo = ((Transition*) arc->getTo());

			transitionTo->setArcAsActive(arc, tokensTime, true);

			if (transitionTo->isStatic()) {
				if(arc->getRelativeMinValue().getValue() < (int) tokensTime) {
					getPetriNet()->pushTransitionToCrossWhenAcceleration(transitionTo);
				}
			} else {
				if(arc->getRelativeMaxValue().getValue() < (int) tokensTime) {
					getPetriNet()->pushTransitionToCrossWhenAcceleration(transitionTo);
				}
			}

		}
	}



}
Пример #27
0
int Flow::createVarX()
{
	int nvars = 0;
	double coeff = 1.0;
	double lb = 0.;
	double ub = 1e20;
	VariableHash::iterator vit;
	Variable::VARTYPE varType = Variable::V_X;
	Column::COLTYPE colType = Column::COLTYPE::CONTINUOUS;

	for (int i = 1; i <= g->nVertices; ++i)
	{
		for (int j = 0; j < g->adjList[i].size(); ++j)
		{
			Arc arc = g->adjList[i][j];

			Variable x(colType, coeff, lb, ub);
			x.setType(varType);
			x.setArc(arc.toEdge());

			vit = vHash[varType].find(x);
			if (vit != vHash[varType].end())
				continue;

			bool isInserted = addCol(&x);
			if (isInserted)
			{
				x.setColIdx(getNCols() - 1);
				vHash[varType][x] = x.getColIdx();
				++nvars;
			}
		}
	}

	return nvars;
}
Пример #28
0
void stringPairToFst(Strings const& inputTokens, std::vector<std::string> const& outputTokens,
                     IMutableHypergraph<Arc>* pHgResult,
                     StringToHypergraphOptions const& opts = StringToHypergraphOptions()) {
  if (inputTokens.size() != outputTokens.size()) {
    SDL_THROW_LOG(Hypergraph.stringPairToFst, IndexException,
                  "The two strings must have same number of words");
  }

  // 1. Create simple FSA from input tokens:
  stringToHypergraph(inputTokens, pHgResult, opts);

  // 2. Insert output tokens:
  IVocabularyPtr pVoc = pHgResult->getVocabulary();
  std::vector<std::string>::const_iterator it = outputTokens.begin();
  StateId stateId = pHgResult->start();
  const StateId finalId = pHgResult->final();
  while (stateId != finalId) {
    Arc* arc = pHgResult->outArc(stateId, 0);
    const Sym sym = opts.terminalMaybeUnk(pVoc.get(), *it);
    setFsmOutputLabel(pHgResult, *arc, sym);
    ++it;
    stateId = arc->head();
  }
}
Пример #29
0
void calcTailSums(
		const POF& pof,
		const typename POF::Order& po,
		ParentsetMap<Real>& scores,
		int node,
		Arc feature,
		typename POF::template IdealMap<Real>& tailSums
		) {
	tailSums.setAll(0.0);
	StackSubset x(scores.maxParents);
	StackSubset xt(scores.maxParents); // translated x
	typename POF::Ideal xId(pof);
	do {
		translateSubset(po.getOrder(), x, xt);
		//size_t xti = scores.getParentsetIndex(xt);
		xId.setSuperOf(x);
		if (feature.holds(node, xt))
			tailSums[xId] += scores(node, xt);
	} while (x.next(0, scores.nNodes, scores.maxParents));
}/**/
Пример #30
0
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * **
*   Routine for Viterbi backtrace.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
double viterbi_backtrace(const Graph& graph, matrix<VitCell>& chart,
    vector<int>& outLabelList, bool doAlign)
    {
    int frmCnt = chart.size1() - 1;
    int stateCnt = chart.size2();

    //  Find best final state.
    vector<int> finalStates;
    int finalCnt = graph.get_final_state_list(finalStates);
    double bestLogProb = g_zeroLogProb;
    int bestFinalState = -1;
    for (int finalIdx = 0; finalIdx < finalCnt; ++finalIdx)
        {
        int stateIdx = finalStates[finalIdx];
        if (chart(frmCnt, stateIdx).get_log_prob() == g_zeroLogProb)
            continue;
        double curLogProb = chart(frmCnt, stateIdx).get_log_prob() +
            graph.get_final_log_prob(stateIdx);
        if (curLogProb > bestLogProb)
            bestLogProb = curLogProb, bestFinalState = stateIdx;
        }
    if (bestFinalState < 0)
        throw runtime_error("No complete paths found.");

    //  Do backtrace, collect appropriate labels.
    outLabelList.clear();
    int stateIdx = bestFinalState;
    for (int frmIdx = frmCnt; --frmIdx >= 0; )
        {
        assert((stateIdx >= 0) && (stateIdx < stateCnt));
        int arcId = chart(frmIdx + 1, stateIdx).get_arc_id();
        Arc arc;
        graph.get_arc(arcId, arc);
        assert((int) arc.get_dst_state() == stateIdx);
        if (doAlign)
            {
            if (arc.get_gmm() < 0)
                throw runtime_error("Expect all arcs to have GMM.");
            outLabelList.push_back(arc.get_gmm());
            }
        else if (arc.get_word() > 0)
            outLabelList.push_back(arc.get_word());
        stateIdx = graph.get_src_state(arcId);
        }
    if (stateIdx != graph.get_start_state())
        throw runtime_error("Backtrace does not end at start state.");
    reverse(outLabelList.begin(), outLabelList.end());
    return bestLogProb;
    }