Prolog , return permutations with a max value - prolog

i have made predicate schedule(A,B,C) that returns possible permutations at lists A,B,C with backtracking
| ?- schedule(A,B,C).
A = [im204,im212,im217]
B = [im209,im214,im218]
C = [im210,im216] ? ;
A = [im204,im212,im218]
B = [im209,im214,im217]
C = [im210,im216] ? ;
A = [im204,im212,im216]
B = [im209,im214,im218]
C = [im210,im217] ?
I also have the predicate schedule_score(A,B,C,S) which returns score(dont mind what the score means) from lists A,B,C to S.
| ?- score_schedule([im204,im209,im212],[im210,im214,im216],[im217,im218],S).
S = 578
In my new predicate
all_schedule_scores(A,B,C,S):-
schedule(A,B,C),
score_schedule(A,B,C,S).
it returns possible permutations along with the score
| ?- all_schedule_scores(A,B,C,S).
A = [im204,im212,im217]
B = [im209,im214,im218]
C = [im210,im216]
S = 342 ? ;
A = [im204,im212,im218]
B = [im209,im214,im217]
C = [im210,im216]
S = 371 ? ;
A = [im204,im212,im216]
B = [im209,im214,im218]
C = [im210,im217]
S = 294 ?
I was wondering if there was a way i can return only the permutations with the max score(or not return any permutations whose score isnt max).

It's not clear what Prolog implementation you're using. Here's a solution that uses setof/3 (which orders its results low to high):
max_scored(MaxA, MaxB, MaxC, MaxS) :-
setof((S,A,B,C), all_scheduled_scores(A,B,C,S), AllScoresLowToHigh),
reverse(AllScoresLowToHigh, [(MaxS,MaxA,MaxB,MaxC)|_]).
Sorting uses a natural ordering, so (S1,A1,B1,C1) is considered greater than (S2,A2,B2,C2) if S1 is greater than S2.
This solution just finds a single maximum result. If you have multiple that are at the same maximum, I'll leave that as an exercise for you. You would just need to choose the first elements of the 2nd argument to reverse/2 that have the same score.

If your Prolog supports it, you could use library(aggregate):
max_scored_schedule(ScA,ScB,ScC,Score) :-
aggregate(max(S,[A,B,C]), (schedule(A,B,C),score_schedule(A,B,C,S)), max(Score,[ScA,ScB,ScC])).
Tested with hardcoded data you provided:
?- max_scored_schedule(A,B,C,S).
A = [im204, im209, im212],
B = [im210, im214, im216],
C = [im217, im218],
S = 578.
As you can see, it's just a matter to properly order arguments...
Edit:
library(solutionsequences) allows for a SQL like query, that should solve your problem
?- order_by([desc(S)], group_by(S, (A,B,C), (schedule(A,B,C),score_schedule(A,B,C,S)), G)).
but the straightforward answer by #lurker is neat (+1), and doesn't require you to port another library to your Prolog

Related

Prolog nth1 anonymous variables

