void sat_path_enumeratort::record_path(scratch_programt &program) { distinguish_valuest path_val; for(const auto &expr : distinguishers) path_val[expr]=program.eval(expr).is_true(); accelerated_paths.push_back(path_val); }
void disjunctive_polynomial_accelerationt::record_path(scratch_programt &program) { distinguish_valuest path_val; for (std::list<exprt>::iterator it = distinguishers.begin(); it != distinguishers.end(); ++it) { path_val[*it] = program.eval(*it).is_true(); } accelerated_paths.push_back(path_val); }
void polynomial_acceleratort::stash_variables(scratch_programt &program, expr_sett modified, substitutiont &substitution) { find_symbols_sett vars; for (expr_sett::iterator it = modified.begin(); it != modified.end(); ++it) { find_symbols(*it, vars); } irep_idt loop_counter_name = to_symbol_expr(loop_counter).get_identifier(); vars.erase(loop_counter_name); for (find_symbols_sett::iterator it = vars.begin(); it != vars.end(); ++it) { symbolt orig = symbol_table.lookup(*it); symbolt stashed_sym = utils.fresh_symbol("polynomial::stash", orig.type); substitution[orig.symbol_expr()] = stashed_sym.symbol_expr(); program.assign(stashed_sym.symbol_expr(), orig.symbol_expr()); } }
void polynomial_acceleratort::assert_for_values(scratch_programt &program, std::map<exprt, int> &values, std::set<std::pair<expr_listt, exprt> > &coefficients, int num_unwindings, goto_programt::instructionst &loop_body, exprt &target, overflow_instrumentert &overflow) { // First figure out what the appropriate type for this expression is. typet expr_type = nil_typet(); for (std::map<exprt, int>::iterator it = values.begin(); it != values.end(); ++it) { typet this_type=it->first.type(); if (this_type.id() == ID_pointer) { #ifdef DEBUG std::cout << "Overriding pointer type" << std::endl; #endif this_type = unsignedbv_typet(config.ansi_c.pointer_width); } if (expr_type == nil_typet()) { expr_type = this_type; } else { expr_type = join_types(expr_type, this_type); } } assert(to_bitvector_type(expr_type).get_width()>0); // Now set the initial values of the all the variables... for (std::map<exprt, int>::iterator it = values.begin(); it != values.end(); ++it) { program.assign(it->first, from_integer(it->second, expr_type)); } // Now unwind the loop as many times as we need to. for (int i = 0; i < num_unwindings; i++) { program.append(loop_body); } // Now build the polynomial for this point and assert it fits. exprt rhs = nil_exprt(); for (std::set<std::pair<expr_listt, exprt> >::iterator it = coefficients.begin(); it != coefficients.end(); ++it) { int concrete_value = 1; for (expr_listt::const_iterator e_it = it->first.begin(); e_it != it->first.end(); ++e_it) { exprt e = *e_it; if (e == loop_counter) { concrete_value *= num_unwindings; } else { std::map<exprt, int>::iterator v_it = values.find(e); if (v_it != values.end()) { concrete_value *= v_it->second; } } } // OK, concrete_value now contains the value of all the relevant variables // multiplied together. Create the term concrete_value*coefficient and add // it into the polynomial. typecast_exprt cast(it->second, expr_type); exprt term = mult_exprt(from_integer(concrete_value, expr_type), cast); if (rhs.is_nil()) { rhs = term; } else { rhs = plus_exprt(rhs, term); } } exprt overflow_expr; overflow.overflow_expr(rhs, overflow_expr); program.add_instruction(ASSUME)->guard = not_exprt(overflow_expr); rhs = typecast_exprt(rhs, target.type()); // We now have the RHS of the polynomial. Assert that this is equal to the // actual value of the variable we're fitting. exprt polynomial_holds = equal_exprt(target, rhs); // Finally, assert that the polynomial equals the variable we're fitting. goto_programt::targett assumption = program.add_instruction(ASSUME); assumption->guard = polynomial_holds; }
void disjunctive_polynomial_accelerationt::build_path( scratch_programt &scratch_program, patht &path) { goto_programt::targett t = loop_header; do { goto_programt::targett next; goto_programt::targetst succs; goto_program.get_successors(t, succs); // We should have a looping path, so we should never hit a location // with no successors. assert(succs.size() > 0); if (succs.size() == 1) { // Only one successor -- accumulate it and move on. path.push_back(path_nodet(t)); t = succs.front(); continue; } // We have multiple successors. Examine the distinguisher variables // to see which branch was taken. bool found_branch = false; for (goto_programt::targetst::iterator it = succs.begin(); it != succs.end(); ++it) { exprt &distinguisher = distinguishing_points[*it]; bool taken = scratch_program.eval(distinguisher).is_true(); if (taken) { if (!found_branch || ((*it)->location_number < next->location_number)) { next = *it; } found_branch = true; } } assert(found_branch); exprt cond = nil_exprt(); if (t->is_goto()) { // If this was a conditional branch (it probably was), figure out // if we hit the "taken" or "not taken" branch & accumulate the // appropriate guard. cond = not_exprt(t->guard); for (goto_programt::targetst::iterator it = t->targets.begin(); it != t->targets.end(); ++it) { if (next == *it) { cond = t->guard; break; } } } path.push_back(path_nodet(t, cond)); t = next; } while (t != loop_header && (loop.find(t) != loop.end())); }
void disjunctive_polynomial_accelerationt::assert_for_values( scratch_programt &program, std::map<exprt, exprt> &values, std::set<std::pair<expr_listt, exprt> > &coefficients, int num_unwindings, goto_programt &loop_body, exprt &target) { // First figure out what the appropriate type for this expression is. typet expr_type = nil_typet(); for (std::map<exprt, exprt>::iterator it = values.begin(); it != values.end(); ++it) { if (expr_type == nil_typet()) { expr_type = it->first.type(); } else { expr_type = join_types(expr_type, it->first.type()); } } // Now set the initial values of the all the variables... for (std::map<exprt, exprt>::iterator it = values.begin(); it != values.end(); ++it) { program.assign(it->first, it->second); } // Now unwind the loop as many times as we need to. for (int i = 0; i < num_unwindings; i++) { program.append(loop_body); } // Now build the polynomial for this point and assert it fits. exprt rhs = nil_exprt(); for (std::set<std::pair<expr_listt, exprt> >::iterator it = coefficients.begin(); it != coefficients.end(); ++it) { exprt concrete_value = from_integer(1, expr_type); for (expr_listt::const_iterator e_it = it->first.begin(); e_it != it->first.end(); ++e_it) { exprt e = *e_it; if (e == loop_counter) { mult_exprt mult(from_integer(num_unwindings, expr_type), concrete_value); mult.swap(concrete_value); } else { std::map<exprt, exprt>::iterator v_it = values.find(e); assert(v_it != values.end()); mult_exprt mult(concrete_value, v_it->second); mult.swap(concrete_value); } } // OK, concrete_value now contains the value of all the relevant variables // multiplied together. Create the term concrete_value*coefficient and add // it into the polynomial. typecast_exprt cast(it->second, expr_type); exprt term = mult_exprt(concrete_value, cast); if (rhs.is_nil()) { rhs = term; } else { rhs = plus_exprt(rhs, term); } } rhs = typecast_exprt(rhs, target.type()); // We now have the RHS of the polynomial. Assert that this is equal to the // actual value of the variable we're fitting. exprt polynomial_holds = equal_exprt(target, rhs); // Finally, assert that the polynomial equals the variable we're fitting. goto_programt::targett assumption = program.add_instruction(ASSUME); assumption->guard = polynomial_holds; }
void acceleratet::build_state_machine( trace_automatont::sym_mapt::iterator begin, trace_automatont::sym_mapt::iterator end, state_sett &accept_states, symbol_exprt state, symbol_exprt next_state, scratch_programt &state_machine) { std::map<unsigned int, unsigned int> successor_counts; unsigned int max_count=0; unsigned int likely_next=0; // Optimisation: find the most common successor state and initialise // next_state to that value. This reduces the size of the state machine // driver substantially. for(trace_automatont::sym_mapt::iterator p=begin; p!=end; ++p) { trace_automatont::state_pairt state_pair=p->second; unsigned int to=state_pair.second; unsigned int count=0; if(successor_counts.find(to)==successor_counts.end()) { count=1; } else { count=successor_counts[to] + 1; } successor_counts[to]=count; if(count > max_count) { max_count=count; likely_next=to; } } // Optimisation: if there is only one possible successor state, just // jump straight to it instead of driving the whole machine. if(successor_counts.size()==1) { if(accept_states.find(likely_next)!=accept_states.end()) { // It's an accept state. Just assume(false). state_machine.assume(false_exprt()); } else { state_machine.assign(state, from_integer(likely_next, next_state.type())); } return; } state_machine.assign(next_state, from_integer(likely_next, next_state.type())); for(trace_automatont::sym_mapt::iterator p=begin; p!=end; ++p) { trace_automatont::state_pairt state_pair=p->second; unsigned int from=state_pair.first; unsigned int to=state_pair.second; if(to==likely_next) { continue; } // We're encoding the transition // // from -loc-> to // // which we encode by inserting: // // next_state=(state==from) ? to : next_state; // // just before loc. equal_exprt guard(state, from_integer(from, state.type())); if_exprt rhs(guard, from_integer(to, next_state.type()), next_state); state_machine.assign(next_state, rhs); } // Update the state and assume(false) if we've hit an accept state. state_machine.assign(state, next_state); for(state_sett::iterator it=accept_states.begin(); it!=accept_states.end(); ++it) { state_machine.assume( not_exprt(equal_exprt(state, from_integer(*it, state.type())))); } }