Skip to content

Equivalent expressions

Use <=> to check whether two expressions are equivalent.

sample code #1, size constraints and their equivalences

sig A {}

assert equivalence{
 some A <=> #A > 0
 no A <=> #A = 0
 one A <=> #A = 1
 lone A <=> #A <= 1
}

check equivalence

sample code #2, quantified constrains and their equivalences

Use comprehension (a kind of set builder) in the equivalences

sig A {
  relation:  set A
}
pred expr[a: A]{
  a in a.relation
}
assert equivalence{
  ( some a : A | expr[a] ) <=> ( #{ a : A | expr[a] } > 0 )
  ( no a : A | expr[a] ) <=> ( #{ a : A | expr[a] } = 0 )
  ( one a : A | expr[a] ) <=> ( #{ a : A | expr[a] } = 1 )
  ( lone a : A | expr[a] ) <=> ( #{ a : A | expr[a] } <= 1 )
  ( all a: A | expr[a]) <=> ( #{ a: A | expr[a] } = #A )
}

check equivalence

sample code #3, none equivalent

This code will generate counterexample. So (one a1, a2 : A | expr[a1 , a2] ) and (one a1: A | one a2: A | expr[a1, a2]) are not equivalent.

sig A {
  relation:  set A
}
pred expr[a1: A, a2: A]{
  a2 in a1.relation
}
assert equivalence{
 (one a1, a2 : A | expr[a1 , a2] ) <=> (one a1: A | one a2: A | expr[a1, a2])
}
check equivalence

Let's construct a counterexample.

viz.png

Expression Boolean
a1 in A True
a2 in A True
a1 in a1.relation False
a1 in a2.relation True
a2 in a1.relation True
a2 in a2.relation True
expr[a1 , a1] False
expr[a1 , a2] True
expr[a2 , a1] True
expr[a2 , a2] True
(one a1, a2 : A | expr[a1 , a2] ) False
(one a1: A | one a2: A | expr[a1, a2]) True

The reason for (one a1, a2 : A | expr[a1 , a2] ) to be false is because there are 3 pairs to make expr to be true, not one pair.

The reason for (one a1: A | one a2: A | expr[a1, a2]) to be true is because there is only one pair to meet this criteria. That happens to be, a1 = a1 and a2 = a2.