what is the item followed by square bracket in prolog? A relation, a variable, or a function...? - datalog

I am new to prolog, and I was trying to write rules for shortest path finding, I tried many times writing rules like path(X, Y) := ... and they never work as intented, until I find these rules
(path[X,Y]==P) <= ((path[X,Z]==P2) & nextTo(Z,Y)
& (X!=Y) & (X._not_in(P2)) & (Y._not_in(P2))
& (P==P2+[Z]))
(path[X,Y]==P) <= nextTo(X,Y) & (P==[])
and it works like a charm. The tool is pydatalog.
The rules are very similar with what I have been trying (of course there are other mistakes in my code), but I was keep using round bracket path(X, Y) := .... I have never seen terms followed with square brackets like (path[X,Y]==P) <= ... before, is path[X,Y] a relation? a function? or a term? I googled but coundn't find satisfying answers.

Related

Programming the Quadratic Formula in Prolog

First of all, I saw this same question being asked earlier today and I decided to give it a try myself (and had trouble with it). I hope it's alright that I created a new question for this!
I'm trying to make a prolog program that solves the quadratic formula X = ​(​​−b±√​b​2​​−4ac)​/2a. The implemented predicate quadratic([A,B,C], [Result]) takes a list of a, b and c as an the first argument and a list of the result(s) as the second. The lists are giving me trouble however; I wrote this code:
quadratic([A,B,C], [X]):-
underRoot([A,B,C], UnderRootResult),
UnderRootResult<0,
X is 0.
quadratic([A,B,C], [X]):-
underRoot([A,B,C], UnderRootResult),
UnderRootResult=:=0,
X is -B/2*A.
quadratic([A,B,C], [X]):-
underRoot([A,B,C], UnderRootResult),
UnderRootResult>0,
X is -B - sqrt(UnderRootResult)/2*A,
X is -B + sqrt(UnderRootResult)/2*A.
(This is probably full of mistakes, so excuse me in advance)
Running this will give me the undefined procedure error for underRoot/2. I don't really get why this happens. I feel like I have the general idea of how to program this but that I'm making lots of newbie mistakes. I can;t seem to find out what the problem is though, so I would appreciate any help!
edit: Also, if I'm allowed to ask two questions at once, how would I get both X's in the case of >0 in a list as one result?
There are many things here. First of all, usually all calls in the body are put on the same column, but that is not really an error.
Furthermore I do not find an underRoot/2 predicate. We can implement one like:
underRoot([A,B,C],X) :-
X is B*B-4*A*C.
Furthermore you always put [X] in the head of the clauses. But in case UnderRoot is less than zero, there are no solutions, so the list should be []. Furthermore in case UnderRoot > 0, there are two solutions, so the solution should be [X1,X2].
Finally if you write -B/2*A, it will be interpreted like: (-B/2)*A, so you will multiply with A. So you will need to use -B/(2*A).
So this brings us to a following proposal:
quadratic(L, []) :-
underRoot(L, U),
U < 0.
quadratic([A,B,C], [X]) :-
underRoot([A,B,C],0),
X is -B/(2*A).
quadratic([A,B,C], [X1, X2]) :-
underRoot([A,B,C],U) :-
SU is sqrt(U),
X1 is (-B-SU)/(2*A),
X2 is (-B+SU)/(2*A).

Representing syntactically different terms in TPTP

