Deciding inhabitation? - logic

Consider the basic system of simple types usually known as TAλ. One can prove that (as a consequence of the so called Subject Reduction Property and the fact that any typable term is strongly β-normalising)
If τ has an inhabitant, then it has one in β-normal form.
It follows that given an inhabitation problem Γ ⊢ X : τ we can effectively construct an algorithm that nondeterministically guesses step by step the shape of a normal solution: either (i) X is xY_1...Y_n or (ii) X is λz.Y:
(i) If for some n ≥ 0 there a judgment x : σ_1 → ... → σ_n → τ in Γ, then nondeterministically select it, set X = xY_1...Y_n and (only if n > 0) consider parallel problems
Γ ⊢ Y_1 : σ_1,...,Γ ⊢ Y_n : σ_n
(ii) If τ is τ_1 → τ_2, then for a fresh variable z, set X = λz.Y and consider the problem
Γ, z : τ_1 ⊢ Y : τ_2.
Furthermore, since all types in the constraints at each step of the algorithm are proper subtypes of the original input, the number of steps of the algorithm is at most polynomial in the size of τ. Therefore, the algorithm above is a decision procedure for the inhabitation problem.
My question is the following: what's wrong in the above reasoning? I've been searching all day for a decision procedure for the inhabitation problem for simple types, but all the proofs I can find are rather long and use complicated machinery (e.g. long normal forms, Curry-Howard isomorphism, etc...). There must be something that I don't see.
Sorry, I'm not used to unicode and SO doesn't support LaTeX. I also asked the same question on MO https://mathoverflow.net/questions/140045/is-there-an-easy-decision-algorithm-for-the-inhabitation-problem-for-simple-type, but the lambda calculus group doesn't seem too active there.

Related

Combine boolean and integer logic in linear arithmetic using the Z3 Solver?

I would like to solve problems combining boolean and integer logic in linear arithmetic with a SAT/SMT solver. At first glance, Z3 seems promising.
First of all, is it at all possible to solve the following problem? This answer makes it seem like it works.
int x,y,z
boolean a,b,c
( (3x + y - 2z >= 10) OR (A AND (NOT B OR C)) OR ((A == C) AND (x + y >= 5)) )
If so, how does Z3 solve this kind of problem in theory and is there any documentation about it?
I could think of two ways to solve this problem. One would be to convert the Boolean operations into a linear integer expression. Another solution I read about is to use the Nelson-Oppen Combination Method described in [Kro 08].
I found a corresponding documentation in chapter 3.2.2. Solving Arithmetical Fragments, Table 1 a listing of the implemented algorithms for a certain logic.
Yes, SMT solvers are quite good at solving problems of this sort. Your problem can be expressed using z3's Python interface like this:
from z3 import *
x, y, z = Ints('x y z')
A, B, C = Bools('A B C')
solve (Or(3*x + y - 2*z >= 10
, And(A, Or(Not(B), C))
, And(A == C, x + y >= 5)))
This prints:
[A = True, z = 3, y = 0, B = True, C = True, x = 5]
giving you a (not necessarily "the") model that satisfies your constraints.
SMT solvers can deal with integers, machine words (i.e., bit-vectors), reals, along with many other data types, and there are efficient procedures for combinations of linear-integer-arithmetic, booleans, uninterpreted-functions, bit-vectors amongst many others.
See http://smtlib.cs.uiowa.edu for many resources on SMT solving, including references to other work. Any given solver (i.e., z3, yices, cvc etc.) will be a collection of various algorithms, heuristics and tactics. It's hard to compare them directly as each shine in their own way for certain sublogics, but for the base set of linear-integer arithmetic, booleans, and bit-vectors, they should all perform fairly well. Looks like you already found some good references, so you can do further reading as necessary; though for most end users it's neither necessary nor that important to know how an SMT solver internally works.

How to implement a union-find (disjoint set) data structure in Coq?

