def version_constraints(lo, hi): return set(generate_constraints(eq, m, [lo, hi], alg=alg))
def solve2(self, specs, features, guess=True, alg='sorter', returnall=False): log.debug("Solving for %s" % str(specs)) # First try doing it the "old way", i.e., just look at the most recent # version of each package from the specs. This doesn't handle the more # complicated cases that the pseudo-boolean solver does, but it's also # much faster when it does work. try: dists = self.get_dists(specs, max_only=True) except NoPackagesFound: # Handle packages that are not included because some dependencies # couldn't be found. pass else: v = {} # map fn to variable number w = {} # map variable number to fn i = -1 # in case the loop doesn't run for i, fn in enumerate(sorted(dists)): v[fn] = i + 1 w[i + 1] = fn m = i + 1 dotlog.debug("Solving using max dists only") clauses = self.gen_clauses(v, dists, specs, features) solutions = min_sat(clauses) if len(solutions) == 1: ret = [w[lit] for lit in solutions.pop(0) if 0 < lit] if returnall: return [ret] return ret dists = self.get_dists(specs) v = {} # map fn to variable number w = {} # map variable number to fn i = -1 # in case the loop doesn't run for i, fn in enumerate(sorted(dists)): v[fn] = i + 1 w[i + 1] = fn m = i + 1 clauses = list(self.gen_clauses(v, dists, specs, features)) if not clauses: if returnall: return [[]] return [] eq, max_rhs = self.generate_version_eq(v, dists) # Check the common case first dotlog.debug("Building the constraint with rhs: [0, 0]") constraints = list(generate_constraints(eq, m, [0, 0], alg=alg)) # Only relevant for build_BDD if constraints and constraints[0] == [false]: # XXX: This should *never* happen. build_BDD only returns false # when the linear constraint is unsatisfiable, but any linear # constraint can equal 0, by setting all the variables to 0. solution = [] else: if constraints and constraints[0] == [true]: constraints = [] dotlog.debug("Checking for solutions with rhs: [0, 0]") solution = sat(clauses + constraints) if not solution: # Second common case, check if it's unsatisfiable dotlog.debug("Checking for unsatisfiability") solution = sat(clauses) if not solution: if guess: stderrlog.info('\nError: Unsatisfiable package ' 'specifications.\nGenerating hint: ') sys.exit(self.guess_bad_solve(specs, features)) raise RuntimeError("Unsatisfiable package specifications") def version_constraints(lo, hi): return list(generate_constraints(eq, m, [lo, hi], alg=alg)) log.debug("Bisecting the version constraint") constraints = bisect_constraints(0, max_rhs, clauses, version_constraints) dotlog.debug("Finding the minimal solution") solutions = min_sat(clauses + constraints, N=m+1) assert solutions, (specs, features) if len(solutions) > 1: print('Warning:', len(solutions), "possible package resolutions:") for sol in solutions: print('\t', [w[lit] for lit in sol if 0 < lit <= m]) if returnall: return [[w[lit] for lit in sol if 0 < lit <= m] for sol in solutions] return [w[lit] for lit in solutions.pop(0) if 0 < lit <= m]
def solve2(self, specs, features, guess=True, alg='sorter', returnall=False, minimal_hint=False): log.debug("Solving for %s" % str(specs)) # First try doing it the "old way", i.e., just look at the most recent # version of each package from the specs. This doesn't handle the more # complicated cases that the pseudo-boolean solver does, but it's also # much faster when it does work. try: dists = self.get_dists(specs, max_only=True) except NoPackagesFound: # Handle packages that are not included because some dependencies # couldn't be found. pass else: v = {} # map fn to variable number w = {} # map variable number to fn i = -1 # in case the loop doesn't run for i, fn in enumerate(sorted(dists)): v[fn] = i + 1 w[i + 1] = fn m = i + 1 dotlog.debug("Solving using max dists only") clauses = self.gen_clauses(v, dists, specs, features) solutions = min_sat(clauses) if len(solutions) == 1: ret = [w[lit] for lit in solutions.pop(0) if 0 < lit] if returnall: return [ret] return ret dists = self.get_dists(specs) v = {} # map fn to variable number w = {} # map variable number to fn i = -1 # in case the loop doesn't run for i, fn in enumerate(sorted(dists)): v[fn] = i + 1 w[i + 1] = fn m = i + 1 clauses = list(self.gen_clauses(v, dists, specs, features)) if not clauses: if returnall: return [[]] return [] eq, max_rhs = self.generate_version_eq(v, dists) # Check the common case first dotlog.debug("Building the constraint with rhs: [0, 0]") constraints = list(generate_constraints(eq, m, [0, 0], alg=alg)) # Only relevant for build_BDD if constraints and constraints[0] == [false]: # XXX: This should *never* happen. build_BDD only returns false # when the linear constraint is unsatisfiable, but any linear # constraint can equal 0, by setting all the variables to 0. solution = [] else: if constraints and constraints[0] == [true]: constraints = [] dotlog.debug("Checking for solutions with rhs: [0, 0]") solution = sat(clauses + constraints) if not solution: # Second common case, check if it's unsatisfiable dotlog.debug("Checking for unsatisfiability") solution = sat(clauses) if not solution: if guess: stderrlog.info('\nError: Unsatisfiable package ' 'specifications.\nGenerating hint: ') if minimal_hint: sys.exit( self.minimal_unsatisfiable_subset(clauses, v, w)) else: sys.exit(self.guess_bad_solve(specs, features)) raise RuntimeError("Unsatisfiable package specifications") def version_constraints(lo, hi): return list(generate_constraints(eq, m, [lo, hi], alg=alg)) log.debug("Bisecting the version constraint") constraints = bisect_constraints(0, max_rhs, clauses, version_constraints) dotlog.debug("Finding the minimal solution") solutions = min_sat(clauses + constraints, N=m + 1) assert solutions, (specs, features) if len(solutions) > 1: print('Warning:', len(solutions), "possible package resolutions:") for sol in solutions: print('\t', [w[lit] for lit in sol if 0 < lit <= m]) if returnall: return [[w[lit] for lit in sol if 0 < lit <= m] for sol in solutions] return [w[lit] for lit in solutions.pop(0) if 0 < lit <= m]