Find unique tuples in a relation represented by a BDD - algorithm

Let's suppose I use a BDD to represent the set of tuples in a relation. For simplicity consider tuples with 0 or 1 values. For instance:
R = {<0,0,1>, <1,0,1>, <0,0,0>} represent a ternary relation in a BDD with three variables, say x, y and z (one for each tuple's element). What I want is to implement an operation that given a bdd like for R and a cube C returns the subset of R that contains unique tuples when the variables in C are abstracted.
For instance, if C contains the variable x (which represents the first element in each tuple) the result of the function must be {<0,0,0>}. Notice that when x is abstracted away tuples <0,0,1> and <1,0,1> become "the same".
Now suppose R = {<0,0,1>, <1,0,1>, <0,0,0>, <1,0,0>} and we want to abstract x again. In this case I would expect the constant false as result because there is no unique tuple in R after abstracting x.
Any help is highly appreciated.

This could be done in three simple steps:
Make two BDDs with restricted value of the variable you want to abstract:
R[x=0] = restrict R with x = 0
R[x=1] = restrict R with x = 1
Apply XOR operation to this new BDDs
Q = R[x=0] xor R[x=1]
Enumerate all models of Q
Applying this to your examples:
R = {<0,0,1>, <1,0,1>, <0,0,0>} = (¬x ∧ ¬y ∧ z) ∨ (x ∧ ¬y ∧ z) ∨ (¬x ∧ ¬y ∧ ¬z)
R[x=1] = {<0,1>} = (¬y ∧ z)
R[x=0] = {<0,1>,<0,0>} = (¬y ∧ z) ∨ (¬y ∧ ¬z)
Q = R[x=1] xor R[x=0] = (¬y ∧ ¬z)
Intuition here is that XOR will cancel entries that occur in both BDDs.
This is easily (but with exponential complexity) generalized to the case with several abstracted variables.

Related

How do you use the Ring solver in Cubical Agda?

I have started playing around with Cubical Agda. Last thing I tried doing was building the type of integers (assuming the type of naturals is already defined) in a way similar to how it is done in classical mathematics (see the construction of integers on wikipedia). This is
data dInt : Set where
_⊝_ : ℕ → ℕ → dInt
canc : ∀ a b c d → a + d ≡ b + c → a ⊝ b ≡ c ⊝ d
trunc : isSet (dInt)
After doing that, I wanted to define addition
_++_ : dInt → dInt → dInt
(x ⊝ z) ++ (u ⊝ v) = (x + u) ⊝ (z + v)
(x ⊝ z) ++ canc a b c d u i = canc (x + a) (z + b) (x + c) (z + d) {! !} i
...
I am now stuck on the part between the two braces. A term of type x + a + (z + d) ≡ z + b + (x + c) is asked. Not wanting to prove this by hand, I wanted to use the ring solver made in Cubical Agda. But I could never manage to make it work, even trying to set it up for simple ring equalities like x + x + x ≡ 3 * x.
How can I make it work ? Is there a minimal example to make it work for naturals ? There is a file NatExamples.agda in the library, but it makes you have to rewrite your equalities in a convoluted way.
You can see how the solver for natural numbers is supposed to be used in this file in the cubical library:
Cubical/Tactics/NatSolver/Examples.agda
Note that this solver is different from the solver for commutative rings, which is designed for proving equations in abstract rings and is explained here:
Cubical/Tactics/CommRingSolver/Examples.agda
However, if I read your problem correctly, the equality you want to prove requires the use of other propositional equalities in Nat. This is not supported by any solver in the cubical library (as far as I know, also the standard library doesn't support it). But of course, you can use the solver for all the steps that don't use other equalities.
Just in case you didn't spot this: here is a definition of the integers in math-style using the SetQuotients of the cubical library. SetQuotients help you to avoid the work related to your third constructor trunc. This means you basically just need to show some constructions are well defined as you would in 'normal' math.
I've successfully used the ring solver for exactly the same problem: defining Int as a quotient of ℕ ⨯ ℕ. You can find the complete file here, the relevant parts are the following:
Non-cubical propositional equality to path equality:
open import Cubical.Core.Prelude renaming (_+_ to _+̂_)
open import Relation.Binary.PropositionalEquality renaming (refl to prefl; _≡_ to _=̂_) using ()
fromPropEq : ∀ {ℓ A} {x y : A} → _=̂_ {ℓ} {A} x y → x ≡ y
fromPropEq prefl = refl
An example of using the ring solver:
open import Function using (_$_)
import Data.Nat.Solver
open Data.Nat.Solver.+-*-Solver
using (prove; solve; _:=_; con; var; _:+_; _:*_; :-_; _:-_)
reorder : ∀ x y a b → (x +̂ a) +̂ (y +̂ b) ≡ (x +̂ y) +̂ (a +̂ b)
reorder x y a b = fromPropEq $ solve 4 (λ x y a b → (x :+ a) :+ (y :+ b) := (x :+ y) :+ (a :+ b)) prefl x y a b
So here, even though the ring solver gives us a proof of _=̂_, we can use _=̂_'s K and _≡_'s reflexivity to turn that into a path equality which can be used further downstream to e.g. prove that Int addition is representative-invariant.

can you help me to transform forall FO logical formula to it equivalent not exist formula?

i have this formula
∀x ∀y (A(x,y) V A(y,x) → B(y,c1) ∧ B(x,c2) ∧ c1≠c2)
to the equivalent formula that by using existential quantifier
?
∀x ∀y X is the same as ¬∃(x, y) ¬X
'X → Y' is the same as 'There is no counterexample when X but not Y'
¬(A(x,y) V A(y,x) → B(x,c1) ∧ B(x,c2) ∧ c1≠c2) = (A(x,y) V A(y,x)) ∧ ¬(B(x,c1) ∧ B(x,c2) ∧ c1≠c2)) - our counterexample. If we put negation of the second part in it and collect everything together, we get:
¬∃(x, y) (A(x,y) V A(y,x)) ∧ (¬B(x,c1) v ¬B(x,c2) v c1 = c2)
Update: replaced ¬∃x ¬∃ y with ¬∃(x, y). I suppose that's what you originally meant, right?
When you want to make that change, you basically want to find the opposite of what the inner statement says , because if a statement is true **for every ** x, then it means the opposite of it does not happen, ever; not exist means just that, there is no x such that makes the statement true.

How to formalize the definition of likeness/similarity between relations in Coq?

I am reading the book Introduction to Mathematics Philosophy by B.Russell and trying to formalize the definitions. Whereas I got stuck on proving the equivalence between the two definitions of similarity posed in the book.
Here are the text quoted from the book. (context)
1) Defining similarity directly:
We may define two relations P and Q as “similar,” or as having
“likeness,” when there is a one-one relation S whose domain is the
field of P and whose converse domain is the field of Q, and which is
such that, if one term has the relation P to another, the correlate of
the one has the relation Q to the correlate of the other, and vice
versa.
Here's my comprehension of the above text:
Inductive similar {X} (P : relation X) (Q : relation X) : Prop :=
| similar_intro : forall (S : relation X),
one_one S ->
(forall x, field P x <-> domain S x) ->
(forall x y z w, P x y -> S x z -> S y w -> Q z w) ->
(forall x y z w, Q z w -> S x z -> S y w -> P x y) ->
similar P Q.
2) Defining similarity through the concept of 'correlator':
A relation S is said to be a “correlator” or an “ordinal correlator”
of two relations P and Q if S is one-one, has the field of Q for its
converse domain, and is such that P is the relative product of S and Q
and the converse of S.
Two relations P and Q are said to be “similar,” or to have “likeness,”
when there is at least one correlator of P and Q.
My definition to this is:
Inductive correlator {X} (P Q : relation X) : relation X -> Prop :=
| correlator_intro : forall (S : relation X),
one_one S ->
(forall x, field P x <-> domain S x) ->
(forall x y, relative_product (relative_product S Q) (converse S) x y <-> P x y) ->
correlator P Q S.
Inductive similar' {X} (P Q : relation X) : Prop :=
| similar'_intro : forall S, correlator P Q S -> similar' P Q.
But I couldn't prove that similar is equivalent to similar', where did I make the mistake? Thanks a lot.