I am quite new to Coq, but for my project I have to use a union-find data structure in Coq. Are there any implementations of the union-find (disjoint set) data structure in Coq?
If not, can someone provide an implementation or some ideas? It doesn't have to be very efficient. (no need to do path compression or all the fancy optimizations) I just need a data structure that can hold an arbitrary data type (or nat if it's too hard) and perform: union and find.
Thanks in advance
If all you need is a mathematical model, with no concern for actual performance, I would go for the most straightforward one: a functional map (finite partial function) in which each element optionally links to another element with which it has been merged.
If an element links to nothing, then its canonical representative is itself.
If an element links to another element, then its canonical representative is the canonical representative of that other element.
Note: in the remaining of this answer, as is standard with union-find, I will assume that elements are simply natural numbers. If you want another type of elements, simply have another map that binds all elements to unique numbers.
Then you would define a function find : UnionFind → nat → nat that returns the canonical representative of a given element, by following links as long as you can. Notice that the function would use recursion, whose termination argument is not trivial. To make it happen, I think that the easiest way is to maintain the invariant that a number only links to a lesser number (i.e. if i links to j, then i > j). Then the recursion terminates because, when following links, the current element is a decreasing natural number.
Defining the function union : UnionFind → nat → nat → UnionFind is easier: union m i j simply returns an updated map with max i' j' linking to min i' j', where i' = find m i and j' = find m j.
[Side note on performance: maintaining the invariant means that you cannot adequately choose which of a pair of partitions to merge into the other, based on their ranks; however you can still implement path compression if you want!]
As for which data structure exactly to use for the map: there are several available.
The standard library (look under the title FSets) has several implementations (FMapList, FMapPositive and so on) satisfying the interface FMapInterface.
The stdpp libray has gmap.
Again if performance is not a concern, just pick the simplest encoding or, more importantly, the one that makes your proofs the simplest. I am thinking of just a list of natural numbers.
The positions of the list are the elements in reverse order.
The values of the list are offsets, i.e. the number of positions to skip forward in order to reach the target of the link.
For an element i linking to j (i > j), the offset is i − j.
For a canonical representative, the offset is zero.
With my best pseudo-ASCII-art skills, here is a map where the links are { 6↦2, 4↦2, 3↦0, 2↦1 } and the canonical representatives are { 5, 1, 0 }:
6 5 4 3 2 1 0 element
↓ ↓ ↓ ↓ ↓ ↓ ↓
/‾‾‾‾‾‾‾‾‾↘
[ 4 ; 0 ; 2 ; 3 ; 1 ; 0 ; 0 ] map
\ \____↗↗ \_↗
\___________/
The motivation is that the invariant discussed above is then enforced structurally. Hence, there is hope that find could actually be defined by structural induction (on the structure of the list), and have termination for free.
A related paper is: Sylvain Conchon and Jean-Christophe Filliâtre. A Persistent Union-Find Data Structure. In ACM SIGPLAN Workshop on ML.
It describes the implementation of an efficient union-find data structure in ML, that is persistent from the user perspective, but uses mutation internally. What may be more interesting for you, is that they prove it correct in Coq, which implies that they have a Coq model for union-find. However, this model reflects the memory store for the imperative program that they seek to prove correct. I’m not sure how applicable it is to your problem.
Maëlan has a good answer, but for an even simpler and more inefficient disjoint set data structure, you can just use functions to nat to represent them. This avoids any termination stickiness. In essence, the preimages of any total function form disjoint sets over the domain. Another way of looking at this is as representing any disjoint set G as the curried application find_root G : nat -> nat since find_root is the essential interface that disjoint sets provide.
This is also analogous to using functions to represent Maps in Coq like in Software Foundations. https://softwarefoundations.cis.upenn.edu/lf-current/Maps.html
Require Import Arith.
Search eq_nat_decide.
(* disjoint set *)
Definition ds := nat -> nat.
Definition init_ds : ds := fun x => x.
Definition find_root (g : ds) x := g x.
Definition in_same_set (g : ds) x y :=
eq_nat_decide (g x) (g y).
Definition union (g : ds) x y : ds :=
fun z =>
if in_same_set g x z
then find_root g y
else find_root g z.
You can also make it generic over the type held in the disjoint set like so
Definition ds (a : Type) := a -> nat.
Definition find_root {a} (g : ds a) x := g x.
Definition in_same_set {a} (g : ds a) x y :=
eq_nat_decide (g x) (g y).
Definition union {a} (g : ds a) x y : ds a :=
fun z =>
if in_same_set g x z
then find_root g y
else find_root g z.
To initialize the disjoint set for a particular a, you need an Enum instance for your type a basically.
Definition init_bool_ds : ds bool := fun x => if x then 0 else 1.
You may want to trade out eq_nat_decide for eqb or some other roughly equivalent thing depending on your proof style and needs.

