class Ilp: """ Attributes and their signification @ http://www.gurobi.com/documentation/8.1/refman/attributes.html#sec:Attributes """ gurobi_log_file = "gurobi.log" vars_attrs = [ "VarName", "VType", "LB", "UB", "Obj", "X", "Xn", "RC", "BarX", "Start", "VarHintVal", "VarHintPri", "BranchPriority", "Partition", "VBasis", "PStart", "IISLB", "IISUB", "PWLObjCvx", "SAObjLow", "SAObjUp", "SALBLow", "SALBUp", "SAUBLow", "SAUBUp", "UnbdRay", ] cstr_attrs = [ "ConstrName", "Sense", "RHS", "Pi", "Slack", "CBasis", "DStart", "Lazy", "IISConstr", "SARHSLow", "SARHSUp", "FarkasDual", ] def __init__(self, variables, model, verbose=True): self.variables = variables self.model = model self.verbose = verbose self.assignment = None def solve(self, variables_path=None, constraints_path=None): open(self.gurobi_log_file, "w").close() self.model.params.Threads = 12 self.model.optimize() self.assignment = Assignment(self.variables) f_vars, f_cstr = None, None if constraints_path is not None: f_cstr = open(constraints_path, "w") f_cstr.write("\t".join(Ilp.cstr_attrs) + "\n") if f_cstr is not None: for constraint in self.model.getConstrs(): for attr in Ilp.cstr_attrs: value = "" try: value = constraint.getAttr(attr) except: pass f_cstr.write(str(value) + "\t") f_cstr.write("\n") f_cstr.close() if variables_path is not None: f_vars = open(variables_path, "w") f_vars.write("\t".join(Ilp.vars_attrs) + "\n") inner_confidence = [] for gurobi_var in self.model.getVars(): if gurobi_var.varName[0] not in "PTRS": continue if gurobi_var.rc == 0: up = min(2, gurobi_var.SAObjUp) low = max(-2, gurobi_var.SAObjLow) inner_confidence.append((gurobi_var.x - .51) * (up - low)) if len(inner_confidence) == 0: a, b = 0, 1 else: a, b = min(inner_confidence), max(inner_confidence) for gurobi_var in self.model.getVars(): if f_vars is not None: for attr in Ilp.vars_attrs: value = "" try: value = gurobi_var.getAttr(attr) except: pass f_vars.write(str(value) + "\t") f_vars.write("\n") letter = gurobi_var.varName[0] if letter not in "PTRS": continue index = int(gurobi_var.varName[2:-1]) confidence = 0 if gurobi_var.rc != 0: confidence = gurobi_var.rc else: confidence = gurobi_var.x + gurobi_var.obj + Parameters.EVIDENCE_OFFSET self.assignment.assign( Variable(index, Dimensions.from_letter(letter)), gurobi_var.x >= .5, confidence, ) if f_vars is not None: f_vars.close() return self.assignment def report(self): with open(self.gurobi_log_file) as file: text = file.read() report = Report() report.add(text) return report
class MaxSat: def __init__(self, variables, clauses, verbose=True): self.verbose = verbose self.variables = variables self.clauses = ClauseSet(variables, clauses) self.assignment = Assignment(variables) self.queue = self.variables[:] self.counts = [dict(), dict()] def update_counts(self, mask=None): clauses = self.clauses.get_units() if mask is not None: clauses = clauses.intersection(mask) for x in self.assignment.get_unassigned(): self.counts[1][x] = 0. self.counts[0][x] = 0. for c in clauses: if x in c.positives: self.counts[1][x] += c.get_weight() if x in c.negatives: self.counts[0][x] += c.get_weight() def update_queue(self): self.queue.sort( key=lambda x: abs(self.counts[1][x] - self.counts[0][x])) def find_safe_var(self): for x in self.assignment.get_unassigned(): for truth_value in [True, False]: if truth_value: units = self.clauses.get_pos_units(x) unsatisfieds = self.clauses.get_neg_unsatisfieds(x) else: units = self.clauses.get_neg_units(x) unsatisfieds = self.clauses.get_pos_unsatisfieds(x) confidence = sum([c.get_weight() for c in units]) - sum( [c.get_weight() for c in unsatisfieds]) if confidence >= 0: return x, truth_value, { True: 1., False: -1. }[truth_value] * confidence return None, None, None def solve(self): self.update_counts() self.update_queue() if self.verbose: bar = ProgressBar(len(self.queue)) print("Starting reasoning...") bar.start() while len(self.queue) > 0: x = self.queue.pop() if self.verbose: bar.increment() self.assignment.assign(x, self.counts[1][x] > self.counts[0][x], self.counts[1][x] - self.counts[0][x]) self.clauses.update(x, self.counts[1][x] > self.counts[0][x]) while True: safe_var, truth_value, confidence = self.find_safe_var() if safe_var is None: break self.assignment.assign(safe_var, truth_value, confidence) self.clauses.update(safe_var, truth_value) self.queue.remove(safe_var) if self.verbose: bar.increment() self.update_counts(self.clauses.get_occurences(x)) self.update_queue() if self.verbose: bar.stop() return self.assignment def report(self): report = Report() unsatisfieds = self.clauses.get_unsatisfieds() n_clauses = len(self.clauses) n_satisfieds = n_clauses - len(unsatisfieds) w_total = sum([c.get_weight() for c in self.clauses]) w_satisfieds = w_total - sum([c.get_weight() for c in unsatisfieds]) report.add_value_ratio("Satisfied weight", w_satisfieds, w_total) report.add_value_ratio("Satisfied clauses", n_satisfieds, n_clauses) return report