Skip to content

Commit

Permalink
optimizeLargeSubgraphs(&changes)
Browse files Browse the repository at this point in the history
  • Loading branch information
vbrover committed May 19, 2021
1 parent 00e8f2c commit 438255a
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 35 deletions.
131 changes: 108 additions & 23 deletions phylogeny/distTree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2763,7 +2763,8 @@ void Image::processSmall (const DTNode* center_arg,


void Image::processLarge (const Steiner* subTreeRoot,
const VectorPtr<Tree::TreeNode> &possibleBoundary)
const VectorPtr<Tree::TreeNode> &possibleBoundary,
const VectorOwn<Change>* changes)
{
ASSERT (subgraph. empty ());
ASSERT (! tree);
Expand Down Expand Up @@ -2803,7 +2804,49 @@ void Image::processLarge (const Steiner* subTreeRoot,
rootInArea = (! subgraph. area_root || subgraph. area_root == wholeTree. root);

// Optimization
tree->optimizeLargeSubgraphs ();
if (changes)
{
VectorOwn<Change> newChanges; newChanges. reserve (changes->size ());
const DiGraph::Node2Node old2new (DiGraph::reverse (new2old));
Tree::LcaBuffer buf;
for (const Change* change : *changes)
if (const DTNode* from = getOld2new (change->from, old2new, buf))
{
ASSERT (from->graph == tree);
const DTNode* to = getOld2new (change->to, old2new, buf);
if (! to)
{
const Tree::TreeNode* lca_ = nullptr;
const VectorPtr<Tree::TreeNode>& path = Tree::getPath (change->from, change->to, nullptr, lca_, buf);
ASSERT (lca_);
for (const Tree::TreeNode* node : path)
if (node != change->from && boundary. containsFast (node))
{
EXEC_ASSERT (to = static_cast <const DistTree_sp::DTNode*> (findPtr (old2new, node)));
break;
}
}
if ( to
&& ( from->getParent () == to
|| from->getParent () == to->getParent ()
)
&& from->getParent () -> arcs [false]. size () <= 2
)
to = nullptr;
if (to)
{
auto newChange = new Change (from, to);
ASSERT (newChange->valid ());
newChange->improvement = change->improvement;
newChange->arcDist = change->arcDist; // May be not correct due to *to change
newChanges << newChange;
}
}
//PRINT (newChanges. size ());
tree->applyChanges (newChanges, true);
}
else
tree->optimizeLargeSubgraphs (nullptr);

tree->qc ();
}
Expand Down Expand Up @@ -2997,6 +3040,42 @@ bool Image::apply ()



const DTNode* Image::getOld2new (const DTNode* old,
const DiGraph::Node2Node &old2new,
Tree::LcaBuffer &buf) const
{
ASSERT (old);
ASSERT (tree);
ASSERT (old->graph == & subgraph. tree);

if (! subgraph. area. containsFast (old))
return nullptr;

const DTNode* node1 = old;
while (! subgraph. boundary. containsFast (node1))
{
ASSERT (node1->arcs [false]. size () >= 2);
node1 = static_cast <const DTNode*> (node1->arcs [false]. front () -> node [false]);
}

const DTNode* node2 = old;
while (! subgraph. boundary. containsFast (node2))
{
ASSERT (node2->arcs [false]. size () >= 2);
node2 = static_cast <const DTNode*> (node2->arcs [false]. back () -> node [false]);
}

const Tree::TreeNode* lca = Tree::getLca ( static_cast <const Tree::TreeNode*> (findPtr (old2new, node1))
, static_cast <const Tree::TreeNode*> (findPtr (old2new, node2))
, buf
);
ASSERT (lca);

return static_cast <const DTNode*> (lca);
}




// DistTree

Expand Down Expand Up @@ -6788,7 +6867,7 @@ void reinsert_thread (size_t from,



bool DistTree::optimizeReinsert ()
void DistTree::optimizeReinsert ()
{
ASSERT (! subDepth);

Expand All @@ -6814,8 +6893,10 @@ bool DistTree::optimizeReinsert ()
changes << threadChanges;

changes. sort (Change::longer);
//PRINT (changes. size ());

return applyChanges (changes, true);
optimizeLargeSubgraphs (& changes);
// Invokes: applyChanges (changes, true);
}


Expand Down Expand Up @@ -7089,16 +7170,17 @@ namespace

void processLargeImage_thread (Image &image,
const Steiner* subTreeRoot,
const VectorPtr<Tree::TreeNode> possibleBoundary) // needs a copy
const VectorPtr<Tree::TreeNode> possibleBoundary, // needs a copy
const VectorOwn<Change>* changes)
{
image. processLarge (subTreeRoot, possibleBoundary);
image. processLarge (subTreeRoot, possibleBoundary, changes);
}

}



