Example #1
0
def test_BDD():
    L = [
        ([(1, 1), (2, 2)], [0, 2], 10000),
        ([(1, 1), (2, -2)], [0, 2], 10000),
        ([(1, 1), (2, 2), (3, 3)], [3, 3], 10000),
        ([(0, 1), (1, 2), (2, 3), (0, 4), (1, 5), (0, 6), (1, 7)], [0, 2], 10000),
        ([(1, 15), (2, 16), (3, 17), (4, 18), (5, 6), (5, 19), (6, 7),
          (6, 20), (7, 8), (7, 21), (7, 28), (8, 9), (8, 22), (8, 29), (8, 41), (9,
          10), (9, 23), (9, 30), (9, 42), (10, 1), (10, 11), (10, 24), (10, 31),
          (10, 34), (10, 37), (10, 43), (10, 46), (10, 50), (11, 2), (11, 12), (11,
          25), (11, 32), (11, 35), (11, 38), (11, 44), (11, 47), (11, 51), (12, 3),
          (12, 4), (12, 5), (12, 13), (12, 14), (12, 26), (12, 27), (12, 33), (12,
          36), (12, 39), (12, 40), (12, 45), (12, 48), (12, 49), (12, 52), (12, 53),
          (12, 54)], [192, 204], 100),
        ([(0, 12), (0, 14), (0, 22), (0, 59), (0, 60), (0, 68), (0,
        102), (0, 105), (0, 164), (0, 176), (0, 178), (0, 180), (0, 182), (1,
            9), (1, 13), (1, 21), (1, 58), (1, 67), (1, 101), (1, 104), (1,
                163), (1, 175), (1, 177), (1, 179), (1, 181), (2, 6), (2, 20),
        (2, 57), (2, 66), (2, 100), (2, 103), (2, 162), (2, 174), (3, 11), (3,
            19), (3, 56), (3, 65), (3, 99), (3, 161), (3, 173), (4, 8), (4,
                18), (4, 55), (4, 64), (4, 98), (4, 160), (4, 172), (5, 5),
        (5, 17), (5, 54), (5, 63), (5, 97), (5, 159), (5, 171), (6, 10), (6,
            16), (6, 52), (6, 62), (6, 96), (6, 158), (6, 170), (7, 7), (7,
                15), (7, 50), (7, 61), (7, 95), (7, 157), (7, 169), (8, 4),
        (8, 48), (8, 94), (8, 156), (8, 168), (9, 3), (9, 46), (9, 93), (9,
            155), (9, 167), (10, 2), (10, 53), (10, 92), (10, 154), (10, 166),
        (11, 1), (11, 51), (11, 91), (11, 152), (11, 165), (12, 49), (12, 90),
        (12, 150), (13, 47), (13, 89), (13, 148), (14, 45), (14, 88), (14,
            146), (15, 39), (15, 87), (15, 144), (16, 38), (16, 86), (16,
                142), (17, 37), (17, 85), (17, 140), (18, 44), (18, 84), (18,
                    138), (19, 43), (19, 83), (19, 153), (20, 42), (20, 82),
        (20, 151), (21, 41), (21, 81), (21, 149), (22, 40), (22, 80), (22,
            147), (23, 36), (23, 79), (23, 145), (24, 32), (24, 70), (24,
                143), (25, 35), (25, 78), (25, 141), (26, 34), (26, 77), (26,
                    139), (27, 31), (27, 76), (27, 137), (28, 30), (28, 75),
        (28, 136), (29, 33), (29, 74), (29, 135), (30, 29), (30, 73), (30,
            134), (31, 28), (31, 72), (31, 133), (32, 27), (32, 71), (32,
                132), (33, 25), (33, 69), (33, 131), (34, 24), (34, 130), (35,
                    26), (35, 129), (36, 23), (36, 128), (37, 125), (38, 124),
        (39, 123), (40, 122), (41, 121), (42, 120), (43, 119), (44, 118), (45,
            117), (46, 116), (47, 115), (48, 114), (49, 113), (50, 127), (51,
                126), (52, 112), (53, 111), (54, 110), (55, 109), (56, 108),
        (57, 107), (58, 106)], [21, 40], 1000)
        ]
    for eq, rhs, max_iter in L:
        N = max(a for c,a in eq)
        C = Clauses(N)
        Cneg = Clauses(N)
        Cpos = Clauses(N)
        x = C.build_BDD(eq, rhs[0], rhs[1])
        xneg = Cneg.build_BDD(eq, rhs[0], rhs[1], polarity=False)
        xpos = Cpos.build_BDD(eq, rhs[0], rhs[1], polarity=True)
        for _, sol in zip(range(max_iter), my_itersolve([(x,)] + C.clauses)):
            assert rhs[0] <= evaluate_eq(eq,sol) <= rhs[1]
        for _, sol in zip(range(max_iter), my_itersolve([(xpos,)] + Cpos.clauses)):
            assert rhs[0] <= evaluate_eq(eq,sol) <= rhs[1]
        for _, sol in zip(range(max_iter), my_itersolve([(-x,)] + C.clauses)):
            assert not(rhs[0] <= evaluate_eq(eq,sol) <= rhs[1])
        for _, sol in zip(range(max_iter), my_itersolve([(-xneg,)] + Cneg.clauses)):
            assert not(rhs[0] <= evaluate_eq(eq,sol) <= rhs[1])
