Example #1
0
 def version_constraints(lo, hi):
     return set(generate_constraints(eq, m, [lo, hi], alg=alg))
Example #2
0
    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]
Example #3
0
 def version_constraints(lo, hi):
     return set(generate_constraints(eq, m, [lo, hi], alg=alg))
Example #4
0
    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]