I am having a look at first order logic theorem provers such as Vampire and E-Prover, and the TPTP syntax seems to be the way to go. I am more familiar with Logic Programming syntaxes such as Answer Set Programming and Prolog, and although I try refering to a detailed description of the TPTP syntax I still don't seem to grasp how to properly distinguish between interpreted and non interpreted functor (and I might be using the terminology wrong).
Essentially, I am trying to prove a theorem by showing that no model acts as a counter-example. My first difficulty was that I did not expect the following logic program to be satisfiable.
fof(all_foo, axiom, ![X] : (pred(X) => (X = foo))).
fof(exists_bar, axiom, pred(bar)).
It is indeed satisfiable because nothing prevents bar from being equal to foo. So a first solution would be to insist that these two terms are distinct and we obtain the following unsatisfiable program.
fof(all_foo, axiom, ![X] : pred(X) => (X = foo)).
fof(exists_bar, axiom, pred(bar)).
fof(foo_not_bar, axiom, foo != bar).
The Techinal Report clarifies that different double quoted strings are different objects indeed, so another solution is to put quotes here and there, so as to obtain the following unsatisfiable program.
fof(all_foo, axiom, ![X] : (pred(X) => (X = "foo"))).
fof(exists_bar, axiom, pred("bar")).
I am happy not to have manually specify the inequality as that would obviously not scale to a more realistic scenario. Moving closer to my real situation, I actually have to handle composed terms, and the following program is unfortunately satisfiable.
fof(all_foo, axiom, ![X] : (pred(X) => (X = f("foo")))).
fof(exists_bar, axiom, pred(g("bar"))).
I guess f("foo") is not a term but the function f applied to the object "foo". So it could potentially coincide with function g. Although a manual specification that f and g never coincide does the trick, the following program is unsatisfiable, I feel like I'm doing it wrong. And it probably wouldn't scale to my real setting with plenty of terms all to be interpreted as distinct when they are syntactically distinct.
fof(all_foo, axiom, ![X] : (pred(X) => (X = f("foo")))).
fof(exists_bar, axiom, pred(g("bar"))).
fof(f_not_g, axiom, ![X, Y] : f(X) != g(Y)).
I have tried throwing single quotes around, but I didn't find the proper way to do it.
How do I make syntactically different (composed) terms and test for syntactical equality?
Subsidiary question: the following program is satisfiable, because the automated-theorem prover understands f as a function rather than a uninterpreted functor.
fof(exists_f_g, axiom, (?[I] : ((f(foo) = f(I)) & pred(g(I))))).
fof(not_g_foo, axiom, ~pred(g(foo))).
To make it unsatisfiable, I need to manually specify that f is injective. What would be the natural way to obtain this behaviour without specifying injectivity of all functors that occur in my program?
fof(exists_f_g, axiom, (?[I] : ((f(foo) = f(I)) & pred(g(I))))).
fof(not_g_foo, axiom, ~pred(g(foo))).
fof(f_injective, axiom, ![X,Y] : (f(X) = f(Y) => (X = Y))).
First of all let me point you to the Syntax BNF of TPTP. In principle, you have Prolog terms with some predefined infix/prefix operators of appropriate precedences. This means, variables are written in upper case and constants are written in lower case. Also like Prolog, escaping with single quotes allows us to write a constant starting with a capital letter i.e. 'X'. I have never seen double quoted atoms so far, so you might want look up the instructions of the prover on how to interpret them.
But even though the syntax is Prolog-ish, automated theorem proving is a different kind of beast. There is no closed world assumption nor are different constants assumed to be different - that's why you cannot find a proof for:
fof(c1, conjecture, a=b ).
and neither for:
fof(c1, conjecture, ~(a=b) ).
So if you want to have syntactic dis-equality, you need to axiomatize it. Now, assuming a different from b trivially shows that they are different, so I at least claimed: "Suppose there are two different constants a and b, then there exists some variable which is not b."
fof(a1, axiom, ~(a=b)).
fof(c1, conjecture, ?[X]: ~(X=b)).
Since functions in first-order logic are not necessarily injective, you also don't get around of adding your assumption in there.
Please also note the different roles of input formulas: so far you only stated axioms and no conjectures i.e. you ask the prover to show your axiom set to be inconsistent. Some provers might even give up because they use some resolution refinements (e.g. set of support) which restricts resolution between axioms[1]. In any case, you need to be aware that the formula you are trying to prove is of the form A1 ∧ ... ∧ An → C1 ∨ ... Cm where the A are axioms and the C are conjectures.[2]
I hope that at least the syntax is a bit clearer now - unfortunately the answer to the questions is more that atomated theorem provers don't make the same assumptions as you expect, so you have to axiomatize them. These axiomatizations are also often ineffective and you might get better perfomance from specialized tools.
[1] As you already notice, advanced provers like Vampire or E Prover tell you about (counter-)satisfyability instead.
[2] A resolution based theorem prover will first negate that formula and perform a CNF transformation, but even though most TPTP accepting provers are resolution based, that's not a requirement.

