Skip to content

Commit b88f3ba

Browse files
committed
Saving enumerated mutation trees in a single file
1 parent 4e2ad11 commit b88f3ba

14 files changed

+376
-259
lines changed

src/enumeratecanonicalclonetrees.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ void EnumerateCanonicalCloneTrees::enumerate(const std::string& outputDirectory,
3737

3838
gm::RootedCladisticNoisySparseEnumeration enumerate(G, limit, -1,
3939
nrThreads,
40-
_F.getNrCharacters(),
40+
1, //_F.getNrCharacters(),
4141
true,
4242
false,
4343
IntSet());

src/enumeratemutationtrees.cpp

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ EnumerateMutationTrees::EnumerateMutationTrees(const FrequencyMatrix& F)
1717
void EnumerateMutationTrees::enumerate(const std::string& outputDirectory,
1818
const int nrThreads,
1919
const int limit,
20+
const int timeLimit,
2021
TreeVector& mutationTrees) const
2122
{
2223
// 1. Construct frequency tensors F_lb and F_ub
@@ -35,15 +36,17 @@ void EnumerateMutationTrees::enumerate(const std::string& outputDirectory,
3536
G.init();
3637
G.setLabels(F_lb);
3738

38-
gm::RootedCladisticNoisyEnumeration enumerate(G, limit, -1,
39+
gm::RootedCladisticNoisyEnumeration enumerate(G, limit, timeLimit,
3940
nrThreads,
40-
_F.getNrCharacters(),
41+
1, //_F.getNrCharacters(),
4142
true,
4243
false,
4344
IntSet());
4445

4546
enumerate.run();
4647

48+
int size = enumerate.objectiveValue();
49+
4750
gm::SolutionSet solutionSet;
4851
enumerate.populateSolutionSet(solutionSet);
4952

@@ -112,7 +115,7 @@ void EnumerateMutationTrees::enumerate(const std::string& outputDirectory,
112115
}
113116
}
114117

115-
std::cerr << "Found " << mutationTrees.size() << " mutation trees." << std::endl;
118+
std::cerr << "Found " << mutationTrees.size() << " mutation trees with " << size << " out of " << _F.getNrCharacters() << " mutations" << std::endl;
116119
}
117120

118121
void EnumerateMutationTrees::getFrequencyTensor(RealTensor& F_lb,
@@ -142,3 +145,63 @@ void EnumerateMutationTrees::getFrequencyTensor(RealTensor& F_lb,
142145
}
143146
}
144147
}
148+
149+
std::ostream& operator<<(std::ostream& out,
150+
const EnumerateMutationTrees::TreeVector& trees)
151+
{
152+
out << trees.size() << " #trees" << std::endl;
153+
int idx = 0;
154+
for (const CloneTree& T : trees)
155+
{
156+
out << lemon::countArcs(T.tree()) << " # edges, tree " << idx + 1 << std::endl;
157+
T.write(out);
158+
++idx;
159+
}
160+
return out;
161+
}
162+
163+
std::istream& operator>>(std::istream& in,
164+
EnumerateMutationTrees::TreeVector& trees)
165+
{
166+
int nrTrees = -1;
167+
168+
std::string line;
169+
getline(in, line);
170+
171+
std::stringstream ss(line);
172+
ss >> nrTrees;
173+
174+
if (nrTrees < 0)
175+
{
176+
throw std::runtime_error("Error: number of trees should be nonnegative");
177+
}
178+
179+
for (int i = 0; i < nrTrees; ++i)
180+
{
181+
int nrEdges = -1;
182+
183+
getline(in, line);
184+
ss.clear();
185+
ss.str(line);
186+
ss >> nrEdges;
187+
188+
if (nrEdges < 0)
189+
{
190+
throw std::runtime_error("Error: number of edges should be nonnegative");
191+
}
192+
193+
ss.clear();
194+
for (int j = 0; j < nrEdges; ++j)
195+
{
196+
getline(in, line);
197+
ss << line;
198+
}
199+
200+
CloneTree T;
201+
T.read(ss);
202+
203+
trees.push_back(T);
204+
}
205+
206+
return in;
207+
}

src/enumeratemutationtrees.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,12 @@ class EnumerateMutationTrees
2828
/// @param outputDirectory Output directory, may be empty
2929
/// @param nrThreads Number of threads to use in the enumeration
3030
/// @param limit Maximum number of trees to enumerate
31+
/// @param timeLimit Time limit for the enumeration
3132
/// @param mutationTrees Vector to store enumerated mutation trees
3233
void enumerate(const std::string& outputDirectory,
3334
const int nrThreads,
3435
const int limit,
36+
const int timeLimit,
3537
TreeVector& mutationTrees) const;
3638

3739
private:
@@ -47,4 +49,7 @@ class EnumerateMutationTrees
4749
const FrequencyMatrix& _F;
4850
};
4951

