dep_selector 1.0.3 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 233352ee3f369d535368e3765da67ed3821279aa
4
- data.tar.gz: e56f298dd78e1fb13281ee40e69f95e9e78f3c05
3
+ metadata.gz: 2c2b77c7e96ffbe77d1c03fc080b94d221b6daeb
4
+ data.tar.gz: 96c96d4e9b17c475c538651ab186f2bd6a200a12
5
5
  SHA512:
6
- metadata.gz: c3f8401ecf5158eb61d7920896346303971df4221c8a9de6690cb06b22a2b47d03447c16bd40992a89d348878ee6f85ff435f27fd1999eb08e4304e1e7e18209
7
- data.tar.gz: 4854b4a1c16d8a41bd4e5d53fb093ec0ed6ab5cd55ee009a256c5a87162d5661a5e7a9a8074132b68dd9eff287ab24c3ebd45afc068e2e88fd368df89ade533f
6
+ metadata.gz: 160d6cebdbe86f5a0e44434a8c87293b1e680940420bcced8caa12059461d21991b3be15b1f59bbcd95d238b511d6484452c181ce6ba88dce7b7c97f83eb4382
7
+ data.tar.gz: b6f36b5d3aba61b1c9a7ef755ced8d92fc61be0a911a3f4dc8487fb896740624910463c2f21681bd2bb73ae145e28c7293e69fd0de3aa8ce4240c5dde614d8b0
@@ -100,9 +100,10 @@ void VersionProblemPool::DeleteAll()
100
100
 
101
101
  int VersionProblem::instance_counter = 0;
102
102
 
103
- VersionProblem::VersionProblem(int packageCount, bool dumpStats, bool debug, const char * logId)
103
+ VersionProblem::VersionProblem(int packageCount, bool dumpStats, bool debug, const char * logId,
104
+ unsigned long int _timeout)
104
105
  : size(packageCount), version_constraint_count(0), dump_stats(dumpStats),
105
- debugLogging(debug),
106
+ debugLogging(debug), timeout(_timeout), solutionState(SOLUTION_STATE_UNSTARTED),
106
107
  finalized(false), cur_package(0), package_versions(*this, packageCount),
107
108
  disabled_package_variables(*this, packageCount, 0, 1), total_disabled(*this, 0, packageCount*MAX_TRUST_LEVEL),
108
109
  total_required_disabled(*this, 0, packageCount), total_induced_disabled(*this, 0, packageCount),
@@ -128,16 +129,16 @@ VersionProblem::VersionProblem(int packageCount, bool dumpStats, bool debug, con
128
129
  if (debugLogging) {
129
130
  DEBUG_STREAM << std::endl;
130
131
  DEBUG_STREAM << debugPrefix << "Creating VersionProblem inst# " << instance_id << " with " << packageCount << " packages, "
131
- << dumpStats << " stats, " << debug << " debug" << std::endl;
132
+ << dumpStats << " stats, " << debug << " debug " << timeout << " timeout" << std::endl;
132
133
  DEBUG_STREAM.flush();
133
134
  }
134
135
  }
135
136
 
136
137
  VersionProblem::VersionProblem(bool share, VersionProblem & s)
137
138
  : Space(share, s),
138
- size(s.size), version_constraint_count(s.version_constraint_count),
139
- dump_stats(s.dump_stats),
140
- debugLogging(s.debugLogging),
139
+ size(s.size), version_constraint_count(s.version_constraint_count),
140
+ dump_stats(s.dump_stats),
141
+ debugLogging(s.debugLogging), timeout(s.timeout), solutionState(s.solutionState),
141
142
  finalized(s.finalized), cur_package(s.cur_package),
142
143
  disabled_package_variables(s.disabled_package_variables), total_disabled(s.total_disabled),
143
144
  total_required_disabled(s.total_required_disabled), total_induced_disabled(s.total_induced_disabled),
@@ -204,10 +205,10 @@ VersionProblem::AddPackage(int minVersion, int maxVersion, int currentVersion)
204
205
  }
205
206
 
