Related
I am trying to find the maximum element in multilayered list (meaning list in list in list...) in Prolog. The thing is, I reviewed all the predicates 1 by 1 and they all work, except for the one that is actually supposed to solve my problem. My approach is to flatten the list (make it single-layered) and the find the maximum element in THAT list. This is my code:
is_list([]).
add([],L,L).
add([X|L1],L2,[X|L3]):-add(L1,L2,L3).
maximum([X|O],M) :- max(O,X,M),!.
max([X|O],Y,M) :- X=<Y, max(O,Y,M).
max([X|O],Y,M) :- X>Y, max(O,X,M).
max([],M,M).
flatten([],[]).
flatten([X|L1],[X|L2]):-not(is_list(X)),!,flatten(L1,L2).
flatten([X|L1],L2):-flatten(X,LX),flatten(L1,LL1),add(LX,LL1,L2).
maximum_in_multilayered_list(L,M):-flatten(L,L1),maximum(L1,N), M is N.
For some reason, I get the following error:
?- maximum_in_multilayered_list([1,[2,3],4],X).
ERROR: Type error: `[]' expected, found `[2,3]' (a list) ("x" must hold one character)
ERROR: In:
ERROR: [13] [2,3]=<1
ERROR: [12] max([[2|...],4],1,_7284) at c:/users/ace_m/documents/prolog/bp.pl:47
ERROR: [11] maximum([1,...|...],_7328) at c:/users/ace_m/documents/prolog/bp.pl:46
ERROR: [10] maximum_in_multilayered_list([1,...|...],_7366) at c:/users/ace_m/documents/prolog/bp.pl:75
ERROR: [9] <user>
Exception: (12) max([[2, 3], 4], 1, _7596) ? creep
I understand that the problem is that I am actually comparing a list of integers with an integer meaning they are incompatible types, but why does it even come to that? What am I doing wrong?
Remove your is_list([]) and it works.
As it is, any non-empty list is not considered to be is_list/1 material, so for [2,3] in [1,[2,3],4] the second clause in the flatten/2 definition applies, and adds X = [2,3] as is into the "flattened" list [X|L2].
But is_list/1 is already a built-in predicate which does exactly what you want.
Another way to implement this is with library(aggregate).
First we define a backtrackable predicate which enumerates all non-lists (i.e. "plain values") through the nested lists (taken from this somewhat related recent answer of mine):
nembr(Z, A) :- % member in nested lists
is_list(A), member(B,A), nembr(Z,B)
;
\+ is_list(A), A=Z.
Then
18 ?- nembr(X, [1,[2,3],4]).
X = 1 ;
X = 2 ;
X = 3 ;
X = 4 ;
false.
19 ?- use_module(library(aggregate)).
true
20 ?- L = [1,[2,3],4], aggregate( max(X), nembr(X,L), R).
L = [1, [2, 3], 4],
R = 4.
I was challenged with a CS problem.
The problem consists of recursively finding which expressions of the form ((10+10)/(10+10)) produces a number. For example, ((10+10)/(10+10)) produces 1. Find all the other expressions using the operators +, -, *, /, with 4 numbers of 10, and all the combinations of parentheses to enforce orders of operations.
I was referred to the Reverse Polish Notation, but that relies on postfix notation, which isn’t required to solve this problem.
Some pseudocode I have is this. I know using recursion is the easiest way to solve this problem. But don't know how to make sure I get all combinations.
build([10,10,10,10], Expression) :-
Operator
/ \
[10] [10,10,10]
Operator
/ \
[10] [10,10]
Operator
/ \
[10] [10]
This is a problem I am trying to solve in Prolog but C++ is good as well.
I have a partial solution which I will outline here and hopefully it will get you moving and you can find the complete solution.
The first tool you need is the ability to make some expressions:
build_expr(X, Y, X+Y).
build_expr(X, Y, X*Y).
build_expr(X, Y, X-Y).
build_expr(X, Y, X/Y).
This defines build_expr/3, which takes two variables or expressions and produces a new expression. This is how we are going to permute the operators. Now we need a way to handle the lists, so let's define build_expr/2 that operates on a list at once:
% base case: we are down to two variables and call build_expr/3
build_expr([X,Y], Expr) :- build_expr(X, Y, Expr).
% inductive case: make the expression on the rest of the list and combine
% with the leading variable here
build_expr([X|Rest], Expr) :-
build_expr(Rest, Expr0),
build_expr(X, Expr0, Expr).
Let's get a few solutions so we get the flavor of what it's doing:
3 ?- build_expr([10,10,10,10],X).
X = 10+(10+(10+10)) ;
X = 10*(10+(10+10)) ;
X = 10-(10+(10+10)) ;
X = 10/(10+(10+10)) ;
X = 10+10*(10+10) ;
X = 10*(10*(10+10)) ;
X = 10-10*(10+10) ;
X = 10/(10*(10+10)) ;
X = 10+(10-(10+10)) ;
X = 10*(10-(10+10)) ;
X = 10-(10-(10+10)) ;
X = 10/(10-(10+10)) ;
This looks pretty good to me. But like I said, I'm only generating the right-leaning tree. You will have to modify or replace build_expr/2 to produce the other shapes, if they actually matter (which I'm not convinced they do).
Now let's make the next step simpler by bundling in evaluation:
build_eval(L, Value) :- build_expr(L, Expr), Value is Expr.
Now we should be able to find all the unique solutions using setof/3:
6 ?- setof(X, build_eval([10,10,10,10],X), Results).
ERROR: Arithmetic: evaluation error: `zero_divisor'
ERROR: In:
ERROR: [15] _582 is 10/(10* ...)
ERROR: [14] build_eval([10,10|...],_622) at /Users/dlyons/fourtens.pl:11
ERROR: [13] '$bags':findall_loop(_664,user:build_eval(...,_682),_668,[]) at /usr/local/Cellar/swi-prolog/7.6.4/libexec/lib/swipl-7.6.4/boot/bags.pl:97
ERROR: [12] setup_call_catcher_cleanup('$bags':'$new_findall_bag','$bags':findall_loop(_728,...,_732,[]),_710,'$bags':'$destroy_findall_bag') at /usr/local/Cellar/swi-prolog/7.6.4/libexec/lib/swipl-7.6.4/boot/init.pl:443
ERROR: [8] '$bags':setof(_770,user:build_eval(...,_786),_774) at /usr/local/Cellar/swi-prolog/7.6.4/libexec/lib/swipl-7.6.4/boot/bags.pl:240
ERROR: [7] <user>
ERROR:
ERROR: Note: some frames are missing due to last-call optimization.
ERROR: Re-run your program in debug mode (:- debug.) to get more detail.
ERROR: [13] '$bags':findall_loop(_664,user:build_eval(...,_682),_668,[]) aabort
% Execution Aborted
Oops. Division by zero error. No problem, let's catch that and fail in those cases instead:
9 ?- setof(X, catch(build_eval([10,10,10,10],X), E, fail), Results), writeln(Results).
[-990,-900,-190,-100,-80,-20,-1,-0.1111111111111111,
0,0.01,0.05,0.09090909090909091,0.3333333333333333,1.0,1,
5.0,9.5,9.9,10,10.1,10.5,20.0,20,40,100.0,100,
120,210,300,1010,1100,2000,10000]
I fiddled with the formatting there a little, but I think that's a pretty good solution, but I can already see one missing solution: (10+10)*(10+10)=400. So you will have to get more creative with build_expr/2 to make it produce other shapes of tree.
Edit: Adding the rest of the solutions
I found an answer by #gusbro that gives a way to enumerate the trees. I wasn't able to get it to work with the recursive trickery I was doing there (maybe someone else will show me a very easy trick) but I was able to adapt his answer to your problem, to wit:
build_tree([I1,I2|Items], Expr) :-
append([L0|LR], [R0|RR], [I1,I2|Items]),
build_tree([L0|LR], Left),
build_tree([R0|RR], Right),
build_expr(Left, Right, Expr).
build_tree([E], E).
Why am I using [L0|LR] and [R0|RR] instead of LeftList and RightList or some such? This is how I'm turning #gusbro's numeric constraints into list length constraints and ensuring that I always have at least one element in both the left and right lists, so my recursive calls to build_tree/2 will succeed.
Simplifying build_expr/3 from above down to a single operator you can see this generates all the various flavors you'd expect:
?- build_tree([10,10,10,10],X).
X = 10+(10+(10+10)) ;
X = 10+(10+10+10) ;
X = 10+10+(10+10) ;
X = 10+(10+10)+10 ;
X = 10+10+10+10 ;
false.
Switch it back, because we're still using the build_expr/3 function from the earlier example. I have simplified the evaluation somewhat using this build_eval/2 predicate:
build_eval(L, Value) :-
build_tree(L, Expr), catch(Value is Expr, _, fail).
Here's what the final solution looks like:
?- setof(X, build_eval([10,10,10,10], X), Res), writeln(Res).
[-990,-900,-190,-100,-99,-90,-80,-20,-19,-10,-9.9,-9.5,-9,
-8,-1.1111111111111112,-1,-0.9,-0.1111111111111111,
0,0.01,0.05,0.09090909090909091,0.1111111111111111,
0.2,0.3333333333333333,0.9,0.9090909090909091,1.0,1,
1.1,1.1111111111111112,2,3,5.0,5,8,9,9.5,9.9,10,10.1,10.5,11,
12,19,20.0,20,21,40,80,90,99,100.0,100,101,110,120,190,
200,210,300,400,900,990,1010,1100,2000,10000]
Wow, quite a few alternatives, 68 to be exact!
I am trying to create a Prolog program for solving the recurrent equation:
f(1)=2, f(2)=5, f(n)=f(n-1)+2*f(n-2)
I managed with the rec function below, but I have trouble when I want to store the result in the list (by function recList).
This is my implementation:
rec(1,2).
rec(2,5).
rec(X,N) :- X1 is X-1, X2 is X-2, rec(X1,N1), rec(X2,N2), N is N1+2*N2.
recList(0,[]).
recList(X,[N|L]) :- rec(X,N), X1 is X-1, recList(X1,L).
My implementation of recList works for calling it by the first value
?- recList(4,X).
->
X = [19, 9, 5, 2] .
but it doesn't when I call it by the second one if it is longer than two elements:
?- rekurList(X,[2]).
X = 1 .
?- rekurList(X,[5,2]).
X = 2 .
?- rekurList(X,[9,5,2]).
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR: [9] rec(_12587334,9)
ERROR: [8] rekurList(_12587360,[9,5|...]) at /locaiton/rec.pl:6
ERROR: [7] <user>
What is wrong, please?
The predicate is/2 fails because is/2 evaluates the right-hand structure as an arithmetic expression. If it is not a valid arithmetic expression or a number, is/2 fails. So when you call
recList(X, [19, 9, 5, 2]).
you get rec/2: Arguments are not sufficiently instantiated. If you run the tracer (in SWISH, which is SWI on line: trace, recList(X, [19, 9, 5, 2]). In ECLiPSe you can use tkeclipse Tools->Tracer) you get something like:
Call:recList(_13806, [19, 9, 5, 2])
Call:rec(_13806, 19)
Call:_14048 is _13806+-1
Exception:_14102 is _13806+-1
is/2: Arguments are not sufficiently instantiated
To solve this problem you can use the library clpfd in this way (i wrote the solution using SWI):
:- use_module(library(clpfd)).
rec(1,2).
rec(2,5).
rec(X,N):-
X1 #> 0,
X1 #= X-1,
rec(X1,N1),
X2 #> 0,
X2 #= X-2,
rec(X2,N2),
N #= N1+2*N2, !. %notice the cut (!)
recList(0,[]):-!.
recList(X,[N|L]):-
rec(X,N),
X1 #= X-1,
recList(X1,L).
Query:
?- recList(X, [19, 9, 5, 2]).
X = 4.
false.
?- recList(4,L).
L = [19, 9, 5, 2]
false
Note that the cut ! is needed because otherwise, after the first solution, if you click more, the computation will never end. Also X1 #> 0 and X2 #> 0 are needed because otherwise you get a out of local stack error.
I want to have a functionality like below. I have tried many things but still unable to achieve it.
>>> a, b = [1], [2]
>>> k = [a, a, b]
>>> k
[[1], [1], [2]]
Now as expected, if I change the second value the first value will be changed automatically.
>>> k[0][0] = 3
>>> k
[[3], [3], [2]]
You see how changing one value affects the other.
Now I want to somehow link the third element with the first two such that whenever I change any of the three elements, every element that it's linked to changes. I want to have the following behavior:
>>> *Do something to link k[1] or k[0] with k[2]*
>>> k[-1][0] = 4
>>> k
>>> [[4], [4], [4]]
I have tried doing the following and failed as you can see below:
>>> b = a
>>> k
>>> [[3], [3], [2]]
Please help me achieve the above.
The real problem I want to solve:
I am implementing min-cut algorithm. In this algorithm I need to merge two vertices at every step. I am trying doing this by linking the two vertices together which I want to merge.
Is this what you want?
a,b = [1],[2]
k = [a,a,b] # store references to lists a and b
print(k)
k[0][0] = 3 # change the first cell's list's first element
print(k) # second cell changes as well since it references same list
k[-1] = k[0] # store the first cell's reference in the last cell. All reference the same list 'a' now.
k[1][0] = 4
print(k)
Output:
[[1], [1], [2]]
[[3], [3], [2]]
[[4], [4], [4]]
I have a function that outputs names that fit a specific constraint. This function is fine.
But I need to use that function to make another function that turns the outputs of the former function into a list. Being a complete beginner with Prolog, I have no clue how to do this.
My problem is that I don't know how to iterate over the outputs to append it to an accumulator. The function which outputs names does so, then I press ";" or SPACE and it outputs the next answer until it's out of answers. I figure this means I have to make multiple calls to the function then append it. But I don't know how many times I need to call it, since I can't iterate over it like a list with [Head|Tail].
Here's what I have so far(although it's probably wrong):
%p1(L,X) determines if chemicals in List X are in any of the products and stores those products in L
p1(L,X) :- p1_helper(L,X,[]).
p1_helper(L,X,Acc) :- has_chemicals(A,X),append(Acc,[A],K),L=K, p1_helper(L,X,K).
function that outputs names with query has_chemicals(X,[List of Chemicals]).:
%has_chemicals(X,Is) determines if the chemicals in List Is are in the chemical list of X.
has_chemicals(X,Is) :- chemicals(X,Y), hc(Y,Is).
%hc(X,Y) determines if elements of Y are in elements of X.
hc(Y,[]).
hc(Y,[C|D]) :- isin(C,Y), hc(Y,D).
Any help is appreciated.
But I need to use that function to make another function that turns the outputs of the former function into a list. Being a complete beginner with Prolog, I have no clue how to do this.
findall(+Template, :Goal, -Bag):
Creates a list of the instantiations Template gets successively on backtracking over Goal and unifies the result with Bag.
For example, how to collect all odd numbers from 1 to 15:
odd( X ) :-
X rem 2 =:= 1.
We can get all that odds one-by-one.
?- between( 1, 15, X ), odd( X ).
X = 1 ;
X = 3 ;
X = 5 ;
X = 7 ;
X = 9 ;
X = 11 ;
X = 13 ;
X = 15.
And we can collect them into a list:
?- findall(X, (between( 1, 15, X ), odd( X )), List).
List = [1, 3, 5, 7, 9, 11, 13, 15].
I think you are looking for a way to capture the output of isin/2. Then you can use the builtin with_output_to/2, and combine it with findall/3, as suggested by other answers.
I encourage you to visit this page especially if you use swi-prolog.
There are 4 predicates that do what you want : findall/3, findall/4, bagof/3 and setof/3.
To summarize, here is the test predicate I'll be working with :
test(0, 3).
test(1, 3).
test(2, 5).
test(3, 4).
First, the simplest, findall/3 and findall/4 :
?- findall(C, test(X, C), Cs).
Cs = [3, 3, 5, 4].
?- findall(C, test(X, C), Cs, TailCs).
Cs = [3, 3, 5, 4|TailCs].
They just return all the alternatives, with duplicates, without sorting, without binding the other free variables, as a normal list for findall/3 and difference list for findall/4. both findalls predicates succeed when the list is empty.
Then, bagof. Basically, bagof/3 works as findall/3 but binds free variables. That means that the same query than above but with bagof/3 returns :
?- bagof(C, test(X, C), Cs).
X = 0,
Cs = [3] ;
X = 1,
Cs = [3] ;
X = 2,
Cs = [5] ;
X = 3,
Cs = [4].
By telling bagof/3 not to bind all the free variables, you obtain findall/3 :
?- bagof(C, X^test(X, C), Cs).
Cs = [3, 3, 5, 4].
Still you have to note that bagof/3 fails when the result is empty, where findall/3 doesn't.
Finally, setof/3. It's basically bagof/3 but with the results sorted and no duplicates :
?- setof(C, X^test(X, C), Cs).
Cs = [3, 4, 5].