void DistTree::optimizeLargeSubgraphs ()
void DistTree::optimizeLargeSubgraphs (const VectorOwn<Change>* changes)
{
ASSERT (threads_max);

Expand All @@ -7116,7 +7198,10 @@ void DistTree::optimizeLargeSubgraphs ()

if (! largeParts)
{
optimizeSmallSubgraphs (areaRadius_std);
if (changes)
applyChanges (*changes, true);
else
optimizeSmallSubgraphs (areaRadius_std);
return;
}

Expand Down Expand Up @@ -7196,7 +7281,10 @@ void DistTree::optimizeLargeSubgraphs ()
}
if (cuts. empty ())
{
optimizeSmallSubgraphs (areaRadius_std);
if (changes)
applyChanges (*changes, true);
else
optimizeSmallSubgraphs (areaRadius_std);
return;
}
ASSERT (boundary. empty ());
Expand Down Expand Up @@ -7234,15 +7322,15 @@ void DistTree::optimizeLargeSubgraphs ()
images << image;
ASSERT (cut->isTransient ());
if (th. get ())
*th << thread (processLargeImage_thread, ref (*image), cut, possibleBoundary);
*th << thread (processLargeImage_thread, ref (*image), cut, possibleBoundary, changes);
// Use functional ??
else
image->processLarge (cut, possibleBoundary);
image->processLarge (cut, possibleBoundary, changes);
possibleBoundary << cut;
}
// Top subgraph
prog ();
mainImage. processLarge (nullptr, possibleBoundary);
mainImage. processLarge (nullptr, possibleBoundary, changes);
}
// Image::apply() can be done by Threads if it is done in the order of cuts and for sibling subtrees ??!
{
Expand All @@ -7259,7 +7347,9 @@ void DistTree::optimizeLargeSubgraphs ()
}
}
}

if (failed)
throw runtime_error (FUNC "OUT OF MEMORY"); // if threads_num > 1 then try thread-free execution ??

// DTNode::stable
for (DiGraph::Node* node : nodes)
static_cast <DTNode*> (node) -> stable = true;
Expand All @@ -7283,16 +7373,11 @@ void DistTree::optimizeLargeSubgraphs ()
qc ();
qcPaths ();

if (failed)
{ ERROR_MSG ("OUT OF MEMORY"); } // if threads_num > 1 then try thread-free execution ??
else
{
if (! subDepth)
cerr << "Optimizing cut nodes ..." << endl;
optimizeSmallSubgraphsUnstable (areaRadius_std); // PAR
qc ();
qcPredictionAbsCriterion ();
}
if (! subDepth)
cerr << "Optimizing cut nodes ..." << endl;
optimizeSmallSubgraphsUnstable (areaRadius_std); // PAR
qc ();
qcPredictionAbsCriterion ();
}


Expand Down
21 changes: 12 additions & 9 deletions phylogeny/distTree.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -869,8 +869,8 @@ struct Change : Root
&& ! to_arg->inDiscernible ()
&& from_arg->getParent ()
&& ! to_arg->descendantOf (from_arg)
&& ! (from_arg->getParent() == to_arg->getParent() && from_arg->getParent() -> arcs [false]. size () <= 2)
&& ! (from_arg->getParent() == to_arg && from_arg->getParent() -> arcs [false]. size () <= 2);
&& ! (from_arg->getParent () == to_arg->getParent() && from_arg->getParent () -> arcs [false]. size () <= 2)
&& ! (from_arg->getParent () == to_arg && from_arg->getParent () -> arcs [false]. size () <= 2);
}
~Change ()
{
Expand Down Expand Up @@ -1048,7 +1048,6 @@ struct Image : Nocopy
// In subgraph.tree
// May be delete'd
DistTree* tree {nullptr};
// = &subgraph.tree
// nullptr <=> bad_alloc
DiGraph::Node2Node new2old;
// Initially: newLeaves2boundary
Expand All @@ -1065,12 +1064,16 @@ struct Image : Nocopy
// Invokes: tree->{optimizeLenArc(),optimizeLenNode(),optimizeWholeIter() or optimizeSmallSubgraphs()}
// Time: ~ O(|area| (log(|area|) log^2(n) + |area|) + Time(optimizeWholeIter(|area|)))
void processLarge (const Steiner* subTreeRoot,
const VectorPtr<Tree::TreeNode> &possibleBoundary);
const VectorPtr<Tree::TreeNode> &possibleBoundary,
const VectorOwn<Change>* changes);
// Time: ~ O(|area| log(|area|) log^2(n) + Time(optimizeSmallSubgraphs(|area|)))
bool apply ();
// Return: false <=> bad_alloc
// Output: DTNode::stable = true
// Time: ~ O(|area| log(|area|) log^2(n))
const DTNode* getOld2new (const DTNode* old,
const DiGraph::Node2Node &old2new,
Tree::LcaBuffer &buf) const;
};