206
207
  if (debugLogging) {
207
- sprintf(outputBuffer, "%s DepSelector inst# %d - Adding package id %d/%d: min = %d, max = %d, current version %d",
208
+ sprintf(outputBuffer, "%sDepSelector inst# %d - Adding package id %d/%d: min = %d, max = %d, current version %d\n",
208
209
  debugPrefix, instance_id, cur_package, size, minVersion, maxVersion, currentVersion);
209
210
  DEBUG_STREAM << outputBuffer;
210
- // DEBUG_STREAM << debugPrefix << "DepSelector inst# " << instance_id
211
+ // DEBUG_STREAM << debugPrefix << "DepSelector inst# " << instance_id
211
212
  // << " - Adding package id " << cur_package << '/' << size << ": min = " << minVersion << ", max = " << maxVersion << ", current version " << currentVersion << std::endl;
212
213
  DEBUG_STREAM.flush();
213
214
  }
@@ -232,10 +233,10 @@ VersionProblem::AddVersionConstraint(int packageId, int version,
232
233
 
233
234
  version_constraint_count++;
234
235
  if (debugLogging) {
235
- sprintf(outputBuffer, "%sDepSelector inst# %d - Adding VC for %d @ %d depPkg %d [%d, %d]",
236
+ sprintf(outputBuffer, "%sDepSelector inst# %d - Adding VC for %d @ %d depPkg %d [%d, %d]\n",
236
237
  debugPrefix, instance_id, packageId, version, dependentPackageId, minDependentVersion, maxDependentVersion);
237
238
  DEBUG_STREAM << outputBuffer;
238
- // DEBUG_STREAM << debugPrefix << "DepSelector inst# " << instance_id
239
+ // DEBUG_STREAM << debugPrefix << "DepSelector inst# " << instance_id
239
240
  // << " - Adding VC for " << packageId << " @ " << version << " depPkg " << dependentPackageId
240
241
  // << " [ " << minDependentVersion << ", " << maxDependentVersion << " ]" << std::endl;
241
242
  DEBUG_STREAM.flush();
@@ -270,7 +271,7 @@ VersionProblem::MarkPackageSuspicious(int packageId)
270
271
  sprintf(outputBuffer, "%sDepSelector inst# %d - Marking Package Suspicious %d",
271
272
  debugPrefix, instance_id, packageId);
272
273
  DEBUG_STREAM << outputBuffer;
273
- // DEBUG_STREAM << debugPrefix << "DepSelector inst# " << instance_id
274
+ // DEBUG_STREAM << debugPrefix << "DepSelector inst# " << instance_id
274
275
  // << " - Marking Package Suspicious " << packageId << std::endl;
275
276
  DEBUG_STREAM.flush();
276
277
  }
@@ -283,7 +284,7 @@ VersionProblem::MarkPackageRequired(int packageId)
283
284
 
284
285
  if (debugLogging) {
285
286
  sprintf(outputBuffer, "%sDepSelector inst# %d - Marking Package Required %d", debugPrefix, instance_id, packageId);
286
- DEBUG_STREAM << debugPrefix << "DepSelector inst# " << instance_id
287
+ DEBUG_STREAM << debugPrefix << "DepSelector inst# " << instance_id
287
288
  << " - Marking Package Required " << packageId << std::endl;
288
289
  DEBUG_STREAM.flush();
289
290
  }
@@ -297,7 +298,7 @@ VersionProblem::MarkPackagePreferredToBeAtLatest(int packageId, int weight)
297
298
  if (debugLogging) {
298
299
  sprintf(outputBuffer, "%sDepSelector inst# %d - Marking Package Preferred Latest %d weight %d",
299
300
  debugPrefix, instance_id, packageId, weight);
300
- DEBUG_STREAM << debugPrefix << "DepSelector inst# " << instance_id
301
+ DEBUG_STREAM << debugPrefix << "DepSelector inst# " << instance_id
301
302
  << " - Marking Package Preferred Latest " << packageId << " weight " << weight << std::endl;
302
303
  DEBUG_STREAM.flush();
303
304
  }
@@ -310,6 +311,7 @@ void VersionProblem::Finalize()
310
311
  DEBUG_STREAM.flush();
311
312
  }
312
313
  finalized = true;
314
+ solutionState = SOLUTION_STATE_FINALIZED;
313
315
 
314
316
  // Setup constraint for cost
315
317
  // We wish to minimize the total number of disabled packages, by priority ranks
@@ -381,11 +383,51 @@ void VersionProblem::Finalize()
381
383
  }
382
384
 
383
385
  #ifdef USE_DUMB_BRANCHING
386
+ AddBrancherPoor(DEBUG_STREAM);
387
+ #else // USE_DUMB_BRANCHING
388
+ AddBrancherV2(DEBUG_STREAM);
389
+ #endif // USE_DUMB_BRANCHING
390
+
391
+ if (debugLogging) {
392
+ DEBUG_STREAM << debugPrefix << "Finalization Done" << std::endl;
393
+ DEBUG_STREAM.flush();
394
+ }
395
+ }
396
+
397
+ // GECODE VERSION NUMBER is 100000 * x + 100 * y + z for version x.y.z
398
+ #ifndef GECODE_VERSION_3
399
+ #undef INT_VAL_MAX
400
+ #undef INT_VAL_MIN
401
+ #undef INT_VAR_DEGREE_MAX
402
+ #undef INT_VAR_DEGREE_MIN
403
+ #undef INT_VAR_SIZE_MAX
404
+ #undef INT_VAR_SIZE_MIN
405
+
406
+ #define INT_VAL_MAX INT_VAL_MAX()
407
+ #define INT_VAL_MIN INT_VAL_MIN()
408
+ #define INT_VAR_DEGREE_MAX INT_VAR_DEGREE_MAX()
409
+ #define INT_VAR_DEGREE_MIN INT_VAR_DEGREE_MINX()
410
+ #define INT_VAR_SIZE_MAX INT_VAR_SIZE_MAX()
411
+ #define INT_VAR_SIZE_MIN INT_VAR_SIZE_MIN()
412
+
413
+ #endif
414
+
415
+ // Define various branchers:
416
+ //
417
+ // The ordering here is important; we make variable choices in
418
+ // order that the branchings are listed, and a bad variable choice
419
+ // can be orders of magnitude slower to solve. In general we want to
420
+ // choose variables that generate lots of propagations; each variable
421
+ // choice can involve a backtrack, so the bias is towards maximizing the
422
+ // bindings induced by a choice.
423
+
424
+ // This branching starts as far as possible from the solution, in order to exercise the optimization functions.
425
+ void VersionProblem::AddBrancherPoor(std::ostream & o) {
384
426
  if (debugLogging) {
385
427
  DEBUG_STREAM << debugPrefix << " Adding branching (POOR)" << std::endl;
386
428
  DEBUG_STREAM.flush();
387
429
  }
388
- // This branching starts as far as possible from the solution, in order to exercise the optimization functions.
430
+
389
431
  branch(*this, disabled_package_variables, INT_VAR_SIZE_MIN, INT_VAL_MAX);
390
432
  branch(*this, package_versions, INT_VAR_SIZE_MIN, INT_VAL_MIN);
391
433
  branch(*this, total_required_disabled, INT_VAL_MAX);
@@ -395,12 +437,19 @@ void VersionProblem::Finalize()
395
437
  branch(*this, at_latest, INT_VAR_SIZE_MIN, INT_VAL_MIN);
396
438
  branch(*this, total_preferred_at_latest, INT_VAL_MIN);
397
439
  branch(*this, total_not_preferred_at_latest, INT_VAL_MIN);
398
- #else // USE_DUMB_BRANCHING
440
+ }
441
+
442
+ // This is the 'classic' brancher that's been used since 2012. Has
443
+ // some pathological solves
444
+ void VersionProblem::AddBrancherOriginal(std::ostream & o) {
399
445
  if (debugLogging) {
400
- DEBUG_STREAM << debugPrefix << " Adding branching (BEST)" << std::endl;
446
+ DEBUG_STREAM << debugPrefix << " Adding branching (ORIGINAL)" << std::endl;
401
447
  DEBUG_STREAM.flush();
402
448
  }
403
449
  // This branching is meant to start with most probable solution
450
+ // The ordering here is important; we make variable choices in
451
+ // order that the branchings are listed, and a bad variable choice
452
+ // can be orders of magnitude slower to solve.
404
453
  branch(*this, disabled_package_variables, INT_VAR_SIZE_MIN, INT_VAL_MIN);
405
454
  branch(*this, package_versions, INT_VAR_SIZE_MIN, INT_VAL_MAX);
406
455
  branch(*this, total_required_disabled, INT_VAL_MIN);
@@ -410,12 +459,50 @@ void VersionProblem::Finalize()
410
459
  branch(*this, at_latest, INT_VAR_SIZE_MIN, INT_VAL_MAX);
411
460
  branch(*this, total_preferred_at_latest, INT_VAL_MAX);
412
461
  branch(*this, total_not_preferred_at_latest, INT_VAL_MAX);
413
- #endif // USE_DUMB_BRANCHING
462
+ }
414
463
 
