Fact formation with ceiling in prolog - prolog

Can I define a fact of the following form,
test(X, ceiling(sqrt(X))).
Where, X is related to ceiling(sqrt(X)).
I think , I could have done the following to receive the desired output,
test(X, Y) :- Y is ceiling(sqrt(X)).

You can define:test(X, ceiling(sqrt(X))).
This means that you have as fact atoms in the above form so if you query:
?- test(X, ceiling(sqrt(X))).
true.
because you defined this clause.
But note that if you query:
?- test(1.5, 2).
false.
It returns false because 2 is ceiling(sqrt(1.5)) but the predicate is waiting a syntax like ceiling(sqrt(1.5)) and not the result 2.
Another example:
?- test(1.5, Y).
Y = ceiling(sqrt(1.5)).
and
?- test(X,ceiling(sqrt(1.5))).
X = 1.5.
Also notice that :
test(X) :- X is ceiling(sqrt(X)).
is always failing for any input X (because there is no such X that equals to ceiling(sqrt(X)). )and querying test(X) will have instantiation problems due to is/2.
Maybe what you meant to write is:
test(X,X1) :- X1 is ceiling(sqrt(X)).

Sorry but I don't understand your clause
test(X) :- X is ceiling(sqrt(X)).
You're imposing the equation (not assignment: equation) " X = ceiling(sqrt(X)) ".
I think you're intention was
test(X, Y) :- Y is ceiling(sqrt(X)).
Is this what do you want?

Related

Find parameter values that satsify logical formula in Prolog

I have a fact base of a single logical formula, e.g.
check(A,B) :- A,B.
I can query check(true,true). or check(true,false). and the compiler will give correct results. But I would like to also make queries where some parameters are variables, to obtain all values of those variables that make the query true. E.g., I'd like to query check(X,Y). and obtain X=true, Y=true., or check(X,true) and obtain X=true. However, I can't get it to work even for this trivial case, nor find the solution anywhere. All queries with variables return Arguments are not sufficiently instantiated.
I've also tried findall(X,check(true,X),Solution). and various variants using bagof or setof.
check_both(X, Y) :-
check_single(X),
check_single(Y).
check_single(true) :- !.
check_single(X) :- call(X).
Results in swi-prolog:
?- check_both(X, Y).
X = Y, Y = true.
?- X=1, check_both(X=1, Y).
X = 1,
Y = true.
?- X=1, check_both(X=2, Y).
false.
?- X=1, check_both(true, X=1).
X = 1.
?- X=1, check_both(true, X=2).
false.
?- member(X, [a, b]), check_both(X=Y, true).
X = Y, Y = a ;
X = Y, Y = b.

Why does my predicate not work, when a similar predicate does?

