def addHistory(self): for clock in self.newClocks: history = None tick = self.tickDict["t_%s" % (clock)] if ("h_%s" % (clock)) not in self.historyDict.keys(): history = z3.Function("h_%s" % (clock), z3.IntSort(), z3.IntSort()) self.historyDict["h_%s" % (clock)] = history else: history = self.historyDict["h_%s" % (clock)] # self.solver.add(history(0) == z3.IntVal(0)) self.solver.add(history(1) == z3.IntVal(0)) if self.bound > 0: # If the bound is finite, we define the history of the clock with a fixed bound. for i in range(1, self.bound + 1): self.solver.add( z3.If(tick(i), history(i + 1) == history(i) + 1, history(i + 1) == history(i))) # self.solver.add(z3.If(tick(i), # history(i + 1) == history(i) + 1, # history(i + 1) == history(i))) elif self.bound == 0: x = z3.Int("x") # If the bound is infinite, we define the history of the clock infinitely. self.solver.add( z3.ForAll( x, z3.Implies( x >= 1, z3.If(tick(x), history(x + 1) == history(x) + 1, history(x + 1) == history(x)))))
def __init__(self, s: z3.Solver, g: Graph): (G, G_nodes) = z3.EnumSort(g.name_, tuple(g.nodes())) # Function that returns true if there is an edge between two nodes, # and false otherwise edges_f = z3.Function('G_%s_edges' % (g.name_,), G, G, z3.BoolSort()) for (n1,n2) in itertools.product(iter(G_nodes), iter(G_nodes)): n1_str = repr(n1) n2_str = repr(n2) s.add(edges_f(n1,n2) == g.has_edge(n1_str,n2_str)) self.nodes_s = G # Nodes Sort self.nodes = G_nodes self.edges_f = edges_f
def addTickSMT(self): for each in self.newClocks: self.tickDict["t_%s" % (each)] = z3.Function( "t_%s" % (each), z3.IntSort(), z3.BoolSort()) tick = self.tickDict["t_%s" % (each)] if self.bound > 0: y = z3.Int("y") if self.period > 0: for y in range(1, self.bound + 1): self.solver.add( z3.Implies( y >= self.k, tick((y - self.l) % self.p + self.l) == tick(y))) # self.solver.add( # z3.ForAll(y,z3.Implies( # z3.And(y >= self.k,y <= self.bound), # tick((y - self.l) % self.p + self.l) == tick(y)))) elif self.bound == 0: x = z3.Int("x") if self.period > 0: y = z3.Int("y") self.solver.add( z3.ForAll( y, z3.Implies( y >= self.k, tick((y - self.l) % self.p + self.l) == tick(y)))) clockListTmp = [] x = z3.Int("x") for each in self.tickDict.keys(): tick = self.tickDict[each] clockListTmp.append(tick(x)) if self.bound == 0: self.solver.add( z3.ForAll(x, z3.Implies(x >= 1, z3.Or(clockListTmp)))) else: for i in range(1, self.bound + 1): tmp = [] for tick in self.tickDict.values(): tmp.append(tick(i)) self.solver.add(z3.Or(tmp))
def z3_graph_mapping(s: z3.Solver, g1: GraphZ3, g2: GraphZ3): map_f = z3.Function('Map', g1.nodes_s, g2.nodes_s) x = z3.Const('x', g1.nodes_s) y = z3.Const('y', g1.nodes_s) s.add([ z3.ForAll([x,y], g1.edges_f(x,y) == g2.edges_f(map_f(x), map_f(y))) ]) # Check if can satisfy the specified constraints if s.check(): # If can, get the model (i.e., a solution that satisfies the # constrains) for the Map function and return it m = s.model() for d in m.decls(): if d.name() == 'Map': iso_m = m[d] return iso_m raise RuntimeError("Isomorphism function not found in model") return None
def addTickStep(self, clock): tick = self.tickDict["t_%s" % (clock)] history = self.historyDict["h_%s" % (clock)] if "s_%s" % (clock) not in self.tickStep.keys(): tickStep = z3.Function("s_%s" % (clock), z3.IntSort(), z3.IntSort()) self.tickStep["s_%s" % (clock)] = tickStep if self.bound > 0: x = z3.Int("x") # If the bound is infinite, we define the history of the clock infinitely. for i in range(1, self.bound + 1): self.solver.add( z3.Implies(tick(i), tickStep(history(i) + 1) == i)) elif self.bound == 0: x = z3.Int("x") # If the bound is infinite, we define the history of the clock infinitely. self.solver.add( z3.ForAll( x, z3.Implies(z3.And(x >= 1, tick(x)), tickStep(history(x) + 1) == x)))