415
- if (debugLogging) {
416
- DEBUG_STREAM << debugPrefix << "Finalization Done" << std::endl;
464
+ // This is the minimal tweak to the 'classic' brancher that avoids the solves.
465
+ void VersionProblem::AddBrancherV2(std::ostream & o) {
466
+ if (debugLogging) {
467
+ DEBUG_STREAM << debugPrefix << " Adding branching (V2)" << std::endl;
417
468
  DEBUG_STREAM.flush();
418
469
  }
470
+ // This branching is meant to start with most probable solution
471
+ // The ordering here is important; we make variable choices in
472
+ // order that the branchings are listed, and a bad variable choice
473
+ // can be orders of magnitude slower to solve.
474
+ branch(*this, disabled_package_variables, INT_VAR_SIZE_MIN, INT_VAL_MIN);
475
+ // Using INT_VAR_SIZE_MIN (what old versions do; can cause 12E3 x slowdown)
476
+ branch(*this, package_versions, INT_VAR_DEGREE_MAX, INT_VAL_MAX);
477
+ branch(*this, total_required_disabled, INT_VAL_MIN);
478
+ branch(*this, total_induced_disabled, INT_VAL_MIN);
479
+ branch(*this, total_suspicious_disabled, INT_VAL_MIN);
480
+ branch(*this, total_disabled, INT_VAL_MIN);
481
+ branch(*this, at_latest, INT_VAR_SIZE_MIN, INT_VAL_MAX);
482
+ branch(*this, total_preferred_at_latest, INT_VAL_MAX);
483
+ branch(*this, total_not_preferred_at_latest, INT_VAL_MAX);
484
+ }
485
+
486
+ // This behaves better on some problems, and worse on others; still
487
+ // figuring out why. Behaves very well on gecode 4.x
488
+ void VersionProblem::AddBrancherAtLatest(std::ostream & o) {
489
+ if (debugLogging) {
490
+ DEBUG_STREAM << debugPrefix << " Adding branching (AtLatest)" << std::endl;
491
+ DEBUG_STREAM.flush();
492
+ }
493
+ // We total preferred at latest at maximum first, to trigger as much
494
+ // propagation as possible, followed by all other packages at
495
+ // latest in order of degree (# of constraints related to this variable)
496
+ //
497
+ branch(*this, package_versions, INT_VAR_DEGREE_MAX, INT_VAL_MAX);
498
+ branch(*this, at_latest, INT_VAR_DEGREE_MAX, INT_VAL_MAX);
499
+ branch(*this, disabled_package_variables, INT_VAR_SIZE_MIN, INT_VAL_MIN);
500
+ branch(*this, total_preferred_at_latest, INT_VAL_MAX);
501
+ branch(*this, total_disabled, INT_VAL_MIN);
502
+ branch(*this, total_required_disabled, INT_VAL_MIN);
503
+ branch(*this, total_induced_disabled, INT_VAL_MIN);
504
+ branch(*this, total_suspicious_disabled, INT_VAL_MIN);
505
+ branch(*this, total_not_preferred_at_latest, INT_VAL_MAX);
419
506
  }
420
507
 
421
508
  ////////////////////////////////////////////////////////////////////////
@@ -490,6 +577,7 @@ void VersionProblem::constrain(const Space & _best_known_solution)
490
577
  IntVarArgs best(5);
491
578
  BuildCostVector(current);
492
579
  best_known_solution.BuildCostVector(best);
580
+ // rel(*this, best, IRT_LE, current);
493
581
  ConstrainVectorLessThanBest(current, best);
494
582
  }
495
583
  #endif // VECTOR_CONSTRAIN
@@ -502,7 +590,34 @@ void VersionProblem::BuildCostVector(IntVarArgs & costVector) const {
502
590
  costVector[4] = total_required_disabled;
503
591
  }
504
592
 
593
+ // We want to sort vectors
594
+ // This constrains current to be less than best by a process analogous to subtraction
595
+ // we compute current - best, pairwise with borrows from less significant elements. We require it to be less than zero by requiring the most
596
+ // significant element to generate a borrow.
597
+ //
598
+ // DEPRECATED; remove once replacement is validated
599
+ void VersionProblem::ConstrainVectorLessThanBest(IntVarArgs & current, IntVarArgs & best) {
600
+ BoolVarArray borrow(*this, current.size()+1, 0, 1);
505
601
 
602
+ // No borrows can happen at the least significant element.
603
+ rel(*this, borrow[0], IRT_EQ, 0);
604
+
605
+ for (int i = 0; i < current.size(); i++) {
606
+ // If best+borrow is greater than current (equivalently current-(best+borrow) is < 0) then a more significant element
607
+ // must have decreased, so we propagate a borrow to the next most significant element.
608
+ int best_val = best[i].val();
609
+ IntVar delta = expr(*this, current[i] - best_val - borrow[i]);
610
+ // (delta < 0) <=> borrow[i+1]
611
+ rel(*this, delta, IRT_LE, 0, borrow[i+1]);
612
+ if (debugLogging) {
613
+ DEBUG_STREAM << debugPrefix << " ConstrainVector: borrow[" << i+1 << "] " << borrow[i+1] << ",\tdelta " << delta << std::endl;
614
+ DEBUG_STREAM << debugPrefix << " ConstrainVector: current[" << i << "] " << current[i] << ",\tbest_val " << best_val << std::endl;
615
+ }
616
+ }
617
+
618
+ // must borrow off past the most significant element.
619
+ rel(*this, borrow[current.size()], IRT_EQ, 1);
620
+ }
506
621
 
507
622
  IntVar * VersionProblem::GetPackageVersionVar(int packageId)
508
623
  {
@@ -546,6 +661,16 @@ int VersionProblem::GetDisabledVariableCount()
546
661
  }
547
662
  }
548
663
 
664
+ void VersionProblem::SetTimeout(unsigned long int _timeout)
665
+ {
666
+ timeout = _timeout;
667
+ }
668
+
669
+ int VersionProblem::GetSolutionState()
670
+ {
671
+ return solutionState;
672
+ }
673
+
549
674
 
550
675
  // Utility
551
676
  void VersionProblem::Print(std::ostream & out)
@@ -580,88 +705,124 @@ bool VersionProblem::CheckPackageId(int id)
580
705
  return (id < size);
581
706
  }
582
707
 