I have the following facts:
loves(andy, julia).
loves(andrew, maria).
loves(bob, sofia).
loved(juila).
loved(maria).
loved(sofia).
and I want to have two predicates:
do_love(X, Y) :- ...
is_loved(X, Y) :- ...
which returns Y as the name of the person, and X as the fact itself. For the loved fact, I wrote:
is_loved(X, Y) :- X = loved(Y), X.
which as expected, returns:
is_loved(X,Y).
X = loved(juila),
Y = juila ;
X = loved(maria),
Y = maria ;
X = loved(sofia),
Y = sofia.
However, when I write the predicate for the loves fact in a similar way:
do_love(X, Y) :- X = loves(X, Y), X.
it returns false for the query:
do_love(X,Y).
false.
I'm new to prolog, and can't really see why this is the case. Why does the query for is_loved work, while the one for do_love doesn't?
The problem is you're trying to unify X with two different values:
X = loves(...) and
loves(X, ...)
(I truncate using ... because those parts are irrelevant to what I'm saying).
In other words, your do_love predicate is saying "X must unify with a loves predicate" and also "X must unify with the first argument in a loves predicate". With the data set you've set up, no single value fulfills both requirements.
Depending on what you're trying to do, this might be what you want:
do_love(X, Y) :- loves(X, Y).
Sidenote 1: Predicates don't "return" values like they do in other languages with functions. You don't need the , X in your predicates for them to work.
Sidenote 2: The = is a "unify" operator, rather than an "assignment" like other languages. See this page for more info.

Prolog ... define predicate that checks if both arguments are/point to the same atom

I have a prolog predicate that takes two parameters (both labelled X here since they should be the same) and compares them to see if they evaluate to the same atom. That is the intent. However, the predicate unexpectedly returns false when both arguments are variables.
I'm trying to define a notion of an expression in sentential logic / propositional calculus being in "implication normal form" in Prolog. Implication normal form here meaning that all connectives are replaced with -> and falsum.
As a base case, I want to say that an expression consisting entirely of an atom is already in normal form with itself.
Here's how I'm attempting to express that. I'm repeating a parameter name instead of doing some type of check of sameness between the parameters.
% foo.P
implication_normal(X, X) :- atom(X).
This incomplete-but-still-useful definition is intended to capture the fact that implication_normal(x, x) is true but implication_normal(x, y) is false.
In some ways it seems to work:
$ swipl -s foo.P
?- implication_normal(x, x).
true.
?- implication_normal(x, y).
false.
?- implication_normal(1, 1).
false.
It does the wrong thing with variables (It should be enumerating pairs of "binding contexts" where X and Z happen to point to the same atom).
?- implication_normal(X, Z).
false.
It also just returns false if you give it the same variable twice.
?- implication_normal(X, X).
false.
for some strange reason, the behavior is correct if you give it a variable and a single atom (and you get failure with an integer).
?- implication_normal(X, z).
X = z.
?- implication_normal(X, 1).
false.
and similarly if the variable is second.
?- implication_normal(z, X).
X = z.
?- implication_normal(1, X).
false.
How do I change the definition of implication_normal so that it enumerates in all the cases where variables are supplied?
The standard atom/1 predicate is a type-checking predicate. It doesn't enumerate atoms. It just deterministically checks if its argument is an atom. Moreover, your definition of the implication_normal /2 predicate attempts to unify its two arguments and, if the unification is successful, calls atom/1 with the resulting term. That's why a call such as implication_normal(X, z) succeeds: X is unified with z and atom(z) is true.
Note that some Prolog systems provide a current_atom/1 that does enumerate atoms. On those systems, you could write instead:
implication_normal(X, X) :- current_atom(X).
Some sample calls using SWI-Prolog:
?- implication_normal(X, Z).
X = Z, Z = '' ;
X = Z, Z = abort ;
X = Z, Z = '$aborted'
...
?- implication_normal(X, X).
X = '' ;
X = abort ;
X = '$aborted' ;
...
?- implication_normal(X, z).
X = z.
?- implication_normal(X, 1).
false.

First steps to a CAS

I tried to run this code:
eq(mul(a,b),mul(c,b)).
eq(X,Y) :- eq(mul(X,Z),mul(Y,Z))
with the query: eq (X, Y)
I expected the results:
X=mul(a,b),Y=(mul(c,b)) and X=a,Y=c
But I just got the first one.
I think you want:
eq(mul(a, b), mul(c, b)).
equal(X,Y) :-
eq(mul(X, Z), mul(Y, Z)).
Note that I have used different predicate names, to prevent a common mistake of infinite recursion/looping if a predicate (e.g. "eq") is calling itself.
Result in swi-prolog:
?- equal(X, Y).
X = a,
Y = c.
This rule would be wrong:
eq(X,Y) :- eq(mul(X,Z),mul(Y,Z)).
because X cannot be simultaneously mul(something) and part of the same something inside the mul(). Also, it falls into the trap of infinite recursion/looping.

Prolog - Make two Instantiations Equal

I'm very new to Prolog so please bear with me.
Lets say I have the following:
foo(bar(a,b)).
foo(bar(b,a)).
Then I enter foo(X) as a query:
?- foo(X).
X = bar(a, b) ;
X = bar(b, a).
Prolog returns two instantiations of X to satisfy the query: bar(a, b) and bar(b,a).
Is there away I can make these two instantiations equivalent? Once Prolog instantiates X to bar(a,b), it won't instantiate it to bar(b,a).
So when I enter foo(X) as a query:
?- foo(X).
X = bar(a, b).
X was no instantiated as bar(b,a), because it's equivalent to bar(a,b). Is this possible to do with Prolog, or does it go against the fundamental principals of Prolog?
The first clause of symmetry/2 deals with cases in which both foo(bar(a,b)) and foo(bar(b,a)) occur. I use the standard order of terms in order to return only the former. Notice that the use of #< would have falsely excluded results like foo(bar(e,e)).
The second clause treats cases in which either foo(bar(c,d)) or foo(bar(d,c)) occur.
foo(bar(a, b)).
foo(bar(b, a)).
foo(bar(c, d)).
foo(bar(e, e)).
symmetry(X, Y):-
foo(bar(X, Y)),
foo(bar(Y, X)),
X #=< Y.
symmetry(X, Y):-
foo(bar(X, Y)),
\+ foo(bar(Y, X)).
Example of usage:
?- symmetry(X, Y).
X = a,
Y = b ;
X = Y, Y = e ;
X = c,
Y = d ;
false
Hope this helps!
Identity of literals it's the core of unification - the fundamental operation of Prolog algorithm - and then the answer to your question it's no, it's not possible to handle bar(a,b) as bar(b,a).

Resources