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); } } }
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; }
// 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; }
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); }
IntPair add(IntPair x, IntPair y) { return IntPair(x.i+y.i,x.j+y.j); }
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); }