Expanding all definitions in Isabelle lemma

How can I tell Isabelle to expand all my definitions, please, because that way the proof is trivial? Unfortunately there is no default expansion or simplification happens, and basically I get back the original expression as the subgoal.
Example:
theory Test
imports Main
begin
definition b0 :: "nat⇒nat"
where "b0 n ≡ (n mod 2)"
definition b1 :: "nat⇒nat"
where "b1 n ≡ (n div 2)"
lemma "(a::nat)≤3 ∧ (b::nat)≤3 ⟶
2*(b1 a)+(b0 a)+2*(b1 b)+(b0 b) = a+b"
apply auto
oops
end
Respose before oops:
proof (prove)
goal (1 subgoal):
1. a ≤ 3 ⟹
b ≤ 3 ⟹ 2 * b1 a + b0 a + 2 * b1 b + b0 b = a + b
My recommendation: unfolding
There is a special keyword unfolding for unpacking definitions at the start of proofs. For your example this would read:
unfolding b0_def b1_def by simp
I consider unfolding the most elegant way. It also helps while writing the proofs. Internally, this is (mostly?) equivalent to using the unfold-method:
apply (unfold b0_def b1_def) by simp
This will recursively (!) use the set of equalities you supply to rewrite the proof goal. (Due to the recursion, you should rather not supply a set of equalities that could generate cycles...)
Alternative: Using the simplifier
In cases with possible loops, the simplifier might be able to reach a nice unfolding without running into these cycles, maybe by interleaving with other simplifications. In such cases, by (simp add: b0_def b1_def), as you've suggested, is great!
Alternative definition: Maybe it's just an abbreviation (and no definition)?
If you find yourself unfolding a definition in every single instance, you could consider, using abbreviation instead of definition. Then, some Isabelle magic will do the packing/unpacking for you without further hints. abbeviation does only affect how the user communicates with Isabelle. It does not introduce new symbols at the object level, and consequently, there would be no b1_def facts and the like.
abbreviation b0 :: "nat⇒nat"
where "b0 n ≡ (n mod 2)"
Usually not recommended: Building something like an abbreviation using the simplifier
If you (for whatever reason) want to have a defined name at the object level, but unfold it in almost every instance, you can also feed the defining equality directly into the simplifier.
definition b0 :: "nat⇒nat"
where [simp]: "b0 n ≡ (n mod 2)"
(Usually there should be little reason for the last option.)
Yes, I keep forgetting that definitions are not used in simplifications by default.
Adding the definitions explicitly to the simplification rules solves this problem:
lemma "(a::nat)≤3 ∧ (b::nat)≤3 ⟶
2*(b1 a)+(b0 a)+2*(b1 b)+(b0 b) = a+b"
by (simp add: b0_def b1_def)
This way the definitions (b0, b1) are correctly used.

How to Implement a Trig Identity Proving Algorithm