52+
std::ostream& operator<<(std::ostream& out, const EnumerateMutationTrees::TreeVector& trees);
53+
std::istream& operator>>(std::istream& in, EnumerateMutationTrees::TreeVector& trees);
54+
5055
#endif // ENUMERATEMUTATIONTREES_H

src/generatemutationtreesmain.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@ int main(int argc, char** argv)
2020
bool canonicalCloneTrees = false;
2121
int nrThreads = 1;
2222
int limit = -1;
23+
int timeLimit = -1;
2324

2425
lemon::ArgParser ap(argc, argv);
2526
ap.refOption("o", "Output directory" , outputDirectory);
26-
ap.refOption("l", "Maxim number of mutation trees to enumerate (default: -1, unlimited)" , limit);
27+
ap.refOption("l", "Maximum number of mutation trees to enumerate (default: -1, unlimited)" , limit);
28+
ap.refOption("tl", "Time limit in seconds (default: -1, unlimited)" , timeLimit);
2729
ap.refOption("C", "Output canonical clone trees", canonicalCloneTrees);
2830
ap.refOption("t", "Number of threads (default: 1)", nrThreads);
2931
ap.other("frequencies", "Frequencies");
@@ -73,7 +75,16 @@ int main(int argc, char** argv)
7375
{
7476
EnumerateMutationTrees::TreeVector trees;
7577
EnumerateMutationTrees enumerate(F);
76-
enumerate.enumerate(outputDirectory, nrThreads, limit, trees);
78+
enumerate.enumerate(outputDirectory,
79+
nrThreads,
80+
limit,
81+
timeLimit,
82+
trees);
83+
84+
if (outputDirectory.empty())
85+
{
86+
std::cout << trees;
87+
}
7788
}
7889

7990
return 0;