583
- // We want to sort vectors
584
- // This constrains current to be less than best by a process analogous to subtraction
585
- // we compute current - best, pairwise with borrows from less significant elements. We require it to be less than zero by requiring the most
586
- // significant element to generate a borrow.
587
- //
588
- void VersionProblem::ConstrainVectorLessThanBest(IntVarArgs & current, IntVarArgs & best) {
589
- BoolVarArray borrow(*this, current.size()+1, 0, 1);
590
-
591
- // No borrows can happen at the least significant element.
592
- rel(*this, borrow[0], IRT_EQ, 0);
593
-
594
- for (int i = 0; i < current.size(); i++) {
595
- // If best+borrow is greater than current (equivalently current-(best+borrow) is < 0) then a more significant element
596
- // must have decreased, so we propagate a borrow to the next most significant element.
597
- int best_val = best[i].val();
598
- IntVar delta = expr(*this, current[i] - best_val - borrow[i]);
599
- // (delta < 0) <=> borrow[i+1]
600
- rel(*this, delta, IRT_LE, 0, borrow[i+1]);
601
- if (debugLogging) {
602
- DEBUG_STREAM << debugPrefix << " ConstrainVector: borrow[" << i+1 << "] " << borrow[i+1] << ",\tdelta " << delta << std::endl;
603
- DEBUG_STREAM << debugPrefix << " ConstrainVector: current[" << i << "] " << current[i] << ",\tbest_val " << best_val << std::endl;
604
- }
605
- }
606
-
607
- // must borrow off past the most significant element.
608
- rel(*this, borrow[current.size()], IRT_EQ, 1);
609
- }
610
-
611
- VersionProblem * VersionProblem::InnerSolve(VersionProblem * problem, int &itercount)
708
+ int VersionProblem::InnerSolve(VersionProblem * problem, int &itercount, VersionProblem** best_solution)
612
709
  {
613
- Gecode::Support::Timer timer;
614
- timer.start();
615
-
616
710
  #ifdef MEMORY_DEBUG
617
711
  DEBUG_STREAM << "Creating solver" << std::endl << std::flush;
618
712
  #endif
619
- VersionProblem *best_solution = NULL;
620
- Restart<VersionProblem> solver(problem);
713
+ Gecode::Support::Timer timer;
714
+ timer.start();
715
+ *best_solution = NULL;
716
+ int result_code = SOLUTION_STATE_FAILED;
717
+
718
+ // This needs to accumulate over multiple steps.
719
+ Search::TimeStop timeStop(problem->timeout);
720
+ Search::Options options;
721
+ options.stop = &timeStop;
722
+
723
+ #ifdef GECODE_VERSION_3
724
+ // Restart strategy starts branching from scratch. BNB adds the
725
+ // constraint but keeps on going from where it was currently.
726
+ Restart<VersionProblem> solver(problem, options);
727
+ #else
728
+ options.cutoff = Search::Cutoff::geometric();
729
+ RBS<DFS, VersionProblem> solver(problem, options);
730
+ #endif
731
+
621
732
 
622
733
  #ifdef MEMORY_DEBUG
623
734
  DEBUG_STREAM << "Starting Solve" << std::endl << std::flush;
624
735
  #endif
625
736
 
626
- while (VersionProblem *solution = solver.next())
627
- {
737
+ // Iterate over solutions; each call to solver.next creates a new
738
+ // copy of the problem, and constrains it to be better than the
739
+ // last solution. Null is returned if no solution is found.
740
+ while (VersionProblem *solution = solver.next()) {
741
+
628
742
  #ifdef MEMORY_DEBUG
629
- DEBUG_STREAM << "Solver Next " << solution << std::endl << std::flush;
743
+ DEBUG_STREAM << "Solver Next " << solution << std::endl << std::flush;
630
744
  #endif
631
- if (best_solution != NULL)
632
- {
633
- delete best_solution;
634
- }
635
- best_solution = solution;
636
- ++itercount;
637
- if (problem->debugLogging) {
638
- DEBUG_STREAM << problem->debugPrefix << "Trial Solution #" << itercount << "===============================" << std::endl;
639
- const Search::Statistics & stats = solver.statistics();
640
- DEBUG_STREAM << problem->debugPrefix << "Solver stats: Prop:" << stats.propagate << " Fail:" << stats.fail << " Node:" << stats.node;
641
- DEBUG_STREAM << " Depth:" << stats.depth << " memory:" << stats.memory << std::endl;
642
- solution->Print(DEBUG_STREAM);
643
- }
745
+ delete *best_solution;
746
+ *best_solution = solution;
747
+
748
+ ++itercount;
749
+ const Search::Statistics & stats = solver.statistics();
750
+ DebugLogStep(solution, itercount, stats);
751
+ }
752
+
753
+ // Solve with GIST:
754
+ VersionProblem * last = *best_solution ? *best_solution : problem;
755
+ last->GistSolveStep();
756
+
757
+ // If we fail to find a solution in time we treat it as no
758
+ // solution. We could return a special token to differentiate a
759
+ // timeout, but that could cause problems for the FFI interface.
760
+ if (solver.stopped()) {
761
+ result_code = SOLUTION_STATE_TIMED_OUT;
762
+ if (problem->debugLogging) {
763
+ DEBUG_STREAM << problem->debugPrefix << "Solver FAILED: timed out with timeout set to "
764
+ << problem->timeout << " ms" << std::endl;
765
+ const Search::Statistics & stats = solver.statistics();
766
+ LogStats(DEBUG_STREAM, problem->debugPrefix, stats);
644
767
  }
645
768
 
769
+ } else if (*best_solution) {
770
+ result_code = SOLUTION_STATE_OPTIMAL;
771
+ } else {
772
+ result_code = SOLUTION_STATE_FAILED;
773
+ }
774
+
646
775
  double elapsed_time = timer.stop();
647
776
 
648
777
  if (problem->dump_stats) {
649
- if (problem->debugLogging) std::cerr << problem->debugPrefix;
650
- std::cerr << "dep_selector solve: ";
651
- std::cerr << (best_solution ? "SOLVED" : "FAILED") << " ";
652
- std::cerr << problem->size << " packages, " << problem->version_constraint_count << " constraints, ";
653
- std::cerr << "Time: " << elapsed_time << "ms ";
654
778
  const Search::Statistics & final_stats = solver.statistics();
655
- std::cerr << "Stats: " << itercount << " steps, ";
656
- std::cerr << final_stats.memory << " bytes, ";
657
- std::cerr << final_stats.propagate << " props, " << final_stats.node << " nodes, " << final_stats.depth << " depth ";
658
- std::cerr << std::endl << std::flush;
779
+ DebugLogFinal(problem, itercount, elapsed_time, final_stats, result_code);
659
780
  }
660
781
 
661
- return best_solution;
782
+ return result_code;
662
783
  }
663
784
 
664
- VersionProblem * VersionProblem::Solve(VersionProblem * problem)
785
+ void VersionProblem::GistSolveStep() {
786
+ #ifdef GIST_ENABLED
787
+ VersionProblem * trial = dynamic_cast<VersionProblem*>(this->copy(false));
788
+ trial->constrain(*this);
789
+ Gist::Options options;
790
+ Gist::dfs(trial, options);
791
+ delete trial;
792
+ #endif
793
+ }
794
+
795
+ void VersionProblem::LogStats(std::ostream & o, const char * debugPrefix, const Search::Statistics & stats) {
796
+ o << debugPrefix << "Solver stats: Prop:" << stats.propagate << " Fail:" << stats.fail << " Node:" << stats.node;
797
+ o << " Depth:" << stats.depth;
798
+ #ifdef GECODE_VERSION_3
799
+ o << " memory:" << stats.memory;
800
+ #endif // GECODE_VERSION_3
801
+ o << std::endl;
802
+ }
803
+
804
+ void VersionProblem::DebugLogStep(VersionProblem *problem, int itercount, const Search::Statistics & stats) {
805
+ if (problem->debugLogging) {
806
+ DEBUG_STREAM << problem->debugPrefix << "Trial Solution #" << itercount << "===============================" << std::endl;
807
+ LogStats(DEBUG_STREAM, problem->debugPrefix, stats);
808
+ problem->Print(DEBUG_STREAM);
809
+ }
810
+ }
811
+
812
+ void VersionProblem::DebugLogFinal(VersionProblem *problem, int itercount, double elapsed_time, const Search::Statistics & stats, int solutionState) {
813
+ if (problem->debugLogging) std::cerr << problem->debugPrefix;
814
+ std::cerr << "dep_selector solve: ";
815
+ std::cerr << ((solutionState == SOLUTION_STATE_OPTIMAL) ? "SOLVED" : "FAILED") << " ";
816
+ std::cerr << problem->size << " packages, " << problem->version_constraint_count << " constraints, ";
817
+ std::cerr << "Time: " << elapsed_time << "ms ";
818
+
819
+ std::cerr << "Stats: " << itercount << " steps, ";
820
+ LogStats(std::cerr, (problem->debugLogging ? problem->debugPrefix : ""), stats);
821
+ std::cerr << std::flush;
822
+ }
823
+
824
+
825
+ int VersionProblem::Solve(VersionProblem * problem, VersionProblem ** solution)
665
826
  {
666
827
 
667
828
  problem->Finalize();
@@ -676,19 +837,19 @@ VersionProblem * VersionProblem::Solve(VersionProblem * problem)
676
837
  }
677
838
  int itercount = 0;
678
839
 
679
- VersionProblem *best_solution = InnerSolve(problem, itercount);
840
+ int result_code = InnerSolve(problem, itercount, solution);
680
841
 
681
842
  if (problem->debugLogging) {
682
- DEBUG_STREAM << problem->DebugPrefix() << "Solver Best Solution " << best_solution << std::endl << std::flush;
843
+ DEBUG_STREAM << problem->DebugPrefix() << "Solver Best Solution " << *solution << std::endl << std::flush;
683
844
  }
684
845
 
685
- pool->Delete(best_solution);
846
+ pool->Delete(*solution);
686
847
  problem->pool = 0;
687
848
 
688
849
  pool->DeleteAll();
689
850
  delete pool;
690
851
 
691
- return best_solution;
852
+ return result_code;
692
853
  }
