IntPair TrinomialRand::Variate() const
{
    if (X.GetProbability() > Y.GetProbability()) {
        int x = X.Variate();
        int y = BinomialDistribution::Variate(n - x, p2_1mp1, localRandGenerator);
        return IntPair(x, y);
    }
    int y = Y.Variate();
    int x = BinomialDistribution::Variate(n - y, p1_1mp2, localRandGenerator);
    return IntPair(x, y);
}
// Description: Calculates matrix of distances and matrix of paths between lambdas
void TSPSolver::SetMatrixes()
{
	int size = nodes.size();
	int maxPath = (int) mine->GetWidth()*mine->GetHeight()/sqrt(2.0); // this is the maximum possible path on this map
	int dist;
	vector<IntPair> pathToNode;

	for (int i = 0; i < size - 1; i++) {
		// Get start node coordinates
		IntPair firNode = nodes[i];
		int startX = firNode.first;
		int startY = firNode.second;

		for (int j = i + 1; j < size; j++) {
			dist = 0;
			pathToNode.clear();

			// Get target node coordinates
			IntPair secNode = nodes[j];
			int targetX = secNode.first;
			int targetY = secNode.second;

			// Map the distance to the IntPair of nodes between lambda node and lift node
			// Using method allows to transform the closed graph to unclosed graph
			// and still using closed graph's algorithms.
			//
			// NOTE: we need to calculate optimal path from the last lambda to the lift using Astar algorithm later.

			if (j == size - 1) {
				if (i == 0) {
					dist = 2*maxPath;		// distance between robot and lift
					// Map the distance to the IntPair of nodes
					distMatrix[IntPair (i, j)] = dist;
					continue;
				} else dist = 3*maxPath;	// distance between lambda and lift
			}

			// Get distance between nodes
			pathToNode = FindPath(startX, startY, targetX, targetY);
			if (pathToNode.empty()) {
				int pathlen = pathToNode.size();
				dist += pathlen;
			} else dist += mine->GetHeight()*mine->GetWidth();													// TBD: in this case it seems better to delete lambda from list and ignore it

			// Map the distance to the IntPair of nodes
			distMatrix[IntPair (i, j)] = dist;
			// Map the path to the IntPair of nodes
			pathMatrix[IntPair (i, j)] = pathToNode;
		}
	}
}
int main()
{
    int target = 20;
    vector<vector<IntPair>> vset;
    vset.resize(target+1);
    vset[1].push_back(IntPair(1,1));

    //for each level
    for(int n=2; n<=target; ++n) {
        vmap.clear();
        vmap.resize(msize*msize, false);
        vector<IntPair>& cset=vset[n-1];
        printf("%d %zu\n", n-1, cset.size());
        for(int n1 = 1; n1 <= n/2; ++n1)
            find_all(vset[n], vset[n1], vset[n-n1]);
    }

    vmap.clear();
    vmap.resize(msize*msize, false);

    int cnt = 0;
    for( int i = 3; i<=target; ++i) {
        for(auto iter = vset[i].begin(); iter != vset[i].end(); ++iter) {
            if(!vmap[iter->first*msize+iter->second]) {
                vmap[iter->first*msize+iter->second]= true;
                ++cnt;
            }
        }
    }
    printf("%d %d\n", target, cnt*2-1);
}
// Description: Returns path between Start and Target nodes
vector<IntPair> TSPSolver::GetPath(const int & start, const int & target)
{
	// Check node's order
	if (start < target)
		return this->pathMatrix[IntPair (start, target)];
	else {
		// pathMatrix contains paths from A to B, where A < B.
		// But path from A to B, where A > B, is path from B to A in reverse order.
		// So, we need to reverse vector

		vector<IntPair> resultPath;
		vector<IntPair> * ptr = & this->pathMatrix[IntPair (target, start)];
		int size = ptr->size();
		for (int i = size - 1; i >= 0; i--) {
			resultPath.push_back(ptr->at(i));
		}
		return resultPath;
	}
}
// Description: Loads map from file and fills Field's fields =)
int Field::LoadMap(istream &sin)
{
	mapWidth = -1;
	mapHeight = -1;
	map = NULL;
	liftIsOpen = false;
	robotIsDead = false;
	lambdas.clear();

	vector<string> buf;
	string str;
	size_t width = 0;

	// Counting mine's dimension
	while (!sin.eof()) {
		getline(sin, str);
		buf.push_back(str);
		if (str.size() > width) width = str.size(); // remember the longest row
	}

	mapWidth = width;
	mapHeight = buf.size();
	sin.seekg(0, ios::beg);

	map = new char * [mapHeight];
	for (size_t i = 0; i < mapHeight; i++) {
		map[i] = new char [mapWidth];
		for (size_t j = 0; j < mapWidth; j++) {

			// All rows shorter than map width are supplemented with whitespaces
			if (j >= buf.at(i).size()) {
				map[i][j] = EMPTY;
				continue;
			}
			map[i][j] = buf.at(i)[j];

			if (map[i][j] == ROBOT) {				// remembering robot coordinates
				robot.first = i;
				robot.second = j;
			} else if (map[i][j] == LAMBDA)
				lambdas.push_back(IntPair(i, j));		// filling lambdas's list
			else if (map[i][j] == CLOSED_LIFT) {	// remembering closed lift coordinates
				lift.first = i;
				lift.second = j;
			} else if (map[i][j] == OPENED_LIFT) {	// remembering open lift coordinates
				lift.first = i;
				lift.second = j;
				liftIsOpen = true;
			}
		}
	}

	return 0;
}
void HashSparseMatrix::Add( int i, int j, double value, TripletVector & data )
{
	int key = i + j * 65536;
	HashMapIterator it = map_.find( key );
	if ( it == map_.end() ) {
		map_.insert( IntPair( key, data.size() ) );
		data.push_back( Triplet( i + ioffset_, j + joffset_, value ) );
	} else {
		data[ it->second ].m_value += value;
	}
}
void find_all(vector<IntPair>& cset, vector<IntPair>& s1, vector<IntPair>& s2)
{
    for(auto iter = s1.begin(); iter != s1.end(); ++iter) {
        rational r1 = rational(iter->first, iter->second, 1, 0);
        for(auto iter2 = s2.begin(); iter2 !=s2.end(); ++iter2) {
            rational r2 = rational(iter2->first, iter2->second, 1, 0);
            rational result = r1 + r2;
            if(result > 1)
                insert(IntPair(result.pden(), result.pnum()), cset );
            else
                insert(IntPair(result.pnum(), result.pden()), cset);
            result = rational(iter->first*(iter2->first), iter->second*(iter2->first ) + iter->first*(iter2->second));
            insert(IntPair(result.pnum(), result.pden()), cset);
            result = rational(iter->first*(iter2->second), iter->second*(iter2->second ) + iter->first*(iter2->first));
            insert(IntPair(result.pnum(), result.pden()), cset);
            result = rational(iter2->first*(iter->second), iter->second*(iter2->second) + iter->first*(iter2->first));
            insert(IntPair(result.pnum(), result.pden()), cset);
        }
    }
}
Exemple #8
0
void UdmComparator::tallyChildrenClasses( const UdmObjectSet &udmObjectSet1, const UdmObjectSet &udmObjectSet2 ) {

	ChildrenClassesTallyMap childrenClassesTallyMap;

	for( UdmObjectSet::const_iterator uosCit = udmObjectSet1.begin() ; uosCit != udmObjectSet1.end() ; ++uosCit ) {

		std::string className = uosCit->type().name();

		ChildrenClassesTallyMap::iterator ctmItr = childrenClassesTallyMap.find( className );
		if ( ctmItr == childrenClassesTallyMap.end() ) {
			ctmItr = childrenClassesTallyMap.insert(  std::make_pair(  className, IntPair( 0, 0 )  )   ).first;
		}

		++(ctmItr->second.first);
	}

	for( UdmObjectSet::const_iterator uosCit = udmObjectSet2.begin() ; uosCit != udmObjectSet2.end() ; ++uosCit ) {

		std::string className = uosCit->type().name();

		ChildrenClassesTallyMap::iterator ctmItr = childrenClassesTallyMap.find( className );
		if ( ctmItr == childrenClassesTallyMap.end() ) {
			ctmItr = childrenClassesTallyMap.insert(  std::make_pair(  className, IntPair( 0, 0 )  )   ).first;
		}

		++(ctmItr->second.second);
	}

	std::cerr << "Disparity in number of child objects for the following classes:" << std::endl;
	for( ChildrenClassesTallyMap::iterator ctmItr = childrenClassesTallyMap.begin() ; ctmItr != childrenClassesTallyMap.end() ; ++ctmItr ) {
		IntPair intPair = ctmItr->second;
		if ( intPair.first != intPair.second ) {
			std::cerr << "\t" << ctmItr->first << " => " << intPair.first << "," << intPair.second << std::endl << std::endl;
		}
	}
	std::cerr << std::endl;

}
	bool ContainerContentWindow::handleItemDroppedOnContainer(const EventArgs& evt)
	{
		const DragDropEventArgs& evtArgs = static_cast<const DragDropEventArgs&>(evt);

		if (evtArgs.dragDropItem->testClassName("ItemDragContainer"))
		{
			ItemDragContainer* dragcont = dynamic_cast<ItemDragContainer*>(
				evtArgs.dragDropItem);
			Item* item = dragcont->getItem();


			CEGUI::Vector2 relPos = evtArgs.dragDropItem->getPosition().asAbsolute(evtArgs.dragDropItem->getParentPixelSize()) - 
									mContentWindow->getPosition().asAbsolute(mContentWindow->getParentPixelSize());
			int x = relPos.d_x, y = relPos.d_y;

            // übergangspixel
            x += 14;
            y += 14;

            x = x / 30;
            y = y / 30;

			if( mContainer->addItem(item,IntPair(x,y)) )
            {
                if( dragcont != getItemWindow(item) )
                {
                    CEGUI::WindowManager::getSingleton().destroyWindow(dragcont);
                    //dragcont->destroyWindow();
                    dragcont = createItemWindow(item);
                    mContentWindow->addChildWindow(dragcont);
                }
			    std::pair<unsigned int, unsigned int> pos = mContainer->getItemPosition(item);
			    dragcont->setPosition(
				    UVector2(
					    cegui_absdim(pos.first*30),
					    cegui_absdim(pos.second*30)));
			    dragcont->setItemParent(mContainer);

                handleItemLeavesContainer(evt);
			    return true;
            }
		}
        handleItemLeavesContainer(evt);
		return false;
	}