Example #2
0
    def solve(self, specs, installed=[], update_deps=True, returnall=False,
              guess=True, minimal_hint=False):
        try:
            stdoutlog.info("Solving package specifications: ")
            res = self.explicit(specs)
            if res is not None:
                return res

            # If update_deps=True, set the target package in MatchSpec so that
            # the solver can minimize the version change. If update_deps=False,
            # fix the version and build so that no change is possible.
            len0 = len(specs)
            specs = list(map(MatchSpec, specs))
            snames = {s.name for s in specs}
            for pkg in installed:
                name, version, build = self.package_triple(pkg)
                if pkg not in self.index:
                    self.index[pkg] = {
                        'name':name, 'version':version,
                        'build':build, 'build_number':0
                    }
                    self.groups.setdefault(name,[]).append(pkg)
                if name in snames:
                    continue
                if update_deps:
                    spec = MatchSpec(name, target=pkg)
                else:
                    spec = MatchSpec('%s %s %s'%(name,version,build))
                specs.append(spec)
                snames.add(spec)
            dotlog.debug("Solving for %s" % specs)

            try:
                dists, specs = self.get_dists(specs)
            except NoPackagesFound:
                raise

            # Clear out our caches to reduce memory usage before the solve
            self.find_matches_.clear()
            self.ms_depends_.clear()

            # Check if satisfiable
            dotlog.debug('Checking satisfiability')
            groups = build_groups(dists)
            m, v, w = self.build_vw(groups)
            clauses = list(self.gen_clauses(v, groups, specs))
            solution = sat(clauses)
            if not solution:
                if guess:
                    if minimal_hint:
                        stderrlog.info('\nError: Unsatisfiable package '
                            'specifications.\nGenerating minimal hint: \n')
                        sys.exit(self.minimal_unsatisfiable_subset(clauses, v, w))
                    else:
                        stderrlog.info('\nError: Unsatisfiable package '
                            'specifications.\nGenerating hint: \n')
                        sys.exit(self.guess_bad_solve(specs))
                raise RuntimeError("Unsatisfiable package specifications")

            eq_version = self.generate_version_eq(v, groups, specs[:len0], majoronly=True)
            clauses, solution, obj1 = optimize(eq_version, clauses, solution)
            dotlog.debug('Requested version metric: %d'%obj1)

            eq_features, n0 = self.generate_feature_eq(v, groups, specs)
            clauses, solution, obj = optimize(eq_features, clauses, solution)
            dotlog.debug('Feature count metric: %d'%(obj+n0))

            eq_version2 = self.generate_version_eq(v, groups, specs, majoronly=False)
            clauses, solution, obj2 = optimize(eq_version2, clauses, solution)
            dotlog.debug('Total version metric: %d'%obj2)

            eq_version3 = self.generate_package_count(v, groups, specs)
            clauses, solution, obj3 = optimize(eq_version3, clauses, solution)
            dotlog.debug('Weak dependency metric: %d'%obj3)

            dotlog.debug('Final metrics: (%d,%d,%d,%d)'%(
                (n0+evaluate_eq(eq_features,solution),
                    evaluate_eq(eq_version,solution),
                    evaluate_eq(eq_version2,solution),
                    evaluate_eq(eq_version3,solution))))

            solution = [s for s in solution if 0 < s <= m]

            dotlog.debug('Looking for alternate solutions')
            solutions = [solution]
            nsol = 1
            while True:
                nclause = tuple(-q for q in solution if 0 < q <= m)
                clauses.append(nclause)
                solution = sat(clauses)
                if solution is None:
                    break
                solution = [s for s in solution if 0 < s <= m]
                nsol += 1
                if nsol > 10:
                    dotlog.debug('Too many solutions; terminating')
                    break
                solutions.append(solution)

            psolutions = [set(w[lit] for lit in sol if 0 < lit <= m and '@' not in w[lit]) for sol in solutions]
            if nsol > 1:
                stdoutlog.info(
                    '\nWarning: %s possible package resolutions (only showing differing packages):\n' %
                    ('>10' if nsol > 10 else nsol))
                common  = set.intersection(*psolutions)
                for sol in psolutions:
                    stdoutlog.info('\t%s,\n' % sorted(sol - common))

            if obj1 > 0 or obj2 > 0 or (obj3 > 0 and any(i>1 for i,_ in eq_version3)):
                log.debug("Older versions in the solution(s):")
                for sol in solutions:
                    v = ([(i, w[j]) for i, j in eq_version if j in sol] +
                         [(i, w[j]) for i, j in eq_version2 if j in sol] +
                         [(i, w[j]) for i, j in eq_version3 if i>1 and j in sol])
                    log.debug(v)
            stdoutlog.info('\n')
            return list(map(sorted, psolutions)) if returnall else sorted(psolutions[0])
        except:
            stdoutlog.info('\n')
            raise
