Inference from generic situation S - prolog

I hope that someone can help me. Is it possible inference from a situation S different to s0 in Prolog?
I have a s0 (initial situation) like this:
isoven(oven).
isoff(oven,s0).
ison(X,do(a,S)):- a=switchOn(X),isoven(X); isOff(X,S),\+ a=swicthOff(X). (fluent inon)
If I prompted:
?- isOn(oven,s0).
false.
?- ison(oven,do(swicth(oven)s0)).
true
It would be nice if existed a command like "save(do(swicth(oven)s0)) to S'" in order to obtained a result like this:
?- ison(oven,S').
true.

Prolog is not magic, you need to implement things properly.
It appears you want to use situation calculus, there's plenty of material online about it.
Also:
a=switchOn(X)
This is meaningless, it always fail. You need a variable there (the first letter must be upper case)

Related

Prolog Cut operator

I defined my knowledge base as:
edge(mammal,isa,animal).
edge(human,isa,mammal).
edge(simba,isa,human).
edge(animal,swim,bybirth).
edge(human,swim,mustlearn).
path(X,Y) :- edge(X,isa,Y).
path(X,Y) :- edge(X,isa,Z), path(Z,Y).
swim(X,Y) :- edge(X,swim,Y).
swim(X,Y) :- path(X,Z), swim(Z,Y).
Now, to use the above knowledge base, I use the following:
?- swim(simba,bybirth).
?- swim(simba,mustlearn).
And for both the queries, Prolog returns true. I want Prolog to check for the property swim locally first, then look at the direct parent, and so on in a hierarchical fashion. And it should stop searching as soon as we know that Simba "mustlearn" to swim, and shouldn't look any further. Thus, it should return false for the first query and true for the second.
I know it has to be done by limiting backtracking. I tried using the cut and not operators, but couldn't succeed. Is there a way to achieve this?
I tried it and ran into a problem too. I thought this might work:
swim(X,Y) :- once((edge(X,swim,Y); path(X,Z), swim(Z,Y))).
It doesn't work, because if Y is already instantiated on the way in, the first step will fail to unify and it will try the second route going through the human intermediate. So even though the query only produces one result, it can be fooled into producing swim(simba, bybirth). The solution is to force Prolog to commit to a binding on another variable and then check that binding after the commitment:
swim(X,Y) :-
once((edge(X,swim,Method); path(X,Z), swim(Z,Method))),
Method = Y.
This tells Prolog, there is only one way to get to this method, so find that method, and then it must be Y. If you find the wrong method, it won't go on a search, it will just fail. Try it!

How do I use this Prolog predicate so as to receive the result? Cannot figure out input

Our textbook gave us this example of a structurer for a math equation in Prolog:
math(Result) --> number(Number1), operator(Operator), number(Number2), { Result = [Number1, Operator, Number2] }.
operator('+') --> ['+'].
number('number') --> ['NUMBER'].
I'm quite new to Prolog, however, and I have no idea how to use this example to get the output. I'm under the impression it restructures the input using Result and outputs it for use.
The only input I've tried that doesn't cause an error is math('number', '+', 'number'). but it always outputs false and I don't know why. Furthermore shouldn't it restructure it and give me the result in Result as well?
What should I be inputting here?
This example is a DCG. You should use the phrase/2 interface predicate to access DCGs.
To find out what the DCG describes, start with the most general query, relating the nonterminal math(R) to a list Ls that is described by the first argument:
?- phrase(math(R), Ls).
From the answer you get (very easy exercise!), you will notice that R is probably not what you meant it to be. Hint: Look up (=..)/2.
Notice in particular that you need not be "inputting" anything here: A DCG describes a list. The list can be specified, but need not be given: A variable will do too! Think in terms of relations between arbitrary terms.

In Prolog (SWI), how to build a knowledge base of user supplied pairs and assert to be equal

I am very new to Prolog and trying to learn.
For my program, I would like to have the user provide pairs of strings which are "types of".
For example, user provides at command line the strings "john" and "man". These atoms would be made to be equal, i.e. john(man).
At next prompt, then user provides "man" and "tall", again program asserts these are valid, man(tall).
Then the user could query the program and ask "Is john tall?". Or in Prolog: john(tall) becomes true by transitive property.
I have been able to parse the strings from the user's input and assign them to variables Subject and Object.
I tried a clause (where Subject and Object are different strings):
attribute(Subject, Object) :-
assert(term_to_atom(_ , Subject),
term_to_atom(_ , Object)).
I want to assert the facts that Subject and Object are valid pair. If the user asserts it, then they belong to together. How do I force this equality of the pairs?
What's the best way to go about this?
Questions of this sort have been asked a lot recently (I guess your professors all share notes or something) so a browse through recent history might have been productive for you. This one comes to mind, for instance.
Your code is pretty wide of the mark. This is what you're trying to do:
attribute(Subject, Object) :-
Fact =.. [Object, Subject],
assertz(Fact).
Using it works like this:
?- attribute(man, tall).
true.
?- tall(X).
X = man.
So, here's what you should notice about this code:
We're using =../2, the "univ" operator, to build structures from lists. This is the only way to create a fact from some atoms.
I've swapped subject and object, because doing it the other way is almost certainly not what you want.
The predicate you want is assertz/1 or asserta/1, not assert/2. The a and z on the end just tells Prolog whether you want the fact at the beginning or end of the database.
Based on looking at your code, I think you have a lot of baggage you need to shed to become productive with Prolog.
Prolog predicates do not return values. So assert(term_to_atom(... wasn't even on the right track, because you seemed to think that term_to_atom would "return" a value and it would get substituted into the assert call like in a functional or imperative language. Prolog just plain works completely differently from that.
I'm not sure why you have an empty variable in your term_to_atom predicates. I think you did that to satisfy the predicate's arity, but this predicate is pretty useless unless you have one ground term and one variable.
There is an assert/2, but it doesn't do what you want. It should be clear why assert normally only takes one argument.
Prolog facts should look like property(subject...). It is not easy to construct facts and then query them, which is what you'd have to do using man(tall). What you want to say is that there is a property, being tall, and man satisfies it.
I would strongly recommend you back up and go through some basic Prolog tutorials at this point. If you try to press forward you're only going to get more lost.
Edit: In response to your comment, I'm not sure how general you want to go. In the basic case where you're dealing with a 4-item list with [is,a] in the middle, this is sufficient:
build_fact([Subject,is,a,Object], is_a(Subject, Object)).
If you want to isolate the first and last and create the fact, you have to use univ again:
build_fact([Subject|Rest], Fact) :-
append(PredicateAtoms, [Object], Rest),
atomic_list_concat(PredicateAtoms, '_', Predicate),
Fact =.. [Predicate, Subject, Object].
Not sure if you want to live with the articles ("a", "the") that will wind up on the end though:
?- build_fact([john,could,be,a,man], Fact).
Fact = could_be_a(john, man)
Don't do variable fact heads. Prolog works best when the set of term names is fixed. Instead, make a generic place for storing properties using predefined, static term name, e.g.:
is_a(john, man).
property(man, tall).
property(john, thin).
(think SQL tables in a normal form). Then you can use simple assertz/1 to update the database:
add_property(X, Y) :- assertz(property(X, Y)).

Prolog Relational Tracking without Lists

I am trying to get a predicate to relate from 1 fact to another fact and to keep going until a specified stopping point.
For example,
let's say I am doing a logistics record where I want to know who got a package from who, and where did they get it from until the end.
Prolog Code
mailRoom(m).
gotFrom(annie,brock).
gotFrom(brock,cara).
gotFrom(cara,daniel).
gotFrom(daniel,m).
gotFrom(X,Y) :- gotFrom(Y,_).
So what I am trying to do with the predicate gotFrom is for it to recursively go down the list from what ever point you start (ex: gotFrom(brock,Who)) and get to the end which is specified by m, which is the mail room.
Unfortunately when I run this predicate, it reads out,
Who = annie.
Who = brock.
Who = cara.
etc.etc....
I tried stepping through the whole thing but Im not sure where it goes from brock to annie, to cara and all the way down till it cycles through trues for infinity. I have a feeling that it has something to do with the wildcard in the function (_), but Im not sure how else I could express that part of the function in order for the predicate to search for the next fact in the program instead of skipping to the end.
I tried using a backcut (!) in my program but it gives me the same error.
Any help is greatly appreciated. I don't want code I just want to know what I am doing wrong so I can learn how to do it right.
Thanks.
I'm afraid this rule is meaningless:
gotFrom(X,Y) :- gotFrom(Y,_).
There is nothing here to constrain X or Y to any particular values. Also, the presence of singleton variable X and the anonymous variable _ means that basically anything will work. Try it:
?- gotFrom([1,2,3], dogbert).
true ;
true ;
What I think you're trying to establish here is some kind of transitive property. In that case, what you want is probably more like this:
gotFrom(X,Z) :- gotFrom(X, Y), gotFrom(Y, Z).
This produces an interesting result:
?- gotFrom(brock, Who).
Who = cara ;
Who = daniel ;
Who = m ;
ERROR: Out of local stack
The reason for the problem may not be immediately obvious. It's that there is unchecked recursion happening twice in that rule. We recursively unify gotFrom/2 and then we recursively unify it again. It would be better to break this into two predicates so that one of them can be used non-recursively.
got_directly_from(annie,brock).
got_directly_from(brock,cara).
got_directly_from(cara,daniel).
got_directly_from(daniel,m).
gotFrom(X,Y) :- got_directly_from(X, Y).
gotFrom(X,Z) :- got_directly_from(X, Y), gotFrom(Y, Z).
This gives us the desired behavior:
?- gotFrom(brock, Who).
Who = cara ;
Who = daniel ;
Who = m ;
false.
Notice this one is resilient to my attack of meaningless data:
?- gotFrom([1,2,3], dogbert).
false.
Some general advice:
Never ignore singleton variable warnings. They are almost always a bug.
Never introduce a cut when you don't understand what's going on. The cut should be used only where you understand the behavior first and you understand how the cut will affect it. Ideally, you should try to restrict yourself to green cuts—cuts that only affect performance and have no observable effects. If you don't understand what Prolog is up to, adding a red cut is just going to make your problems more complex.

Can I use variables with assert/1?

What I have now checks that X(Y) is not an accepted fact in my small DB. Since X(Y) returns false it will attempt to assert it. (I realize this presents problems when X is a rule and not a fact)
ifNotAdd(X,Y):-
not(call(X,Y)),
!,
assert(X(Y)).
For example, let's say that this fact is in the DB
mammal(dolphin).
I ask
ifNotAdd(mammal, elephant).
I want it to see that ? mammal(elephant). is false and then assert mammal(elephant).
Obviously the "assert(X(Y))." line is wrong but what do I replace it with? I'm trawling prolog documentation and forums for the answer but no luck so far. I'm also trying to write something that will do this on my own.
EDIT
I need to edit the DB in order to have a dynamic database the user can interact with. I'm building an argument machine and I need to allow the user to tell the system that they "know the fact for sure" so that the system can deal with knowledge outside of it's domain.
In the vein of http://en.wikipedia.org/wiki/Reason_maintenance
Cheers,
You can use the univ operator =../2 to construct the term before asserting it (note that the predicate in question has to be declared dynamic for it to work) :
ifNotAdd(X,Y):-
not(call(X,Y)),
!,
Term =.. [X, Y],
assert(Term).
BTW if you want ifNotAdd/2 not to fail when it doesn't need to add the fact to the db, you should wrap that in a if structure, plus, not/1 is deprecated, (\+)/1 is preferred :
:- dynamic(mammal/1).
mammal(dolphin).
ifNotAdd(X, Y):-
( \+ call(X, Y)
-> Term =.. [X, Y],
assert(Term)
; true).
But I'm not sure what you're trying to do is right there. Quite often when a beginner in prolog wants to manipulate the database it's because a particular prolog mechanism isn't properly understood. Then again you might not be a beginner and my remark could be dumb, in which case, just forget it ! But if you do are a beginner, you may want to precise what you're trying to achieve here so that we can confirm that those manipulations are needed !

Resources