existential search and query without the fuss

Is there an extensible, efficient way to write existential statements in Haskell without implementing an embedded logic programming language? Oftentimes when I'm implementing algorithms, I want to express existentially quantified first-order statements like
∃x.∃y.x,y ∈ xs ∧ x ≠ y ∧ p x y
where ∈ is overloaded on lists. If I'm in a hurry, I might write perspicuous code that looks like
find p [] = False
find p (x:xs) = any (\y -> x /= y && (p x y || p y x)) xs || find p xs
or
find p xs = or [ x /= y && (p x y || p y x) | x <- xs, y <- xs]
But this approach doesn't generalize well to queries returning values or predicates or functions of multiple arities. For instance, even a simple statement like
∃x.∃y.x,y,z ∈ xs ∧ x ≠ y ≠ z ∧ f x y z = g x y z
requires writing another search procedure. And this means a considerable amount of boilerplate code. Of course, languages like Curry or Prolog that implement narrowing or a resolution engine allow the programmer to write statements like:
find(p,xs,z) = x ∈ xs & y ∈ xs & x =/= y & f x y =:= g x y =:= z
to abuse the notation considerably, which performs both a search and returns a value. This problem arises often when implementing formally specified algorithms, and is often solved by combinations of functions like fmap, foldr, and mapAccum, but mostly explicit recursion. Is there a more general and efficient, or just general and expressive, way to write code like this in Haskell?
There's a standard transformation that allows you to convert
∃x ∈ xs : P
to
exists (\x -> P) xs
If you need to produce a witness you can use find instead of exists.
The real nuisance of doing this kind of abstraction in Haskell as opposed to a logic language is that you really must pass the "universe" set xs as a parameter. I believe this is what brings in the "fuss" to which you refer in your title.
Of course you can, if you prefer, stuff the universal set (through which you are searching) into a monad. Then you can define your own versions of exists or find to work with the monadic state. To make it efficient, you can try Control.Monad.Logic, but it may involve breaking your head against Oleg's papers.
Anyway, the classic encoding is to replace all binding constructs, including existential and universal quantifiers, with lambdas, and proceed with appropriate function calls. My experience is that this encoding works even for complex nested queries with a lot of structure, but that it always feels clunky.
Maybe I don't understand something, but what's wrong with list comprehensions? Your second example becomes:
[(x,y,z) | x <- xs, y <- xs, z <- xs
, x /= y && y /= z && x /= z
, (p1 x y z) == (p2 x y z)]
This allows you to return values; to check if the formula is satisfied, just use null (it won't evaluate more than needed because of laziness).

Associativity in Lambda calculus

I am working on the exercise questions of book The Lambda calculus. One of the questions that I am stuck is proving the following:
Show that the application is not associative; in fact, x(yz) not equals (xy)z
Here is what I have worked on so far:
Let x = λa.λb. ab
Let y = λb.λc. bc
Let z = λa.λc. ac
(xy)z => ((λa.λb. ab) (λb.λc. bc)) (λa.λc. ac)
=> (λb. (λb.λc. bc) b) (λa.λc. ac)
=> (λb.λc. bc) (λa.λc. ac)
=> (λc. (λa.λc. ac) c)
x(yz) => (λa.λb. ab) ((λb.λc. bc) (λa.λc. ac))
=> (λb. ((λb.λc. bc) (λa.λc. ac)) b)
=> (λb. (λc. (λa.λc. ac) c) b)
Is this correct? Please help me understand.
I also think that your counter-example is correct.
You can probably get a simpler counter-example like this:
let x = λa.n and y, z variables then:
(xy)z => ((λa.n) y) z => n z
x(yz) => (λa.n) (y z) => n
The derivations seem fine, at a glance.
Conceptually, just think that x, y, and z can represent any computable functions, and clearly, some of those functions are not associative. Say, x is 'subtract 2', y is 'divide by 2', and z is 'double'. For this example, x(yz) = 'subtract 2' and (xy)z = 'substract 1'.
It seems ok, but for simplicity, how about prove by contradiction?
Assume (xy)z = x(yz), and let
x = λa.λb. a # x = const
y = λa. -a # y = negate
z = 1 # z = 1
and show that ((xy)z) 0 ≠ (x(yz)) 0.
The book you mention by Barendregt is extremely formal and precise (a great book), so it would be nice to have the precise statement of the exercise.
I guess the actual goal was to find instantiations for x, y and z such that
x (y z) reduces to the boolean true = \xy.x and (x y) z reduces to the boolean false = \xy.y
Then, you can take e.g. x = \z.true and z = I = \z.z (y arbitrary).
But how can we prove that true is not convertible with false? You have no way to prove it inside the calculus, since you have no negation: you can only prove equalities and not inequalities. However, let us observe that if true=false then all terms are equal.
Indeed, for any M and N, if true = false then
true M N = false M N
but true M N reduces to M, while false M N reduces to N, so
M = N
Hence, if true = false all terms would be equal, and the calculus would be trivial. Since we can find not trivial models of the lambda calculus, no such
model may equate true and false (more generally may equate terms with different normal forms, that would require us to talk about the bohm-out technique).

Resources