Exemple #10
0
// Returns endKeyFlags in .first and valueCode in .second.
IntPair GetSortCode(int bit, int endBit, sortData_t data, bool firstPass) {

	int endKeyFlags = 0;
	if(bit == data->firstBit) {
		endKeyFlags |= SORT_END_KEY_SET;
		if(data->preserveEndKeys) endKeyFlags |= SORT_END_KEY_SAVE;
	}

	int valueCode;
	switch(data->valueCount) {
		case 0: valueCode = 0; break;
		case 1: valueCode = 2; break;
		case -1: valueCode = firstPass ? 1 : 2; break;
		default: valueCode = 3; break;
	}
	
	return IntPair(endKeyFlags, valueCode);
}
IntPairs NearestNeighborsClosePairsFinder::get_close_pairs(
    const algebra::BoundingBox3Ds &bas,
    const algebra::BoundingBox3Ds &bbs) const {
  set_was_used(true);
  IMP_OBJECT_LOG;
  IMP_LOG_TERSE("Quadratic add_close_pairs called with "
                << bas.size() << " and " << bbs.size() << std::endl);
  IntPairs ret;
  const double d2 = get_distance() / 2.0;
  for (unsigned int i = 0; i < bas.size(); ++i) {
    algebra::BoundingBox3D bi = bas[i] + d2;
    for (unsigned int j = 0; j < bbs.size(); ++j) {
      algebra::BoundingBox3D bj = bbs[j] + d2;
      if (get_interiors_intersect(bi, bj)) {
        ret.push_back(IntPair(i, j));
      }
    }
  }
  return ret;
}
IntPairs QuadraticClosePairsFinder::get_close_pairs(
    const algebra::BoundingBox3Ds &bbs) const {
  set_was_used(true);
  IMP_OBJECT_LOG;
  IMP_LOG_TERSE("Adding close pairs from "
                << bbs.size() << " boxes with threshold " << get_distance()
                << std::endl);
  IntPairs ret;
  const double d2 = get_distance() / 2.0;
  for (unsigned int i = 0; i < bbs.size(); ++i) {
    algebra::BoundingBox3D bi = bbs[i] + d2;
    for (unsigned int j = 0; j < i; ++j) {
      algebra::BoundingBox3D bj = bbs[j] + d2;
      if (get_interiors_intersect(bi, bj)) {
        ret.push_back(IntPair(i, j));
      }
    }
  }
  return ret;
}
Exemple #13
0
  void run()
	{
	  IntPair ip;
	  test_(ip.getX() == 0 && ip.getY() == 0);
	  
	  IntPair ip2(3,-5);
	  test_(ip2.getX() == 3 && ip2.getY() == -5);
	  
	  IntPair ip3 = ip2;
	  test_(ip3.getX() == 3 && ip3.getY() == -5);
	  
	  IntPair ip4 = ip3 + ip2;
	  test_(ip4.getX() == 6 && ip4.getY() == -10);

	  test_(ip2 == ip4 - ip3);
	  
	  test_(ip3 < ip4);
	  IntPair ip5(6,-4);
	  test_(ip5 > ip4);
	  test_(ip4 < ip5);
	  test_((ip4 + ip5) == (ip5 + ip4));
	  
	  Direction left = Direction(Direction::LEFT);
	  test_(*(left.getDirPair()) == IntPair(-1,0));
	  test_(*(left.getDirPair()) < IntPair(0,0));
	
		Direction right = Direction();
	  test_(*(right.getDirPair()) == IntPair(1,0));
  
	  //Direction::initialize();
	  int n = Direction::getRandom().getNo();
	  test_(n < 4 && n >=0);
	  n = Direction::getRandom().getNo();
	  test_(n < 4 && n >=0);
	  n = Direction::getRandom().getNo();
	  test_(n < 4 && n >=0);
	  n = Direction::getRandom().getNo();
	  test_(n < 4 && n >=0);
	  n = Direction::getRandom().getNo();
	  test_(n < 4 && n >=0);

	  n = Direction::getRandomNew(Direction(Direction::RIGHT)).getNo();
	  test_(n < 4 && n >=0 && n != 2);
	  n = Direction::getRandomNew(Direction::UP).getNo();
	  test_(n < 4 && n >=0 && n != 3);
	  n = Direction::getRandomNew(Direction::LEFT).getNo();
	  test_(n < 4 && n >=0 && n != 0);
	  n = Direction::getRandomNew(Direction::DOWN).getNo();
	  test_(n < 4 && n >=0 && n != 1);
	  
	  ip4.print();
	  
	  Direction up = Direction(IntPair(0,1));
	  test_(up.getNo() == Direction::UP);
	  left = Direction(IntPair(-1,0));
	  test_(left.getNo() == Direction::LEFT);
	  
	  Direction child = Direction::getFirstChild(up);
	  test_(child.getNo() == Direction::RIGHT);
	  Direction child2 = Direction::getSecondChild(up);
	  test_(child2.getNo() == Direction::UP);
	  child2 = Direction::getNextChild(up, child);
	  test_(child2.getNo() == Direction::UP);
	  Direction child3 = Direction::getThirdChild(up);
	  test_(child3.getNo() == Direction::LEFT);
	  child3 = Direction::getNextChild(up, child2);
	  test_(child3.getNo() == Direction::LEFT);
	  
	  Direction down(Direction::DOWN);

	  child = Direction::getFirstChild(down);
	  test_(child.getNo() == Direction::LEFT);
	  child2 = Direction::getSecondChild(down);
	  test_(child2.getNo() == Direction::DOWN);
	  child2 = Direction::getNextChild(down, child);
	  test_(child2.getNo() == Direction::DOWN);
	  child3 = Direction::getThirdChild(down);
	  test_(child3.getNo() == Direction::RIGHT);
	  
	  child = Direction::getFirstChild(left);
	  test_(child.getNo() == Direction::UP);
	  child = Direction::getNextChild(left, child);
	  test_(child.getNo() == Direction::LEFT);
	  child = Direction::getNextChild(left, child);
	  test_(child.getNo() == Direction::DOWN);
	  
	  
	  right = Direction(IntPair(1,0));
	  child = Direction::getFirstChild(right);
	  test_(child.getNo() == Direction::DOWN);
	  child2 = Direction::getSecondChild(right);
	  test_(child2.getNo() == Direction::RIGHT);
	  child2 = Direction::getNextChild(right, child);
	  test_(child2.getNo() == Direction::RIGHT);
	  child3 = Direction::getThirdChild(right);
	  test_(child3.getNo() == Direction::UP);
	  
	  IntPair ip10 = IntPair(-1,+20);
	  IntPair ip11 = IntPair::parseIntPair("(-1,+20)");
	  test_(ip10 == ip11);
	}
