swi-prolog truth assignment? - prolog

So I have this exercise that I'm stuck on:
A formula is:
tru
fls
variable(V) iff V is an atom.
or(Flist) iff every element in the list is a formula
there are implies, and, neg too. the form looks similar.
We can represent a truth assignment (an assignment of values to variables) by a Prolog list of the form [Var1/Value1, Var2/Value2,...VarN/ValueN]. Write a predicate sub(?F,?Asst,?G) which succeeds iff G is a formula which is a result of substituting the variables of F with corresponding values from the assignment Asst. (You can assume that the truth assignment A is at least partially instantiated).
E.g.
sub(variable(x), [x/tru], tru).
true
sub(or([variable(a),variable(b)]), [a/tru,b/fls], G).
G = or(tru,fls)
true
I've tried
sub(variable(x),[x/value],G):-
G = variable(value).
But it just returns false.
Edit: Sorry I didn't make the question clear, Can someone explain to me if there's a way to assign values associated with variables in a list to another variable? I think it has something to do with unification.

Variables are placeholders.
Beware of case sensitivity: Prolog variable names start with an uppercase character or underscore, atoms with a lowercase character.
Your code snippet of sub/3 assumes that the list of
key-value pairs has exactly a length of one ([x/value]).
By using member/2 the lists can have arbitrary length.
When handling n-ary logical connectives like and / or, you probably want a short-circuit implementation that returns as soon as possible. Like so:
sub(tru,_,tru).
sub(fls,_,fls).
sub(variable(X),Assoc,Value) :-
member(X/Value,Assoc).
sub(or([]),_,fls).
sub(or([X|Xs]),Assoc,V) :-
sub(X,Assoc,T),
( T = tru, V = tru % short-circuit logical-or
; T = fls, sub(or(Xs),Assoc,V)
).

Related

Is nonexistence queriable in Datalog?

Suppose I've defined a few values for a function:
+(value[1] == "cats")
+(value[2] == "mice")
Is it possible to define a function like the following?
(undefined[X] == False) <= (value[X] == Y)
(undefined[X] == True) <= (value[X] does not exist)
My guess is that it can't, for two reasons:
(1) Queries are guaranteed to terminate in Datalog, and you could query for undefined[X] == True.
(2) According to Wikipedia, one of the ways Datalog differs from Prolog is that Datalog "requires that every variable appearing in a negative literal in the body of a clause also appears in some positive literal in the body of the clause".
But I'm not sure, because the terms involved ("terminate", "literal", "negative") have so many uses. (For instance: Does negative literal mean f[X] == not Y or does it mean not (f[X] == Y)? Does termination mean that it can evaluate a single expression like undefined[3] == True, or does it mean it would have found all X for which undefined[X] == True?)
Here another definition of "safe".
A safety condition says that every variable in the body of a rule must occur in at least one positive (i.e., not negated)
atom.
Source: Datalog and Recursive Query Processing
And an atom (or goal) is a predicate symbol (function) along with a list of terms as arguments. (Note that “term” and “atom” are used differently here than they are in Prolog.)
The safety problem is to decide whether the result of a given Datalog program can be guaranteed to be finite even when some source relations are infinite.
For example, the following rule is not safe because the Y variable appears only in a negative atom (i.e. not predicate2(Z,Y)).
rule(X,Y) :- predicate1(X,Z), not predicate2(Z,Y) .
To meet the condition of safety the Y variable should appear in a positive predicate too:
rule(X,Y) :- predicate1(X,Z), not predicate2(Z,Y), predicate3(Y) .

What does the following recursive Prolog call output?