I have a List with Integers and anonymous variables and I try to find the index of a special values. Problem is as soon I'm using nth1/3 to find the indices Prolog assigns values to the anonymous variables and therefore I find way too indices.
Example:
List = [1,\_,1], where I want as result X = 1, X = 3 from nth1(X,List,1), but as stated before I get X = 1, X = 2, X = 3.
There is a somewhat problematic issue hidden in your requirements: They violate an important declarative property called monotonicity. By this we mean that adding constraints can at most make the solution more specific, never more general.
For example, with the solution you posted, we get:
?- list_el_index([_], 1, N).
false.
Now I add a constraint by imposing an additional requirement on the hitherto free anonymous variable:
?- Var = 1, list_el_index([Var], 1, N).
Var = 1,
N = 0 .
I mean: Come on! We have added a constraint, and as a result get more solutions than before? Such a result is unfortunate and prevents us from reasoning in a logical way about this program.
The program also fails us in other respects. For example, let us ask: Which solutions are there at all?
?- list_el_index(Ls, El, I).
nontermination
Ideally, we would like the program to generate solutions in such cases! This generality is one of the foremost attractions of logic programming, and distinguishes it from more low-level paradigms.
One way to solve such issues is to symbolically distinguish the different kinds of elements that appear in your list.
For example, let us use:
u for an unknown value.
i(I) for an integer I.
With this new representation, your solution becomes:
list_el_index([i(I)|_], I, 0).
list_el_index([_|Tail], Element, Index) :-
list_el_index(Tail, Element, Index0),
Index #= Index0+1.
I have also taken the liberty to replace (is)/2 by (#=)/2, to advertise and stick to more general integer arithmetic that lets us more freely reorder the goals, if necessary. Depending on your Prolog implementation, you may have to import a library to benefit from (#=)/2.
With this representation, your initial case becomes:
?- list_el_index([i(1),u,i(1)], 1, Index).
Index = 0 ;
Index = 2 ;
false.
This works as desired!
Importantly, we can use the predicate also more generally, namely to generate possible answers:
?- list_el_index(Ls, El, I).
Ls = [i(El)|_2994],
I = 0 ;
Ls = [_2992, i(El)|_3000],
I = 1 ;
Ls = [_2992, _2998, i(El)|_3006],
I = 2 ;
Ls = [_2992, _2998, _3004, i(El)|_3012],
I = 3 .
Due to the program's monotonicity, we can fairly enumerate solutions by iterative deepening:
?- length(Ls, _), list_el_index(Ls, El, I).
Ls = [i(El)],
I = 0 ;
Ls = [i(El), _4812],
I = 0 ;
Ls = [_4806, i(El)],
I = 1 ;
Ls = [i(El), _4812, _4818],
I = 0 ;
etc.
This has become possible by using a representation that lets us distinguish the cases by pattern matching. Consider using this approach to make your programs usable in all directions, and to make logical reasoning applicable. It is quite easy to apply by using the appropriate wrapper or constant, and greatly increases the generality of your programs.
This works :
- L = [1,_,1], nth1(X, L, Y), ground(Y), Y= 1.
L = [1,_310914,1],
X = Y, Y = 1 ;
L = [1,_310914,1],
X = 3,
Y = 1.
Thanks to lurkers hint, I came up with this solution.
list_el_index([El1|_], El2, 0) :-
El1 == El2.
list_el_index([_|Tail], Element, Index) :-
list_el_index(Tail, Element, Index1),
Index is Index1+1.

Prolog findall list of predicates

I've been searching but I can't find the right answer for my question.
The problem is:
a predicate
initial_estates([rb(1,1),rb(2,2),rb(3,5)]).
I want to use findall to get me a list of all the second term of rb's.
Like in this example [1,2,5]
Anyone can help
You can use lists:member/2 to interactively find all values of the pairs rb/2 in your list:
?- initial_estates(L),member(rb(X,Y),L).
L = [rb(1,1),rb(2,2),rb(3,5)],
X = Y = 1 ? ;
L = [rb(1,1),rb(2,2),rb(3,5)],
X = Y = 2 ? ;
L = [rb(1,1),rb(2,2),rb(3,5)],
X = 3,
Y = 5 ? ;
no
And based on that findall to get all second elements (Y) in one list (Res):
?- findall(Y,(initial_estates(L),member(rb(X,Y),L)),Res).
Res = [1,2,5]
Alternatively, you could also write a predicate, say rb_2nd/2, that describes the second argument to be the second element in the pair that is the first argument:
rb_2nd(rb(X,Y),Y).
And then use apply:maplist/3 to apply that relation to the list described by initial_estates/1:
?- initial_estates(L), maplist(rb_2nd,L,Res).
L = [rb(1,1),rb(2,2),rb(3,5)],
Res = [1,2,5]
I find the latter easier to read than the query using findall/3.

Defining the rule to avoid Arithmetic Error is/2 in Prolog

I'm trying to implement a binary tree in Prolog and I'm getting the following error:
ERROR: is/2: Arithmetic: `z/0' is not a function
I understand that this error occurs because the RHS of is/2 has not been instantiated properly.
But I'm finding it difficult to figure out how to instantiate my variable z in the second tree_eval/3 .
tree_eval(_,tree(empty,Num,empty),Num).
tree_eval(Value,tree(empty,z,empty),Value):-
z = Value.
tree_eval(Value,tree(L,Op,R),Eval):-
tree_eval(Value,L,LEval),
tree_eval(Value,R,REval),
eval(LEval,REval,Op,Eval).
eval(LEval,REval,Op,Result):-
Op = '+',
Result is LEval + REval.
eval(LEval,REval,Op,Result):-
Op = '-',
Result is LEval - REval.
eval(LEval,REval,Op,Result):-
Op ='/',
Result is LEval/REval.
How do I assign Value to z here?
Thanks in advance.
By z=Value you are actually unifying the variable Value with the atom z. If you mean z to be a variable you have to write it as a capital letter Z as #vmg pointed out:
tree_eval(Value,tree(empty,Z,empty),Value):-
Z = Value.
In that case it is interesting to consider what happens when querying the predicate:
?- tree_eval(V,tree(empty,3,empty),E).
E = 3 ? ;
E = V = 3 ? ;
no
The first solution is produced by your first rule in which you have an anonymous variable for the first argument. The second solution is produced by your second rule in which you demand the first and third arguments to be the same. So essentially you have two derivation paths for the value that is 3 in both cases. Now let's look at a slightly bigger tree:
?- tree_eval(V,tree(tree(empty,2,empty),+,tree(empty,3,empty)),E).
E = 5 ? ;
E = 5,
V = 3 ? ;
E = 5,
V = 2 ? ;
no
The first answer is hardly suprising as the tree evaluates to 5 indeed but what about the next two solutions? Let's take a look how prolog comes to these solutions: The term
tree(tree(empty,2,empty),+,tree(empty,3,empty))
matches only with the third rule because the subtrees are not empty. So tree_eval/3 is called with the subtree tree(empty,2,empty) and yields as first solution: (_,tree(empty,2,empty),2)
Then tree_eval/3 is called for the subtree tree(empty,3,empty) with the first solution: (_,tree(empty,3,empty),3)
Now eval(2,3,+,Eval) yields Eval=5. The first argument however is still Value=_. So the first solution for the query is: E=5.
If you ask for other answers prolog will try if there are further solutions for the 3rd goal, determine there are none, hence backtracking to the 2nd goal: the right subtree, and indeed your second rule delivers: (3,tree(empty,3,empty),3). eval(2,3,+,Eval) again contributes Eval=5, hence the second solution to the query: E=5, V=3.
If you still ask for more solutions prolog has to backtrack further to the 1st goal: and your 2nd rule delivers again: (2,tree(empty,2,empty),2). Now your second goal again matches the 1st rule: (_,tree(empty,3,empty),3), eval/4 delivers again Eval=5, so the 3rd solution to the query is: E=5, V=2
Backtracking one more time to goal 2 prolog is trying the 2nd rule again and fails because the first argument can't be 2 and 3 at the same time. So there is no 4th solution to the query.
However, if tree_eval/3 would be queried with the same tree structure but both leaves being 2 it is, by the above reasoning, not really suprising that there are 4 solutions:
?- tree_eval(V,tree(tree(empty,2,empty),+,tree(empty,2,empty)),E).
E = 4 ? ;
E = 4,
V = 2 ? ;
E = 4,
V = 2 ? ;
E = 4,
V = 2 ? ;
no
Looking at those multiple solutions it is apparent that your third argument is delivering the correct solution, and that you don't really need the first argument. You can also do without the second rule. Incorporating some improvements suggested by #mat, your predicate might then look something like that:
tree_evaluation(tree(empty,Num,empty),Num).
tree_evaluation(tree(L,Op,R),Val) :-
tree_evaluation(L,LVal),
tree_evaluation(R,RVal),
evaluation(LVal,RVal,Op,Val).
evaluation(L,R,+,V) :-
V is L + R.
evaluation(L,R,-,V) :-
V is L - R.
evaluation(L,R,/,V) :-
V is L / R.
This version yields unique answers:
?- tree_evaluation(tree(empty,3,empty),E).
E = 3 ? ;
no
?- tree_evaluation(tree(tree(empty,2,empty),+,tree(empty,3,empty)),E).
E = 5 ? ;
no

Prolog returning false for summation query

I'm new to Prolog as I'm just starting to learn and write up my own small set of database rules. Using my own .pl file of database rules, I'm having a small problem with a query that I enter in Prolog, using these rules. Below shows my small database of rules:
staff(andy,18235,3).
staff(beth,19874,4).
staff(andy,18235,5).
staff(carl,16789,2).
staff(earl,34567,9).
sum([], 0).
sum([H|T], X) :-
sum(T, X1),
X is X1 + H.
getincome(Name, Income) :-
findall(Income,staff(Name,_,Income),Member),
sum(Member, Income).
As you can see, I have written a rule that finds the total income for a particular member of staff. This works very fine, as when I input:
?- getincome(andy, X).
The program always returns:
X = 8
As it should do, however whenever I instead input:
?- getincome(andy, 8).
This always returns false, when it should be true.
However when I also input:
?- getincome(andy, 3).
This returns true, due to already being in the database.
I'm just wondering, how could I modify this rule so that this could output true for the correct summation value, entered for any given staff (most particularly Andy), as opposed to the value already in the given database?
Ignore my question above!
Thanks for the help 'false'. I'm also having another issue, this time to do with working out and displaying the sum of the income for each member. I have modified my rules, in order to display this, as follows:
getincome(Name, I) :- staff(Name, _, _ ), findall(Income,staff(Name,_,Income),Member), sum(Member, I).
Whenever I enter the query:
?- getincome(X, Y).
I keep getting duplicate results of staff (most notably Andy, of course), as show below:
X = andy,
Y = 8 ;
X = beth,
Y = 4 ;
X = andy,
Y = 8 ;
X = carl,
Y = 2 ;
X = earl,
Y = 9.
What changes can I make to avoid these duplicates?
library(aggregate) offers a clean interface to solve such kind of problems:
?- aggregate(sum(S), K^staff(E,K,S), I).
E = andy,
I = 8 ;
E = beth,
I = 4 ;
E = carl,
I = 2 ;
E = earl,
I = 9.
One way to do this is to use bagof to collect each set of incomes:
person_income(Name, Income) :-
bagof(I, X^staff(Name,X,I), Incomes), % Incomes for a given name
sumlist(Incomes, Income). % Sum the incomes
With results:
| ?- person_income(Name, Income).
Income = 8
Name = andy ? a
Income = 4
Name = beth
Income = 2
Name = carl
Income = 9
Name = earl
yes
| ?- person_income(andy, Income).
Income = 8
yes
| ?- person_income(Name, 8).
Name = andy ? a
no
| ?-
I named this person_income to emphasize that it's a relation between a person and their income, rather than getincome which is more of an imperative notion, and doesn't really reflect that you can do more with the relation than just "get the income". Also, I'm using SWI Prolog's sumlist/2 here. GNU Prolog has sum_list/2. And as #CappeliC indicates in his answer, SWI Prolog has a handy aggregate predicate for operations like this.

How do I work with equations that are passed on in the goal/query of prolog?

I have this scenario wherein I get a linear equation in the Prolog query like below:
?- myquery( 3X + 5Y = 10, Result).
So my query has an equation 3X + 5Y = 10, which in general assumes the form AX + BY = C, where A=3, B=5 and C=10.
Now, in my prolog program, I am trying to define a predicate that can take in the expression mentioned in the query above. That is, I somehow want to get A, B and C values and also the operator involved (in the above case the plus operator) stored and then used on the logic that I define withing the program. I am wondering how this can be done.
To be more generic, the question is how do I identify the constants and the operator involved in an equation that is passed on through the goal/query?
SWI-Prolog has a constraint library clp(Q,R) that solve at symbolic level these equations:
[debug] ?- [library(clpq)].
% library(clpq) compiled into clpq 0,27 sec, 992 clauses
true.
?- {3 * X + 5 * Y = 10}.
{Y=2-3 rdiv 5*X}.
Eclipse will surely have something more advanced. These libraries aren't simple, tough...
Of interest to you, the Prolog syntax is used, as a host language, so the usual builtins could be applied for identify vars, constants, and the like.
The following transcript may prove illuminating:
32 ?- Term = (3*_X + 5*_Y = 10), functor(Term,F,A).
Term = 3*_G527+5*_G530=10
F = =
A = 2
33 ?- Term = (3*_X + 5*_Y = 10), arg(Arg,Term,Val).
Term = 3*_G459+5*_G462=10
Arg = 1
Val = 3*_G459+5*_G462 ; % user pressed ';' interactively
Term = 3*_G459+5*_G462=10
Arg = 2
Val = 10 ; % user pressed ';' interactively
No
35 ?- Term = (3*_X + 5*_Y = 10), arg(1,Term,Val1), functor(Val1,F1,A1),
arg(2,Val1,Val12).
Term = 3*_G693+5*_G696=10
Val1 = 3*_G693+5*_G696
F1 = +
A1 = 2
Val12 = 5*_G696
The last query reads: for Term as given, 1st arg of Term is Val1, the functor of Val1 is F1 with arity A1 (meaning, it has A1 args - subparts - itself), and 2nd arg of the term in Val1 is stored under Val12 name. To clarify, any symbolic data in Prolog is in the form of fff(aa,bb,cc,...) where fff is some name, called functor, and the "arguments" in that expression can be accessed through the arg call.
That means that the original expression (3*_X + 5*_Y = 10) is actually stored in Prolog as '='( '+'( '*'(3,_X), '*'(5,_Y)), 10). When you get to the atomic parts (functors with arity 0), you can check them further:
47 ?- arg(1,(3*X),V), functor(V,F,A), number(V).
X = _G441
V = 3
F = 3
A = 0
Yes
EDIT: to answer your other question (from the comments):
1 ?- (3*_X + 5*_Y = 10) = (A*X + B*Y = C).
A = 3
X = _G412
B = 5
Y = _G415
C = 10
Yes
If you insist on not writing out the multiplication sign * explicitly, you will have to represent your terms as strings, and to analyze that string. That would be a much more involved task.
EDIT: another thing to try is =.. predicate, called "Univ":
4 ?- (3*_X + 5*_Y = 10) =.. X.
X = [=, 3*_G454+5*_G457, 10]
Yes
5 ?- (3*_X + 5*_Y = 10) =.. X, X=[X1,X2,X3], X2 =.. Y.
X = [=, 3*_G545+5*_G548, 10]
X1 = =
X2 = 3*_G545+5*_G548
X3 = 10
Y = [+, 3*_G545, 5*_G548]
Yes
You can for example use term inspection predicates: arg/3, functor/3, var/1, (=..)/2 etc.
You might want to take a look at examples of symbolic differentiation implemented using term rewrite rules; they handle such expressions.
Here's a chapter (minus 1 page) from the book Clause and Effect that you might find useful:
Clause and Effect - Chapter Six: Term Rewriting
Another from The art of Prolog: advanced programming techniques
23 An equation solver
Programming in Prolog also has a section (7.11) on symbolic differentiation.

Resources