Example #3
0
def my_EVAL(eq, sol):
    # evaluate_eq doesn't handle True/False entries
    return evaluate_eq(eq, sol) + sum(c for c, a in eq if a is True)
Example #4
0
    def solve(self, specs, installed=[], update_deps=True, returnall=False,
              guess=True, minimal_hint=False):
        try:
            stdoutlog.info("Solving package specifications: ")
            res = self.explicit(specs)
            if res is not None:
                return res

            # If update_deps=True, set the target package in MatchSpec so that
            # the solver can minimize the version change. If update_deps=False,
            # fix the version and build so that no change is possible.
            len0 = len(specs)
            specs = list(map(MatchSpec, specs))
            snames = {s.name for s in specs}
            for pkg in installed:
                name, version, build = self.package_triple(pkg)
                if pkg not in self.index:
                    self.index[pkg] = {
                        'name':name, 'version':version,
                        'build':build, 'build_number':0
                    }
                    self.groups.setdefault(name,[]).append(pkg)
                if name in snames:
                    continue
                if update_deps:
                    spec = MatchSpec(name, target=pkg)
                else:
                    spec = MatchSpec('%s %s %s'%(name,version,build))
                specs.append(spec)
                snames.add(spec)
            dotlog.debug("Solving for %s" % specs)

            try:
                dists, specs = self.get_dists(specs)
            except NoPackagesFound:
                raise

            # Clear out our caches to reduce memory usage before the solve
            self.find_matches_.clear()
            self.ms_depends_.clear()

            # Check if satisfiable
            dotlog.debug('Checking satisfiability')
            groups = build_groups(dists)
            m, v, w = self.build_vw(groups)
            clauses = list(self.gen_clauses(v, groups, specs))
            solution = sat(clauses)
            if not solution:
                if guess:
                    if minimal_hint:
                        stderrlog.info('\nError: Unsatisfiable package '
                            'specifications.\nGenerating minimal hint: \n')
                        sys.exit(self.minimal_unsatisfiable_subset(clauses, v, w))
                    else:
                        stderrlog.info('\nError: Unsatisfiable package '
                            'specifications.\nGenerating hint: \n')
                        sys.exit(self.guess_bad_solve(specs))
                raise RuntimeError("Unsatisfiable package specifications")

            eq_version = self.generate_version_eq(v, groups, specs[:len0], majoronly=True)
            clauses, solution, obj1 = optimize(eq_version, clauses, solution)
            dotlog.debug('Requested version metric: %d'%obj1)

            eq_features, n0 = self.generate_feature_eq(v, groups, specs)
            clauses, solution, obj = optimize(eq_features, clauses, solution)
            dotlog.debug('Feature count metric: %d'%(obj+n0))

            eq_version2 = self.generate_version_eq(v, groups, specs, majoronly=False)
            clauses, solution, obj2 = optimize(eq_version2, clauses, solution)
            dotlog.debug('Total version metric: %d'%obj2)

            eq_version3 = self.generate_package_count(v, groups, specs)
            clauses, solution, obj3 = optimize(eq_version3, clauses, solution)
            dotlog.debug('Weak dependency metric: %d'%obj3)

            dotlog.debug('Final metrics: (%d,%d,%d,%d)'%(
                (n0+evaluate_eq(eq_features,solution),
                    evaluate_eq(eq_version,solution),
                    evaluate_eq(eq_version2,solution),
                    evaluate_eq(eq_version3,solution))))

            solution = [s for s in solution if 0 < s <= m]

            dotlog.debug('Looking for alternate solutions')
            solutions = [solution]
            nsol = 1
            while True:
                nclause = tuple(-q for q in solution if 0 < q <= m)
                clauses.append(nclause)
                solution = sat(clauses)
                if solution is None:
                    break
                solution = [s for s in solution if 0 < s <= m]
                nsol += 1
                if nsol > 10:
                    dotlog.debug('Too many solutions; terminating')
                    break
                solutions.append(solution)

            psolutions = [set(w[lit] for lit in sol if 0 < lit <= m and '@' not in w[lit]) for sol in solutions]
            if nsol > 1:
                stdoutlog.info(
                    '\nWarning: %s possible package resolutions (only showing differing packages):\n' %
                    ('>10' if nsol > 10 else nsol))
                common  = set.intersection(*psolutions)
                for sol in psolutions:
                    stdoutlog.info('\t%s,\n' % sorted(sol - common))

            if obj1 > 0 or obj2 > 0 or (obj3 > 0 and any(i>1 for i,_ in eq_version3)):
                log.debug("Older versions in the solution(s):")
                for sol in solutions:
                    v = ([(i, w[j]) for i, j in eq_version if j in sol] +
                         [(i, w[j]) for i, j in eq_version2 if j in sol] +
                         [(i, w[j]) for i, j in eq_version3 if i>1 and j in sol])
                    log.debug(v)
            stdoutlog.info('\n')
            return list(map(sorted, psolutions)) if returnall else sorted(psolutions[0])
        except:
            stdoutlog.info('\n')
            raise
