Prover9 hints not being used - logic

I'm running some Lattice proofs through Prover9/Mace4. I'm using a non-standard axiomatization of the lattice join operation, from which it is not immediately obvious that the join is commutative, associative and idempotent. (I can get Prover9 to prove that it is -- eventually.)
I know that Prover9 looks for those properties to help it search faster. I've tried putting those properties in the Additional Input section (I'm running the GUI version 0.5), with
formulas(hints).
x v y = y v x.
% etc
end_of_list.
Q1: Is this the way to get it to look at hints?
Q2: Is there a good place to look for help on speeding up proofs/tips and tricks?
(If I can get this to work, there are further operators I'd like to give hints for.)
For ref, my axioms are (bi-lattice with only one primitive operation):
x ^ y = y ^ x. % lattice meet
x ^ x = x.
(x ^ y) ^ z = x ^ (y ^ z).
x ^ (x v y) = x. % standard absorption for join
x ^ z = x & y ^ z = y <-> z ^ (x v y) = (x v y).
% non-standard absorption
(EDIT after DougS's answer posted.)
Wow! Thank you. Orders-of-magnitude speed-up.
Some follow-on q's if I might ...
Q3: The generated hints seem to include all of the initial axioms plus the goal -- is that what I should expect? (Presumably hence your comment about not needing all of the hints. I've certainly experienced that removing axioms makes a proof go faster.)
Q4: What if I add hints that (as it turns out) aren't justified by the axioms? Are they ignored?
Q5: What if I add hints that contradict the axioms? (From a few trials, this doesn't make Prover9 mis-infer.)
Q6: For a proof (attempt) that times out, is there any way to retrieve the formulas inferred so far and recycle them for hints to speed up the next attempt? (I have a feeling in my waters that this would drag in some sort of fallacy, despite what I've seen re Q3 and Q4.)

Q3: Yes, you should expect the axiom(s) and the goal(s) included as hints. Both of them can serve as useful. I more meant that you might see something like "$F" as a hint doesn't seem to add much to me, and that hints also lead you down a particular path first which can make it more difficult or easier to find shorter proofs. However, if you just want a faster proof, then using all of the suggested hints probably comes as the way to go.
Q4: Hints do NOT need to come as deducible from the axioms.
Q5: Hints can contradict the axioms, sure.
The manual says "A derived clause matches a hint if it subsumes the hint.
...
In short, the default value of the hints_part parameter says to select clauses that match hints (lightest first) whenever any are available."
"Clause C subsumes clause D if the variables of C can be instantiated in such a way that it becomes a subclause of D. If C subsumes D, then D can be discarded, because it is weaker than or equivalent to C. (There are some proof procedures that require retention of subsumed clauses.)"
So let's say that you put
1. x ^((y^z) V v)=x V y as a hint.
Then if Prover9 generates
2. x ^ ((x^x) V v)=x V x
x ^ ((x^x) V v)=x V x will get selected whenever it's available, since it matches the hint.
This explanation isn't complete, because I'm not exactly sure how "subclause" gets defined.
Still, instead of generating formulas with the original axioms and whatever procedure Prover9 uses to generate formulas, formulas that match hints will get put to the front of the list for generating formulas. This can pick up the speed of the program, but from what I've read about some other problems it seems that many difficult problems basically wouldn't have gotten proved automatically if it weren't for things like hints, weighting, and other strategies.
Q6: I'm not sure which formulas you're referring to. In Prover9, of course, you can click on "show output" and look through the dozens of formulas it has generated. You could also set lemmas you think of as useful as additional goals, and then use Prooftrans to generate hints from those lemmas to use as hints on the next run. Or you could use the steps of the proofs of those lemmas as hints for the next run. There's no fallacy in terms of reasoning if you use steps of those proofs as hints, or the hints suggested by Prooftrans, because hints don't actually add any assumptions to the initial set. The hint mechanism works, at least according to my somewhat rough understanding, by changing the search procedure to use a clause that matches a hint once we have something which matches a hint (that is, the program has to deduce something that matches a hint, and only then can what matches the hint get used).

Q1: Yes, that should work for hints. But, to better test it, take the proof you have, and then use the "reformat" option and check the "hints" part. Then copy and paste all of those hints into your "formulas(hints)." list. (well you don't necessarily need them all... and using only some of them might lead to a shorter proof if it exists, but I digress). Then run the proof again, and if it runs like my proofs in propositional calculi with hints do, you'll get the proof "in an instant".
Just in case... you'll need to click on the "additional input" tab, and put your hint list there.
Q2: For strategies, the Prover9 manual has useful information on weighting, hints, and semantic guidance (I haven't tried semantic guidance). You might also want to see Bob Veroff's page (some of his work got done in OTTER, but the programs are similar). There also exists useful information Larry Wos's notebooks, as well as Dr. Wos's published work, though all of Wos's recent work has gotten done using OTTER (again, the programs are similar).

Related

What does the / slash mean in this Prolog Predicate

Would anyone be able to explain to me what the forward slash '/' means in the context of this Prolog predicate. I've tried Googling it, reviewing other questions but I can't find a definitive answer, or at least one that makes sense to me. I'm aware of what arity is but I'm not sure this is related.
move_astar([Square | Path] / G / _, [NextSquare, Square | Path] / SumG / NewH) :-
square(Square, NextSquare, Distance),
not(member(NextSquare, Path)),
SumG is G + Distance,
heuristic(NextSquare, NewH).
It has no implicit meaning, and it is not the same as arity. Prolog terms are name(Arg1, Arg2) and / can be a name. /(Arg1, Arg2).
There is a syntax sugar which allows some names to be written inline, such as *(X,Y) as X * Y and /(X,Y) as X / Y which is useful so they look like arithmetic (but NB. this does not do arithmetic). Your code is using this syntax to keep three things together:
?- write_canonical([Square | Path] / G / _).
/(/([_|_],_),_)
That is, it has no more semantic meaning than xIIPANIKIIx(X,Y) would have, it's Ls/G/H kept together.
The / has no meaning here, except for being a structure and a left associative operator. So it is unrelated to division. Sometimes people like to add such decoration to their code. It is hard to tell if this serves anything from that single clause, but think of someone who just wants to refer to the list and the two values like in:
?- start(A), move_astar(A,A).
So here it would be much more compact to ask that question than to hand over each parameter manually.
Another use would be:
?- start(A), closure(move_astar, A,B).
Using closure/2. That is, existing predicates may expect a single argument.
It's an outdated style. It's bad because:
It conveys no useful information, apart from being a weird-looking delimiter
There's a slight performance hit for Prolog having to assemble and re-assemble those slash delimiters for parsing
It's better to either:
Keep parameters individual (and therefore fast to use)
Group parameters in a reasonably-named term, or e.g. v if brevity is more appropriate than classification of the term

How to understand the recursive search in Prolog?

Here is a section of Prolog code defining numeral in a recursive way:
numeral(0).
numeral(succ(X)) :- numeral(X).
When given query numeral(X). Prolog will return:
X = 0 ;
X = succ(0) ;
X = succ(succ(0)) ;
X = succ(succ(succ(0))) ;
X = succ(succ(succ(succ(0)))) ;
X = succ(succ(succ(succ(succ(0))))) ;
X = succ(succ(succ(succ(succ(succ(0)))))) ;
X = succ(succ(succ(succ(succ(succ(succ(0))))))) ;
X = succ(succ(succ(succ(succ(succ(succ(succ(0))))))))
yes
Based on what I have learned, when doing the query, prolog will firstly make X into a variable like (_G42), then it will search the facts and rules to find the match.
In this case, it will find 0 (fact) as a right match. Then it will also try to match the rule. That is considering _G42 is not 0, and _G42 is the succ of another number. Thus, another variable is generated(like _G44), _G44 will match 0 and will also go further like _G42. Since _G44 matches 0, then it will go backward to _G42, getting _G42 = succ(_G44) = succ(0).
I am not sure if I am right about the understanding. I made a diagram to show my comprehension on this problem.
If the analysis is correct, I still feel difficult to design the recursive function like this. Since I am new to Prolog, I want to know if this kind of definition always used in application (say building an expert system, verifying protocols) or it is just for beginners to better understanding the basic searching procedure? If it is often used, what is the key point to design this kind of recursive definition?
My personal opinion: Especially as a beginner, you have zero chance to"understand the recursive search in Prolog". Countless beginners are trying to understand Prolog in this way, and they very consistently fail.
The sad part is that this hits hardest workers the hardest: You always think you can somehow understand it, but in the end, you cannot, because there are too many ways to invoke even the simplest predicates, with uninstantiated and (partly) instantiated arguments, and even with aliased variables.
Your graph nicely illustrates that such a procedural reading gets extremely unwieldy very quickly for even the simplest conceivable recursive definitions.
A much more tractable approach for understanding the predicate is to read it declaratively:
0 is a numeral
If X is a numeral (whatever X is!), then succ(X) of X is also a numeral.
Note that :- even means &leftarrow;, i.e., an implication from right to left.
My recommendation is to focus on a clear declarative description of what ought to hold. To overcome the initial barriers with Prolog, you must let go the idea that you can trace the steps that the CPU performs in the extreme detail in which you are currently trying to follow it. Prolog is too high-level to be amenable to tracing in this low-level way. It is like trying to interpret between French and English by tracing only the neuronal activities of the speakers.
Write a clear definition and then leave the search to Prolog. There are many other and working ways to understand and break down declarative definitions without getting swamped in low-level details. See for example program-slicing and failure-slicing. They work as long as you stay in the so-called pure monotonic subset of Prolog. Focus on this area, and you will be able to make very fast progress.

Math inside predicate header

Is there a way to make this work?
add(X, X + 1)
input: add(1, Y).
expected output: Y = 2.
output: Y = 1+1.
Or is it only possible by doing this?
add(X, Y):- Y is X+1.
Historically, there have been many attempts to provide this functionality. Let me give as early examples CLP(ℜ) (about 1986) or more recently Prolog IV. However, sooner or later, one realizes that a programmer needs a finer control about the kind of unification that is employed. Take as example a program that wants to differentiate a formula. In that situation an interpreted functor would not be of any use. For this reason most constraints ship today as some added predicates leaving functors otherwise uninterpreted. In this manner they also fit into ISO-Prolog which permits constraints as extensions.
From a programmer's viewpoint, an extension as yours would reduce the number of auxiliary variables needed, however, it also would require to interpret all terms to this end which produces a lot of extra overhead.

Prolog: How to tell if a predicate is deterministic or not

So from what I understand about deterministic predicates:
Deterministic predicate = 1 solution
Non-deterministic predicate = multiple solutions
Are there any type of rules as to how you can detect if the predicate is one or the other? Like looking at the search tree, etc.
There is no clear, generally accepted consensus about these notions. However, they are usually based rather on the observed answers and not based on the number of solutions. In certain contexts the notions are very implementation related. Non-determinate may mean: leaves a choice point open. And sometimes determinate means: never even creates a choice point.
Answers vs. solutions
To see the difference, consider the goal length(L, 1). How many solutions does it have? L = [a] is one, L = [23] another... but all of these solutions are compactly represented with a single answer substitution: L = [_] which thus contains infinitely many solutions.
In any case, in all implementations I know of, length(L, 1) is a determinate goal.
Now consider the goal repeat which has exactly one solution, but infinitely many answers. This goal is considered non-determinate.
In case you are interested in constraints, things become even more evolved. In library(clpfd), the goal X #> Y, Y #> X has no solution, but still one answer. Combine this with repeat: infinitely many answers and no solution.
Further, the goal append(Xs, Ys, []) has exactly one solution and also exactly one answer, nevertheless it is considered non-determinate in many implementations, since in those implementations it leaves a choice point open.
In an ideal implementation, there would be no answers without solutions (except false), and there would be non-determinism only when there is more than one answer. But then, all of this is mostly undecidable in the general case.
So, whenever you are using these notions make sure on what level things are meant. Rather explicitly say: multiple answers, multiple solutions, leaves no (unnecessary) choice point open.
You need understand the difference between det, semidet and undet, it is more than just number of solutions.
Because there is no loop control operator in Prolog, looping (not recursion) is constructed as a 'sequence generating' predicate (undet) followed by the loop body. Also you can store solutions with some of findall-group predicates as a list and loop later with the member/2 predicate.
So, any piece of your program is either part of loop construction or part of usual flow. So, there is a difference in designing det and undet predicates almost in the intended usage. If you can work with a sequence you always do undet and comment it as so. There is a nice unit-test extension in swi-prolog which can check wheter your predicate always the same in mean of det/semidet/undet (semidet is for usage the same way as undet but as a head of 'if' construction).
So, the difference is pre-design, and this question should not be arised with already existing predicates. It is a good practice always comment the intended usage in a comment like.
% member(?El, ?List) is undet.
Deterministic: Always succeeds with a single answer that is always the same for the same input. Think a of a static list of three items, and you tell your function to return value one. You will get the same answer every time. Additionally, arithmetic functions. 1 + 1 = 2. X + Y = Z.
Semi-deterministic: Succeeds with a single answer that is always the same for the same input, but it can fail. Think of a function that takes a list of numbers, and you ask your function if some number exists in the list. It either does, or it doesn't, based on the contents of the list given and the number asked.
Non-deterministic: Succeeds with a single answer, but can exhibit different behaviors on different runs, even for the same input. Think any kind of math.random(min,max) function like random/3
In essence, this is entirely separate from the concept of choice points, as choice points are a function of Prolog. Where I think the Prolog confusion of these terms comes from is that Prolog can find a single answer, then go back and try for another solution, and you have to use the cut operator ! to tell it that you want to discard your choice points explicitly.
This is very useful to know when working with Prolog Unit Testing

Iterative solving for unknowns in a fluids problem

I am a Mechanical engineer with a computer scientist question. This is an example of what the equations I'm working with are like:
x = √((y-z)×2/r)
z = f×(L/D)×(x/2g)
f = something crazy with x in it
etc…(there are more equations with x in it)
The situation is this:
I need r to find x, but I need x to find z. I also need x to find f which is a part of finding z. So I guess a value for x, and then I use that value to find r and f. Then I go back and use the value I found for r and f to find x. I keep doing this until the guess and the calculated are the same.
My question is:
How do I get the computer to do this? I've been using mathcad, but an example in another language like C++ is fine.
The very first thing you should do faced with iterative algorithms is write down on paper the sequence that will result from your idea:
Eg.:
x_0 = ..., f_0 = ..., r_0 = ...
x_1 = ..., f_1 = ..., r_1 = ...
...
x_n = ..., f_n = ..., r_n = ...
Now, you have an idea of what you should implement (even if you don't know how). If you don't manage to find a closed form expression for one of the x_i, r_i or whatever_i, you will need to solve one dimensional equations numerically. This will imply more work.
Now, for the implementation part, if you never wrote a program, you should seriously ask someone live who can help you (or hire an intern and have him write the code). We cannot help you beginning from scratch with, eg. C programming, but we are willing to help you with specific problems which should arise when you write the program.
Please note that your algorithm is not guaranteed to converge, even if you strongly think there is a unique solution. Solving non linear equations is a difficult subject.
It appears that mathcad has many abstractions for iterative algorithms without the need to actually implement them directly using a "lower level" language. Perhaps this question is better suited for the mathcad forums at:
http://communities.ptc.com/index.jspa
If you are using Mathcad, it has the functionality built in. It is called solve block.
Start with the keyword "given"
Given
define the guess values for all unknowns
x:=2
f:=3
r:=2
...
define your constraints
x = √((y-z)×2/r)
z = f×(L/D)×(x/2g)
f = something crazy with x in it
etc…(there are more equations with x in it)
calculate the solution
find(x, y, z, r, ...)=
Check Mathcad help or Quicksheets for examples of the exact syntax.
The simple answer to your question is this pseudo-code:
X = startingX;
lastF = Infinity;
F = 0;
tolerance = 1e-10;
while ((lastF - F)^2 > tolerance)
{
lastF = F;
X = ?;
R = ?;
F = FunctionOf(X,R);
}
This may not do what you expect at all. It may give a valid but nonsense answer or it may loop endlessly between alternate wrong answers.
This is standard substitution to convergence. There are more advanced techniques like DIIS but I'm not sure you want to go there. I found this article while figuring out if I want to go there.
In general, it really pays to think about how you can transform your problem into an easier problem.
In my experience it is better to pose your problem as a univariate bounded root-finding problem and use Brent's Method if you can
Next worst option is multivariate minimization with something like BFGS.
Iterative solutions are horrible, but are more easily solved once you think of them as X2 = f(X1) where X is the input vector and you're trying to reduce the difference between X1 and X2.
As the commenters have noted, the mathematical aspects of your question are beyond the scope of the help you can expect here, and are even beyond the help you could be offered based on the detail you posted.
However, I think that even if you understood the mathematics thoroughly there are computer science aspects to your question that should be addressed.
When you write your code, try to make organize it into functions that depend only upon the parameters you are passing in to a subroutine. So write a subroutine that takes in values for y, z, and r and returns you x. Make another that takes in f,L,D,G and returns z. Now you have testable routines that you can check to make sure they are computing correctly. Check the input values to your routines in the routines - for instance in computing x you will get a divide by 0 error if you pass in a 0 for r. Think about how you want to handle this.
If you are going to solve this problem interatively you will need a method that will decide, based on the results of one iteration, what the values for the next iteration will be. This also should be encapsulated within a subroutine. Now if you are using a language that allows only one value to be returned from a subroutine (which is most common computation languages C, C++, Java, C#) you need to package up all your variables into some kind of data structure to return them. You could use an array of reals or doubles, but it would be nicer to choose to make an object and then you can reference the variables by their name and not their position (less chance of error).
Another aspect of iteration is knowing when to stop. Certainly you'll do so when you get a solution that converges. Make this decision into another subroutine. Now when you need to change the convergence criteria there is only one place in the code to go to. But you need to consider other reasons for stopping - what do you do if your solution starts diverging instead of converging? How many iterations will you allow the run to go before giving up?
Another aspect of iteration of a computer is round-off error. Mathematically 10^40/10^38 is 100. Mathematically 10^20 + 1 > 10^20. These statements are not true in most computations. Your calculations may need to take this into account or you will end up with numbers that are garbage. This is an example of a cross-cutting concern that does not lend itself to encapsulation in a subroutine.
I would suggest that you go look at the Python language, and the pythonxy.com extensions. There are people in the associated forums that would be a good resource for helping you learn how to do iterative solving of a system of equations.

Resources