Beispiel #1
0
 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
Beispiel #2
0
 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
Beispiel #3
0
    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
Beispiel #4
0
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)
Beispiel #5
0
 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()
Beispiel #6
0
    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
Beispiel #7
0
    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)