def swizzle_randvars(self, btor: Boolector, ri: RandInfo, start_rs: int, end_rs: int, bound_m: Dict[FieldModel, VariableBoundModel]): # TODO: we must ignore fields that are otherwise being controlled rand_node_l = [] x = start_rs while x < end_rs: # For each random variable, select a partition with it's known # domain and add the corresponding constraint rs = ri.randsets()[x] field_l = rs.fields_l() if len(field_l) == 1: # Go ahead and pick values in the domain, since there # are no other constraints f = field_l[0] e = self.create_single_var_domain_constraint( field_l[0], bound_m[field_l[0]]) if e is not None: n = e.build(btor) rand_node_l.append(n) # btor.Assume(n) else: for f in field_l: if f.is_used_rand and f in bound_m.keys(): f_bound = bound_m[f] if not f_bound.isEmpty(): e = self.create_rand_domain_constraint(f, f_bound) if e is not None: n = e.build(btor) rand_node_l.append(n) # btor.Assume(n) else: # It's always possible that this value is already fixed. # Just ignore. # rand_node_l.append(None) pass x += 1 if len(rand_node_l) > 0: btor.Assume(*rand_node_l) if btor.Sat() != btor.SAT: # Remove any failing assumptions n_failed = 0 for i, n in enumerate(rand_node_l): if n is not None and btor.Failed(n): rand_node_l[i] = None n_failed += 1 # Re-apply the constraints that succeeded btor.Assume(*filter(lambda n: n is not None, rand_node_l)) if btor.Sat() != btor.SAT: raise Exception("failed to add in randomization")
def randomize(self, ri: RandInfo, bound_m: Dict[FieldModel, VariableBoundModel]): """Randomize the variables and constraints in a RandInfo collection""" # for rs in ri.randsets(): # print("RandSet") # for f in rs.all_fields(): # print(" " + f.name + " " + str(bound_m[f].domain.range_l)) # for uf in ri.unconstrained(): # print("Unconstrained: " + uf.name) rs_i = 0 start_rs_i = 0 max_fields = 20 while rs_i < len(ri.randsets()): btor = Boolector() self.btor = btor btor.Set_opt(pyboolector.BTOR_OPT_INCREMENTAL, True) btor.Set_opt(pyboolector.BTOR_OPT_MODEL_GEN, True) start_rs_i = rs_i constraint_l = [] # Collect up to max_fields fields to randomize at a time n_fields = 0 while rs_i < len(ri.randsets()): rs = ri.randsets()[rs_i] try: for f in rs.all_fields(): f.build(btor) n_fields += 1 except Exception as e: for c in rs.constraints(): print("Constraint: " + self.pretty_printer.do_print(c)) raise e constraint_l.extend( list( map( lambda c: (c, c.build(btor), isinstance(c, ConstraintSoftModel)), rs.constraints()))) rs_i += 1 if n_fields > max_fields: break for c in constraint_l: try: btor.Assume(c[1]) except Exception as e: from ..visitors.model_pretty_printer import ModelPrettyPrinter print("Exception: " + ModelPrettyPrinter.print(c[0])) raise e soft_node_l = list( map(lambda c: c[1], filter(lambda c: c[2], constraint_l))) node_l = list( map(lambda c: c[1], filter(lambda c: not c[2], constraint_l))) # Perform an initial solve to establish correctness if btor.Sat() != btor.SAT: if len(soft_node_l) > 0: # Try one more time before giving up for i, f in enumerate(btor.Failed(*soft_node_l)): if f: soft_node_l[i] = None # Add back the hard-constraint nodes and soft-constraints that # didn't fail for n in filter(lambda n: n is not None, node_l + soft_node_l): btor.Assume(n) # If we fail again, then we truly have a problem if btor.Sat() != btor.SAT: # Ensure we clean up x = start_rs_i while x < rs_i: rs = ri.randsets()[x] for f in rs.all_fields(): f.dispose() x += 1 raise Exception("solve failure") else: # Still need to convert assumptions to assertions for n in filter(lambda n: n is not None, node_l + soft_node_l): btor.Assert(n) else: print("Failed constraints:") i = 1 for c in constraint_l: if btor.Failed(c[1]): print("[" + str(i) + "]: " + self.pretty_printer.do_print(c[0], False)) print("[" + str(i) + "]: " + self.pretty_printer.do_print(c[0], True)) i += 1 # Ensure we clean up for rs in ri.randsets(): for f in rs.all_fields(): f.dispose() print("Solve failure") raise Exception("solve failure") else: # Still need to convert assumptions to assertions btor.Assert(*(node_l + soft_node_l)) self.swizzle_randvars(btor, ri, start_rs_i, rs_i, bound_m) # Finalize the value of the field x = start_rs_i while x < rs_i: rs = ri.randsets()[x] for f in rs.all_fields(): f.post_randomize() f.dispose( ) # Get rid of the solver var, since we're done with it x += 1 uc_rand = list(filter(lambda f: f.is_used_rand, ri.unconstrained())) for uf in uc_rand: bounds = bound_m[uf] range_l = bounds.domain.range_l if len(range_l) == 1: # Single (likely domain-based) range uf.set_val(self.randint(range_l[0][0], range_l[0][1])) else: # Most likely an enumerated type # TODO: are there any cases where these could be ranges? idx = self.randint(0, len(range_l) - 1) uf.set_val(range_l[idx][0])
def randomize(self, ri : RandInfo, bound_m : Dict[FieldModel,VariableBoundModel]): """Randomize the variables and constraints in a RandInfo collection""" if self.debug > 0: for rs in ri.randsets(): print("RandSet") for f in rs.all_fields(): if f in bound_m.keys(): print(" Field: " + f.fullname + " " + str(bound_m[f].domain.range_l)) for c in rs.constraints(): print(" Constraint: " + self.pretty_printer.do_print(c, show_exp=True)) for uf in ri.unconstrained(): print("Unconstrained: " + uf.name) # Assign values to the unconstrained fields first uc_rand = list(filter(lambda f:f.is_used_rand, ri.unconstrained())) for uf in uc_rand: if self.debug > 0: print("Randomizing unconstrained: " + uf.fullname) bounds = bound_m[uf] range_l = bounds.domain.range_l if len(range_l) == 1: # Single (likely domain-based) range uf.set_val( self.randint(range_l[0][0], range_l[0][1])) else: # Most likely an enumerated type # TODO: are there any cases where these could be ranges? idx = self.randint(0, len(range_l)-1) uf.set_val(range_l[idx][0]) # Lock so we don't overwrite uf.set_used_rand(False) rs_i = 0 start_rs_i = 0 max_fields = 20 while rs_i < len(ri.randsets()): btor = Boolector() self.btor = btor btor.Set_opt(pyboolector.BTOR_OPT_INCREMENTAL, True) btor.Set_opt(pyboolector.BTOR_OPT_MODEL_GEN, True) start_rs_i = rs_i constraint_l = [] # Collect up to max_fields fields to randomize at a time n_fields = 0 while rs_i < len(ri.randsets()): rs = ri.randsets()[rs_i] rs_node_builder = RandSetNodeBuilder(btor) all_fields = rs.all_fields() if self.debug > 0: print("Pre-Randomize: RandSet") for f in all_fields: if f in bound_m.keys(): print(" Field: " + f.fullname + " " + str(bound_m[f].domain.range_l)) for c in rs.constraints(): print(" Constraint: " + self.pretty_printer.do_print(c, show_exp=True, print_values=True)) rs_node_builder.build(rs) n_fields += len(all_fields) constraint_l.extend(list(map(lambda c:(c,c.build(btor),isinstance(c,ConstraintSoftModel)), rs.constraints()))) rs_i += 1 if n_fields > max_fields or rs.order != -1: break for c in constraint_l: try: btor.Assume(c[1]) except Exception as e: from ..visitors.model_pretty_printer import ModelPrettyPrinter print("Exception: " + ModelPrettyPrinter.print(c[0])) raise e soft_node_l = list(map(lambda c:c[1], filter(lambda c:c[2], constraint_l))) node_l = list(map(lambda c:c[1], filter(lambda c:not c[2], constraint_l))) # Perform an initial solve to establish correctness if btor.Sat() != btor.SAT: if len(soft_node_l) > 0: # Try one more time before giving up for i,f in enumerate(soft_node_l): if btor.Failed(f): soft_node_l[i] = None # Add back the hard-constraint nodes and soft-constraints that # didn't fail # for n in filter(lambda n:n is not None, node_l+soft_node_l): for n in filter(lambda n:n is not None, node_l): btor.Assume(n) for n in filter(lambda n:n is not None, soft_node_l): btor.Assume(n) # If we fail again, then we truly have a problem if btor.Sat() != btor.SAT: # Ensure we clean up # active_randsets = [] # x=start_rs_i # while x < rs_i: # rs = ri.randsets()[x] # active_randsets.append(rs) # for f in rs.all_fields(): # f.dispose() # x += 1 active_randsets = [] for rs in ri.randsets(): active_randsets.append(rs) for f in rs.all_fields(): f.dispose() raise SolveFailure( "solve failure", self.create_diagnostics(active_randsets)) # raise SolveFailure( # "solve failure", # self.create_diagnostics(active_randsets)) else: # Still need to convert assumptions to assertions for n in filter(lambda n:n is not None, node_l+soft_node_l): btor.Assert(n) else: # print("Failed constraints:") # i=1 # for c in constraint_l: # if btor.Failed(c[1]): # print("[" + str(i) + "]: " + self.pretty_printer.do_print(c[0], False)) # print("[" + str(i) + "]: " + self.pretty_printer.do_print(c[0], True)) # i+=1 # Ensure we clean up active_randsets = [] for rs in ri.randsets(): active_randsets.append(rs) for f in rs.all_fields(): f.dispose() raise SolveFailure( "solve failure", self.create_diagnostics(active_randsets)) else: # Still need to convert assumptions to assertions btor.Assert(*(node_l+soft_node_l)) self.swizzle_randvars(btor, ri, start_rs_i, rs_i, bound_m) # Finalize the value of the field x = start_rs_i reset_v = DynamicExprResetVisitor() while x < rs_i: rs = ri.randsets()[x] for f in rs.all_fields(): f.post_randomize() f.set_used_rand(False, 0) f.dispose() # Get rid of the solver var, since we're done with it f.accept(reset_v) # for f in rs.nontarget_field_s: # f.dispose() for c in rs.constraints(): c.accept(reset_v) RandSetDisposeVisitor().dispose(rs) x += 1 end = int(round(time.time() * 1000))
def swizzle_randvars(self, btor : Boolector, ri : RandInfo, start_rs : int, end_rs : int, bound_m : Dict[FieldModel,VariableBoundModel]): # TODO: we must ignore fields that are otherwise being controlled if self.debug > 0: print("--> swizzle_randvars") rand_node_l = [] rand_e_l = [] x=start_rs while x < end_rs: # For each random variable, select a partition with it's known # domain and add the corresponding constraint rs = ri.randsets()[x] field_l = rs.rand_fields() if self.debug > 0: print(" " + str(len(field_l)) + " fields in randset") if len(field_l) == 1: # Go ahead and pick values in the domain, since there # are no other constraints f = field_l[0] if f in bound_m.keys(): f_bound = bound_m[f] if not f_bound.isEmpty(): e = self.create_rand_domain_constraint(f, f_bound) if e is not None: n = e.build(btor) rand_node_l.append(n) rand_e_l.append(e) elif len(field_l) > 0: field_idx = self.randint(0, len(field_l)-1) f = field_l[field_idx] if self.debug > 0: print("Swizzling field " + f.name) if f in bound_m.keys(): f_bound = bound_m[f] if not f_bound.isEmpty(): e = self.create_rand_domain_constraint(f, f_bound) if e is not None: n = e.build(btor) rand_node_l.append(n) rand_e_l.append(e) # btor.Assume(n) else: # It's always possible that this value is already fixed. # Just ignore. # rand_node_l.append(None) pass else: if self.debug > 0: print("Note: no bounds found for field " + f.name) x += 1 if len(rand_node_l) > 0: btor.Assume(*rand_node_l) # btor.Assert(*rand_node_l) if btor.Sat() != btor.SAT: # Remove any failing assumptions if self.debug > 0: print("Randomization constraint failed") n_failed = 0 for i,n in enumerate(rand_node_l): if n is not None and btor.Failed(n): rand_node_l[i] = None n_failed += 1 # Sanity check if n_failed == 0: for e in rand_e_l: print("Constraint: " + ModelPrettyPrinter.print(e)) raise Exception("UNSAT reported, but no failing assertions") # # Re-apply the constraints that succeeded btor.Assert(*filter(lambda n:n is not None, rand_node_l)) if btor.Sat() != btor.SAT: raise Exception("failed to add in randomization (2)") else: if btor.Sat() != btor.SAT: raise Exception("failed to add in randomization") if self.debug > 0: print("<-- swizzle_randvars")