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])
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
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)
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])