693
854
 
694
855
  //
@@ -21,13 +21,18 @@
21
21
  #define dep_selector_to_gecode_h
22
22
 
23
23
  #include "dep_selector_to_gecode_interface.h"
24
- #include <iostream>
24
+ #include <iostream>
25
25
  #include <vector>
26
26
  #include <set>
27
27
 
28
28
  #include <gecode/driver.hh>
29
29
  #include <gecode/int.hh>
30
30
  #include <gecode/minimodel.hh>
31
+ #include <gecode/support.hh>
32
+
33
+ #if GECODE_VERSION_NUMBER < 400000
34
+ #define GECODE_VERSION_3
35
+ #endif
31
36
 
32
37
  using namespace Gecode;
33
38
 
@@ -39,10 +44,10 @@ using namespace Gecode;
39
44
 
40
45
  // Extend:
41
46
  // Add optimization functions
42
- // Allow non-contiguous ranges in package dependencies.
47
+ // Allow non-contiguous ranges in package dependencies.
43
48
 
44
- // TODO: Add locking
45
- struct VersionProblemPool
49
+ // TODO: Add locking
50
+ struct VersionProblemPool
46
51
  {
47
52
  std::set<VersionProblem *> elems;
48
53
  VersionProblemPool();
@@ -59,15 +64,16 @@ class VersionProblem : public Space
59
64
  {
60
65
  public:
61
66
  static const int UNRESOLVED_VARIABLE;
62
- static const int MIN_TRUST_LEVEL;
67
+ static const int MIN_TRUST_LEVEL;
63
68
  static const int MAX_TRUST_LEVEL;
64
69
  static const int MAX_PREFERRED_WEIGHT;
65
70
 
66
71
  static int instance_counter;
67
72
 
68
- VersionProblem(int packageCount, bool dumpStats = true,
69
- bool debug = false,
70
- const char * logId = 0);
73
+ VersionProblem(int packageCount, bool dumpStats = true,
74
+ bool debug = false,
75
+ const char * logId = 0,
76
+ unsigned long int _timeout = 10000);
71
77
  // Clone constructor; check gecode rules for this...
72
78
  VersionProblem(bool share, VersionProblem & s);
73
79
  virtual ~VersionProblem();
@@ -80,20 +86,20 @@ public:
80
86
  virtual int AddPackage(int minVersion, int maxVersion, int currentVersion);
81
87
 
82
88
  virtual void AddVersionConstraint(int packageId, int version,
83
- int dependentPackageId, int minDependentVersion, int maxDependentVersion);
89
+ int dependentPackageId, int minDependentVersion, int maxDependentVersion);
84
90
 
85
- // We may wish to indicate that some packages have suspicious constraints, and when chosing packages to disable we
86
- // would disable them first.
91
+ // We may wish to indicate that some packages have suspicious constraints, and when chosing packages to disable we
92
+ // would disable them first.
87
93
  void MarkPackageSuspicious(int packageId);
88
94
 
89
- void MarkPackageRequired(int packageId);
95
+ void MarkPackageRequired(int packageId);
90
96
 
91
97
  // Packages marked by this method are preferentially chosen at
92
98
  // latest according to weights
93
99
  void MarkPackagePreferredToBeAtLatest(int packageId, int weight);
94
100
 
95
101
  void Finalize();
96
-
102
+
97
103
  virtual void constrain(const Space & _best_known_solution);
98
104
 
99
105
  int GetPackageVersion(int packageId);
@@ -101,17 +107,27 @@ public:
101
107
  int GetMax(int packageId);
102
108
  int GetMin(int packageId);
103
109
  int GetDisabledVariableCount();
104
-
110
+
111
+ void SetTimeout(unsigned long int _timeout);
112
+ int GetSolutionState();
113
+
105
114
  // Support for gecode
106
115
  virtual Space* copy(bool share);
107
116
 
108
117
  // Debug and utility functions
109
118
  void Print(std::ostream &out);
110
119
  void PrintPackageVar(std::ostream & out, int packageId) ;
120
+ void GistSolveStep();
121
+
111
122
  const char * DebugPrefix() const { return debugPrefix; }
112
123
 
113
- static VersionProblem *InnerSolve(VersionProblem * problem, int & itercount);
114
- static VersionProblem *Solve(VersionProblem *problem);
124
+ static int InnerSolve(VersionProblem * problem, int & itercount, VersionProblem** solution);
125
+
126
+ static void DebugLogStep(VersionProblem *problem, int itercount, const Search::Statistics & stats);
127
+ static void LogStats(std::ostream & o, const char * debugPrefix, const Search::Statistics & stats);
128
+ static void DebugLogFinal(VersionProblem *problem, int itercount, double elapsed_time, const Search::Statistics & stats, int solutionState);
129
+
130
+ static int Solve(VersionProblem *problem, VersionProblem**solution);
115
131
 
116
132
  protected:
117
133
  int instance_id;
@@ -122,6 +138,9 @@ public:
122
138
  bool debugLogging;
123
139
  char debugPrefix[DEBUG_PREFIX_LENGTH];
124
140
  char outputBuffer[1024];
141
+ unsigned long int timeout;
142
+ int solutionState;
143
+
125
144
  bool finalized;
126
145
 
127
146
  BoolVarArgs version_flags;
@@ -147,19 +166,16 @@ public:
147
166
  void AddPackagesPreferredToBeAtLatestObjectiveFunction(const VersionProblem & best_known_solution);
148
167
  void ConstrainVectorLessThanBest(IntVarArgs & current, IntVarArgs & best);
149
168
  void BuildCostVector(IntVarArgs & costVector) const;
150
-
169
+
170
+ void AddBrancherPoor(std::ostream & o);
171
+ void AddBrancherOriginal(std::ostream & o);
172
+ void AddBrancherV2(std::ostream & o);
173
+ void AddBrancherAtLatest(std::ostream & o);
174
+
151
175
  friend class VersionProblemPool;
152
176
  };
153
177
 
154
178
  template<class T> void PrintVarAligned(const char * message, T & var);
155
179
  template<class S, class T> void PrintVarAligned(const char * message, S & var1, T & var2);
156
180
 
157
- class Solver {
158
- public:
159
- Solver(VersionProblem *s);
160
- VersionProblem GetNextSolution();
161
- private:
162
- Restart<VersionProblem> solver;
163
- };
164
-
165
181
  #endif // dep_selector_to_gecode_h
@@ -30,9 +30,10 @@
30
30
 
31
31
  // FFI friendly
