0
votes

I am trying to use Prolog to represent state of a room.

I have a set of rules and a set of facts, but sometimes some of the facts are not defined. For instance, temperature in a room can decrease due to either cooling or opening a window, but sometimes I do not have a window sensor.

% Rules

temperature_trend(decrease) :-
    cooling(on).
temperature_trend(decrease) :-
    window(open).

% Facts

cooling(off).

%window(close).  % Unknown, I do not have a window sensor

% Main

main() :-
    temperature_trend(decrease).

If I run this program I would get an undefined procedure error. I can deal with this by explicitly setting the window status to "anything" with window(W). (I programmatically prepare the Prolog source, so this is quite easy).

Now the query temperature_trend(decrease) would succeed because window(W) would lead to window(open). However, in this case I want to know that W = open.

Is there a way to return the variable assignments for this fact? Or maybe am I approaching the problem in the wrong way?

Note that the rule tree could be arbitrarily deep, for instance I could add a new rule next_temperature(lower) :- temperature_trend(decrease). and I still want to know that next_temperature(lower) succeeds only by setting W = open. Terms are also more complex because they also have a time index (T = 232).

Maybe one option would be to return a list of assignments, which would be empty if all facts were known.

1
Declare window/1 as dynamic so that window(X) query will simply fail if the facts don't exist. :- dynamic(window/1).lurker
Ideally I do not want it to fail if the fact does not exist. I want it tell me it would succeed by adding such fact.Claudio
Well, of course it will succeed by adding such a fact, by definition. So I'm not sure what you mean by that. Without declaring it dynamic, if there's no match to the query via fact or predicate, you get an interpreter error that it doesn't exist. If you declare it dynamic, and make the query, and it doesn't exist, the query simply fails as if the facts/predicates were there, but there was not match. Maybe you need a clearer example shown in your question.lurker
If I add window(W). as a fact, the interpreter will "assign" W = open and the query would succeed. I want to know that such "assignment" happened, i.e., that the query would succeed by adding window(open). to my facts.Claudio

1 Answers

0
votes

Write a meta-interpreter that gives you what is true, e.g.,

prove(Goal, True) :-
    phrase(prove(Goal), True).

prove(true) -->
    !.
prove((A,B)) -->
    !,
    prove(A),
    prove(B).
prove((A;B)) -->
    !,
    (   prove(A)
    ;   prove(B)
    ).
prove(Fact) -->
    [Fact],
    { clause(Fact, Body) },
    prove(Body).

Now, given window(_), we get:

?- prove(temperature_trend(decrease), L).
L = [temperature_trend(decrease), window(open)].

Lots of variations are possible!