I have a complex program, a part of which looks somewhat like this:
check_list([]).
check_list([X|List]) :- (try_something(X) -> write(1);write(0)),nl,check_list(List).
The problem is that, when my list gets very large, Prolog gives me "Resource error: insufficient memory". I thought the problem might be somewhere in the if-then-clause. So I tried the following:
check_list([]).
check_list([X|List]) :- (\+try_something(X) -> write(0);write(1)),nl,check_list(List).
With that, the problem is gone (or at least it only appears with much much bigger lists). However, I have no clue why. What is so different in the two versions? Shouldn't both be the same?
Related
I've got a problem with Prolog lists.
Let's say I've got this predicate:
array(p, [A,B,C]).
When I do:
array(p,X).
I got: X = [_,_,_]
Now, considering I've got this predicate:
p1(1) :- array(p1, [1,B1,C1]).
I expected to get:
X = [1,_,_]
but instead, the result is the same as before. Is such a thing even possible in Prolog? Another question is if somehow we can set these values, could we overwrite these values in the same way? I understand that in the prolog variables are assigned only once but I would like to somehow get a dynamic list.
I'm not sure what you mean by "paradigm," and I'm very unclear on what you're trying to do with this code. If you have this at the toplevel:
array(p, [A,B,C]).
you are defining a fact array/2, which associates p with a list of three uninstantiated variables. Your first query amounts to retrieving this fact.
Your second "paradigm" is really the definition of a rule or predicate p1/1, which takes a single argument, which must be 1 for the rule to fire. The body of this second predicate is a call to the predicate array/2 which is definitely going to fail. I don't see how you could possibly get the same result as before, because you defined array(p, ...) before and now you are looking for array(p1, ...). Furthermore, there is no X in your second query, so there is no reason for X to appear in the result, and it definitely would not, even if you had called array(p, ...) instead of array(p1, ...).
I think what you're trying to do here is probably set up some kind of set of three variables and then unify each of them in turn as you proceed along some calculation. To do something like that is possible and easy in Prolog, but the fact database is not going to participate in this process really. You're going to have to write predicates that pass your variables along to other predicates that will unify them and return them bound. None of this is very hard, but it looks like you're going to have to go back and understand the fundamentals here a little better. You're far enough off track here that I don't think anyone can really answer your question as stated, because there's too much confusion in it.
I recently needed to make a data structure which was a nested list of and/or questions. Since most every interesting thing has been discovered by someone else previously, I’m looking for the name of this data structure. it looks something like this.
‘((a b c) (b d e) (c (a b) (f a)))
The interpretation is I want to find abc or bde or caf or caa or cbf or cba and the list encapsulates that. At the top level each item is or’ed together and sub-lists of the top level are and’ed together and sub-lists of sub-lists are or’ed again sub-lists of those are and’ed and sub-lists of those or’ed ad infinitum. Note that in my example, all the lists are the same length, in my real application the lists vary in length.
The code to walk such a “tree” is relatively simple, but I’m assuming that there is a name for that type of tree and there is stuff I can read about it.
These lists are equivalent to fixed length regular expressions (which I've seen referred to as "network expressions", but I am particularly interested in this data structure and representation thereof.
In general (in the very high level of abstraction) it is:
Context free grammar -Wiki
If you allow it to be infinitely nested, then it is not a regular expression because of presence of parentheses (left and right should match).
If you consider, that expressions inside parentheses are ordered. I mean that a and b and c is equivalent to (a and b) and c. You get then Binary expression tree -Wiki
But for your particular case, it is probably: Disjunctive normal form -Wiki
I am not sure, but my intuition says that it is regular expression again because you have only 2 levels of nesting (1st - for 'or-ed' and 2nd - for 'and-ed' parts)
The trees are also a subset of DAWGS - directed acyclic word graphs and one could construct them the same way.
In my case, I have a very small set that I have built by hand and I don't worry about getting the minimal set, but instead just want something that I can easily write down but deals with the types of simple variations I see. Basically, I have different ways of finding where I keep my .el files based upon the different directory structures of various OSes I use. (E.g. when I was working at Google, the /usr/local/emacs/site-lisp directory was actually more like /usr/local/Google/emacs/site-lisp.)
I don't need a full regex, but there are about a dozen variations, some having quite long lists of nested sub-directories (c:\users\cfclark\appData\roaming\emacs.emacs.d or some other awful thing) that I wanted to write down (and then have emacs make an automated search to find the one that is appropriate to this particular installation). And every time I go to a new job, I can simply add to the list a description of where they are in that setup.
Anyway, as that code has evolved, I found that I had I was doing (nested or's and and's and realized that the structure generalized to the alternating or/and/or/and/... case). So, my assumption is that someone must have discovered this before. I had hints of it myself several years ago, but didn't set down to implement it. The Disjunctive Normal Form link mpasko256 gave is also particularly relevant. I don't normalize to that level, I still keep nested and's and or's rather than flattening to 2, but I do have a distinct structure, or's at the top, then and's, then or's....
I have a dynamic list:
:- dynamic queue/1.
queue([Bob,Steve,Richard,Katie]).
and a predicate:
delete_person(Person) :-
queue(Q),
retractall(queue(_)),
delete(Q, Person, Z),
assert(queue(Z)).
Logically, this follows to me, but I've obviously made a mistake as the list stays the same after running the predicate delete_person
There are multiple problems in this snippet. First of all, you have posted the following program:
:- dynamic queue/1.
queue([Bob,Steve,Richard,Katie]).
delete_person(Person) :-
queue(Q),
delete(Q, Person, Z).
assert(queue(Z)).
This means that you have a fact of the form assert/1 in your code. That's probably not what you intended to write.
Second, if you correct delete_person/1 to read:
delete_person(Person) :-
queue(Q),
delete(Q, Person, Z),
assert(queue(Z)).
then we still have the following singleton warning:
Singleton variables: [Bob,Steve,Richard,Katie]
This is because Bob, Steve etc. are all (probably inadvertently) Prolog variables.
If you correct this to read:
queue([bob,steve,richard,katie]).
Then at least the program compiles without warnings.
Now we can talk about the actual issue:
?- delete_person(bob).
true.
?- queue(Q).
Q = [bob, steve, richard, katie] ;
Q = [steve, richard, katie].
Next time, please include:
the query you tried
the expected result
the obtained result.
In the case above, why is the queue not modified?
That's because you inadvertently only add an additional fact for queue/1, but you do not remove the already existing fact.
That's a typical mistake when modifying the global database. You are already getting a glimpse of the issues that await you if you use Prolog like an imperative language. It will make your code extremely hard to reason about, yield several hard to debug problems, makes it hard to test your code, and generally combines the disadvantages of imperative languages with their severe lack of generality.
A declarative solution of your program is to think in terms of relations between queues. Think of it this way: What is the relation between 2 queues if a specific element is removed from the first queue, and the second queue is the same as the first queue except for that element?
For example, think about: queue_without_element/3, whose definition could start like this:
queue_without_element(Q0, E, Q) :-
...
Advantages:
Usable in several directions.
Can be tested in isolation of other predicates.
Is automatically thread safe.
Is almost certainly more efficient than modifying the global database.
etc.
I'm new to Prolog and what I want to achieve is to perform an operation like append/3 over two lists that are saved in my program. I don't need to open swi-prolog and type append([a,b,c],[h,j,k],X). in order to obtain X=[a,b,c,h,j,k]. What I need is something like retrieve two lists from the program and perform the append over them.
I don't even know if what I want to obtain is possible in Prolog.
This is my situation: I got this "esempio.pl" file where I have the following rule and these two facts:
personal_union(F,C,Xs) :-
personal_list(F,Fs),personal_list(C,Cs),append(Fs,Cs,Xs).
personal_list(family,[alessandro,cinzia,fabio]).
personal_list(colors,[blu,giallo,lilla,verde,rosso]).
I'd like to question "esempio.pl" from SWI-prolog and ask it:
personal_union(family,colors,X).
And obtain the unified lists:
X=[alessandro,cinzia,fabio,blu,giallo,lilla,verde,rosso]`
Is my code a possible solution? I couldn't try it myself because it keeps giving me this error: Syntax error: illegal start of term stating that the error is at the start of the body of my rule.
Your code is valid as I tested it on Swish, and it produces the requested result.
The error you get is usually derived of mistaken syntax such as additional commas or brackets issues. Check the rest of you code. Also, you might find http://swish.swi-prolog.org/ comfortable for such debugging.
I would like to check for an arbitrary fact and do something if it is in the knowledge base and something else if it not, but without the ( I -> T ; E)syntax.
I have some facts in my knowledge base:
unexplored(1,1).
unexplored(2,1).
safe(1,1).
given an incomplete rule
foo:- safe(A,B),
% do something if unexplored(A,B) is in the knowledge base
% do something else if unexplored(A,B) is not in the knowledge base
What is the correct way to handle this, without doing it like this?
foo:-
safe(A,B),
( unexplored(A,B) -> something ; something_else ).
Not an answer but too long for a comment.
"Flow control" is by definition not declarative. Changing the predicate database (the defined rules and facts) at run time is also not declarative: it introduces state to your program.
You should really consider very carefully if your "data" belongs to the database, or if you can keep it a data structure. But your question doesn't provide enough detail to be able to suggest anything.
You can however see this example of finding paths through a maze. In this solution, the database contains information about the problem that does not change. The search itself uses the simplest data structure, a list. The "flow control" if you want to call it this is implicit: it is just a side effect of Prolog looking for a proof. More importantly, you can argue about the program and what it does without taking into consideration the exact control flow (but you do take into consideration Prolog's resolution strategy).
The fundamental problem with this requirement is that it is non-monotonic:
Things that hold without this fact may suddenly fail to hold after adding such a fact.
This inherently runs counter to the important and desirable declarative property of monotonicity.
Declaratively, from adding facts, we expect to obtain at most an increase, never a decrease of the things that hold.
For this reason, your requirement is inherently linked to non-monotonic constructs like if-then-else, !/0 and setof/3.
A declarative way to reason about this is to entirely avoid checking properties of the knowledge base. Instead, focus on a clear description of the things that hold, using Prolog clauses to encode the knowledge.
In your case, it looks like you need to reason about states of some search problem. A declarative way to solve such tasks is to represent the state as a Prolog term, and write pure monotonic rules involving the state.
For example, let us say that a state S0 is related to state S if we explore a certain position Pos that was previously not explored:
state0_state(S0, S) :-
select(Pos-unexplored, S0, S1),
S = [Pos-explored|S1].
or shorter:
state0_state(S0, [Pos-explored|S1) :-
select(Pos-unexplored, S0, S1).
I leave figuring out the state representation I am using here as an easy exercise. Notice the convenient naming convention of using S0, S1, ..., S to chain the different states.
This way, you encode explicit relations about Prolog terms that represent the state. Pure, monotonic, and works in all directions.