Recursive reference in prolog

I meet some problem when I try to implement
friends(mia, ellen).
friends(mia, lucy).
friends(X,Y) :-
friends(X,Z),
friends(Y,Z).
and when i ask ?- friends(mia, X)., it run out of local stack.
Then I add
friends(ellen, mia) friends(lucy, mia)
I ask ?- friends(mia, X). ,it keeps replying X = mia.
I can't understand, why it is recursive?
First, two assumptions:
the actual code you wanted to write is the following one, with appropriate dots:
friends(mia,ellen).
friends(mia,lucy).
friends(X,Y) :-
friends(X,Z),
friends(Z,Y).
transivity holds: friends of friends are my friends too (I would rather model friendship as a distance: "A is near B" and "B is near C" does not necessarly imply "A is near C"). repeat's answer is right about figuring out first what you want to model.
Now, let's see why we go into infinite recursion.
Step-by-step
So, what happens when we ask: friends(mia,X) ?
First clause gives Y=ellen (you ask for more solutions)
Second clause gives Y=lucy (you ask again for more solutions)
Stack overflow !
Let's detail the third clause:
I want to know if friends(mia,Y) holds for some variable Y.
Is there a variable Z such that friends(mia,Z) holds ?
Notice that apart from a renaming from Y to Z, we are asking the same question as step 1 above? This smells like infinite recursion, but let's see...
We try the first two clauses of friends, but then we fail because there is no friends(ellen,Y) nor friends(lucy,Y), so...
We call the third clause in order to find if there is a transitive friendship, and we are back to step 1 without having progressed any further => infinite recursion.
This problem is analogous to infinite Left recursion in context-free grammars.
A fix
Have two predicates:
known_friends/2, which gives direct relationships.
friends/2, which also encodes transitivity
known_friends(mia,ellen).
known_friends(mia,lucy).
friends(X,Y) :- known_friends(X,Y).
friends(X,Y) :- known_friends(X,Z), friends(Z,Y).
Now, when we ask friends(mia,X), friends/2 gives the same answer as the two clauses of known_friends/2, but does not find any answer for the transitive clause: the difference here is that known_friends will make a little progress, namely find a known friend of mia (without recursion), and try to find (recursively) if that friend is a friend of some other people.
Friends' friends
If we add known_friends(ellen, bishop) :-) then friends will also find Y=bishop, because:
known_friends(mia,ellen) holds, and
friends(ellen,bishop) is found recursively.
Circularity
If you add cyclic dependencies in the friendship graph (in known_friends), then you will have an infinite traversal of this graph with friends. Before you can fix that, you have to consider the following questions:
Does friends(X,Y) <=> friends(Y,X) hold for all (X,Y) ?
What about friends(X,X), for all X ?
Then, you should keep a set of all seen people when evaluating friends in order to detect when you are looping through known_friends, while taking into account the above properties. This should not be too difficult too implement, if you want to try.
This clause of friends/2 is flawed:
friends(X,Y) :- friends(X,Z),friends(Y,Z).
Translate that into English: "If X and Y have a mutual friend Z, then X and Y are friends."
Or, let's specialize, let X be "me", let Y be my neighbour "FooBert", and let Z be "you": So if I am your friend and FooBert is your friend... does that make me and FooBert friends? I don't think so, I hate that guy---he always slams the door when he gets home. :)
I suggest you consider the algebraic properties that the relation friends/2 should have, the ones it may have, and ones it should not have. What about reflexivity, symmetry, anti-symmetry, transitivity?

i am using ancient turbo prolog . and continously facing error in following code :- mis-spelling or not declared predicate