src/ilpbinarizationsolver.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ void IlpBinarizationSolver::run(const CloneTree& T,
258258
bool outputILP,
259259
bool outputSearchGraph,
260260
int timeLimit,
261-
double UB,
261+
const IntTriple& bounds,
262262
const StringPairList& forcedComigrations)
263263
{
264264
char buf[1024];
@@ -289,7 +289,7 @@ void IlpBinarizationSolver::run(const CloneTree& T,
289289
pattern,
290290
filenameGurobiLog,
291291
forcedComigrations);
292-
solver.init(UB);
292+
solver.init(bounds);
293293

294294
if (outputSearchGraph)
295295
{

src/ilpbinarizationsolver.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ class IlpBinarizationSolver : public IlpSolver
7777
/// @param outputILP Output ILP model
7878
/// @param outputSearchGraph Output search graph
7979
/// @param timeLimit Time limit in seconds
80-
/// @param UB Upper bound on objective value
80+
/// @param bounds Upper bounds on mu, gamma and sigma
8181
/// @param forcedComigrations List of ordered pairs of anatomical sites
8282
/// that must be present
8383
static void run(const CloneTree& T,
@@ -89,7 +89,7 @@ class IlpBinarizationSolver : public IlpSolver
8989
bool outputILP,
9090
bool outputSearchGraph,
9191
int timeLimit,
92-
double UB,
92+
const IntTriple& bounds,
9393
const StringPairList& forcedComigrations);
9494

9595
protected:

src/ilpsolver.cpp

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,14 @@ IlpSolver::IlpSolver(const CloneTree& T,
3636
{
3737
}
3838

39-
void IlpSolver::init(double upperBound)
39+
void IlpSolver::init(const IntTriple& bounds)
4040
{
4141
initIndices();
4242
initVariables();
4343
initConstraints();
4444
initLeafConstraints();
4545
initForcedComigrations();
46-
initObjective(upperBound);
46+
initObjective(bounds);
4747
_model.update();
4848
}
4949

@@ -454,12 +454,12 @@ void IlpSolver::initParallelSingleSourceSeedingConstraints()
454454
}
455455
}
456456

457-
void IlpSolver::initObjective(double upperBound)
457+
void IlpSolver::initObjective(const IntTriple& bounds)
458458
{
459459
const int nrArcs = _indexToArc.size();
460460
const int nrAnatomicalSites = _indexToAnatomicalSite.size();
461461

462-
GRBLinExpr obj, sum_migrations, sum_comigrations;
462+
GRBLinExpr obj, sum_migrations, sum_comigrations, sum_seeding_sites;
463463
// migrations
464464
for (int ij = 0; ij < nrArcs; ++ij)
465465
{
@@ -468,6 +468,11 @@ void IlpSolver::initObjective(double upperBound)
468468
}
469469
_model.addConstr(sum_migrations >= nrAnatomicalSites - 1);
470470

471+
if (bounds.first != -1)
472+
{
473+
_model.addConstr(sum_migrations <= bounds.first);
474+
}
475+
471476
if (_forcedComigrations.empty()
472477
|| _pattern == MigrationGraph::M
473478
|| _pattern == MigrationGraph::R)
@@ -487,19 +492,25 @@ void IlpSolver::initObjective(double upperBound)
487492
_model.addConstr(sum_comigrations >= nrAnatomicalSites - 1);
488493
_model.addConstr(sum_migrations >= sum_comigrations);
489494

495+
if (bounds.second.first != -1)
496+
{
497+
_model.addConstr(sum_comigrations <= bounds.second.first);
498+
}
499+
490500
// seeding sites
491501
{
492502
const double g = (1. / (nrArcs + 1)) * (1. / (nrAnatomicalSites + 1));
493503
for (int s = 0; s < nrAnatomicalSites; ++s)
494504
{
495505
obj += g * _d[s];
506+
sum_seeding_sites += _d[s];
496507
}
497508
}
498-
}
499-
500-
if (upperBound >= 0)
501-
{
502-
_model.addConstr(obj <= upperBound);
509+
510+
if (bounds.second.second != -1)
511+
{
512+
_model.addConstr(sum_seeding_sites <= bounds.second.second);
513+
}
503514
}
504515

505516
_model.setObjective(obj, GRB_MINIMIZE);
@@ -564,7 +575,7 @@ bool IlpSolver::solve(int nrThreads, int timeLimit)
564575
_model.getEnv().set(GRB_IntParam_LogToConsole, 0);
565576
_model.optimize();
566577
int status = _model.get(GRB_IntAttr_Status);
567-
if (status == GRB_OPTIMAL || status == GRB_TIME_LIMIT)
578+
if (status == GRB_OPTIMAL || status == GRB_SUBOPTIMAL)
568579
{
569580
_LB = _model.get(GRB_DoubleAttr_ObjBound);
570581
_UB = _model.get(GRB_DoubleAttr_ObjVal);
@@ -588,6 +599,17 @@ bool IlpSolver::solve(int nrThreads, int timeLimit)
588599
std::cerr << "Model is unbounded" << std::endl;
589600
return false;
590601
}
602+
else if (status == GRB_TIME_LIMIT)
603+
{
604+
_LB = _model.get(GRB_DoubleAttr_ObjBound);
605+
_UB = _model.get(GRB_DoubleAttr_ObjVal);
606+
if (_UB <= lemon::countNodes(_T.tree()) * _T.getNrAnatomicalSites())
607+
{
608+
processSolution();
609+
return true;
610+
}
611+
return false;
612+
}
591613
}
592614
catch (const GRBException& e)
593615
{
@@ -613,7 +635,7 @@ void IlpSolver::run(const CloneTree& T,
613635
bool outputILP,
614636
bool outputSearchGraph,
615637
int timeLimit,
616-
double UB,
638+
const IntTriple& bounds,
617639
const StringPairList& forcedComigrations)
618640
{
619641
char buf[1024];
@@ -642,7 +664,7 @@ void IlpSolver::run(const CloneTree& T,
642664
pattern,
643665
filenameGurobiLog,
644666
forcedComigrations);
645-
solver.init(UB);
667+
solver.init(bounds);
646668

647669
if (!outputDirectory.empty() && outputILP)
648670
{

src/ilpsolver.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ class IlpSolver
5959
}
6060

6161
/// Initialize ILP
62-
virtual void init(double upperBound);
62+
///
63+
/// @param bounds Upper bounds on mu, gamma and sigma
64+
virtual void init(const IntTriple& bounds);
6365

6466
/// Return lower bound
6567
double LB() const
@@ -84,8 +86,7 @@ class IlpSolver
8486
/// @param outputILP Output ILP model
8587
/// @param outputSearchGraph Output search graph
8688
/// @param timeLimit Time limit in seconds
87-
///
88-
/// @param UB Upper bound on objective value
89+
/// @param bounds Upper bounds on mu, gamma and sigma
8990
/// @param forcedComigrations List of ordered pairs of anatomical sites
9091
/// that must be present
9192
static void run(const CloneTree& T,
@@ -97,7 +98,7 @@ class IlpSolver
9798
bool outputILP,
9899
bool outputSearchGraph,
99100
int timeLimit,
100-
double UB,
101+
const IntTriple& bounds,
101102
const StringPairList& forcedComigrations);
102103

103104
protected:
@@ -124,8 +125,8 @@ class IlpSolver
124125

125126
/// Initialize ILP objective
126127
///
127-
/// @param upperBound Upper bound on objective function
128-
virtual void initObjective(double upperBound);
128+
/// @param bounds Upper bounds on mu, gamma and sigma
129+
virtual void initObjective(const IntTriple& bounds);
129130

130131
/// Initialize ILP constraints regarding primary tumor anatomical site
131132
/// (only applicable for PS and S)

0 commit comments

Comments
 (0)