def _compute_WMI_PA_no_boolean(self, lab_formula, pa_vars, labels, other_assignments={}): """Finds all the assignments that satisfy the given formula using AllSAT. Args: lab_formula (FNode): The labelled pysmt formula to examine. pa_vars (): labels (dict): The dictionary containing the correlation between each label and their true value. Yields: dict: One of the assignments that satisfies the formula. """ solver = Solver(name="msat", solver_options={"dpll.allsat_minimize_model" : "true"}) converter = solver.converter solver.add_assertion(lab_formula) lra_assignments = [] mathsat.msat_all_sat( solver.msat_env(), [converter.convert(v) for v in pa_vars], lambda model : WMI._callback(model, converter, lra_assignments)) for mu_lra in lra_assignments: assignments = {} for atom, value in WMI._get_assignments(mu_lra).items(): if atom in labels: atom = labels[atom] assignments[atom] = value assignments.update(other_assignments) yield assignments
def _compute_TTAs(self, formula): """Computes the total truth assignments of the given formula. This method first labels the formula and then uses the funtionality of mathsat called AllSAT to retrieve all the total truth assignments. Args: formula (FNode): The pysmt formula to examine. Returns: list: The list of all the total truth assignments. dict: The dictionary containing all the correspondence between the labels and their true value. """ labels = {} expressions = [] allsat_variables = set() # Label LRA atoms with fresh boolean variables labelled_formula, pa_vars, labels = self.label_formula(formula, formula.get_atoms()) # Perform AllSMT on the labelled formula solver = Solver(name="msat") converter = solver.converter solver.add_assertion(labelled_formula) models = [] mathsat.msat_all_sat(solver.msat_env(), [converter.convert(v) for v in pa_vars], lambda model : WMI._callback(model, converter, models)) return models, labels
def _compute_TTAs(self, formula, weights): labels = {} expressions = [] allsat_variables = set() index = 0 # label LRA atoms with fresh boolean variables labelled_formula, pa_vars, labels = WMI.label_formula(formula, formula.get_atoms()) solver = Solver(name="msat") converter = solver.converter solver.add_assertion(labelled_formula) models = [] # perform AllSMT on the labelled formula mathsat.msat_all_sat(solver.msat_env(), [converter.convert(v) for v in pa_vars], lambda model : WMI._callback(model, converter, models)) return models, labels
def callback(model, converter, result): """Callback for msat_all_sat. This function is called by the MathSAT API everytime a new model is found. If the function returns 1, the search continues, otherwise it stops. """ # Elements in model are msat_term . # Converter.back() provides the pySMT representation of a solver term. py_model = [converter.back(v) for v in model] result.append(And(py_model)) return 1 # go on x, y = Symbol("x"), Symbol("y") f = Or(x, y) with Solver(name="msat") as msat: converter = msat.converter # .converter is a property implemented by all solvers msat.add_assertion(f) # This is still at pySMT level result = [] # Directly invoke the mathsat API !!! # The second term is a list of "important variables" mathsat.msat_all_sat(msat.msat_env(), [converter.convert(x)], # Convert the pySMT term into a MathSAT term lambda model : callback(model, converter, result)) print("'exists y . %s' is equivalent to '%s'" %(f, Or(result))) #exists y . (x | y) is equivalent to ((! x) | x)
def all_sat(self, important, callback): self.push() mathsat.msat_all_sat(self.msat_env, [self._var2term(x) for x in important], callback) self.pop()
def _compute_WMI_PA(self, formula, weights): """Computes WMI using the Predicate Abstraction (PA) algorithm. Args: formula (FNode): The formula on whick to compute WMI. weights (Weight): The corresponding weight. Returns: real: The final volume of the integral computed by summing up all the integrals' results. int: The number of problems that have been computed. """ problems = [] boolean_variables = get_boolean_variables(formula) if len(boolean_variables) == 0: # Enumerate partial TA over theory atoms lab_formula, pa_vars, labels = self.label_formula(formula, formula.get_atoms()) # Predicate abstraction on LRA atoms with minimal models for assignments in self._compute_WMI_PA_no_boolean(lab_formula, pa_vars, labels): problem = self._create_problem(assignments, weights) problems.append(problem) else: solver = Solver(name="msat") converter = solver.converter solver.add_assertion(formula) boolean_models = [] # perform AllSAT on the Boolean variables mathsat.msat_all_sat( solver.msat_env(), [converter.convert(v) for v in boolean_variables], lambda model : WMI._callback(model, converter, boolean_models)) logger.debug("n_boolean_models: {}".format(len(boolean_models))) # for each boolean assignment mu^A of F for model in boolean_models: atom_assignments = {} boolean_assignments = WMI._get_assignments(model) atom_assignments.update(boolean_assignments) subs = {k : Bool(v) for k, v in boolean_assignments.items()} f_next = formula # iteratively simplify F[A<-mu^A], getting (possibily part.) mu^LRA while True: f_before = f_next f_next = simplify(substitute(f_before, subs)) lra_assignments, over = WMI._parse_lra_formula(f_next) subs = {k : Bool(v) for k, v in lra_assignments.items()} atom_assignments.update(lra_assignments) if over or lra_assignments == {}: break if not over: # predicate abstraction on LRA atoms with minimal models lab_formula, pa_vars, labels = self.label_formula(f_next, f_next.get_atoms()) expressions = [] for k, v in atom_assignments.items(): if k.is_theory_relation(): if v: expressions.append(k) else: expressions.append(Not(k)) lab_formula = And([lab_formula] + expressions) for assignments in self._compute_WMI_PA_no_boolean(lab_formula, pa_vars, labels, atom_assignments): problem = self._create_problem(assignments, weights) problems.append(problem) else: # integrate over mu^A & mu^LRA problem = self._create_problem(atom_assignments, weights) problems.append(problem) results, cached = self.integrator.integrate_batch(problems, self.cache) volume = fsum(results) return volume, len(problems)-cached, cached
def _compute_WMI_PA(self, formula, weights): latte_problems = [] index = 0 boolean_variables = get_boolean_variables(formula) if len(boolean_variables) == 0: # enumerate partial TA over theory atoms lab_formula, pa_vars, labels = WMI.label_formula(formula, formula.get_atoms()) # predicate abstraction on LRA atoms with minimal models solver = Solver(name="msat", solver_options={"dpll.allsat_minimize_model" : "true"}) converter = solver.converter solver.add_assertion(lab_formula) lra_assignments = [] mathsat.msat_all_sat( solver.msat_env(), [converter.convert(v) for v in pa_vars], lambda model : WMI._callback(model, converter, lra_assignments)) for mu_lra in lra_assignments: assignments = {} for atom, value in WMI._get_assignments(mu_lra).iteritems(): if atom in labels: atom = labels[atom] assignments[atom] = value integrand, polytope = WMI._convert_to_latte( assignments, weights) latte_problems.append((integrand, polytope, index)) index += 1 else: solver = Solver(name="msat") converter = solver.converter solver.add_assertion(formula) boolean_models = [] # perform AllSAT on the Boolean variables mathsat.msat_all_sat( solver.msat_env(), [converter.convert(v) for v in boolean_variables], lambda model : WMI._callback(model, converter, boolean_models)) self.logger.debug("n_boolean_models: {}".format(len(boolean_models))) # for each boolean assignment mu^A of F for model in boolean_models: atom_assignments = {} boolean_assignments = WMI._get_assignments(model) atom_assignments.update(boolean_assignments) subs = {k : Bool(v) for k, v in boolean_assignments.iteritems()} f_next = formula # iteratively simplify F[A<-mu^A], getting (possibily part.) mu^LRA while True: f_before = f_next f_next = simplify(substitute(f_before, subs)) lra_assignments, over = WMI._parse_lra_formula(f_next) subs = {k : Bool(v) for k, v in lra_assignments.iteritems()} atom_assignments.update(lra_assignments) if over or (serialize(f_before) == serialize(f_next)): break if not over: # predicate abstraction on LRA atoms with minimal models lab_formula, pa_vars, labels = WMI.label_formula(f_next, f_next.get_atoms()) expressions = [] for k, v in atom_assignments.iteritems(): if k.is_theory_relation(): if v: expressions.append(k) else: expressions.append(Not(k)) ssformula = And([lab_formula] + expressions) secondstep_solver = Solver(name="msat", solver_options={"dpll.allsat_minimize_model" : "true"}) converter = secondstep_solver.converter secondstep_solver.add_assertion(ssformula) ssmodels = [] mathsat.msat_all_sat( secondstep_solver.msat_env(), [converter.convert(v) for v in pa_vars], lambda model : WMI._callback(model, converter, ssmodels)) for ssmodel in ssmodels: secondstep_assignments = {} for atom, value in WMI._get_assignments(ssmodel).iteritems(): if atom in labels: atom = labels[atom] secondstep_assignments[atom] = value secondstep_assignments.update(atom_assignments) integrand, polytope = WMI._convert_to_latte( secondstep_assignments, weights) latte_problems.append((integrand, polytope, index)) index += 1 else: # integrate over mu^A & mu^LRA integrand, polytope = WMI._convert_to_latte(atom_assignments, weights) latte_problems.append((integrand, polytope, index)) index += 1 formula_volume = self._parallel_volume_computation(latte_problems) return formula_volume, len(latte_problems)