my(Selected_action,S,Result1):-
Selected_action = move(X,Y),
atomics_to_string([X, ",", Y], '', Tuple),
atomics_to_string(["move(", Tuple, ")"], '', Action),
atomics_to_string([Action, "scores", S], ' ', Result).
So when running the code like this:
?- my(move(3,4),5,X).
X = "move(3,4) scores 5".
But what I want is:
X = move(3,4) scores 5.
Note that the code you posted does not behave in the way you said; you have singleton variables Result1 and Result that should be the same.
As for your question, Prolog has (in a sense) two forms of providing "output". One is through the answer substitutions (the equations) that you see in the interactive shell. The idea of these substitutions is to give you equations that are syntactically valid Prolog fragments. But the version you ask for, X = move(3,4) scores 5. is not syntactically valid Prolog.
This form of output through answer substitutions is useful for programmers, but not necessarily for end users or for other tools that try to parse your program's output. The other form of output is therefore the printing of things to the terminal or to files, like the print functions of many other programming languages. In Prolog, you can do this, for example:
run_my(Query, Score) :-
my(Query, Score, Result),
format('~s~n', [Result]).
Which will hide the intermediate Result and just print the string without quotes:
?- run_my(move(3, 4), 5).
move(3,4) scores 5
true.
I implemented this predicate as a wrapper around your existing definition of my/3, which remains unchanged. This is the recommended approach: Do not mix terminal output with the essence of your computation, only add it in special wrappers.
You can use the op functionality of prolog like this...
program
([user]) .
:- op( 10'1 , 'xfy' , 'scores' ) .
my(SELECTED_ACTION,SCORE,RESULT)
:-
(
SELECTED_ACTION = move(X,Y) ,
RESULT = SELECTED_ACTION scores SCORE
) .
%^D
example usage
?-
my(move(3,4),5,X)
.
%# X = move(3,4) scores 5
alternate program
An alternate version shows the difference between an xfy op and a yfx op.
The x represents the domain and/\or the source.
The y represents the codomain and/\or the target.
Terminology from https://en.wikipedia.org/wiki/Morphism#Definition.
...
([user]) .
:- op( 10'1 , 'yfx' , 'scoreof' ) .
my(SELECTED_ACTION,SCORE,RESULT)
:-
(
SELECTED_ACTION = move(X,Y) ,
RESULT = SCORE scoreof SELECTED_ACTION
) .
%^D
alternate example usage
?-
my(move(3,4),5,X)
.
#% X = 5 scoreof move(3,4)
Related
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.
I know this looks a bit silly, but I'm trying to find the average of a given student using Prolog, here's my piece of code:
score( jason , math101 , 90 ).
score( sami , math102 , 67 ).
score( smith , phys101 , 82 ).
score( sami , chem101 , 88 ).
do(X,S,I) :-
score(X,_,B) ,
write(B) ,
S is S+B ,
I is I+1 ,
write(I) ,
fail.
start :-
read(X) ,
do(X,0,0)
.
I'm trying to do it using recursion, the problem is that I (stands for index) and S(stands for sum) wont increment ! what did I do wrong? thanks !
You code has some problems:
Expressions like S is S+B don't work in prolog. Once a variable is unified with a term (assigned a value), it ceases to be variable: it becomes that with which it was unified. Hence the name unification.
Your do/3 predicate will always fail. It looks like you are forcing backtracking via fail/0 and expecting your counters to be incremented as you go. Prolog doesn't work like that: As you backtrack, unification is undone, so even if you'd managed to increment your S and B variables, the increment would have been rolled back as you backtracked through it.
You are invoking your do/3 predicate with S and B already unified to a value (0). So your is/2 expressions are the exact equivalent of this:
0 is 0+B , % S is S+B ,
0 is 0+1 , % I is I+1 ,
You can see how that won't work.
What you need to do is collect the scores for each student as a list. Since you can only get them one at a time via backtracking, building that list is a little difficult. If you tried to build that list via recursion, on each recursion you find yourself starting over from ground zero. Conveniently, Prolog offers a set of predicates for collecting data from all solutions to a goal as a list:
setof/3 finds the set of all solutions to a goal, presenting them as a list.
findall/3 finds the bag of all solutions to a goal, presenting them as a list.
bagof/3 finds the bag of all solutions to a goal, presenting them as a list.
Notes: findall/3 and bagof/3 are similar but different: to quote the docs, "findall/3 is equivalent to bagof/3 with all free variables bound with the existential operator ^". You'll probably need to play with it a bit to grok just what that means. The difference between set and bag is that by definition, sets are unique and have no duplicates. Bags, on the other hand are not necessarily unique and may contain duplicates.
At any rate, you're interested in bagof/3.
The first thing to do is decompose your problem into simple pieces. The first thing you need to do is compute the average score for a single student. to do that you need:
The student's name,
The list of individual scores for that student, and
a way to compute the arithmetic mean from a list of numbers.
So, let's tackle each of this in turn. The 1st two problems are solved with bagof/3. This:
bagof(Score,score(Student,_,Score),Scores) .
will find the list of scores for a student, unifying Student with the student's name and Scores with the list of individual scores. On backtracking it will successively do the same for all students.
That takes care of the first two simple problems. The 3rd problem isn't much more difficult. Here we will introduce two concepts that are integral to prolog: recursion and the use of accumulators to develop a value. we have to do this because as noted, in Prolog, all variables are local and can only be assigned a value once. So to develop a value, we have to recursively carry the state around that we need. A common idiom is the use of helper predicates that do all the work and are invoked by the "public" predicate that the user actually uses.
We can compute the arithmetic mean of a list of numbers like this:
compute_mean( Ns, M ) :- % to compute the mean of a list of numbers,
compute_mean( Ns , 0 , 0 , M ) % - just invoke the helper with the counters seeded as zero.
. % Also easy!
compute_mean( [] , S , N , M ) :- % if the source list is exhausted,
N > 0 , % - and we have a non-zero N (division by zero being undefined),
M is float(S) / float(N) % - compute the arithmetic mean, casting both counters to floats
. % otherwise...
compute_mean( [X|Xs] , S , N , M ) :- % if the source list isn't yet exhausted,
S1 is S+X , % - add the data point to the running total,
N1 is N+1 , % - increment the count of data points,
compute_mean(Xs,S1,N1,M) % - and recurse down on the tail of the list.
. % Easy!
That's all we need to compute the average score for a student, and on backtracking, successively do so for all students. Just put the two things together:
mean_score( Student , Mean ) :- % to compute the mean score for a student,
bagof( Mean , score(Student,_,Score) , Scores ) , % - get the bag of the scores for the student
compute_mean( Scores , Mean ) % - and then compute the mean score
. % Easy!
Once you have that, you could then just say something like this:
list_mean_scores_for_all_students :-
mean_score(Student,Mean) ,
write( Student:Mean) , nl ,
fail .
list_mean_scores_for_all_students .
The problem with the above is that list_mean_scores_for_all_students/0 will always succeed, even if something untowards happened. So, you might want to use findall/3 to collect them all at once and then process them.
Then we can say:
list_mean_scores_for_all_students :-
findall( Student:Mean , mean_score(Student,Mean) , Results ) ,
log_results(Results)
.
log_results( [] ) .
log_results( [S:M|Xs] ) :-
write(S:M),nl ,
log_results(Xs)
.
If something fails, list_means_scores_for_all_students/0 will fail.
I am using Swi-Prolog for what I think is a slightly weird use of Prolog. Reason I say that is 'cause I don't know what people use Prolog for normally aside from Watson.
In any case, I am making a prolog program for defining emotions based off what I tell it like:
emotion(anxiety,emotion):-
emotion(anxiety,prime).
emotion(fear,emotion):-
emotion(anxiety,prime),
emotion(when,prime),
emotion(bad,prime).
emotion(horrified,emotion):-
emotion(surprise,prime),
(emotion(fear,emotion);emotion(aversion,prime)).
The primes are unary so they're not the issue.
I can find emotion(X,Y). which will be everything that I defined with two arguments.
The issue is how can I find words based off the definitions? Could I tell prolog to find all emotions that contained some kind of definition of anxiety? Which would technically be anxiety as an emotion, fear and one of the "horrified" since I made it be definable through either surprise and fear (which entails anxiety) or surprise and aversion.
Is there a command I can use or would I have to program something in order to have prolog produce such a list?
I can find emotion(X,Y).
If you actually enter ?- emotion(X,Y). you'll get just false. as answer.
When you will add some of the facts required by these rules, for instance, assert(emotion(anxiety,prime)). you will get X=anxiety Y=emotion.
(I think that you should have distinct predicates for 'raw data' and categorization.)
Prolog allows inspecting programs, the primary 'reflexive' built in is clause/2. On your program:
?- clause(emotion(X,Y),Body).
X = anxiety,
Y = emotion,
Body = emotion(anxiety, prime) ;
X = fear,
Y = emotion,
Body = (emotion(anxiety, prime), emotion(when, prime), emotion(bad, prime)) ;
X = horrified,
Y = emotion,
Body = (emotion(surprise, prime), (emotion(fear, emotion);emotion(aversion, prime))).
This allows to meta interpret programs (see here for a clear introduction), and to inspect any detail, after providing the 'navigation' tools. Of course, a statement like some kind of definition of anxiety must be detailed: does anxiety occurs as primal, etc etc.
For instance
?- [user].
|: occurs(E,emotion(E,_)).
|: occurs(E,(A,B)) :- occurs(E,A);occurs(E,B).
|: occurs(E,(A;B)) :- occurs(E,A);occurs(E,B).
|: % user://1 compiled 0,20 sec, 4 clauses
true.
?- findall(E, (clause(emotion(E,_),B), occurs(anxiety,B)),L).
L = [anxiety, fear].
Here's a snippet on the classic SENDMORY crypt-arithmetic problem solutiong using prolog constraint solving mechanism-
:- lib(ic).
sendmore(Digits) :-
Digits = [S,E,N,D,M,O,R,Y],
Digits :: [0..9],
alldifferent(Digits),
S #\= 0,
M #\= 0,
1000*S + 100*E + 10*N + D
+ 1000*M + 100*O + 10*R + E
#= 10000*M + 1000*O + 100*N + 10*E + Y,
labeling(Digits).
Now, to execute this, I would send a goal/query like this:
?- sendmore(Digits).
And that would return me the possible solutions for the digits.
Now, my question is, I do not want to sort of "hard-code" the variables (like S,E,N,...) this way, but the goal/query would give the number of variables. For example, if the query I pass is something like:
?- sendmore(S,E,N,D,M).
then, it should compute only the values of SENDM and assume that the other variables are not applicable, and hence assign 0 to those variables and then proceed with the computation. And the next time I query, I may pass a different number of variables in the query.. like example:
?- sendmore(S,N,D,M,O,Y).
and the program should compute likewise.
What I am trying to achieve is a more generalised problem solver for the above scenario. Any directions on this is really appreciated. I am quite new to prolog,and am using ECLIPSE constraint solver.
Thank You.
Here are 2 ideas:
You can define sendmore() with different numbers of parameters, which would call the "real" version with the missing ones filled in. But you couldn't have different versions with the same NUMBER of parameters but DIFFERENT ones (since Prolog matches args to parameters by position).
You could expand/complicate your list format to allow the specification of which parameters you are passing; something line [(s,S),(e,E),(n,N),(d,D),(m,M)] for your middle example. A little tedious, but gives you the flexibility you seem to want.
Normally, variables in a goal and variables in a clause head are matched by their positions, not their names. So a call ?- sendmore0([S,E,N,D,M]). should be implemented as:
sendmore0([S,E,N,D,M]) :- sendmore([S,E,N,D,M,_,_,_]).
However, this would mean that you would need to implement this for every possible combination.
If you really want to implement what you describe, then you need to give the variable stable names. In ECLiPSe, you can do this with the library var_name. It's quite a hack, though...
:- lib(var_name).
sendmore0(L) :-
build_arg(["S","E","N","D","M',"O","R","Y"], L, A),
sendmore(A).
build_arg([], _, []) :- !.
build_arg([H|T], L, [HA|HT]) :-
match_arg(L, H, HA),
build_arg(T, L, HT).
match_arg([], _, _). % or use 0 as last argument if you want
match_arg([H|T], Base, A) :-
(
get_var_name(H, S),
split_string(S,"#","",[Base,_])
->
A = H
;
match_arg(T, Base, A)
).
Then you can call sendmore0/1 with a shorter list of variables. Don't forget to set the variable names!
?- set_var_name(S, "S"), set_var_name(E, "E"), sendmore0([S, E]).
S = 9
E = 5
Yes (0.00s cpu, solution 1, maybe more)
Disclaimer: this is not what stable names are for. They are meant for debugging purposes. If Joachim ever sees this, he'll give me a sharp clip round the ears...
Disclaimer: This is informal and non-assessed coursework to do in my own time. I have tried it myself, failed and am now looking for some guidance.
I am trying to implement a version of the member/2 function which will only return members for a list once.
For example:
| ?- member(X, [1,2,3,1]).
X = 1 ? ;
X = 2 ? ;
X = 3 ? ;
X = 1 ? ;
I would like it to only print out each number a maximum of once.
| ?- once_member(X, [1,2,3,1]).
X = 1 ? ;
X = 2 ? ;
X = 3 ? ;
no
We have been told to do this with the cut '!' operator but I have looked over the notes for my course for cut and more online and yet still can't make it click in my head!
So far I have managed to get:
once_member(E, [E | L]) :- !.
once_member(E, [_, L]) :-
once_member(E, L).
Which returns 1 and then nothing else, I feel like my cut is in the wrong place and preventing a backtrack for each possible match but I'm really not sure where to go with it next.
I have looked in my course notes and also at: http://www.cs.ubbcluj.ro/~csatol/log_funk/prolog/slides/5-cuts.pdf and Programming in Prolog (Google Books)
Guidance on how to logically apply the cut would be most useful, but the answer might help me figure that out myself.
We have also been told to do another method which uses '\+' negation by failure but hopefully this may be simpler once cut has twigged for me?
Remove redundant answers and stay pure!
We define memberd/2 based on if_/3 and (=)/3:
memberd(X, [E|Es]) :-
if_(X = E, true, memberd(X, Es)).
Particularly with meta-predicates, a different argument order may come in handy sometimes:
list_memberd(Es, X) :-
memberd(X, Es).
Sample query:
?- memberd(X, [1,2,3,1]).
X = 1 ;
X = 2 ;
X = 3 ;
false.
The solution with cut... at first it sounds quite troublesome.
Assuming that the first argument will be instantiated, a solution is trivial:
once_member(X,L):-
member(X,L),!.
but this will not have the behavior you want if the first arg is not instantiated.
If we know the domain of the lists elements (for example numbers between 1 and 42) we could instantiate the first argument:
once_member(X,L):-
between(1,42,X),
member_(X,L).
member_(X,L):-
member(X,L),!.
but this is veeery inefficient
at this point, I started to believe that it's not possible to do with just a cut (assuming that we dont use + or list_to_set/2
oh wait! < insert idea emoticon here >
If we could implement a predicate (like list_to_set/2 of swi-prolog) that would take a list and produce a list in which all the duplicate elements are removed we could simply use the normal member/2 and don't get duplicate results. Give it a try, I think that you will be able to write it yourself.
--------Spoilers------------
one_member(X,L):-
list_to_set(L,S),
member(X,S).
list_to_set([],[]).
list_to_set([H|T],[H|S]):-
remove_all(H,T,TT),
list_to_set(TT,S).
%remove_all(X,L,S): S is L if we remove all instances of X
remove_all(_,[],[]).
remove_all(X,[X|T],TT):-
remove_all(X,T,TT),!.
remove_all(X,[H|T],[H|TT]):-
remove_all(X,T,TT).
As you see we have to use a cut in remove_all/3 because otherwise the third clause can be matched by remove_all(X,[X|_],_) since we do not specify that H is different from X. I believe that the solution with not is trivial.
Btw, the solution with not could be characterized as more declarative than the solution with cut; the cut we used is typically called a red cut since it alters the behavior of the program. And there are other problems; note that, even with the cut, remove_all(1,[1,2],[1,2]) would succeed.
On the other hand it's not efficient to check twice for a condition. Therefore, the optimal would be to use the if-then-else structure (but I assume that you are not allowed to use it either; its implementation can be done with a cut).
On the other hand, there is another, easier implementation with not: you should not only check if X is member of the list but also if you have encountered it previously; so you will need an accumulator:
-------------Spoilers--------------------
once_member(X,L):-
once_member(X,L,[]).
once_member(X,[X|_T],A):-
\+once_member(X,A).
once_member(X,[H|T],A):-
once_member(X,T,[H|A]).
once_member(X, Xs) :-
sort(Xs, Ys),
member(X, Ys).
Like almost all other solutions posted, this has some anomalies.
?- X = 1, once_member(X, [A,B]).
X = A, A = 1
; X = B, B = 1.
?- X = 1, once_member(X, [A,A]).
X = A, A = 1.
Here's an approach that uses a cut in the definition of once_member/2 together with the classic member/2 predicate:
once_member(X,[H|T]) :-
member(H,T),
!,
once_member(X,T).
once_member(H,[H|_]).
once_member(X,[_|T]) :-
once_member(X,T).
Applied to the example above:
?- once_member(X,[1,2,3,1]).
X = 2 ;
X = 3 ;
X = 1 ;
no
Note: Despite the odd-appearing three clause definition, once_member/2 is last-call/tail-recursive optimization eligible due to the placement of the cut ahead of its first self-invocation.