dep_selector 1.0.3 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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