domains
A,B,C = symbol
N,P = integer
predicates
tower(integer,symbol,symbol,symbol,integer)
go
clauses
go :- clearwindow,
write("enter value of N (For Transfering from A To B)"),
readint(N),
tower(N,'a','b','c',N).
tower(N,A,B,C,P):-
N > 1,
P is N-1
tower(P,A,C,B,P),
write([move , A,B]),nl,
tower(P,C,B,A,P).
tower(0,_,_,_):- !.
You're missing a comma after P is N-1.
Also, your domain declarations don't make sense. The syntax is not for associating variables with domains (symbol and integer are predefined for you), but rather for creating specialized domains from the predefined ones. It doesn't appear that your program needs any domain declarations.
Tutorials for domains, etc. in Turbo Prolog are rather scarce online, due to the passage of time, so your best bet (if you lack original documentation) may be to look at one of Visual Prolog tutorials.
Try replacing is with = [Like: P = N-1]

Prolog dot product with variables (constraint satisfaction)

I'm working on a prolog assignment and I'm currently very very close to the solution. So, the problem is a constraint satisfaction problem where I have to find values for a set of variables such that certain conditions are true. Specifically, given 3 words (W1,W2,W3), assign their variables such that W1+W2=W3. An example of this would be SEND+MORE=MONEY, or IT+IS=ME.
The constraints are: (1) they have to add up correctly, (2) the starting letter cannot be 0 (3) and all variables must be distinct. And it has to work for a general word problem. My issue is happening when I try to ensure that they add up correctly (I've met the other conditions and I understand the problem). In terms of the second word problem we should have:
10*I + 1*T
+10*I + 1*S
___________
10*M + 1*E
So, I have made a function that makes lists of powers of 10 in a certain length, like so:
powlist(1,L) :-
append([1.0],[],L).
powlist(N,L) :-
N1 is N-1,
X is 10**N1,
powlist(N1,L1),
append([X],L1,L),
!.
I also have the actual list of letters, say, [I,T,I,S,M,E]. I then constructed a list of coefficients (I'll explain that part later) out of powlist so we have something like the following: [10,1,10,1,-10,-1]. I did this so if we took the dot product between this list of coefficients and the list of letters, and it was zero, the constraint would be satisfied. But, I can't get this dot product theory to work. I currently have a line that says:
scalar_product(Coefficients, Letters, #=, 0)
But this is giving me the following error:
! Instantiation error in argument 2 of is/2
! goal: _102 is 0+10.0*_109
I'm not sure how to define dot product so it can work on variables (instead of just atoms). All of the rest of the code works perfectly (and I don't want to put it on here because this is a very common question for introductory prolog courses, and I don't want to give lazy people answers). What do you guys suggest?
Your strategy is indeed sound and does work, at least with SWI-Prolog CLP(FD) using the built-in scalar_product/4. I am unfamiliar with the definition of this predicate in SICStus, but it's interface appears to be the same as in SWI-Prolog.
I can make a couple of suggestions. Firstly, perhaps some aspect of the code you've written is generating choicepoints which, when executed in backtracking (e.g., to seek alternate solutions, such as via label/1), the interpreter executes the subgoal _102 is 0+10.0*_109 where _109 is unintentionally unbound. Have you written a predicate which contains such a line? Even if not, I recommend double checking your code to ensure that they do not generate unnecessary choicepoints, such as your definition of powlist/2. I recommend that you try the following instead:
powlist(1, [1]) :- !.
powlist(N, [F|Fs]) :-
N > 1,
N1 is N - 1,
F is 10 ** N1,
powlist(N1, Fs).
This version leaves no choicepoints for the Prolog interpreter to backtrack to, which might resolve the problem (though, without seeing more code, I simply can't tell).
Otherwise, if you are correct and the error is indeed emanating from within the definition of scalar_product/4 (though I'd be surprised), then perhaps you could generate the scalar product constraint term and add it to the store yourself, manually. For example, consider:
my_scalar_product([V|Vs], [C|Cs], Op, Value) :-
construct_constraint(Vs, Cs, (V * C), Constr),
Constraint =.. [Op, Constr, Value],
Constraint.
construct_constraint([], [], Acc, Acc).
construct_constraint([V|Vs], [F|Fs], Acc, Res) :-
construct_constraint(Vs, Fs, '+'(Acc, (V * F)), Res).
This version (my_scalar_product/4) assumes the same interface as the built-in scalar_product/4, but it adds the constraint to the store instead of attempting to execute it using is/2.

Resources