I am a beginner in Z3py and I've been struggling with this for almost a week now... I don't find enough information to help me in tutorials out there neither a good example (of the function Exists) that can help me.
2 Answers
Disclaimer: If your problem is solely that you are struggling with encoding the problem using Z3py, then my suggestions won't help you since they are not about Z3py. However, I assume that your problem is actually more fundamental.
Answer: Axiomatising the lists in Z3/SMTLIB is not at all straight-forward, in particular, because your axiomatisation needs a good triggering strategy (patterns) for your (forall-quantified) axioms, so that your axiomatisation doesn't give rise to matching loops.
I suggest to look at the Boogie prelude of Dafny to see how an axiomatisation of sequences can look. Dafny is an automated software verifier and Boogie is an intermediate verification language. Boogie's syntax is easy to understand (for somebody familiar with SMTLIB's syntax), and you should be able to extend the existing sequence axiomatisation with an axiom (or multiple axioms) that express sequence permutation.
Other sources of inspiration could be this or this paper, both of which discuss axiom triggers and matching loops.

- 12,684
- 4
- 41
- 71
W̶o̶w̶,̶ ̶w̶h̶a̶t̶ ̶t̶h̶e̶ ̶h̶e̶c̶k̶.̶.̶.̶ ̶T̶h̶a̶t̶ ̶l̶i̶t̶e̶r̶a̶t̶u̶r̶e̶ ̶l̶i̶s̶t̶ ̶i̶s̶ ̶i̶n̶t̶i̶m̶i̶d̶a̶t̶i̶n̶g̶.̶ Forgive me my arrogance; does the question ask for purely symbolic comparison? If not, this (much more basic) answer might offer something useful.
If all you want is just to find a particular permutation of a known list of unique values, you can probably do away without axiomatizing anything.
Just generate O(n²) pairwise equalities, then add them in groups as n
constraints of AtLeast(…, 1)
form. Code example would explain better:
from itertools import combinations
import z3
solver = z3.Solver()
source_list = ['tau', 'eta', 'mu']
permuted = z3.Strings(['X', 'Y', 'Z'])
for var1, var2 in combinations(permuted, 2):
solver.add(var1 != var2)
#-- here's where we do O(n²) pairwise EQs
for var_ref in permuted:
possible_assigns = [(var_ref == z3.StringVal(s)) for s in source_list]
solver.add(z3.AtLeast(*possible_assigns, 1))
#-- TODO: add here the rest of constraints that matter to you
#-- start search
while solver.check() == z3.sat:
model = solver.model()
print(model)
this_solution = z3.And(*[
var_ref == z3.StringVal(model[var_ref].as_string())
for var_ref in permuted
])
solver.append(z3.Not(this_solution))
print("No more solutions.")
#-- output:
# [Z = tau, X = mu, Y = eta]
# [Z = tau, X = eta, Y = mu]
# [Z = mu, X = eta, Y = tau]
# [Z = eta, X = mu, Y = tau]
# [Z = mu, X = tau, Y = eta]
# [Z = eta, X = tau, Y = mu]
# No more solutions.
This will need some tweaking if the permuted
list is allowed to have dupes.
This won't work if both lists live "in-z3". See Malte's answer for that case.

- 14,740
- 10
- 56
- 88
-
I think Malte's answer is spot on here. If you *knew* your input was a constant ahead of time, you wouldn't use z3 to start with. The whole point is that the input is symbolic and the OP wanted to express two such lists are permutations of each other; which is definitely not an easy thing to do with the current technology. – alias Jan 26 '19 at 18:17
-
I disagree on the *you wouldn't use z3 to start with* part. Of course, using z3 to *only* generate list permutations is overkill. However in my case, I employ its SAT-solving ability to find such an input to a logical circuit that... *complicated conditions* hold; pretty much the straightforward use-case. But the twist is, I also happen to know that a portion of the input is going to be a permutation (it's unknown which exactly) of a static list of integers. This might be unclear from my example, where I didn't include any meaningful constraint checking parts. – ulidtko Jan 26 '19 at 19:07
-
I acknowledge the technical challenge explained by Malte, and appreciate the references he gives. However I also think that my *much narrower* use-case is valid as well; and since the original question doesn't specify in detail what they want (and what the search engine traffic will see), I hold that my answer is good enough, and together with working code, doesn't deserve a downvote. – ulidtko Jan 26 '19 at 19:15