32
32
  VersionProblem * VersionProblemCreate(int packageCount, bool dump_stats,
33
- bool debug, const char * logId)
33
+ bool debug, const char * logId,
34
+ unsigned long int _timeout)
34
35
  {
35
- return new VersionProblem(packageCount, dump_stats, debug, logId);
36
+ return new VersionProblem(packageCount, dump_stats, debug, logId, _timeout);
36
37
  }
37
38
 
38
39
  void VersionProblemDestroy(VersionProblem * p)
@@ -40,12 +41,12 @@ void VersionProblemDestroy(VersionProblem * p)
40
41
  delete p;
41
42
  }
42
43
 
43
- int VersionProblemSize(VersionProblem *p)
44
+ int VersionProblemSize(VersionProblem *p)
44
45
  {
45
46
  return p->Size();
46
47
  }
47
48
 
48
- int VersionProblemPackageCount(VersionProblem *p)
49
+ int VersionProblemPackageCount(VersionProblem *p)
49
50
  {
50
51
  return p->PackageCount();
51
52
  }
@@ -58,7 +59,7 @@ void VersionProblemDump(VersionProblem *p)
58
59
  std::cout.flush();
59
60
  }
60
61
 
61
- void VersionProblemPrintPackageVar(VersionProblem *p, int packageId)
62
+ void VersionProblemPrintPackageVar(VersionProblem *p, int packageId)
62
63
  {
63
64
  p->PrintPackageVar(std::cout, packageId);
64
65
  std::cout.flush();
@@ -68,16 +69,16 @@ void VersionProblemPrintPackageVar(VersionProblem *p, int packageId)
68
69
  int AddPackage(VersionProblem *problem, int min, int max, int currentVersion) {
69
70
  return problem->AddPackage(min,max,currentVersion);
70
71
  }
71
- // Add constraint for package pkg @ version,
72
+ // Add constraint for package pkg @ version,
72
73
  // that dependentPackage is at version [minDependentVersion,maxDependentVersion]
73
74
  // Returns false if system becomes insoluble.
74
75
  void AddVersionConstraint(VersionProblem *problem, int packageId, int version,
75
- int dependentPackageId, int minDependentVersion, int maxDependentVersion)
76
+ int dependentPackageId, int minDependentVersion, int maxDependentVersion)
76
77
  {
77
78
  return problem->AddVersionConstraint(packageId, version, dependentPackageId, minDependentVersion, maxDependentVersion);
78
79
  }
79
80
 
80
- void MarkPackageSuspicious(VersionProblem *problem, int packageId)
81
+ void MarkPackageSuspicious(VersionProblem *problem, int packageId)
81
82
  {
82
83
  return problem->MarkPackageSuspicious(packageId);
83
84
  }
@@ -117,7 +118,16 @@ int GetDisabledVariableCount(VersionProblem *problem)
117
118
  return problem->GetDisabledVariableCount();
118
119
  }
119
120
 
121
+ void SetTimeout(VersionProblem *problem, unsigned long int timeout)
122
+ {
123
+ problem->SetTimeout(timeout);
124
+ }
125
+
126
+ int GetSolutionState(VersionProblem * problem)
127
+ {
128
+ return problem->GetSolutionState();
129
+ }
120
130
 
