Untitled

 avatar
unknown
plain_text
5 months ago
3.4 kB
2
Indexable
from z3 import *


#State vector function per state
S_f = {0: lambda S: And(*[Not(si) for si in S])
    , 1: lambda S: And(S[0],Not(S[1]),Not(S[2]),S[3])
              , 2: lambda S: And(S[0],S[1],Not(S[2]),S[3])
    ,3: lambda S: And(Not(S[0]),S[1],S[2],Not(S[3]))
              , 4: lambda S: And(S[0],S[1],S[2],Not(S[3]))
              , 5: lambda S: And(Not(S[0]),S[1],Not(S[2]),Not(S[3]))
              , 6: lambda S: And(S[0],S[1],Not(S[2]),Not(S[3]))}


edges = {
    0: [1,5],
    1: [2],
    2: [1],
    3: [0,3,5],
    4: [3],
    5: [0,6],
    6: [4]
}

solver = Solver()
K = 2

#Make the state vectors
S = []

for i in range(0,K+1):
    si = []
    for attribute in ["start","closed","heat","error"]: #Change the attributes
        si += [Bool(f"{attribute}_{i}")]
    S += [si]


#First we make the transition system
I0 = S_f[0](S[0])
solver.add(I0)

#We add all possible transitions

#Set the initial state
Q = [0]
visited = dict()

def transition_si_sj(si,sj,k):
    return [And(S_f[si](S[k]),S_f[sj](S[k + 1]))]

for k in range(K):
    bigV = []
    Q_new = []
    while len(Q)>0:
        si = Q.pop()
        for sj in edges[si]:
            if(sj == 6):
                pass
            bigV += transition_si_sj(si,sj,k)

            #Add to the queue
            Q_new += [sj]
            visited[sj] = True

    solver.add(Or(*bigV))
    Q = Q_new

#The last states in Q are the states K depth away from the initial state
"""
Lk = []
for sk in Q:
    for si in range(7):
        for i in range(K):
            if(si != sk):
                Lk += [And(S_f[sk](S[K]),S_f[si](S[k]))]

print(Or(*Lk))

"""

Lk = [
    And(S_f[2](S[K]),S_f[1](S[1])),
    And(S_f[0](S[K]),S_f[5](S[1])),
]
solver.add(Or(*Lk))

def get_solutions(s: z3.z3.Solver):
    result = s.check()
    # While we still get solutions
    while (result == z3.sat):
      m = s.model()
      yield m
      # Add new solution as a constraint
      block = []
      for var in m:
          block.append(var() != m[var])
      s.add(z3.Or(block))
      # Look for new solution
      result = s.check()


def pretty_print_all_solutions(solver):
    # Continue to find solutions as long as the solver can satisfy the constraints
    solution_count = 0
    while solver.check() == sat:
        solution_count += 1
        model = solver.model()

        # Print the current solution in a readable way
        print(f"Solution {solution_count}:")
        for d in model.decls():
            if is_true(model[d]):  # Only print variables that are True
                print(f"{d.name()} = True")
        print()

        # Add a new constraint to block the current model (to find other solutions)
        # This constraint ensures that the next solution must differ from the current one
        blocking_clause = []
        for d in model.decls():
            blocking_clause.append(d() != model[d])
        solver.add(Or(blocking_clause))

    if solution_count == 0:
        print("No solutions found.")



if __name__ == "__main__":
    if solver.check() == sat:
        print("sat")
        pretty_print_all_solutions(solver)
        """
        solutions = get_solutions(solver)
        upper_bound = 100
        r = set()
        for m, _ in zip(solutions, range(upper_bound)):
            for x in m:
                if(is_true(m[x])):
                    r.add(x)
            #print(r)
        """
Editor is loading...
Leave a Comment