def transition_condition(self, transition_name, state): """ The values of the variables in the state can be symbolic. """ guard = self.transition_by_name(transition_name)[2]['guard'] return util.evaluate_expression(guard, {}, state)
def guard_enabled(self, state, guard, verbose=0): if guard.decl().name().startswith('table'): conditional = self.tables[guard.decl().name()] expression = z3p.BoolVal(False) for condition, result in conditional: expression = z3p.Or(expression, condition if z3p.is_true(result) else z3p.BoolVal(False)) guard = expression guard_evaluated = util.evaluate_expression(guard, {}, state, self.tables) if verbose > 0: print 'Evaluated guard is {}'.format(guard_evaluated) print 'Simplified guard is {}'.format(z3p.simplify(guard_evaluated)) s = z3p.Solver() s.add(z3p.Neq(guard_evaluated, True)) if s.check() == z3p.unsat: return True else: return False
def transitions_from_state(self, state1, state2, verbose=0): possible_transitions = dict([(a, []) for a in self.automata]) possible_channels = dict([(a, set([])) for a in self.automata]) possible_internal_transitions = dict([(a, []) for a in self.automata]) transition_channels = {} for a in self.automata: if state1[a] == state2[a]: possible_transitions[a].append(None) for t in a.edges(data=True): if a.can_transition(state1[a], state2[a], t): possible_transitions[a].append(t) channel = t[2]['channel'] if channel is None: possible_internal_transitions[a].append(t) else: possible_channels[a].add(channel) for a in self.automata: for c in list(possible_channels[a]): assert c in self.readers, "{} not in {}".format(c, self.readers) assert c in self.writer, "{} not in {}".format(c, self.writer) automata = self.readers[c] + [self.writer[c]] if (any(c not in possible_channels[ap] for ap in automata) or any(None not in possible_transitions[ap] for ap in self.automata if ap not in automata)): possible_channels[a].remove(c) if any(len(possible_channels[a]) > 0 for a in self.automata): c = next(list(possible_channels[a])[0] for a in self.automata if len(possible_channels[a]) > 0) if verbose > 0: print "Checking channel {}".format(c) for t in possible_transitions[self.writer[c]]: writer_transition = t if verbose > 0: print "Checking writer transition {}".format(t) if t is not None and t[2]['channel'] == c: channel_expressions = t[2]['channel_expression'] channel_expression_values = [util.evaluate_expression(channel_expression, {}, state1[self.writer[c]], tables=self.writer[c].tables) for channel_expression in channel_expressions] if verbose > 0: print 'Writer tables are {}'.format(self.writer[c].tables) print 'Channel expressions are {}'.format(channel_expressions) print 'Channel expression values are {}'.format(channel_expression_values) reader_transitions = [next(t for t in possible_transitions[a] if t is not None and t[2]['channel'] == c) for a in self.readers[c]] writer_matches_readers = True for rt in reader_transitions: if verbose > 0: print "Checking against reader transition {}".format(rt) ra = rt[2]['automaton'] updates = rt[2]['update'] for update in updates: if c in z3p.variables_in_expression(update[1]): if isinstance(c, z3p.ArrayRef): selects = util.selects_in_expression(update[1]) new_reader_concrete_memory = dict(state1[ra]) for select in selects: index = select.arg(1) new_reader_concrete_memory[c[index]] = channel_expression_values[index.as_long()] if state2[ra][update[0]] != util.evaluate_expression(update[1], {}, new_reader_concrete_memory): writer_matches_readers = False else: new_reader_concrete_memory = dict(state1[ra]) new_reader_concrete_memory[c] = channel_expression_values[0] s = z3p.Solver() s.add(z3p.Neq(state2[ra][update[0]], util.evaluate_expression(update[1], {}, new_reader_concrete_memory))) if s.check() != z3p.unsat: if verbose: print "update does not match {}, {}".format(state2[ra][update[0]], util.evaluate_expression(update[1], {}, new_reader_concrete_memory)) writer_matches_readers = False if writer_matches_readers: return [writer_transition] + reader_transitions else: for a in self.automata: other_automata = [ap for ap in self.automata if a != ap] if (len(possible_internal_transitions[a]) > 0 and all(None in possible_transitions[ap] for ap in other_automata)): return [possible_internal_transitions[a]]
def transitions_from_state(self, state1, state2, verbose=0): possible_transitions = dict([(a, []) for a in self.automata]) possible_channels = dict([(a, set([])) for a in self.automata]) possible_internal_transitions = dict([(a, []) for a in self.automata]) transition_channels = {} for a in self.automata: if state1[a] == state2[a]: possible_transitions[a].append(None) for t in a.edges(data=True): if a.can_transition(state1[a], state2[a], t): possible_transitions[a].append(t) channel = t[2]["channel"] if channel is None: possible_internal_transitions[a].append(t) else: possible_channels[a].add(channel) for a in self.automata: for c in list(possible_channels[a]): assert c in self.readers, "{} not in {}".format(c, self.readers) assert c in self.writer, "{} not in {}".format(c, self.writer) automata = self.readers[c] + [self.writer[c]] if any(c not in possible_channels[ap] for ap in automata) or any( None not in possible_transitions[ap] for ap in self.automata if ap not in automata ): possible_channels[a].remove(c) if any(len(possible_channels[a]) > 0 for a in self.automata): c = next(list(possible_channels[a])[0] for a in self.automata if len(possible_channels[a]) > 0) if verbose > 0: print "Checking channel {}".format(c) for t in possible_transitions[self.writer[c]]: writer_transition = t if verbose > 0: print "Checking writer transition {}".format(t) if t is not None and t[2]["channel"] == c: channel_expressions = t[2]["channel_expression"] channel_expression_values = [ util.evaluate_expression( channel_expression, {}, state1[self.writer[c]], tables=self.writer[c].tables ) for channel_expression in channel_expressions ] if verbose > 0: print "Writer tables are {}".format(self.writer[c].tables) print "Channel expressions are {}".format(channel_expressions) print "Channel expression values are {}".format(channel_expression_values) reader_transitions = [ next(t for t in possible_transitions[a] if t is not None and t[2]["channel"] == c) for a in self.readers[c] ] writer_matches_readers = True for rt in reader_transitions: if verbose > 0: print "Checking against reader transition {}".format(rt) ra = rt[2]["automaton"] updates = rt[2]["update"] for update in updates: if c in z3p.variables_in_expression(update[1]): if isinstance(c, z3p.ArrayRef): selects = util.selects_in_expression(update[1]) new_reader_concrete_memory = dict(state1[ra]) for select in selects: index = select.arg(1) new_reader_concrete_memory[c[index]] = channel_expression_values[ index.as_long() ] if state2[ra][update[0]] != util.evaluate_expression( update[1], {}, new_reader_concrete_memory ): writer_matches_readers = False else: new_reader_concrete_memory = dict(state1[ra]) new_reader_concrete_memory[c] = channel_expression_values[0] s = z3p.Solver() s.add( z3p.Neq( state2[ra][update[0]], util.evaluate_expression(update[1], {}, new_reader_concrete_memory), ) ) if s.check() != z3p.unsat: if verbose: print "update does not match {}, {}".format( state2[ra][update[0]], util.evaluate_expression(update[1], {}, new_reader_concrete_memory), ) writer_matches_readers = False if writer_matches_readers: return [writer_transition] + reader_transitions else: for a in self.automata: other_automata = [ap for ap in self.automata if a != ap] if len(possible_internal_transitions[a]) > 0 and all( None in possible_transitions[ap] for ap in other_automata ): return [possible_internal_transitions[a]]