int main()
{
    int range = 2000000000LL;
    //range = 10000;
    period = 6308948;
    vn.resize(2*period+1);
    i64 s0 = 290797;
    vn[0] = s0;
    i64 nmod = 50515093LL;
    //generate  all numbers twice, this needs relatively 
    //large memory 
    for(unsigned int i = 1; i <= period; ++i){
        s0 = s0*s0;
        s0 %= nmod;
        vn[i] = s0;
        if(s0 < minimum){
            minimum = s0;
            mpos = i;
        }
        vn[i+period] = vn[i];//lesson, here I made a mistake, rhs used i
    }
    assert(((i64)vn[period] * vn[period])%nmod==vn[1]);
    bool debug = false;
    if(debug){
        vn = {0, 7,4,6,3, 1,8, 9, 7,4,6,3,1,8,9};
        period = 7;
        range = 24;
        minimum = 1;
        mpos = 5;
    }
    //intmax means minimum not found, better than 0;
    vnext.resize(2*period+1, numeric_limits<int>::max());
   
    //generate a max priority queue to find the next less
    priority_queue<pair<int, int>> vpq;
    for( unsigned int i = 1; i < vn.size(); ++i){
        int val = vn[i];

        while(!vpq.empty() && vpq.top().first > val){
             int nx = vpq.top().second;
             //over a period is OK, 
             //assert(vnext[1] == numeric_limits<int>::max());
             assert(vnext[nx] == numeric_limits<int>::max());
             assert(vn[nx] > vn[i]);
             vnext[nx] = i;
             vpq.pop();
        }
        vpq.push(IntPair(val, i));
        if(vpq.empty() || (i >period && vpq.top().first == minimum))
           break; 
    }
    //now vnext has all the next smaller values in the vector
    //we need to count now
    nmid = range % period;
    i64 nfull, ntotal = 0, npart=0; 
    unsigned int nmax = period <= range? period : range;
    int nfirst = 0;
    for(unsigned int i = 1; i <= nmax; ++i){

            i64 nall = compute_part(i, nfirst, npart);
            //printf("%d %lld %lld %d %lld\n", i, npart, nall,nfirst, ntotal);
            //post processing
            nfull = range / period;
            nfull -= nfirst;
            assert(nfull >= 0);
            ntotal += nfull*(nfull + 1)/2 * (minimum * period) + nall * (nfull +1)+npart;
    }
    printf("%lld\n", ntotal);
}
Exemple #15
0
IntPair add(IntPair x, IntPair y) {
  return IntPair(x.i+y.i,x.j+y.j);
}
Exemple #16
0
IntPair addp(const IntPair& x, const IntPair& y) {
  return IntPair(x.i+y.i,x.j+y.j);
}
// Description: Finds a path using A*.
vector<IntPair> TSPSolver::FindPath(int startX, int startY, int targetX, int targetY, bool useHcost)
{
	vector<IntPair> resultPath;			// vector of coordinates of cells in found path
	int path = 0;
	const int nonexistent = 0, found = 1;		// path-related constants
	const int inOpenList = 1, inClosedList = 2;	// lists-related constants
	int parentX, parentY, Gcost, index;
	int ** whichList;			// used to record whether a cell is on the open list or on the closed list.
	IntPair ** parent;	// used to record parent of each cage
	OpenListItem * openList;	// array holding open list items, which is maintained as a binary heap.
	int numberOfOpenListItems;

// 1. Checking start and target cells to avoid misunderstandings.

	// If start and target cells are the same cell
	if (startX == targetX && startY == targetY) {
		resultPath.push_back(IntPair (startX, startY));
		return resultPath;
	}

	// If target cell is unwalkable
	if (mine->GetMap()[targetX][targetY] == '#') {
		resultPath.push_back(IntPair (-1, -1));	// its better than return an empty vector
		return resultPath;
	}

// 2. Allocate memory and reset variables

	whichList = new int* [mine->GetHeight() + 1];
	for (int i = 0; i < mine->GetHeight(); i++) {
		whichList[i] = new int [mine->GetWidth() + 1];
		for (int j = 0; j < mine->GetWidth(); j++)
			whichList[i][j] = 0;
	}

	parent = new IntPair* [mine->GetHeight() + 1];
	for (int i = 0; i < mine->GetHeight(); i++) {
		parent[i] = new IntPair [mine->GetWidth() + 1];
	}

	openList = new OpenListItem [mine->GetWidth()*mine->GetHeight()+2];

	resultPath.clear();

// 3. Add the starting cell to the open list.

	numberOfOpenListItems = 1;
	openList[1].SetX(startX);	// assign it as the top item in the binary heap
	openList[1].SetY(startY);
	openList[1].SetGcost(0);	// reset starting cell's G value to 0

// 4. Do it until the path is found or recognized as nonexistent.

	while (true) {
	
// 4.1. If the open list is not empty, take the first cell off of the list (i.e. the lowest F cost cell).

		if (numberOfOpenListItems != 0) {
			// record cell coordinates and Gcost of the item as parent for adjacent cells (see below)
			parentX = openList[1].GetX();
			parentY = openList[1].GetY();
			Gcost = openList[1].GetGcost();

			whichList[parentX][parentY] = inClosedList;	// add item to the closed list
			DeleteTopItemFromBinaryHeap(openList, numberOfOpenListItems);				// delete this item from the open list

// 4.2. Check the adjacent squares and add them to the open list

			for (int x = parentX - 1; x <= parentX + 1; x++) {
				for (int y = parentY - 1; y <= parentY + 1; y++) {
					if ((x != parentX && y != parentY) || (x == parentX && y == parentY))
						continue;

					// If not off the map (avoiding array-out-of-bounds errors)
					if (x != -1 && y != -1 && x != mine->GetHeight() && y != mine->GetWidth()) {
						
						// If not already on the closed list (items on the closed list have already been considered and can now be ignored).
						if (whichList[x][y] != inClosedList) {
							// If not a wall/obstacle square.
							if (mine->GetMap()[x][y] != '#' && mine->GetMap()[x][y] != '*') {																// TBD: use isWalkable(...) method from Field class
								// If cell is not already on the open list, add it to the open list.
								if (whichList[x][y] != inOpenList) {
									numberOfOpenListItems++;					// increment number of items in the heap
									openList[numberOfOpenListItems].SetX(x);	// record the x and y coordinates of the new item
									openList[numberOfOpenListItems].SetY(y);

									// Figure out its G cost
									openList[numberOfOpenListItems].SetGcost(Gcost + 1);
									
									// Figure out its H and F costs and parent
									parent[x][y].first = parentX;							// change the cell's parent
									parent[x][y].second = parentY;
									// F cost includes H cost except when we want to use A* algorithm as Dijkstra's algorithm
									if (useHcost) openList[numberOfOpenListItems].SetHcost( (abs(x - targetX) + abs(y - targetY)) );
									openList[numberOfOpenListItems].CalculateFcost();	// update the F cost
									
									// Move the new open list item to the proper place in the binary heap.
									BubbleItemInBinaryHeap(openList, numberOfOpenListItems);

									whichList[x][y] = inOpenList;	// Change whichList value.
								}
								// If cell is already on the open list, choose better G and F costs.
								else {
									index = GetItemIndexFromBinaryHeapByCoord(openList, numberOfOpenListItems, x, y);
									Gcost += 1;	// Figure out the G cost of this possible new path

									// If this path is shorter (G cost is lower) then change the parent cell, G cost and F cost. 		
									if (Gcost < openList[index].GetGcost()) {
										parent[x][y].first = parentX;			// change the cell's parent
										parent[x][y].second = parentY;
										openList[index].SetGcost(Gcost);	// change the G cost
										openList[index].CalculateFcost();	// update the F cost
										BubbleItemInBinaryHeap(openList, index);		// update cell's position on the open list
									}
								}	
							}
						}
					}
				}
			}
		} else {

// 4.3. If open list is empty then there is no path.	
		
			path = nonexistent;
			break;
		}  

// 5. If target cell is added to open list then path has been found.

		if (whichList[targetX][targetY] == inOpenList) {
			path = found;
			break;
		}
	}	// end while

// 6. Save the path if it exists.

	if (path == found) {

// 6.1. Working backwards from the target to the start by checking each cell's parent.

		int x = targetX, y = targetY;
		int tmp;
		while (true) {
			// Save path in reverse order
			resultPath.push_back(IntPair (x, y));

			if (x == startX && y == startY) break;

			// Look up the parent of the current cell
			tmp = parent[x][y].first;
			y = parent[x][y].second;
			x = tmp;
		} 

// 6.2. Reversing path

		int size = (int) resultPath.size();
		int amount = size/2;
		IntPair tmpIntPair;
		for (int i = 0; i < amount; i++) {
			tmpIntPair = resultPath[size - i - 1];
			resultPath[size - i - 1] = resultPath[i];
			resultPath[i] = tmpIntPair;
		}
		
	} else resultPath.push_back(IntPair (-1, -1));	// its better than return an empty vector

// 7. Freeing used memory

	for (int i = 0; i < mine->GetHeight(); i++)
		delete [] whichList[i];
	for (int i = 0; i < mine->GetHeight(); i++)
		delete [] parent[i];
	delete [] openList;

	return resultPath;
}
void NoisyCnaEnumerate::collapse(const StlIntVector& mapNewCharToOldChar,
                                 const StlIntVector& mapOldCharToNewChar,
                                 RootedCladisticNoisyAncestryGraph& G)
{
  typedef std::set<IntPair> IntPairSet;
  
  int k = _M.k();
  const auto& intervals = _M.intervals();
  for (const IntSet& interval : intervals)
  {
    IntSet remappedInterval;
    for (int c : interval)
    {
      int cc = mapOldCharToNewChar[c];
      if (cc != -1)
        remappedInterval.insert(cc);
    }
    if (remappedInterval.size() > 1)
    {
      // get the copy states
      IntPairSet XY;
      const StateTree& S = G.S(*remappedInterval.begin());
      for (int i = 0; i < k; ++i)
      {
        if (S.isPresent(i))
        {
          const auto& xyz = _M.stateToTriple(i);
          // skip state 1,1
          if (xyz._x != 1 || xyz._y != 1)
          {
            XY.insert(IntPair(xyz._x, xyz._y));
          }
        }
      }
      
      for (const IntPair& xy : XY)
      {
        assert(xy.first != 1 || xy.second != 1);
        
        // collect all char-state pairs correspond to CNAs
        IntPairSet toCollapse;
        for (int c : remappedInterval)
        {
          const StateTree& S_c = G.S(c);
          for (int i = 0; i < k; ++i)
          {
            if (S_c.isPresent(i) && _M.stateToTriple(i)._x == xy.first && _M.stateToTriple(i)._y == xy.second)
            {
              int pi_i = S_c.parent(i);
              assert(0 <= pi_i && pi_i < k);
              
              if (_M.stateToTriple(pi_i)._x != xy.first || _M.stateToTriple(pi_i)._y != xy.second)
              {
                // we got a CNA state
                toCollapse.insert(IntPair(c, i));
              }
            }
          }
        }
        
        G.collapse(toCollapse);
      }
    }
  }
}
void NoisyCnaEnumerate::fixTrunk(const RealTensor& F_ub,
                                 const StateTreeVector& S,
                                 const StlIntVector& mapNewCharToOldChar,
                                 const StlIntVector& mapOldCharToNewChar,
                                 RootedCladisticNoisyAncestryGraph& G)
{
  const int m = F_ub.m();
  const int k = F_ub.k();
  const int n = F_ub.n();
  
  typedef std::set<IntPair> IntPairSet;
  
  IntPairSet truncalCharacters;
  for (int c = 0; c < n; ++c)
  {
    std::cerr << "Character " << _M(0, mapNewCharToOldChar[c]).characterLabel() << " (" << mapNewCharToOldChar[c] << ") : ";
    S[c].writeEdgeList(std::cerr);
    std::cerr << std::endl;
    
    bool truncal = true;
    int mutation_i = -1;
    for (int p = 0; p < m; ++p)
    {
      double ccf = 0;
      for (int i = 0; i < k; ++i)
      {
        if (!S[c].isPresent(i))
          continue;
        
        const auto& xyz = _M.stateToTriple(i);
        if (xyz._z >= 1)
        {
          ccf += F_ub(i, p, c);
          
          const auto& pi_xyz = _M.stateToTriple(S[c].parent(i));
          if (pi_xyz._z == 0 && xyz._z == 1)
          {
            mutation_i = i;
          }
        }
      }
      ccf /= _purityValues[p];
      
      if (g_tol.less(ccf, 1))
      {
        truncal = false;
        break;
      }
    }
    
    if (truncal)
    {
      assert(mutation_i != -1);
      const StateTree& S_c = S[c];
      truncalCharacters.insert(IntPair(c, mutation_i));
      while ((mutation_i = S_c.parent(mutation_i)) != 0)
      {
        truncalCharacters.insert(IntPair(c, mutation_i));
      }
    }
  }
  
  std::cerr << "Truncal:" << std::endl;
  for (auto ci : truncalCharacters)
  {
    auto xyz = _M.stateToTriple(ci.second);
    std::cerr << _M(0, mapNewCharToOldChar[ci.first]).characterLabel()
              << " , (" << xyz._x << "," << xyz._y << "," << xyz._z << ")" << std::endl;
  }
  
  Digraph::Node monoClonalRoot = G.collapse(truncalCharacters);
  G.makeMonoclonal(monoClonalRoot);
}