def _bitblast(aut): """Return `Automaton` with bitvector formulas. For each integer, the corresponding list of bitnames is added to the symbol table (attr `vars`). @type aut: `Automaton` """ players = dict(aut.players) aut = copy.copy(aut) t = bv.bitblast_table(aut.vars) init, action = bv.type_invariants(t) for var, c in init.items(): owner = aut.vars[var]['owner'] # collect type invariants of parameters too, # for convenience later aut.init.setdefault(owner, list()) aut.init[owner].extend(c) for var, c in action.items(): owner = aut.vars[var]['owner'] aut.action.setdefault(owner, list()) aut.action[owner].extend(c) # conjoin to avoid it later over BDD nodes _conj_owner(aut, 'env', 'infix') _conj_owner(aut, 'sys', 'infix') a = Automaton() a.players = players a.vars = t # TODO: replace GR(1) syntax check # spec.check_syntax() _bitblast_owner(aut, a, 'env', t) _bitblast_owner(aut, a, 'sys', t) return a
def test_type_invariants(): t = dict(x=dict(type='int', dom=(0, 3), init=2)) t = bv.bitblast_table(t) init, action = bv.type_invariants(t) init_ = dict(x=['x = 2', '(0 <= x) /\ (x <= 3)']) assert init == init_, init s = ( " (0 <= x) /\ (x <= 3)" " /\ (0 <= x') /\ (x' <= 3)") action_ = dict(x=[s]) assert action == action_, action
def test_mixed_fol_bitblasted(): t = dict(x=dict(type='bool', owner='sys'), y=dict(type='int', dom=(0, 3), owner='sys')) t = bv.bitblast_table(t) s = '(x /\ y_0) \/ (y < 0)' tree_0 = parser.parse(s) q = 'y < 0' tree_1 = parser.parse(q) f0 = tree_0.flatten(t=t) f1 = tree_1.flatten(t=t) assert f0 == ' | & x y_0 {f1} '.format(f1=f1), (f0, f1)
def add_vars(self, dvars): r"""Refine variables in `dvars`. The variables in `dvars` should have type hints. A Boolean-valued variable remains so. An integer-valued variable is assumed to take the value resulting as a function of some (fresh) Boolean-valued variables. Sometimes these variables are called "bits". The function is based on two's complement, see `omega.logic.bitvector` for details. In other words, type hints are used to pick a refinement of integers by finitely many bits. A sufficient number of bits is selected, and operations assume this as type invariant, *not* the exact type hint given. For example, an integer `x` with type hint `x \in 0..2` will be refined using 2 Boolean-valued variables `x_0` and `x_1`. All operations and quantification will assume that `x \in 0..3`. Mind the extra value (3) allowed, compared to the hint (0..2). Attention: - Fine-grained type predicates (`n..m` with `n` and `m` other than powers of 2) are not managed here. - Priming is not reasoned about here. Priming is cared for by other modules. The method `add_vars` adds to `vars[var]` the keys: - `"bitnames"`: `list` - `"signed"`: `True` if signed integer - `"width"`: `len(bitnames)` """ assert dvars, dvars self._avoid_redeclaration(dvars) vrs = {k: v for k, v in dvars.items() if k not in self.vars} if not vrs: return t = bv.bitblast_table(vrs) self.vars.update(t) bits = bv.bit_table(t, t) for bit in bits: self.bdd.add_var(bit)
def _bitblast(aut): aut = copy.copy(aut) players = set(aut.players) players.add(None) t, init, action = bv.bitblast_table(aut.vars, players) init.pop(None) action.pop(None) for k, v in init.iteritems(): aut.init[k].extend(v) for k, v in action.iteritems(): aut.action[k].extend(v) # conjoin now, instead of later with BDDs for k in aut.players: symbolic._conj_owner(aut, k, 'infix') a = Automaton() a.players = aut.players a.vars = t _bitblast_attr(aut, a, t) return a
def _bitblast(aut): aut = copy.copy(aut) players = set(aut.players) players.add(None) t, init, action = bv.bitblast_table(aut.vars, players) init.pop(None) action.pop(None) for k, v in init.items(): aut.init[k].extend(v) for k, v in action.items(): aut.action[k].extend(v) # conjoin now, instead of later with BDDs for k in aut.players: symbolic._conj_owner(aut, k, 'infix') a = Automaton() a.players = aut.players a.vars = t _bitblast_attr(aut, a, t) return a