121
- VersionProblem * Solve(VersionProblem * problem) {
122
- return VersionProblem::Solve(problem);
131
+ int Solve(VersionProblem * problem, VersionProblem ** solution) {
132
+ return VersionProblem::Solve(problem, solution);
123
133
  }
@@ -25,6 +25,15 @@
25
25
  extern "C" {
26
26
  #endif // __cplusplus
27
27
 
28
+ #define SOLUTION_STATE_FAILED 0
29
+ #define SOLUTION_STATE_UNSTARTED 1
30
+ #define SOLUTION_STATE_FINALIZED 2
31
+ #define SOLUTION_STATE_SOLVED 3
32
+ #define SOLUTION_STATE_TIMED_OUT 4
33
+ #define SOLUTION_STATE_OPTIMAL 5
34
+
35
+
36
+
28
37
  #ifdef __cplusplus
29
38
  class VersionProblem;
30
39
  #else
@@ -32,7 +41,8 @@ extern "C" {
32
41
  #endif // __cplusplus
33
42
 
34
43
  VersionProblem * VersionProblemCreate(int packageCount, bool dumpStats,
35
- bool debug, const char * logId);
44
+ bool debug, const char * logId,
45
+ unsigned long int timeout);
36
46
  void VersionProblemDestroy(VersionProblem * vp);
37
47
 
38
48
 
@@ -41,11 +51,11 @@ extern "C" {
41
51
 
42
52
  // Return ID #
43
53
  int AddPackage(VersionProblem *problem, int min, int max, int currentVersion);
44
- // Add constraint for package pkg @ version,
54
+ // Add constraint for package pkg @ version,
45
55
  // that dependentPackage is at version [minDependentVersion,maxDependentVersion]
46
56
  // Returns false if system becomes insoluble.
47
57
  void AddVersionConstraint(VersionProblem *problem, int packageId, int version,
48
- int dependentPackageId, int minDependentVersion, int maxDependentVersion);
58
+ int dependentPackageId, int minDependentVersion, int maxDependentVersion);
49
59
 
50
60
  void MarkPackageSuspicious(VersionProblem *problem, int packageId);
51
61
  void MarkPackageRequired(VersionProblem *problem, int packageId);
@@ -59,10 +69,13 @@ extern "C" {
59
69
 
60
70
  int GetDisabledVariableCount(VersionProblem *problem);
61
71
 
72
+ void SetTimeout(VersionProblem *problem, unsigned long int timeout);
73
+ int GetSolutionState(VersionProblem *problem);
74
+
62
75
  void VersionProblemDump(VersionProblem * problem);
63
76
  void VersionProblemPrintPackageVar(VersionProblem * problem, int packageId);
64
77
 
65
- VersionProblem * Solve(VersionProblem * problem);
78
+ int Solve(VersionProblem * problem, VersionProblem** solution);
66
79
 
67
80
  #ifdef __cplusplus
68
81
  }
data/lib/dep_selector.rb CHANGED
@@ -17,6 +17,7 @@
17
17
  # limitations under the License.
18
18
  #
19
19
 
20
+ require 'dep_selector/debug.rb'
20
21
  require 'dep_selector/dep_selector_version'
21
22
 
22
23
  require 'dep_selector/selector'
@@ -0,0 +1,29 @@
1
+ #
2
+ # Author:: Salim Alam (<salam@chef.io>)
3
+ # Copyright:: Copyright (c) 2016 Chef, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'logger'
20
+
21
+ module DepSelector
22
+ class Debug
23
+ class << self
24
+ def log
25
+ @logger ||= Logger.new(STDOUT)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -38,9 +38,9 @@ module Dep_gecode
38
38
 
39
39
  ffi_lib path
40
40
 
41
- # VersionProblem * VersionProblemCreate(int packageCount, bool dumpStats,
42
- # bool debug, const char * log_id);
43
- attach_function :VersionProblemCreate, [:int, :bool, :bool, :string], :pointer
41
+ # VersionProblem * VersionProblemCreate(int packageCount, bool dumpStats,
42
+ # bool debug, const char * log_id, unsigned long int _timeout);
43
+ attach_function :VersionProblemCreate, [:int, :bool, :bool, :string, :ulong], :pointer
44
44
 
45
45
  # void VersionProblemDestroy(VersionProblem * vp);
46
46
  attach_function :VersionProblemDestroy, [:pointer], :void
@@ -48,7 +48,7 @@ module Dep_gecode
48
48
  # int AddPackage(VersionProblem *problem, int min, int max, int currentVersion);
49
49
  attach_function :AddPackage, [:pointer, :int, :int, :int], :int
50
50
 
51
- # int VersionProblemSize(VersionProblem *p);
51
+ # int VersionProblemSize(VersionProblem *p);
52
52
  attach_function :VersionProblemSize, [:pointer], :int
53
53
 
54
54
  # void MarkPackagePreferredToBeAtLatest(VersionProblem *problem, int packageId, int weight);
@@ -62,7 +62,7 @@ module Dep_gecode
62
62
  attach_function :AddVersionConstraint, [:pointer, :int, :int, :int, :int, :int], :void
63
63
 
64
64
  # VersionProblem * Solve(VersionProblem * problem);
65
- attach_function :Solve, [:pointer], :pointer
65
+ attach_function :Solve, [:pointer, :pointer], :int
66
66
 
67
67
  # int GetDisabledVariableCount(VersionProblem *problem);
68
68
  attach_function :GetDisabledVariableCount, [:pointer], :int
@@ -84,6 +84,9 @@ module Dep_gecode
84
84
 
85
85
  # int GetPackageMin(VersionProblem *problem, int packageId);
86
86
  attach_function :GetPackageMin, [:pointer, :int], :int
87
- end
87
+
88
+ # void SetTimeout(VersionProblem * problem, unsigned long int);
89
+ attach_function :SetTimeout, [:pointer, :ulong], :void
88
90
 
89
91
 
92
+ end
@@ -1,3 +1,3 @@
1
1
  module DepSelector
2
- VERSION = "1.0.3"
2
+ VERSION = "1.0.4"
3
3
  end
@@ -60,11 +60,17 @@ module DepSelector
60
60
  packages.map{ |name, pkg| pkg }
61
61
  end
62
62
 
63
+ logId = SecureRandom.uuid
63
64
  debugFlag = DebugOptionFile && File::exists?(DebugOptionFile)
65
+ Debug.log.level = Logger::INFO unless debugFlag
66
+ Debug.log.formatter = proc do |severity, datetime, progname, msg|
67
+ "#{logId}: #{msg}\n"
68
+ end
69
+
64
70
  # In addition to all the packages that the user specified,
65
71
  # there is a "ghost" package that contains the solution
66
72
  # constraints. See Selector#solve for more information.
67
- @gecode_wrapper = GecodeWrapper.new(packages_in_solve.size + 1, debugFlag)
73
+ @gecode_wrapper = GecodeWrapper.new(packages_in_solve.size + 1, logId, debugFlag)
68
74
  packages_in_solve.each{ |pkg| pkg.generate_gecode_wrapper_constraints }
69
75
  end
70
76
  end
@@ -37,17 +37,27 @@ module DepSelector
37
37
 
38
38
  attr_reader :gecode_problem
39
39
  attr_reader :debug_logs_on
40
+ attr_reader :log_id
41
+
40
42
  DontCareConstraint = -1
41
43
  NoMatchConstraint = -2
42
44
 
45
+ # from dep_selector_to_gecode_interface.h
46
+ SolutionStateUnstarted = 1
47
+ SolutionStateFinalized = 2
48
+ SolutionStateSolved = 3
49
+ SolutionStateTimedOut = 4
50
+ SolutionStateOptimal = 5
51
+
43
52
  # This insures that we properly deallocate the c++ class at the heart of dep_gecode.
44
53
  # modeled after http://www.mikeperham.com/2010/02/24/the-trouble-with-ruby-finalizers/
45
- def initialize(problem_or_package_count, debug=false)
54
+ def initialize(problem_or_package_count, logId, debug=false, timeout = 10000)
46
55
  if (problem_or_package_count.is_a?(Numeric))
47
- logId = SecureRandom.uuid
48
56
  dump_statistics = DepSelector.dump_statistics || debug
57
+ @log_id = logId
49
58
  @debug_logs_on = debug
50
- @gecode_problem = Dep_gecode.VersionProblemCreate(problem_or_package_count, dump_statistics, debug, logId)
59
+ @timeout = timeout
60
+ @gecode_problem = Dep_gecode.VersionProblemCreate(problem_or_package_count, dump_statistics, debug, logId, @timeout)
51
61
  else
52
62
  @gecode_problem = problem_or_package_count
53
63
  end
@@ -155,11 +165,28 @@ module DepSelector
155
165
  Dep_gecode.MarkPackagePreferredToBeAtLatest(gecode_problem, package_id, weight);
156
166
  end
157
167
 
168
+ def set_timeout(timeout)
169
+ raise "Gecode internal failure (set_timeout)" if gecode_problem.nil?
170
+ Dep_gecode.SetTimeout(gecode_problem, timeout)
171
+ end
172
+
173
+ def get_solution_state()
174
+ raise "Gecode internal failure (get_solution_state)" if gecode_problem.nil?
175
+ Dep_gecode.GetSolutionState(gecode_problem);
176
+ end
177
+
158
178
  def solve()
159
179
  raise "Gecode internal failure (solve)" if gecode_problem.nil?
160
- solution = GecodeWrapper.new(Dep_gecode.Solve(gecode_problem), debug_logs_on)
180
+
181
+ solutionPtr = FFI::MemoryPointer.new :pointer
182
+ resultCode = Dep_gecode.Solve(gecode_problem, solutionPtr)
183
+ solutionRaw = solutionPtr.get_pointer(0)
184
+
185
+ solution = GecodeWrapper.new(solutionRaw, log_id, debug_logs_on, @timeout)
186
+
161
187
  raise "Gecode internal failure (no solution found)" if (solution.nil?)
162
188
 
189
+ raise Exceptions::TimeBoundExceeded.new() if resultCode == SolutionStateTimedOut
163
190
  raise Exceptions::NoSolutionFound.new(solution) if solution.package_disabled_count > 0
164
191
  solution
165
192
  end
@@ -37,7 +37,14 @@ module DepSelector
37
37
 
38
38
  # Note: only invoke this method after all PackageVersions have been added
39
39
  def densely_packed_versions
40
- @densely_packed_versions ||= DenselyPackedSet.new(versions.map{|pkg_version| pkg_version.version})
40
+ if @densely_packed_versions.nil?
41
+ @densely_packed_versions = DenselyPackedSet.new(versions.map{|pkg_version| pkg_version.version})
42
+ Debug.log.debug { "Package Versions for '#{@name}' :" }
43
+ versions.each do |v|
44
+ Debug.log.debug { " #{v.to_s(true)}" }
45
+ end
46
+ end
47
+ @densely_packed_versions
41
48
  end
42
49
 
43
50
  # Given a version, this method returns the corresonding
@@ -91,7 +98,11 @@ module DepSelector
91
98
  # invalid portion of the state space instead of naively limiting
92
99
  # it for the purposes of having failure count heuristics?
93
100
  max = densely_packed_versions.range.max || -1
94
- @gecode_package_id ||= dependency_graph.gecode_wrapper.add_package(-1, max, 0)
101
+ if @gecode_package_id.nil?
102
+ @gecode_package_id = dependency_graph.gecode_wrapper.add_package(-1, max, 0)
103
+ Debug.log.debug { "Adding Package '#{@name}' PackageId: #{@gecode_package_id}" }
104
+ end
105
+ @gecode_package_id
95
106
  end
96
107
 
97
108
  def generate_gecode_wrapper_constraints
@@ -67,11 +67,9 @@ module DepSelector
67
67
  packages_to_include_in_solve = trim_unreachable_packages(dep_graph, solution_constraints)
68
68
 
69
69
  begin
70
- Timeout::timeout(@time_bound, Exceptions::TimeBoundExceeded) do
71
- # first, try to solve the whole set of constraints
72
- solve(dep_graph.clone, solution_constraints, valid_packages, packages_to_include_in_solve)
73
- end
74
- rescue Exceptions::NoSolutionFound
70
+ # first, try to solve the whole set of constraints
71
+ solve(dep_graph.clone, solution_constraints, valid_packages, packages_to_include_in_solve)
72
+ rescue Exceptions::NoSolutionFound, Exceptions::TimeBoundExceededNoSolution
75
73
  # since we're here, solving the whole system failed, so add
76
74
  # the solution_constraints one-by-one and try to solve in
77
75
  # order to find the constraint that breaks the system in order
@@ -148,6 +146,7 @@ module DepSelector
148
146
  process_soln_constraints(workspace, solution_constraints, valid_packages)
149
147
 
150
148
  # solve and trim the solution down to only the
149
+ workspace.gecode_wrapper.set_timeout(@time_bound * 1000)
151
150
  soln = workspace.gecode_wrapper.solve
152
151
  trim_solution(solution_constraints, soln, workspace)
153
152
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dep_selector
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christopher Walters
@@ -9,76 +9,76 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-04-22 00:00:00.000000000 Z
12
+ date: 2016-08-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ffi
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - ~>
18
+ - - "~>"
19
19
  - !ruby/object:Gem::Version
20
20
  version: '1.9'
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
- - - ~>
25
+ - - "~>"
26
26
  - !ruby/object:Gem::Version
27
27
  version: '1.9'
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: dep-selector-libgecode
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
- - - ~>
32
+ - - "~>"
33
33
  - !ruby/object:Gem::Version
34
34
  version: '1.0'
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
- - - ~>
39
+ - - "~>"
40
40
  - !ruby/object:Gem::Version
41
41
  version: '1.0'
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: rake
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - ~>
46
+ - - "~>"
47
47
  - !ruby/object:Gem::Version
48
48
  version: '10.0'
49
49
  type: :development
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
- - - ~>
53
+ - - "~>"
54
54
  - !ruby/object:Gem::Version
55
55
  version: '10.0'
56
56
  - !ruby/object:Gem::Dependency
57
57
  name: rspec
58
58
  requirement: !ruby/object:Gem::Requirement
59
59
  requirements:
60
- - - ~>
60
+ - - "~>"
61
61
  - !ruby/object:Gem::Version
62
62
  version: '2.14'
63
63
  type: :development
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
- - - ~>
67
+ - - "~>"
68
68
  - !ruby/object:Gem::Version
69
69
  version: '2.14'
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: solve
72
72
  requirement: !ruby/object:Gem::Requirement
73
73
  requirements:
74
- - - ~>
74
+ - - "~>"
75
75
  - !ruby/object:Gem::Version
76
76
  version: '0.8'
77
77
  type: :development
78
78
  prerelease: false
79
79
  version_requirements: !ruby/object:Gem::Requirement
80
80
  requirements:
81
- - - ~>
81
+ - - "~>"
82
82
  - !ruby/object:Gem::Version
83
83
  version: '0.8'
84
84
  description: Given packages, versions, and a dependency graph, find a valid assignment
@@ -90,13 +90,23 @@ extensions:
90
90
  - ext/dep_gecode/extconf.rb
91
91
  extra_rdoc_files: []
92
92
  files:
93
+ - ext/dep_gecode/define_dummy_init.cxx
94
+ - ext/dep_gecode/dep_gecode-all.def
95
+ - ext/dep_gecode/dep_selector_swig.i
96
+ - ext/dep_gecode/dep_selector_to_gecode.cpp
97
+ - ext/dep_gecode/dep_selector_to_gecode.h
98
+ - ext/dep_gecode/dep_selector_to_gecode_interface.cpp
99
+ - ext/dep_gecode/dep_selector_to_gecode_interface.h
100
+ - ext/dep_gecode/extconf.rb
101
+ - lib/dep_selector.rb
102
+ - lib/dep_selector/debug.rb
93
103
  - lib/dep_selector/densely_packed_set.rb
94
104
  - lib/dep_selector/dep_gecode.rb
95
105
  - lib/dep_selector/dep_selector_version.rb
96
106
  - lib/dep_selector/dependency.rb
97
107
  - lib/dep_selector/dependency_graph.rb
98
- - lib/dep_selector/error_reporter/simple_tree_traverser.rb
99
108
  - lib/dep_selector/error_reporter.rb
109
+ - lib/dep_selector/error_reporter/simple_tree_traverser.rb
100
110
  - lib/dep_selector/exceptions.rb
101
111
  - lib/dep_selector/gecode_wrapper.rb
102
112
  - lib/dep_selector/package.rb
@@ -105,15 +115,6 @@ files:
105
115
  - lib/dep_selector/solution_constraint.rb
106
116
  - lib/dep_selector/version.rb
107
117
  - lib/dep_selector/version_constraint.rb
108
- - lib/dep_selector.rb
109
- - ext/dep_gecode/dep_selector_swig.i
110
- - ext/dep_gecode/define_dummy_init.cxx
111
- - ext/dep_gecode/dep_selector_to_gecode.h
112
- - ext/dep_gecode/dep_selector_to_gecode_interface.h
113
- - ext/dep_gecode/dep_selector_to_gecode.cpp
114
- - ext/dep_gecode/dep_selector_to_gecode_interface.cpp
115
- - ext/dep_gecode/extconf.rb
116
- - ext/dep_gecode/dep_gecode-all.def
117
118
  homepage: http://github.com/opscode/dep-selector
118
119
  licenses:
119
120
  - Apache v2
@@ -124,19 +125,19 @@ require_paths:
124
125
  - lib
125
126
  required_ruby_version: !ruby/object:Gem::Requirement
126
127
  requirements:
127
- - - '>='
128
+ - - ">="
128
129
  - !ruby/object:Gem::Version
129
- version: 1.9.2
130
+ version: 2.1.0
130
131
  required_rubygems_version: !ruby/object:Gem::Requirement
131
132
  requirements:
132
- - - '>='
133
+ - - ">="
133
134
  - !ruby/object:Gem::Version
134
135
  version: '0'
135
136
  requirements:
136
137
  - gecode, version 3.5 or greater
137
138
  - g++
138
139
  rubyforge_project:
139
- rubygems_version: 2.0.3
140
+ rubygems_version: 2.6.4
140
141
  signing_key:
141
142
  specification_version: 4
142
143
  summary: Given packages, versions, and a dependency graph, find a valid assignment