How could I implement a program that takes in the two sides of a trig equation (could be generalized to anything but for now I'll leave it at just trig identities) and the program will output the steps to transform one side into another (or transform them both) to show that they are in fact equal. The program will assume that they are equal in the first place. I am quite stumped as to how I might implement an algorithm to do this. My first thought was something to do with graphs, but I couldn't think of anything beyond this. From there, I thought that I should first parse both sides of the equation into trees. For example (cot x * sin) / (sin x + cos x) would look like this:
division
/ \
* +
/ \ / \
cot sin sin cos
After this, I had two similar ideas, both of which have problems. The first idea was to pick the side with the least number of leaves and try to manipulate it into the other side by using equivalencies that would be represented by "tree regexs." Examples of these "tree regexs" would be csc = 1 / sin or cot = cos / sin (in tree form of course), etc. My second idea would be to pick the side with more leaves and try to find some expression that when multiplied by that expression would equal the other side. Using reciprocals this wouldn't be too bad, however, I would then have to prove that the thing I multiplied by equals 1. Again I am back to this "tree regex" thing.
The major flaw with both of these is in what order/how could I apply these substitutions. Will it just have to be a big mess of if statements or is there a more elegant solution? Is there actually a graph-based solution that I'm not seeing. What (if any) might be a good algorithm to prove trig identities.
To be clear I am not talking about the "solve for x" type problem such as tan(x)sin(x) = 5, find all values of x but rather prove that sqrt((1 + sin x) / (1 - sin x)) = sec x + tan x
This is a simple algorithm for deciding trigonometric identities that can be brought into the form polynomial(sin x, cos x) = 0 :
Get rid of tan x, cot x, sec x, ..., sin 2x, ... by the obvious substitutions (tan x -> (sin x)/(cos x), ..., sin 2x -> 2 (sin x) (cos x), ...)
Transform identity to polynomial by squaring (isolated) roots (getting rid of multiple roots in an identity can be tricky, though), multiplying with denominators and bringing all expanded terms to one side
Replace all terms cos^2 x in the polynomial (cos^3 x = (cos^2 x)(cos x), cos^4 x = (cos^2 x)(cos^2 x), ...) by 1 - sin^2 x and expand the polynomial.
Finally a polynomial without cos^2 x is computed. If it is identical to 0 the identity is proven, otherwise the identity does not hold.
Your example sqrt((1 + sin x)/(1 - sin x)) = sec x + tan x:
Using the substitutions sec x -> 1/(cos x) and tan x -> (sin x)/(cos x) we get
sqrt((1 + sin x)/(1 - sin x)) = 1/(cos x) + (sin x)/(cos x).
For brevity let us write s instead of sin x and c instead of cos x, which gives us:
sqrt((1 + s)/(1 - s)) = 1/c + s/c
Squaring the equation and multiplying both sides with (1 - s)c^2 we get
(1 + s)c^2 = (1 + s)^2(1 - s).
Expanding the parenthesis and bringing everthing to one side we get
c^2 - sc^2 + s^3 + s^2 - s - 1 = 0
Substituting c^2 = 1 - s^2 into the polynomial we get
(1 - s^2) - s(1 - s^2) + s^3 + s^2 - s - 1 which expands to 0.
Hence the identity is proven.
Look out for texts on computer algebra (which I haven't), I'm sure you'll find clever ideas there.
My approach would be a graph-based search, as I doubt that a linear application of transformations will reliably lead to a solution.
Express the whole equation as an expression-tree the way you already started, but including an "equals" node above.
For the search-graph view, take one expression-tree as one search-state. The search-target is a decidable expression-tree like 1=1 or 1=0. When searching (expanding a search-state), create the child states by applying equivalence transformations on your expression (regex-like sounds quite plausible to me). Define an evaluation function that counts the overall complexity of an expression (e.g. number of nodes in the expression-tree). Do a directed search minimizing the evaluation function (expanding the lowest-complexity expression first), thus simplifying the expression until you reach a decidable form.
Depending on the expressions, it's quite possible that an unrestricted search never terminates. I don't know how you'd handle that, maybe by limiting the allowed complexity of expressions to some multiple of the original one. That would reduce the risk of running indefinitely, but leave you with undecided cases.

Combinator logic axioms

I'm carrying out some experiments in theorem proving with combinator logic, which is looking promising, but there's one stumbling block: it has been pointed out that in combinator logic it is true that e.g. I = SKK but this is not a theorem, it has to be added as an axiom. Does anyone know of a complete list of the axioms that need to be added?
Edit: You can of course prove by hand that I = SKK, but unless I'm missing something, it's not a theorem within the system of combinator logic with equality. That having been said, you can just macro expand I to SKK... but I'm still missing something important. Taking the set of clauses p(X) and ~p(X), which easily resolve to a contradiction in ordinary first-order logic, and converting them to SK, performing substitution and evaluating all calls of S and K, my program generates the following (where I am using ' for Unlambda's backtick):
''eq ''s ''s ''s 'k s ''s ''s 'k s ''s 'k k 'k eq ''s ''s 'k s 'k k 'k k ''s 'k k 'k false 'k true 'k true
It looks like maybe what I need is an appropriate set of rules for handling the partial calls 'k and ''s, I'm just not seeing what those rules should be, and all the literature I can find in this area was written for a target audience of mathematicians not programmers. I suspect the answer is probably quite simple once you understand it.
Some textbooks define I as mere alias for ((S K) K). In this case they are identical (as terms) per definitionem. To prove their equality (as functions), we need only to prove that equality is reflexive, which can be achieved by a reflexivity axiom scheme:
Proposition ``E = E'' is deducible (Reflexivity axiom scheme, instantiated for each possible terms denoted here by metavariable E)
Thus, I suppose in the followings, that Your questions investigates another approach: when combinator I is not defined as a mere alias for compound term ((S K) K), but introduced as a standalone basic combinator constant on its own, whose operational semantics is declared explicitly by axiom scheme
``(I E) = E'' is deducible (I-axiom scheme)
I suppose Your question asks
whether we can deduce formally (remaining inside the system), that such a standalone-defined I behaves exactly as ((S K) K), when used as functions in reductions?
I think we can, but we must resort to stronger tools. I conjecture that the usual axiom schemes are not enough, we have to declare also the extensionality property (equality of functions), that's the main point. If we want to formalize extensionality as an axiom, we have to augment our object language with free variables.
I think, we have to adopt such an approach for building combinatory logic, that we have to allow also the use of variables in the object langauge. Oof course, I mean "just" free valuables. Using bound variables would be cheating, we have to remain inside the realm of combinatory logic. Using free varaibles is not cheating, it's a honest tool. Thus, we can do the formal proof You required.
Besides the straightforward equality axioms and rules of inference (transitivity, reflexivity, symmetry, Leibniz rules), we must add an extensionality rule of inference for equality. Here is the point where free variables matter.
In Csörnyei 2007: 157-158, I have found the following approach. I think this way the proof can be done.
Some remarks:
Most of the axioms are in fact axiom schemes, consisting of infinitely many axiom instances. The instances must be instantiated for for every possible E, F, G terms. Here, I use italics for metavariables.
The superficial infinite nature of axiom schemes won't raise computability problems, because they can be tackled in a finite time: our axiom system is recursive. It means that a clever parser can decide in a finite time (moreover, very effectively), whether a given proposition is an instance of an axiom scheme, or not. Thus, the usage of axiom schemes does not raise neither theoretical nor practical problems.
Now let us seem our framework:
Language
ALPHABET
Constants: The following three are called constants: K, S, I.
I added the constant I only because Your question presupposes that we have not defined the combinator I as an mere alias/macro for compound term S K K, but it is a standalone constant on its own.
I shall denote constants by boldface roman capitals.
Sign of application: A sign # of ``application'' is enough (prefix notation with arity 2). As syntactic sugar, I use here parantheses instead of the explicit application sign: I shall use the explicit both opening ( and closing ) signs.
Variables: Although combinator logic does not make use of bound variables, scope etc, but we can introduce free variables. I suspect, they are not only syntactic sugar, they can strengthen the deduction system, too. I conjecture, that Your question will require their usage. Any enumerable infinite set (disjoint of the constants and parenthesis signs) will serve as the alphabet of variables, I will denote them here with unformatted roman lowercase letters x, y, z...
TERMS
Terms are defined inductively:
Any constant is a term
Any variable is a term
If E is a term, and F is a term too, then also (E F) is a term
I sometimes use practical conventions as syntactic sugar, e.g. write
E F G H
instead of
(((E F) G) H).
Deduction
Conversion axiom schemes:
``K E F = E'' is deducible (K-axiom scheme)
``S F G H = F H (G H)'' is deducible (S-axiom scheme)
``I E = E'' is deducible (I-axiom scheme)
I added the third conversion axiom (I rule) only because Your question presupposes that we have not defined the combinator I as an alias/macro for S K K.
Equality axiom schemes and rules of inference
``E = E'' is deducible (Reflexivity axiom)
If "E = F" is deducible, then "F = E" is also deducible (Symmetry rule of inference)
If "E = F" is deducible, and "F = G" is deducible too, then also "E = G" is reducible (Transitivity rule)
If "E = F" is deducible, then "E G = F G" is also deducible (Leibniz rule I)
If "E = F" is deducible, then "G E = G F" is also deducible (Leibniz rule II)
Question
Now let us investigate Your question. I conjecture that the deduction system defined so far is not strong enough to prove Your question.
Is proposition "I = S K K" deducible?
The problem is, that we have to prove the equivalence of functions. We regard two functions equivalent if they behave the same way. Functions act so that they are applied to arguments. We should prove that both functions act the same way if applied to each possible arguments. Again, the problem with infinity! I suspect, axioms schemes can't help us here. Something like
If E F = G F is deducible, then also E = G is deducible
would fail to do the job: we can see that this does not yield what we want. Using it, we can prove that
``I E = S K K E'' is deducible
for each E term instance, but these results are only separated instances of, and cannot be used as a whole for further deductions. We have only concrete results (infinitely many), not being able to summarize them:
it holds for E := K
holds for E := S
it holds for E := K K
.
.
.
...
we cannot summarize these fragmented result instances into a single great result, stating extensionality! We cannot pour these low-value fragment into the funnel a rule of inference that would melt them together into a single more valuable result.
We have to augment the power of our deduction system. We have to find a formal tool that can grasps the problem. Your questions leads to extensionality, and I think, declaring extensionality needs that we can pose propositions that hold for *****arbitrary***** instances. That's why I think we must allow free variables inside our object language. I conjecture that the following additional rule of inference will do the work:
If variable x is not part of terms neither E nor F, and statement (E x) = (F x) is deducible, then E = F is also deducible (Extensionality rule of inference)
The hard thing in this axiom, easily leading to confusion: x is an object variables, fully emancipated and respected parts of our object language, while E and G are metavariables, not parts of the object language, but used only for a concise notation of axiom schemes.
(Remark: More precisely, the extensionality rule of inference should be formalized in a more careful way, introducing a metavariable x over all possible object variables x, y, z..., and also another kind of metavariable E over all possible term instances. But this distinction among the two kinds of metavariables plus the object variables is not so didactic here, it does not affect Your question too much.)
Proof
Let us prove now the proposition that ``I = S K K''.
Steps for left-hand side:
proposition ``I x = x'' is an instance of I-axiom scheme with instatiation [E := x]
Steps for right-hand side:
Proposition "S K K x = K x (K x)" is an instance of S-axiom scheme with instantiations [E := K, F := K, G := x], thus it is deducible
Proposition "K x (K x) = x" is an instance of K-axiom scheme with instantiations [E := x, F := K x], thus it is deducible
Transitivity of equality:
Statement "S K K x = K x (K x)" matches the first premise of transitivity rule of inference, and statement "K x (K x) = x" matches the second premise of this rule of inference. The instantiations are [E := S K K x, F := K x (K x), G = x]. Thus the conclusion holds too: E = G. Rewriting the conclusion with the same instantiations, we get statement "S K K x = x", thus, this is deducible.
Symmetry of equality:
Using "S K K x = x", we can infer "x = S K K x"
Transitivity of equality:
Using "I x = x" and "x = S K K x", we can infer "I x = S K K x"
Now we have paved the way for the crucial point:
Proposition "I x = S K K x" matches with the first premise of Extension rule of inference: (E x) = (F x), with instantiations [E := I, F := S K K]. Thus the conclusion must also hold, that is, "E = F" with the same instantiations ([E := I, F := S K K]), yielding proposition "I = S K K", quod erat demonstrandum.
Csörnyei, Zoltán (2007): Lambda-kalkulus. A funkcionális programozás alapjai. Budapest: Typotex. ISBN-978-963-9664-46-3.
You don't need to define I as an axiom. Start with the following:
I.x = x
K.x y = x
S.x y z = x z (y z)
Since SKanything = anything, then SKanything is an identity function, just like I.
So, I = SKK and I = SKS. No need to define I as an axiom, you can define it as syntax sugar which aliases SKK.
The definitions of S and K are you only axioms.
The usual axioms are complete for beta equality, but do not give eta equality. Curry found a set of about thirty axioms to the usual ones to get completeness for beta-eta equality. They're listed in Hindley & Seldin's Introduction to combinators and lambda-calculus.
Roger Hindley, Curry's Last Problem, lists some additional desiderata we might want from mappings between the lambda calculus and notes that we don't have mappings that satisfy all of them. You likely won't care much about all of the criteria.

Resources