Example #5
0
def my_EVAL(eq, sol):
    # evaluate_eq doesn't handle True/False entries
    return evaluate_eq(eq, sol) + sum(c for c, a in eq if a is True)
Example #6
0
def test_BDD():
    L = [
        ([(1, 1), (2, 2)], [0, 2], 10000), ([(1, 1), (2, -2)], [0, 2], 10000),
        ([(1, 1), (2, 2), (3, 3)], [3, 3], 10000),
        ([(0, 1), (1, 2), (2, 3), (0, 4), (1, 5), (0, 6), (1, 7)], [0,
                                                                    2], 10000),
        ([(1, 15), (2, 16), (3, 17), (4, 18), (5, 6), (5, 19), (6, 7), (6, 20),
          (7, 8), (7, 21), (7, 28), (8, 9), (8, 22), (8, 29), (8, 41), (9, 10),
          (9, 23), (9, 30), (9, 42), (10, 1), (10, 11), (10, 24), (10, 31),
          (10, 34), (10, 37), (10, 43), (10, 46), (10, 50), (11, 2), (11, 12),
          (11, 25), (11, 32), (11, 35), (11, 38), (11, 44), (11, 47), (11, 51),
          (12, 3), (12, 4), (12, 5), (12, 13), (12, 14), (12, 26), (12, 27),
          (12, 33), (12, 36), (12, 39), (12, 40), (12, 45), (12, 48), (12, 49),
          (12, 52), (12, 53), (12, 54)], [192, 204], 100),
        ([(0, 12), (0, 14), (0, 22), (0, 59), (0, 60), (0, 68), (0, 102),
          (0, 105), (0, 164), (0, 176), (0, 178), (0, 180), (0, 182), (1, 9),
          (1, 13), (1, 21), (1, 58), (1, 67), (1, 101), (1, 104), (1, 163),
          (1, 175), (1, 177), (1, 179), (1, 181), (2, 6), (2, 20), (2, 57),
          (2, 66), (2, 100), (2, 103), (2, 162), (2, 174), (3, 11), (3, 19),
          (3, 56), (3, 65), (3, 99), (3, 161), (3, 173), (4, 8), (4, 18),
          (4, 55), (4, 64), (4, 98), (4, 160), (4, 172), (5, 5), (5, 17),
          (5, 54), (5, 63), (5, 97), (5, 159), (5, 171), (6, 10), (6, 16),
          (6, 52), (6, 62), (6, 96), (6, 158), (6, 170), (7, 7), (7, 15),
          (7, 50), (7, 61), (7, 95), (7, 157), (7, 169), (8, 4), (8, 48),
          (8, 94), (8, 156), (8, 168), (9, 3), (9, 46), (9, 93), (9, 155),
          (9, 167), (10, 2), (10, 53), (10, 92), (10, 154), (10, 166), (11, 1),
          (11, 51), (11, 91), (11, 152), (11, 165), (12, 49), (12, 90),
          (12, 150), (13, 47), (13, 89), (13, 148), (14, 45), (14, 88),
          (14, 146), (15, 39), (15, 87), (15, 144), (16, 38), (16, 86),
          (16, 142), (17, 37), (17, 85), (17, 140), (18, 44), (18, 84),
          (18, 138), (19, 43), (19, 83), (19, 153), (20, 42), (20, 82),
          (20, 151), (21, 41), (21, 81), (21, 149), (22, 40), (22, 80),
          (22, 147), (23, 36), (23, 79), (23, 145), (24, 32), (24, 70),
          (24, 143), (25, 35), (25, 78), (25, 141), (26, 34), (26, 77),
          (26, 139), (27, 31), (27, 76), (27, 137), (28, 30), (28, 75),
          (28, 136), (29, 33), (29, 74), (29, 135), (30, 29), (30, 73),
          (30, 134), (31, 28), (31, 72), (31, 133), (32, 27), (32, 71),
          (32, 132), (33, 25), (33, 69), (33, 131), (34, 24), (34, 130),
          (35, 26), (35, 129), (36, 23), (36, 128), (37, 125), (38, 124),
          (39, 123), (40, 122), (41, 121), (42, 120), (43, 119), (44, 118),
          (45, 117), (46, 116), (47, 115), (48, 114), (49, 113), (50, 127),
          (51, 126), (52, 112), (53, 111), (54, 110), (55, 109), (56, 108),
          (57, 107), (58, 106)], [21, 40], 1000)
    ]
    for eq, rhs, max_iter in L:
        N = max(a for c, a in eq)
        C = Clauses(N)
        Cneg = Clauses(N)
        Cpos = Clauses(N)
        x = C.build_BDD(eq, rhs[0], rhs[1])
        xneg = Cneg.build_BDD(eq, rhs[0], rhs[1], polarity=False)
        xpos = Cpos.build_BDD(eq, rhs[0], rhs[1], polarity=True)
        for _, sol in zip(range(max_iter), my_itersolve([(x, )] + C.clauses)):
            assert rhs[0] <= evaluate_eq(eq, sol) <= rhs[1]
        for _, sol in zip(range(max_iter),
                          my_itersolve([(xpos, )] + Cpos.clauses)):
            assert rhs[0] <= evaluate_eq(eq, sol) <= rhs[1]
        for _, sol in zip(range(max_iter), my_itersolve([(-x, )] + C.clauses)):
            assert not (rhs[0] <= evaluate_eq(eq, sol) <= rhs[1])
        for _, sol in zip(range(max_iter),
                          my_itersolve([(-xneg, )] + Cneg.clauses)):
            assert not (rhs[0] <= evaluate_eq(eq, sol) <= rhs[1])