Expand Down Expand Up @@ -1426,10 +1429,10 @@ struct DistTree : Tree
void optimize3 ();
// Optimal solution, does not depend on Obj::mult
// Requires: 3 leaves
bool optimizeReinsert ();
void optimizeReinsert ();
// Re-inserts subtrees with small DTNode::pathDissimNums.size()
// Return: false <=> finished
// Invokes: NewLeaf(DTNode*), Change, applyChanges(), Threads
// Time: O((p + n log^2 n + |changes| p/n log n) log n)
void optimizeWholeIter (uint iter_max,
const string &output_tree);
// Input: iter_max: 0 <=> infinity
Expand All @@ -1448,7 +1451,7 @@ struct DistTree : Tree
// Time: O(min(n,2^areaRadius_std) log^4(n))
bool applyChanges (const VectorOwn<Change> &changes,
bool byNewLeaf);
// Return: false <=> finished
// Return: false <=> no commits
// Input: changes: !byNewLeaf <=> Change::apply()/restore() was done
// Update: topology, changes (sort by Change::improvement descending)
// Output: DTNode::stable
Expand All @@ -1458,8 +1461,8 @@ struct DistTree : Tree
// Update: bestChange: positive(improvement)
// Invokes: Change::{apply(),restore()}
public:
void optimizeLargeSubgraphs ();
// Invokes: optimizeSmallSubgraphs(), Threads
void optimizeLargeSubgraphs (const VectorOwn<Change>* changes);
// Invokes: optimizeSmallSubgraphs() or applyChanges(*changes), Threads
// Time: ~ O(threads_max n log^3(n))

private:
Expand Down
4 changes: 2 additions & 2 deletions phylogeny/makeDistTree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ struct ThisApplication : Application
//addFlag ("whole", "Optimize whole topology, otherwise by subgraphs of radius " + toString (areaRadius_std));
addKey ("subgraph_iter_max", "Max. number of iterations of subgraph optimizations over the whole tree; 0 - unlimited", "0");
addFlag ("skip_len", "Skip length-only optimization");
addFlag ("reinsert", "Reinsert subtrees before subgraph optimizations");
addFlag ("reinsert", "Reinsert subtrees before subgraph optimizations; works faster if hybrid objects have been removed");
//addFlag ("reinsert_orig_weights", "Use original weights in the reinsert optimization");
addFlag ("skip_topology", "Skip topology optimization");
addFlag ("new_only", "Optimize only new objects in an incremental tree, implies not -optimize");
Expand Down Expand Up @@ -599,7 +599,7 @@ struct ThisApplication : Application
const Real absCriterion_old = tree->absCriterion;
ASSERT (absCriterion_old < inf);
tree->optimizeDissimCoeffs ();
tree->optimizeLargeSubgraphs ();
tree->optimizeLargeSubgraphs (nullptr);
if (hybridF. get ())
deleteHybrids ( *tree
, iter + 1 == iter_max
Expand Down
5 changes: 4 additions & 1 deletion version.inc
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#define VERSION "1.8.1"
#define VERSION "1.9.2"


// 1.9.2 05/18/2021 optimizeReinsert() invokes optimizeLargeSubgraphs(&changes)
// 1.9.1 05/15/2021 inc/threads
// distTree_inc_new.sh -reinsert does not process inc/new/
// 1.8.1 05/11/2021 inc/dissim_full
// 1.7.3 04/23/2021 combine_dissims.cpp: weighted combination of all dissimilarities
// str2real() bug in reading nan's
Expand Down

0 comments on commit 438255a

Please sign in to comment.