#!/usr/bin/env python3 from z3 import * def _try (POURINGS): print ("* try %d" % POURINGS) STATES=POURINGS+1 A=[Int('A_%d' % i) for i in range(STATES)] B=[Int('B_%d' % i) for i in range(STATES)] C=[Int('C_%d' % i) for i in range(STATES)] op=[Int('op_%d' % i) for i in range(STATES)] def Z3_min(a,b): return If(a0, B[cur]0, C[cur]0), And(A[next]==A[cur]+B[cur], C[next]==C[cur], B[next]==0), If(And(op[cur]==3, B[cur]>0, C[cur]0), And(A[next]==A[cur]+C[cur], B[next]==B[cur], C[next]==0), If(And(op[cur]==5, C[cur]>0), And(A[next]==A[cur], B[next]==Z3_min(jug_B, B[cur]+C[cur]), C[next]==C[cur]-(B[next]-B[cur])), False))))))) # no state must repeat: for i in range(STATES): for j in range(i): s.add(Or(A[i]!=A[j], B[i]!=B[j], C[i]!=C[j])) # initial and final state: s.add(And(A[0]==8, B[0]==0, C[0]==0)) s.add(And(A[STATES-1]==4, B[STATES-1]==4, C[STATES-1]==0)) if s.check()==unsat: return m=s.model() ops_names=["A->B", "A->C", "B->A", "B->C", "C->A", "C->B"] for i in range(STATES): print ("state %d, %d-%d-%d" % (i, m[A[i]].as_long(), m[B[i]].as_long(), m[C[i]].as_long())) if i!=STATES-1: print ("op_%d = %s" % (i, ops_names[m[op[i]].as_long()])) exit(0) #_try(7) #exit(0) for i in range(20): _try(i)