I'm trying to create a predicate in prolog which will hold true if it reaches the lowest numerical value out of a set of values.
For example:
I have something like this at the moment
Base Step
lowest(Object, Value) :- \+ lessThan(Object, Value, NewValue).
Recursive Step
lowest(Object, Value) :- lessThan(Object, Value, NewValue), lowest(Object, NewValue).
Where Object is some abstract object which can have multiple numerical values attached to it.
lessThan returns Values (NewValue) for the Object which are less than the input Value.
And since NewValue will be lower than the input of Value I can assume that with each recursive step Value will be decreasing.
I have abstracted this problem from another which I am trying to solve, but basically what is happening is that I expect only 2 outputs from the whole recursive function, but instead I am getting as many outputs as lessThan(Object, Initial, X) + 2.
I'm not sure if this question is clear, please let me know so I can clarify.
I believe that my base step is correct, since I am making the assumption that if Value is the lowest coupled with Object, then there are no other values less than Value.
I am unsure where to terminate the recursion also, which is adding to my confusion. My guess is that it will terminate once it reaches a state where there are no lower Values for Object.
This sample should work, renaming value/2 as appropriate for your domain.
value(a, 10).
value(a, 3).
value(a, 100).
lowest(Object, L) :-
value(Object, First), !, lowest(Object, First, L).
lowest(Object, LowestSoFar, Lowest) :-
value(Object, Try), Try < LowestSoFar, !,
lowest(Object, Try, Lowest).
lowest(_, Lowest, Lowest).
it yields
?- lowest(a,X).
X = 3.
Note that it repeats the value 'peek' each time, then is not efficient.
A possible alternative is storing the lower value and run a failure driven loop.
Otherwise, SWI-Prolog (and YAP) has library(aggregate):
?- aggregate(min(V), value(a,V), M).
M = 3.
Related
Here is the main part of my code in Prolog:
state(N, Sf) :-
get_initial_state('test.csv',S),
state_sequence(N, S, Sf).
state_sequence(N, S, S).
state_sequence(N, S, Sf) :-
transition_state(S, S, [], Sn),
N > 0,
N1 is N - 1,
state_sequence(N1, Sn, Sf).
transition_state is just a set of rules which does not matter here. And it is a recursion which keeps going to get value of next state until N reaches 0.
Then for example I want the 48th result of state. So my query is
state(48,S).
Then I need to keep pressing ; and prolog keeps telling me next state and then until 48th it results in false.
So how can I get the 48th result directly without telling me results of each state??
The fastest way is to generate all solutions using findall/3, then get the solution you want. This is a simple example to show you the idea:
test(1,0).
test(2,0).
test(3,0).
test(4,0).
test(5,0).
test(6,0).
getNthSolution(Sol,N):-
findall(S,test(S,0),L),
nth1(N,L,Sol).
?- getNthSolution(S,3)
S = 3
Knowledge Base
add(0,Y,Y). // clause 1
add(succ(X),Y,succ(Z)) :- add(X,Y,Z). // clause 2
Query
add(succ(succ(succ(0))), succ(succ(0)), R)
Trace
Call: (6) add(succ(succ(succ(0))), succ(succ(0)), R)
Call: (7) add(succ(succ(0)), succ(succ(0)), _G648)
Call: (8) add(succ(0), succ(succ(0)), _G650)
Call: (9) add(0, succ(succ(0)), _G652)
Exit: (9) add(0, succ(succ(0)), succ(succ(0)))
Exit: (8) add(succ(0), succ(succ(0)), succ(succ(succ(0))))
Exit: (7) add(succ(succ(0)), succ(succ(0)), succ(succ(succ(succ(0)))))
Exit: (6) add(succ(succ(succ(0))), succ(succ(0)), succ(succ(succ(succ(succ(0))))))
My Question
I see how the recursive call in clause 2 strips the outermost succ()
at each call for argument 1.
I see how it adds an outer succ() to argument 3 at each call.
I see when the 1st argument as a result of these recursive calls
reaches 0. At that point, I see how the 1st clause copies the 2nd
argument to the 3rd argument.
This is where I get confused.
Once the 1st clause is executed, does the 2nd clause automatically
get executed as well, then adding succ() to the first argument?
Also, how does the program terminate, and why doesn't it just keep
adding succ() to the first and 3rd arguments infinitely?
Explanation from LearnPrologNow.com (which I don't understand)
Let’s go step by step through the way Prolog processes this query. The
trace and search tree for the query are given below.
The first argument is not 0 , which means that only the second clause
for add/3 can be used. This leads to a recursive call of add/3 . The
outermost succ functor is stripped off the first argument of the
original query, and the result becomes the first argument of the
recursive query. The second argument is passed on unchanged to the
recursive query, and the third argument of the recursive query is a
variable, the internal variable _G648 in the trace given below. Note
that _G648 is not instantiated yet. However it shares values with R
(the variable that we used as the third argument in the original
query) because R was instantiated to succ(_G648) when the query was
unified with the head of the second clause. But that means that R is
not a completely uninstantiated variable anymore. It is now a complex
term, that has a (uninstantiated) variable as its argument.
The next two steps are essentially the same. With every step the first
argument becomes one layer of succ smaller; both the trace and the
search tree given below show this nicely. At the same time, a succ
functor is added to R at every step, but always leaving the innermost
variable uninstantiated. After the first recursive call R is
succ(_G648) . After the second recursive call, _G648 is instantiated
with succ(_G650) , so that R is succ(succ(_G650) . After the third
recursive call, _G650 is instantiated with succ(_G652) and R therefore
becomes succ(succ(succ(_G652))) . The search tree shows this step by
step instantiation.
At this stage all succ functors have been stripped off the first
argument and we can apply the base clause. The third argument is
equated with the second argument, so the ‘hole’ (the uninstantiated
variable) in the complex term R is finally filled, and we are through.
Let us start by getting the terminology right.
These are the clauses, as you correctly indicate:
add(0, Y, Y).
add(succ(X), Y, succ(Z)) :- add(X, Y, Z).
Let us first read this program declaratively, just to make sure we understand its meaning correctly:
0 plus Y is Y. This makes sense.
If it is true that X plus Y is Z then it is true that the successor of X plus Y is the successor of Z.
This is a good way to read this definition, because it is sufficiently general to cover various modes of use. For example, let us start with the most general query, where all arguments are fresh variables:
?- add(X, Y, Z).
X = 0,
Y = Z ;
X = succ(0),
Z = succ(Y) ;
X = succ(succ(0)),
Z = succ(succ(Y)) .
In this case, there is nothing to "strip", since none of the arguments is instantiated. Yet, Prolog still reports very sensible answers that make clear for which terms the relation holds.
In your case, you are considering a different query (not a "predicate definition"!), namely the query:
?- add(succ(succ(succ(0))), succ(succ(0)), R).
R = succ(succ(succ(succ(succ(0))))).
This is simply a special case of the more general query shown above, and a natural consequence of your program.
We can also go in the other direction and generalize this query. For example, this is a generalization, because we replace one ground argument by a logical variable:
?- add(succ(succ(succ(0))), B, R).
R = succ(succ(succ(B))).
If you follow the explanation you posted, you will make your life very difficult, and arrive at a very limited view of logic programs: Realistically, you will only be able to trace a tiny fragment of modes in which you could use your predicates, and a procedural reading thus falls quite short of what you are actually describing.
If you really insist on a procedural reading, start with a simpler case first. For example, let us consider:
?- add(succ(0), succ(0), R).
To "step through" procedurally, we can proceed as follows:
Does the first clause match? (Note that "matching" is already limited reading: Prolog actually applies unification, and a procedural reading leads us away from this generality.)
Answer: No, because s(_) does not unify with 0. So only the second clause applies.
The second clause only holds if its body holds, and in this case if add(0, succ(0), Z) holds. And this holds (by applying the first clause) if Z is succ(0) and R is succ(Z).
Therefore, one answer is R = succ(succ(0)).. This answer is reported.
Are there other solutions? These are only reported on backtracking.
Answer: No, there are no other solutions, because no further clause matches.
I leave it as an exercise to apply this painstaking method to the more complex query shown in the book. It is straight-forward to do it, but will increasingly lead you away from the most valuable aspects of logic programs, found in their generality and elegant declarative expression.
Your question regarding termination is both subtle and insightful. Note that we must distinguish between existential and universal termination in Prolog.
For example, consider again the most general query shown above: It yields answers, but it does not terminate. For an answer to be reported, it is enough that an answer substitution is found that makes the query true. This is the case in your example. Alternatives, if any potentially remain, are tried and reported on backtracking.
You can always try the following to test termination of your query: Simply append false/0, for example:
?- add(X, Y, Z), false.
nontermination
This lets you focus on termination properties without caring about concrete answers.
Note also that add/3 is a terrible name for a relation: An imperative always implies a direction, but this is in fact much more general and usable also if none of the arguments are even instantiated! A good predicate name should reflect this generality.
I'm working on a small function which checks to see if a tree is just a reversed version of another tree.
For example,
1 1
2 3 = 3 2
1 1
My code is just versions of the following:
treeRev(leaf(Leaf1), leaf(Leaf2)) :-
leaf(Leaf1) is leaf(Leaf2).
treeRev(node1(Leaf1, Node1), node1(Leaf2, Node2)) :-
node1(Leaf1,treeRev(Node1)) is node1(Leaf2, treeRev(Node2)).
treeRev(node2(Leaf1, Node1, Node2), node2(Leaf2, Node3, Node4)) :-
node2(Leaf1, treeRev(Node1), treeRev(Node2)) is
node2(Leaf2, treeRev(Node4), treeRev(Node3)).
Where my basis is as following:
Base case is the two leaves are equal, which just returns true. If it has one node, check the leaves are equal, and call the function recursively on the node.
If it's two nodes, check the trees are equal, and then call the recursive function after having flipped the nodes from the second tree.
My issue is, I keep getting the bug
ERROR: is/2: Arithmetic: `leaf/1' is not a function
Thing is, I don't get this error when using other operations on the tree. Any advice on how to get around this? The only limitation imposed is that I can't use =.
I also figured that the most probable cause is that the sides of the is don't return the same "type", according to searches on google and stackoverflow. The way I see it though, is that shouldn't be the case here since I have almost the exact same thing on both ends.
Thank you for reading, and any help is greatly appreciated :)
The is/2 predicate is used for arithmetic. It calculates and assigns the value of an expression (second argument) to the variable-first argument. For example:
X is 1+(2*Y)/2 where Y is already instantiated so it has a value (in order to calculate the value of the expression otherwise it throws instantiation error).
In you case you can't use is/2 since you don't want to calculate any arithmetic expression (that's why the error). What you need is unification, you need to unify a term (e.g a leaf or node) with another term by using =.
For example:
treeRev(leaf(Leaf1), leaf(Leaf2)) :-
leaf(Leaf1) = leaf(Leaf2).
treeRev(node1(Leaf1, Node1), node1(Leaf2, Node2)) :-
node1(Leaf1,treeRev(Node1)) = node1(Leaf2, treeRev(Node2)).
treeRev(node2(Leaf1, Node1, Node2), node2(Leaf2, Node3, Node4)) :-
node2(Leaf1, treeRev(Node1), treeRev(Node2)) =
node2(Leaf2, treeRev(Node4), treeRev(Node3)).
By using pattern matching you could simply do:
treeRev(leaf(Leaf2), leaf(Leaf2)).
treeRev(node1(Leaf2, treeRev(Node2)), node1(Leaf2, Node2)).
treeRev(node2(Leaf2,Node1,Node2), node2(Leaf2, Node3, Node4)):-
treeRev(Node1,Node4),treeRev(Node2,Node3).
... then call the recursive function...
Prolog predicates are not functions. Writing node1(Leaf1,treeRev(Node1)) will not build a node with "the result of calling the treeRev function", as in other programming languages. Instead, Prolog predicates have extra arguments for the "result". You typically call the predicate and bind such "results" to a variable or unify it with a term.
You will need something like this for a binary node (not tested, and not following your teacher's strange and undocumented tree representation):
tree_mirrored(node(LeftTree, RightTree), node(RightMirrored, LeftMirrored)) :-
tree_mirrored(LeftTree, LeftMirrored),
tree_mirrored(RightTree, RightMirrored).
I deal with a problem; I want to calculate how many recursions a recursive rule of my code does.
My program examines whether an object is component of a computer hardware or not(through component(X,Y) predicate).E.g component(computer,motherboard) -> true.
It does even examine the case an object is not directly component but subcomponent of another component. E.g. subcomponent(computer,ram) -> true. (as ram is component of motherboard and motherboard is component of computer)
Because my code is over 400 lines I will present you just some predicates of the form component(X,Y) and the rule subcomponent(X,Y).
So, some predicates are below:
component(computer,case).
component(computer,power_supply).
component(computer,motherboard).
component(computer,storage_devices).
component(computer,expansion_cards).
component(case,buttons).
component(case,fans).
component(case,ribbon_cables).
component(case,cables).
component(motherboard,cpu).
component(motherboard,chipset).
component(motherboard,ram).
component(motherboard,rom).
component(motherboard,heat_sink).
component(cpu,chip_carrier).
component(cpu,signal_pins).
component(cpu,control_pins).
component(cpu,voltage_pins).
component(cpu,capacitors).
component(cpu,resistors).
and so on....
My rule is:
subcomponent(X,Z):- component(X,Z).
subcomponent(X,Z):- component(X,Y),subcomponent(Y,Z).
Well, in order to calculate the number of components that a given component X to a given component Y has-that is the number of recursions that the recursive rule subcomponents(X,Y), I have made some attempts that failed. However, I present them below:
i)
number_of_components(X,Y,N,T):- T is N+1, subcomponent(X,Y).
number_of_components(X,Y,N,T):- M is N+1, subcomponent(X,Z), number_of_components(Z,Y,M,T).
In this case I get this error: "ERROR: is/2: Arguments are not sufficiently instantiated".
ii)
number_of_components(X,Y):- bagof(Y,subcomponent(X,Y),L),
length(L,N),
write(N).
In this case I get as a result either 1 or 11 and after this number true and that's all. No logic at all!
iii)
count_elems_acc([], Total, Total).
count_elems_acc([Head|Tail], Sum, Total) :-
Count is Sum + 1,
count_elems_acc(Tail, Count, Total).
number_of_components(X,Y):- bagof(Y,subcomponent(X,Y),L),
count_elems_acc(L,0,Total),
write(Total).
In this case I get as results numbers which are not right according to my knowledge base.(or I mistranslate them-because this way seems to have some logic)
So, what am I doing wrong and what should I write instead?
I am looking forward to reading your answers!
One thing you could do is iterative deepening with call_with_depth_limit/3. You call your predicate (in this case, subcomponent/2). You increase the limit until you get a result, and if you get a result, the limit is the deepest recursion level used. You can see the documentation for this.
However, there is something easier you can do. Your database can be represented as an unweighted, directed, acyclic graph. So, stick your whole database in a directed graph, as implemented in library(ugraphs), and find its transitive closure. In the transitive closure, the neighbours of a component are all its subcomponents. Done!
To make the graph:
findall(C-S, component(C, S), Es),
vertices_edges_to_ugraph([], Es, Graph)
To find the transitive closure:
transitive_closure(Graph, Closure)
And to find subcomponents:
neighbours(Component, Closure, Subcomponents)
The Subcomponents will be a list, and you can just get its length with length/2.
EDIT
Some random thoughts: in your case, your database seems to describe a graph that is by definition both directed and acyclic (the component-subcomponent relationship goes strictly one way, right?). This is what makes it unnecessary to define your own walk through the graph, as for example nicely demonstrated in this great question and answers. So, you don't need to define your own recursive subcomponent predicate, etc.
One great thing about representing the database as a term when working with it, instead of keeping it as a flat table, is that it becomes trivial to write predicates that manipulate it: you get Prolog's backtracking for free. And since the S-representation of a graph that library(ugraph) uses is well-suited for Prolog, you most probably end up with a more efficient program, too.
The number of calls of a predicate can be a difficult concept. I would say, use the tools that your system make available.
?- profile(number_of_components(computer,X)).
20===================================================================
Total time: 0.00 seconds
=====================================================================
Predicate Box Entries = Calls+Redos Time
=====================================================================
$new_findall_bag/0 1 = 1+0 0.0%
$add_findall_bag/1 20 = 20+0 0.0%
$free_variable_set/3 1 = 1+0 0.0%
...
so:count_elems_acc/3 1 = 1+0 0.0%
so:subcomponent/2 22 = 1+21 0.0%
so:component/2 74 = 42+32 0.0%
so:number_of_components/2 2 = 1+1 0.0%
On the other hand, what is of utmost importance is the relation among clause variables. This is the essence of Prolog. So, try to read - let's say, in plain English - your rules.
i) number_of_components(X,Y,N,T) what relation N,T have to X ? I cannot say. So
?- leash(-all),trace.
?- number_of_components(computer,Y,N,T).
Call: (7) so:number_of_components(computer, _G1931, _G1932, _G1933)
Call: (8) _G1933 is _G1932+1
ERROR: is/2: Arguments are not sufficiently instantiated
Exception: (8) _G1933 is _G1932+1 ?
ii) number_of_components(X,Y) here would make much sense if Y would be the number_of_components of X. Then,
number_of_components(X,Y):- bagof(S,subcomponent(X,S),L), length(L,Y).
that yields
?- number_of_components(computer,X).
X = 20.
or better
?- aggregate(count, S^subcomponent(computer,S), N).
N = 20.
Note the usage of S. It is 'existentially quantified' in the goal where it appears. That is, allowed to change while proving the goal.
iii) count_elements_acc/3 is - more or less - equivalent to length/2, so the outcome (printed) seems correct, but again, it's the relation between X and Y that your last clause fails to establish. Printing from clauses should be used only when the purpose is to perform side effects... for instance, debugging...
I'm a little surprised that
value "let x = SOME n. n ∈ {1::int,2} in x = x"
returns True. After β-expanding and α-renaming, that term is the same as:
value "(SOME na. na ∈ {1::int,2}) = (SOME nb. nb ∈ {1::int,2})"
I don't see why this equality should hold. Why should the value chosen for na be the same as the value chosen for nb?
The term on the left hand side is exactly the same as the term on the right hand side (modulo alpha conversion). Therefore, they also have the same value. Equal (or rather alpha-equivalent) terms always produce equal values in HOL, since it is deterministic.
You can think of SOME x. P x giving you an arbitrary, but fixed value for which the property P holds (if such a value exists, otherwise just some arbitrary but fixed value about which you know nothing at all). In particular, different “calls” of SOME with the same argument will always give you the same value. The same is true of THE, undefined, and so on.
If you want true nondeterministic choice, you have to either use a different logic or model nondeterminism within HOL. The Refinement Framework offers a nondeterministic monad in which every operation can have zero, one, or many possible results.