I'm trying to learn prologue, but man am I having trouble.
I have an example below as well as what it outputs, and I'm clearly stuck on some concepts but not sure what.
output([]).
output([c|R]):- output(R), !, nl.
output([X|R]) :- output(R), write(X).
?- output([a,b,c,d,e]).
Answer:
ed
ba
true.
Correct me if I'm wrong, but here is what I understand so far...
When we call output([a,b,c,d,e]).
prologue looks for a solution using unification,
it tries output([]) and fails, so it proceeds to the second output([c|R]) which then passes the tail of the list recursively into output([c|R]) until it hits the base case of output([]).
Now I get confused...It then hits the cut which locks R to [] and c with a value of e? how does the output afterwards happens? I'm really confused.
I think you're having a fundamental misunderstanding of what Prolog is doing and what unification is about. In Prolog when you make a query such as output([a,b,c,d,e]). Prolog will start from the beginning of your asserted facts and predicates and attempt to unify this term (your query) with a fact or the head of a predicate.
Unification
We need to stop here for a moment and understand what unification is. In Prolog, the operator =/2 is the unification operator and can be used to query the unification of two terms, term1 = term2. This query will succeed if term and term2 can be successfully unified. How can they be successfully unified? This can happen if there is a binding of variables in term1 and term2 such that the terms become, essentially, identical (by "essentially" I mean they might differ only in syntactic representation but are truly identical when in canonical form - see details below on what that is).
Here are examples of unification attempts that fail. You can enter these at a Prolog prompt and it will show immediate failure.
a = e. % This fails because the atom `a` is different than the atom `e1`
% There are no variables here that can change this fact
foo(X) = bar(Y)
% This fails because the functor `foo` is different than
% the functor `bar`. There's no way to get these terms to match
% regardless of how the variables `X` or `Y` might be instantiated
foo(a, Y) = foo(b, Y)
% This fails because no matter how the variable `Y` is instantiated
% the 1st argument of `foo` just cannot match. That is, the atom
% `a` doesn't match the atom `b`.
foo(a, b, X) = foo(a, b)
% This fails because the `foo/3` and `foo/2` have a different
% number of arguments. No instantiation of the variable `X` can
% change that fact
[1,2] = [1,2,3] % Fails because a list of 2 elements cannot match a list of 3 elements
[] = [_|_] % Fails because the empty list cannot match a list of at
% least one element.
[a,b,c] = [x|T] % Fails, regardless of how `T` might be bound, because `[a,b,c]`
% is a list whose first element is `a`
% and `[x|T]` is a list whose first element is `x`. The
% atoms `a` and `x` do not and cannot match.
Here are examples of successful unifications. You can test these as well at a Prolog prompt and you should get success or, if variables are involved, get at least one solution showing binding of variables that causes it to succeed:
a = a. % Trivial case: an atom successfully unifies with itself
X = a. % Succeeds with `X` bound to `a`
foo(X) = foo(a). % Succeeds with `X` bound to `a`
[a,b,c] = [a|T] % Succeeds with `T` bound to `[b,c]` because the first element
% `a` is the same in both cases.
[1,2,3] = [H|T] % Succeeds with `H` bound to 1, and `T` bound to `[2,3]`
% since `[1,2,3]` is equivalent to `[1|[2,3]]` (they are two
% different syntaxes representing the same term)
Just an aside: Prolog list syntax
We're writing lists using a form that's familiar from other languages. So [] is an empty list, and [1,2,3] is a list of the 3 elements 1, 2, and 3. You can also have lists inside of lists, or any terms in a list for that matter. This, for example, is a valid list of 3 elements: [a, [1,foo(a)], bar(x,Y,[])]. The first element is a, the second is a list of two elements, [1, foo(a)], and the third element is bar(x,Y,[]). In Prolog, you can also write a list in a form that describes the first of one or more elements and a tail. For example [H|T] is a list whose first element is H and the rest of the list is T (itself a list). A list of at least two elements could be written as [H|T] and you'd know that T has at least one element. Or you could write it as [H1,H2|T] and explicitly indicate the first two elements and understand that T would be a list of zero or more arguments. The first elements are individual elements of the list, and the tail is a list representing the rest of the list. The following forms all represent the list [a,b,c,d,e]:
[a,b,c,d,e]
[a|[b,c,d,e]]
[a,b|[c,d,e]]
[a,b,c|[d,e]]
[a,b,c,d|[e]]
[a,b,c,d,e|[]]
If you had a list, L, and wanted prolog to ensure that L had at least two arguments, you could unify L with an anonymous list of 2 elements: L = [_,_|_]. This will only succeed if L is a list of at least two elements.
Another aside: canonical form
Prolog, though, has what it calls a canonical form for terms which is its fundamental representation of a given term. You can see the canonical form of a term by calling write_canonical(Term):
| ?- write_canonical([a,b,c]).
'.'(a,'.'(b,'.'(c,[])))
yes
So that's interesting, what on earth is that? It doesn't look like a list at all! It's actually the canonical form in Prolog of what a list really looks like to Prolog (if you want to think of it that way). The fundamental term form in Prolog is a functor and zero or more arguments. The atom a is a term which could be viewed as a functor a with no arguments. The term foo(1,X) has functor foo and arguments 1 and X. The list [a,b,c] written that way is just a convenient syntax for programmers that make it easy to read. A list is actually formed by the functor '.' and two arguments: the head and the tail. So the list [H|T] in general is '.'(H,T) and the empty list [] is just itself, an atom representing the empty list. When Prolog unifies (or attempts to unify) two lists, it's really looking at a list as '.'(H, T) so it matches the '.' functor, then attempts to match arguments. In the case of multiple elements, it's a recursive match since T is itself a list.
Expressions in Prolog such as X + 3 are also a syntactic convenience for the canonical form, '+'(X, 3).
Back to our story
As we were saying, when you query output([a,b,c,d,e])., Prolog tries to unify this with heads of predicate clauses or facts that you have already asserted. Here's what you have asserted:
output([]).
output([c|R]):- output(R), !, nl.
output([X|R]) :- output(R), write(X).
Starting from the top, Prolog attempts this unification:
output([a,b,c,d,e]) = output([])
This fails since there are no variables to change the terms to make them match. It fails because the list [a,b,c,d,e] and the empty list [] cannot match.
On to the next clause:
output([a,b,c,d,e]) = output([c|R])
This can only succeed if the unification [a,b,c,d,e] = [c|R] can succeed with some binding of R. You can look at this as [a|[b,c,d,e,]] = [c|R]. Clearly, for this unification to succeed, the first element of each list must match. But a and c don't match, so this fails.
On to the next one:
output([a,b,c,d,e]) = output([X|R])
Prolog attempts then to unify [a,b,c,d,e] with [X|R], or [a|[b,c,d,e]] with [X|R]... and this succeeds since X and R are variables and they can be bound as X = a and R = [b,c,d,e]. Now the body of the clause can be executed:
output([b,c,d,e]), write(a).
Before we can get to the write(a), the call output([b,c,d,e]) must execute first and succeed. Following the same logic above, the the first and second clauses of the output/1 predicate do not match. But the 3rd clause matches again with [b,c,d,e] = [X|R] resulting in X = b and R = [c,d,e]. Now the body of this clause is executed again (and you must remember we're now one level deep in a recursive call... the above call to output([b,c,d,e]) is pending awaiting the result):
output([c,d,e]), write(b).
Now it gets more interesting. The first clause of output/1 still doesn't match since [c,d,e] = [] fails. But the second clause now does match since [c,d,e] = [c|R] succeeds with the binding R = [d,e]. So that body is executed:
output([d,e]), !, nl.
Now we need to chase down the call to output([d,e]) (we're now another level deep in recursion remember!). This one fails to match the first two clauses but matches the 3rd clause, by [d,e] = [X|R] with bindings X = d and R = [e].
I could keep going but I'm getting tired of typing and I do have a real job I work at and am running out of time. You should get the idea hear and start working through this logic yourself. The big hint moving forward is that when you finally get to output([]) in a recursive call an you match the first clause, you will start "unwinding" the recursive calls (which you need to keep track of if you're doing this by hand) and the write(X) calls will start to be executed as well as the !, nl portion of the second clause in the case where c was matched as the first element.
Have fun...
The main problem with your reasoning is that c is not a variable but an atom. It cannot be unified with any other value.
So with your example input, for the first 2 calls it will not execute output([c|R]) (since a nor b can be unified with c), but it goes on to output([X|R]) instead. Only for the third call, when the head is c, the former clause is called. After this it will call the latter clause another 2 times for d and e, and then it hits the base case.
From that point on we can easily see the output: if first writes 'e', then 'd', then a new line (for the time we matched c), ad then b and a. Finally you get true as output, indicating that the predicate call succeeded.
Also note that due to the cut we only get a single output. If the cut wasn't there, we would also get edcba, since the c case would also be able to match the last clause.

Prolog - subsitution and evaluation

Hello good people of programming .
Logic programming is always fascinating compare to imperative programming.
As pursuing unknown of logic programming, there is some problems encountering arithmetic expressions.
Here is the code I have done so far.
number_atom(N) :-
(number(N) -> functor(N, _, _); functor(N, _, _), atom(N)).
arithmeticAdd_expression(V,V,Val,Val).
arithmeticAdd_expression(N, _Var, _Val, N) :-
number_atom(N).
arithmeticAdd_expression(X+Y, Var, Val, R) :-
arithmeticAdd_expression(X, Var, Val, RX),
arithmeticAdd_expression(Y, Var, Val, RY),
(number(RX), number(RY) -> R is RX + RY; R = RX + RY).
Taking add operation as example:
arithmeticAdd_expression(Expression, Variable, Value, Result)
?- arithmeticAdd_expression(a+10, a, 1, Result).
?- Result = 11;
?- Result = a + 10.
?- arithmeticAdd_expression(a+10, b, 1, Result).
?- Result = a + 10.
What I would like to achieve is that
if the atom(s) in the Expression can only be substituted by given Variable and value, then Result is the number only like the example shown above(Result = 11). Else, the Result is the Expression itself only. My problem with the code is somewhere there, I just could figure it out. So, Please someone can help me? Thank you.
An important attraction of logic programming over, say, functional programming is that you can often use the same code in multiple directions.
This means that you can ask not only for a particular result if the inputs are given, but also ask how solutions look like in general.
However, for this to work, you have to put some thought into the way you represent your data. For example, in your case, any term in your expression that is still a logical variable may denote either a given number or an atom that should be interpreted differently than a plain number or an addition of two other terms. This is called a defaulty representation because you have to decide what a variable should denote by default, and there is no way to restrict its meaning to only one of the possible cases.
Therefore, I suggest first of all to change the representation so that you can symbolically distinguish the two cases. For example, to represent expressions in your case, let us adopt the convention that:
atoms are denoted by the wrapper a/1
numbers are denoted by the wrapper n/1.
and as is already the case, (+)/2 shall denote addition of two expressions.
So, a defaulty term like b+10 shall now be written as: a(b)+n(10). Note the use of the wrappers a/1 and n/1 to make clear which case we are dealing with. Such a representation is called clean. The wrappers are arbitrarily (though mnemonically) chosen, and we could have used completely different wrappers such as atom/1 and number/1, or atm/1 and nmb/1. The key property is only that we can now symbolically distinguish different cases by virtue of their outermost functor and arity.
Now the key advantage: Using such a convention, we can write for example: a(X)+n(Y). This is a generalization of the earlier term. However, it carries a lot more information than only X+Y, because in the latter case, we have lost track of what these variables stand for, while in the former case, this distinction is still available.
Now, assuming that this convention is used in expressions, it becomes straight-forward to describe the different cases:
expression_result(n(N), _, _, n(N)).
expression_result(a(A), A, N, n(N)).
expression_result(a(A), Var, _, a(A)) :-
dif(A, Var).
expression_result(X+Y, Var, Val, R) :-
expression_result(X, Var, Val, RX),
expression_result(Y, Var, Val, RY),
addition(RX, RY, R).
addition(n(X), n(Y), n(Z)) :- Z #= X + Y.
addition(a(X), Y, a(X)+Y).
addition(X, a(Y), X+a(Y)).
Note that we can now use pattern matching to distinguish the cases. No more if-then-elses, and no more atom/1 or number/1 tests are necessary.
Your test cases work as expected:
?- expression_result(a(a)+n(10), a, 1, Result).
Result = n(11) ;
false.
?- expression_result(a(a)+n(10), b, 1, Result).
Result = a(a)+n(10) ;
false.
And now the key advantage: With such a pure program (please see logical-purity for more information), we can also ask "What do results look like in general?"
?- expression_result(Expr, Var, N, R).
Expr = R, R = n(_1174) ;
Expr = a(Var),
R = n(N) ;
Expr = R, R = a(_1698),
dif(_1698, Var) ;
Expr = n(_1852)+n(_1856),
R = n(_1896),
_1852+_1856#=_1896 ;
Expr = n(_2090)+a(Var),
R = n(_2134),
_2090+N#=_2134 .
Here, I have used logical variables for all arguments, and I get quite general answers from this program. This is why I have used clpfd constraints for declarative integer arithmetic.
Thus, your immediate issue can be readily solved by using a clean representation, and using the code above.
Only one very small challenge remains: Maybe you actually want to use a defaulty representation such as c+10 (instead of a(c)+n(10)). The task you are then facing is to convert the defaulty representation to a clean one, for example via a predicate defaulty_clean/2. I leave this as an easy exercise. Once you have a clean representation, you can use the code above without changes.

replace elements in prolog

Am writing a program that includes a definition for the predicate 'word_replacements/2'. This predicate should be true if the two arguments are lists, and the second list is the same as the first but with all elements that are the single letter 'a' replaced by the letter 'e', and with all elements that are the single letter 'e' replaced by the letter 'a'. Your answer should reproduce the following example input/output:
?- word_replacements([e, a, s, i, l, y],Word_replacements).
Word_replacements = [a, e, s, i, l, y];
false.
?- word_replacements(Word, [a,e,s,i,l,y).
Word = [e, a, s, i, l, y];
false.
This is what I have tried but it just gives me false.
word_replacements([],[]).
word_replacements([H|T], Word_replacements):-
word_replacements(H,Replace_A),
word_replacements(T,Replace_E),
Append(Replaced,[T],Word_replacements).
A first thing to understand about Prolog is that you cannot reassign variables because of unification. Once you assign a value to a variable, it will never change again. This has implications for your example, since it seems you are trying to replace variables holding specific characters.
Of course there are various ways to solve this, but since you stated that you are new to prolog, I'll try to provide a (unfinished) simple way of writing this:
Firstly, we'll evaluate your code:
word_replacements([],[]).
word_replacements([H|T], Word_replacements):-
(1) word_replacements(H,Replace_A),
(2) word_replacements(T,Replace_E),
(3) append(Replaced,[T],Word_replacements).
What you wrote is the following:
(1) : recursive call to word_replacements, however with H as first argument, since H is not a list, but an element, this will never pattern match and thus execution will fail here.
(2) : recursive call to word_replacements, this time with T, the tail of the list, and this indeed is a list as well, so that would be correct. However, as second argument, you specify a new uninstantiated variable 'Replace_E). Prolog does not know where this variable comes from and will thus give you the warning 'Singleton variable'. When you make recursive calls, you want to end up with a result afterwards, this means you will have to pass a known variable between recursive calls, instead of a new singleton variable.
(3) : here you try to append another new variable 'Replaced' with the tail of the letters enclosed in square brackets. This would wrap the tail, which is already in a list, into another list and you would end up with something like [['l','y']], which is not what you want.
Okay, we'll now start by breaking down the problem into the following possible states (this used to help me alot when I was new to Prolog):
The specified list of letters is empty
The current letter being read is an 'a'
The current letter being read is an 'e'
The current letter being read is some other letter than 'a' or 'e'
We now try to translate this into prolog code:
% Empty list
word_replacements([],[]).
% If H is an 'e', we want to add an 'a' to our result
word_replacements([H|T],[a|R]) :-
...
word_replacements(T,R).
% If H is an 'a', we want to add an 'e' to our result
word_replacements([H|T],[e|R]) :-
...
word_replacements(T,R).
% If H is anything other than an 'a' or 'e', we want to keep that letter
word_replacements([H|T],[H|R]) :-
...
word_replacements(T,R).
As you can see, we now wrote a structured model in which it is easy to specify different behaviour for different situations.
All that's left to do now, is for you to specify the conditions for each situation.
Good luck!

how to assign one list to a variable in prolog?

I want to append([],C,C) where C is a list containing some elements . Is it possible? I will append some list in C containing elements append (Found,C,C) if other condition is true.
And also i want to store final value in C to a variable D . How can I do that?
I want to append([],C,C) where C is a list containing some elements. Is it possible?
append([],C,C) is always true. An empty list combined with anything is that anything. Look what Prolog says when you attempt it:
?- append([],C,C).
true.
This true without any bindings tells you that Prolog established the proof but no new bindings were created as a result. This code would have the same result:
meaningless(_, _, _).
?- meaningless(everybody, X, Squant).
true.
This suggests your desire is misplaced. append([], C, C) does not do what you think it does.
I will append some list in C containing elements append (Found,C,C) if other condition is true. And also i want to store final value in C to a variable D. How can I do that?
Thinking in terms of "storing" and other operations implying mutable state is a sure sign that you are not understanding Prolog. In Prolog, you establish bindings (or assert facts into the dynamic store, which is a tar pit for beginners). Something similar could be achieved in a Prolog fashion by doing something like this:
frob(cat, List, Result) :- append([cat], List, Result).
frob(dog, List, List).
This predicate frob/3 has two in-parameters: an atom and a list. If the atom is cat then it will append [cat] to the beginning of the list. The threading you see going between the arguments in the head of the clause and their use in the body of the clause is how Prolog manages state. Basically, all state in Prolog is either in the call stack or in the dynamic store.
To give an example in Python, consider these two ways of implementing factorial:
def fac(n):
result = 1
while n > 1:
result = result * n
n = n - 1
This version has a variable, result, which is a kind of state. We mutate the state repeatedly in a loop to achieve the calculation. While the factorial function may be defined as fac(n) = n * fac(n-1), this implementation does not have fac(n-1) hiding in the code anywhere explicitly.
A recursive method would be:
def fac(n):
if n < 1:
return 1
else:
return n * fac(n-1)
There's no explicit state here, so how does the calculation work? The state is implicit, it's being carried on the stack. Procedural programmers tend to raise a skeptical eyebrow at recursion, but in Prolog, there is no such thing as an assignable so the first method cannot be used.
Back to frob/3, the condition is implicit on the first argument. The behavior is different in the body because in the first body, the third argument will be bound to the third argument of the append/3 call, which will unify with the list of the atom cat appended to the second argument List. In the second body, nothing special will happen and the third argument will be bound to the same value as the second argument. So if you were to call frob(Animal, List, Result), Result will be bound with cat at the front or not based on what Animal is.
Do not get mixed up and think that Prolog is just treating the last argument as a return value! If that were true, this would certainly not work like so:
?- frob(X, Y, [whale]).
X = dog,
Y = [whale].
What appears to have happened here is that Prolog could tell that because the list did not start with cat it was able to infer that X was dog. Good Prolog programmers aspire to maintain that illusion in their APIs, but all that really happened here is that Prolog entered the first rule, which expanded to append([cat], X, [whale]) and then unification failed because Prolog could not come up with an X which, having had [cat] prepended to it, would generate [whale]. As a result, it went to the second rule, which unifies X with dog and the second two arguments with each other. Hence Y = [whale].
I hope this helps!

Resources