I would like to find all solutions to a goal within some time limit. I mean that I would like to search for solutions for at most the time limit, and return all solutions found, whether the time limit has been reached or not, which is regardless of whether the list of solutions is complete or not.
I have tried the following:
catch(call_with_time_limit(60, findall(S,my_goal(S),Sol)), time_limit_exceeded,false)
However, it does not return the partial list of solutions found if the time limit has been reached, and "false" can not be an expression relying on Sol.
This question is related to Prolog: "findall" for limited number of solutions, but instead of having a maximum number of solution I am interested in maximum search time.
Would you please have any insight for this?
Something like this may work to you:
findall_time(Duration, Template, Goal, Bag):-
get_time(TimeStamp),
Time is TimeStamp + Duration,
findall(Template, findall_time1(Time, Goal), Bag).
findall_time1(Time, Goal) :-
catch(setup_call_cleanup(alarm_at(Time,
throw(time_limit_exceeded),
Id),
(get_time(TimeStamp), Time>TimeStamp, Goal),
remove_alarm(Id)),
time_limit_exceeded,
fail).
with this sample code and test:
my_goal(X):-
between(0, 5, X),
sleep(1).
?- findall_time(2.5, X, my_goal(X), Bag).
Bag = [0, 1].
Related
Looking at the code below:
multiple(X,0).
multiple(X,Y) :- lt(0,X), lt(0,Y), diff(Y,X,D), multiple(X,D).
There happens to be something wrong. For your reference:
lt/2 is whether the first argument is less than the second.
diff/3 is whether the third argument is equal to the first argument minus the second.
lt/2 and diff/3 are defined correctly.
Is there a logical mistake in the definition? Is assuming that 0 is the multiple of every number problematic or is the logical mistake somewhere else? I get correct answers but the query goes to infinite loop I think.
EDIT:
here are the other definitions.
natNum(0).
natNum(s(X)) :- natNum(X).
lt(0,s(X)) :- natNum(X).
lt(s(X),s(Y)) :- lt(X,Y).
sum(0,X,X).
sum(s(X),Y,s(Z)) :- sum(X,Y,Z).
diff(X,Y,Z) :- sum(Z,Y,X).
?- multiple(X, s(s(s(s(s(s(0))))))).
where s(0) is 1, s(s(0)) is 2 etc. It gives all the desired answers for X but after the last answer, it gets stuck. I assume in an infinite recursive loop?
What is happening in your program? Does it loop forever, or does it only take some time since you haven't updated your hardware in recent decades? We cannot tell. (Actually, we could tell by looking at your program, but that is much too complex for the moment).
What we can do with ease is narrow down the source of this costly effort. And this, without a deep understanding of your program. Let's start with the query:
?- multiple(X, s(s(s(s(s(s(0))))))).
X = s(0)
; X = s(s(0))
; X = s(s(s(0)))
; X = s(s(s(s(s(s(0))))))
; loops. % or takes too long
Isn't there an easier way to do this? All this semicolon typing. Instead, simply add false to your query. In this manner the solutions found are no longer shown and we can concentrate on this annoying looping. And, if we're at it, you can also add false goals into your program! By such goals the number of inferences might be reduced (or stays the same). And if the resulting fragment (called a failure-slice) is looping, then this is a reason why your original program loops:
multiple(_X,0) :- false.
multiple(X,Y) :- lt(0,X), false, lt(0,Y), diff(Y,X,D), multiple(X,D).
natNum(0) :- false.
natNum(s(X)) :- natNum(X), false.
lt(0,s(X)) :- natNum(X), false.
lt(s(X),s(Y)) :- false, lt(X,Y).
?- multiple(X, s(s(s(s(s(s(0))))))), false.
loops.
Do your recognize your program? Only those parts remained that are needed for a loop. And, actually in this case, we have an infinite loop.
To fix this, we need to modify something in the remaining, visible part. I'd go for lt/2 whose first clause can be generalized to lt(0, s(_)).
But wait! Why is it OK to generalize away the requirement that we have a natural number? Look at the fact multiple(X,0). which you have written. You have not demanded that X is a natural number either. This kind of over-generalizations often appears in Prolog programs. They improve termination properties at a relatively low price: Sometimes they are too general but all terms that additionally fit into the generalization are not natural numbers. They are terms like any or [a,b,c], so if they appear somewhere you know that they do not belong to the solutions.
So the idea was to put false goals into your program such that the resulting program (failure-slice) still loops. In the worst case you put false at a wrong place and the program terminates. By trial-and-error you get a minimal failure-slice. All those things that are now stroked through are irrelevant! In particular diff/3. So no need to understand it (for the moment). It suffices to look at the remaining program.
I need to define a predicate calculator/2 that takes a list of English arithmetic expressions and yields a numerical result. The system should be able to handle numbers 1-20.
Example executions:
?- calculator([three,times,two],Total).
Total=6
yes
?- calculator([twenty,times,three,plus,five,divided_by,two], Total).
Total = 32.5
This is an extremely hard task for somebody who said "This is my first time experiencing prolog and I don't even know where to start."
I'll give you some things to start, but you really need to work through some Prolog tutorials (I've found 'Learn Prolog Now', mentioned by #mbratch in the comments, very good) to be able to do the task.
First, you can define some Prolog facts about number names (since you only have to handle only numbers 1-20, you can simply enumerate all he possibilities):
number(one, 1).
number(two, 2).
...
number(twenty, 20).
Then you can define some predicates that work for just two numbers:
calculator([A, plus, B], Result) :-
number(A, ValA), number(B, ValB), Result is ValA + ValB.
calculator([A, times, B], Result) :-
number(A, ValA), number(B, ValB), Result is ValA * ValB.
Judging from your example precedence rules of the operators are not used. Then if the list contains more than 2 numbers (more than 3 entries), you can apply above predicates to the first three list entries, and proceed recursively.
Hope you can continue from here after working through some Prolog tutorials.
So I have a couple of facts:
%bridge(Name,From,To).
bridge(a,1,2).
bridge(b,1,2).
bridge(c,2,3).
bridge(d,3,4).
Edit:changed to atoms
So this reads like "bridge A crosses from zone 1 to zone 2". This is simple. However, the inverse is also true. Bridge A crosses from zone 2 to zone 1. That's why I thought:
bridge(B,S,E):- bridge(B,E,S).
Thing is, this messes up my program because whenever swi-prolog can't find a match for a bridge, it will keep using the bridge rule to invert it's parameters over and over again. Is there any way to stop this? Or is there any other way to create a simple rule? My program works flawlessly if I add every other fact (bridge(A,2,1), bridge(C,3,2), etc).
First note that you seem to be using variables where you meant to use atoms to identify bridges.
As to your question: You can easily solve this by adding the additional required facts, for example:
bridge(a, 1, 2).
bridge(a, 2, 1).
bridge(b, 1, 2).
bridge(b, 2, 1).
etc.
However, as you already seem to have noticed intuitively, this is clearly redundant and you can refactor it with an auxiliary predicate, say for example bridge_/2, that consists of two clauses:
bridge(B, X, Y) :- bridge_(B, X, Y).
brigde(B, X, Y) :- bridge_(B, Y, X).
bridge_(a, 1, 2).
bridge_(b, 2, 1).
bridge_(c, 2, 3).
etc.
Prolog offers a way to process each clause read, before asserting it, by means of term_expansion/2. Should work this way:
term_expansion(bridge(K,A,B), bridge(K,A,B)) :- assertz(bridge(K,B,A)).
That is, it 'returns' the unchanged term read, and add a term with swapped 'connections'.
Beware that could be difficult to get debug your transformed source with the graphical tracer...
edit my answer was a bit superficial, I'm trying to debug it...
edit thanks to Paulo hint, here is something working...
:- module(bridge, [bridge/3]).
term_expansion(bridge(K,A,B), [bridge(K,A,B),bridge(K,B,A)]).
bridge(a,1,2).
bridge(b,1,2).
bridge(c,2,3).
bridge(d,3,4).
I'm trying to write a prolog program that determines whether one list is a permutation of another. Input is of the form perm(L,M), which will be true if and only if list L is a permutation of list M.
This is for my AI class, so I cannot just use the nifty little permutation predicate that gprolog already provides. Our professor noted that the member predicate might be useful, but any ideas I have that involve it seem to require very tricky and not-so-declarative things (and I'm assuming there is a way to solve this without getting too advanced, since the class is new to prolog.)
Anyway, one way to check would supposedly be to see that L and M are the same size, each L element is in M, and each M element is in L (there's a use of member!). However, this wouldn't be enough for cases like [2,2,4] and [4,4,2], among others.
Another way could be to ensure that the same counts of each element are in the opposite list, but my impression of prolog is that any kind of variable 'memory' is rather difficult business (in fact, it seems that the example programs I see that perform sorts, etc., aren't really manipulating data at all; they're just 'hypothetically' rearranging things and then telling you yes or no...?)
Mentally, one could just sort both lists and check elements side-by-side, but that, among tons of other ways to think of it, seems a little too object-oriented...
Any hints? My biggest trouble seems to be (as mentioned) the fact that doing "operations" seems to be more like asking about them and hoping that things stay true long enough to get where you want.
**UPDATE: gprolog does offer a delete functionality, but it comes with the declarative-related trouble I was expecting, given an attempt like this:
perm([LH|LT], R) :- member(LH,R), delete([LH|LT],LH,R), perm(LT,R).
In the manual, delete is defined like this: "delete(List1, Element, List2) removes all occurrences of Element in List1 to provide List2. A strict term equality is required, cf. (==)/2"
Execution:
{trace}
| ?- perm([1,2,3],[3,1,2]).
1 1 Call: perm([1,2,3],[3,1,2]) ?
2 2 Call: member(1,[3,1,2]) ?
2 2 Exit: member(1,[3,1,2]) ?
3 2 Call: delete([1,2,3],1,[3,1,2]) ?
3 2 Fail: delete([1,2,3],1,[3,1,2]) ?
2 2 Redo: member(1,[3,1,2]) ?
2 2 Fail: member(1,[3,1,2]) ?
1 1 Fail: perm([1,2,3],[3,1,2]) ?
(1 ms) no
**UPDATE 2: I think I might have figured it out! It's kind of verbose, but I have tested it for quite a few cases and haven't found a bad one yet. If someone sees a major issue, please point it out:
perm([],[]).
perm([LH|LT],R) :- length([LH|LT],A), length(R,B), A == B, member(LH,R), select(LH,[LH|LT],X), select(LH,R,Y), perm_recurse(X, Y), !.
perm_recurse([],X). %If we get here, all elements successfully matched
perm_recurse([LH|LT],R) :- member(LH,R), select(LH,[LH|LT],X), select(LH,R,Y), perm_recurse(X, Y), !.
I do like the cut operator..
Always good to define more general predicate and use it in a narrowed fashion:
perm(X,L):- mselect(X,L,[]).
mselect([A|B],L,R):- select(A,L,M), mselect(B,M,R).
mselect([],L,L).
member is no good as it leaves the second list unchanged. delete is no good either as it deletes the multiplicities.
You could use append though. :) It too combines picking and removing:
perm([A|B],L):- length(L,N), between(0,N,I),length(X,I),
append(X,[A],Y), append(Y,Z,L),
append(X,Z,M), perm(B,M).
perm([],[]).
perm(L, M) :- sort(L, X), sort(M, X).
This gets you pretty close and is fully declarative ("two lists are permutations of each other if they have the same sorted representation", but sorting in Prolog removes duplicates). However, it will succeed for cases like perm([1,2], [2,2,2,1]) which I'm not sure if you want. It will handle [2,2,4] and [4,4,2] though, since they both sort to [2,4]. Another solution would be something like this:
perm([], []).
perm([L|Ls], M) :- select(L, M, Ms), !, perm(Ls, Ms).
This version won't succeed for [2,2,4] and [4,4,2], but it will properly fail for [1,2] and [2,2,2,1]. I'm not sure which one you want, but I think one or the other of these is probably correct.
The usual model to follow is inductive.
If you know how to build all permutation of N-1 elements, then all permutations of N elements are obtained inserting the element in all available positions.
A 'trick of the trade' is using the select/3 builtin, that, like member, 'peek' an element, but removes it from the list and 'returns' the smaller list. Those verbs are not really appropriate for Prolog. Let's say that select/3 is a relation among an element, a list containing it, and an identical list where it's missing.
Then let Prolog do all the search... The resulting code is really tiny...
just sort both lists and compare result
I'm trying to teach myself some Prolog so that I can determine its fitness for solving a problem I have. Essentially the problem is, given a bunch of rules about the interaction between items, determine what items are available, unavailable, selected, and not selected.
But I'm failing at even the most simple parts! I drastically reduced the problem size just to see what I could do. Below is my knowledge base:
selected(A) :- implied(A).
implied(B) :- implies(A,B),selected(A).
implied(option_one).
implies(option_one,option_two).
And when I query:
selected(X).
I only get back option_two.
It seems like there is something very basic that I'm not understanding here, but it seems to me that if option_one should also come back in that list (especially since one of the facts is 'implied(option_one)'.
If it matters, I've tried this using P# as well as SWI-Prolog, which give the same result.
When u have your first answer X = option_two press ; to get next answer
?- selected(X).
X = option_two ;
X = option_one.
Or u may use smth like that for showing all matching things:
?- selected(X), writeln(X), fail.
option_two
option_one
false.