user25976
user25976

Reputation: 1025

SWI-Prolog - retrieving information from dynamic database

I'm experimenting with SWI-Prolog and have not figured out how to retrieve information saved in a dynamic database using assertz. In my code below, I'm creating a simple question and answer expert system that narrows down the source of a non functioning lamp.

In the driver (go), I attempt to remember user input response to whether or not the power is working. If the power is not working, it should take certain actions. I am not correctly retrieving and defining the variable 'Response'.

The dynamic variable powerstatus is intended to keep the user's response (even if it is no). The dynamic variable remember is intended to keep the user's response only if it is yes. Something is going wrong with the latter, as answering 'no' to "Power is not working" does not update the database. listing(powerstatus) is only populated if user answers yes.

status(power) :-
  is_true('Power is not working').

issue(fuse) :-
  is_true('Fuse is not working').
issue(circuit) :-
  is_true('Fuse is working'),
  is_true('Circuit breaker is tripped').
issue(failure) :-
  is_true('Fuse is working'),
  is_true('Circuit breaker is not tripped'),
  is_true('Power network failure').

mat_issue(bulb) :-
  is_true('Bulb is not working').
mat_issue(powerswitch) :-
  is_true('Bulb is working'),
  is_true('Power switch is not working').
mat_issue(powerswitch) :-
  is_true('Bulb is working'),
  is_true('Power switch is working'),
  is_true('Plug is not working').
mat_issue(cord) :-
  is_true('Bulb is working'),
  is_true('Power switch is working'),
  is_true('Plug is working'),
  is_true('Cord is not working').
mat_issue(cord) :-
  is_true('Bulb is working'),
  is_true('Power switch is working'),
  is_true('Plug is working'),
  is_true('Cord is working'),
  is_true('Outlet is not working. Replace outlet.').

is_true(X) :- remember(X,"yes"),!.
is_true(X) :- ask(X).

:-dynamic remember/2.
:-dynamic powerstatus/2.

ask(Question) :-
  write(Question), write('? '),
  read_string(user_input,"\n","\r",_,Response), Response == "yes",
  assertz(remember(Question, Response)),
  assertz(powerstatus(Question, Response)).

go:-
  retractall(remember(_,_)),
  retractall(powerstatus(_,_)),
  status(Power),
  powerstatus('Power is not working', Response),
  format('Response is ~w', Response).
  (Response = "no" ->
    mat_issue(Object)
    ;issue(Object)),
    write('I guess that the problematic object is: '),
    write(Object), nl. 
go:-
  write('I cannot recognize your issue').

UPDATE I'm trying something new--setting up a new rule for the ask(Question) function if user answers no. Problem is that the rules (issue(object) and mat_issue(object) are getting cut short and are not iterating through all the rules.

status(power) :-
  is_true('Power is not working').

issue(fuse) :-
  is_true('Fuse is not working').
issue(circuit) :-
  is_true('Fuse is working'),
  is_true('Circuit breaker is tripped').
issue(failure) :-
  is_true('Fuse is working'),
  is_true('Circuit breaker is not tripped'),
  is_true('Power network failure').

mat_issue(bulb) :-
  is_true('Bulb is not working').
mat_issue(powerswitch) :-
  is_true('Bulb is working'),
  is_true('Power switch is not working').
mat_issue(powerswitch) :-
  is_true('Bulb is working'),
  is_true('Power switch is working'),
  is_true('Plug is not working').
mat_issue(cord) :-
  is_true('Bulb is working'),
  is_true('Power switch is working'),
  is_true('Plug is working'),
  is_true('Cord is not working').
mat_issue(cord) :-
  is_true('Bulb is working'),
  is_true('Power switch is working'),
  is_true('Plug is working'),
  is_true('Cord is working'),
  is_true('Outlet is not working. Replace outlet.').

is_true(X) :- remember(X,"yes"),!.
is_true(X) :- ask(X).

:-dynamic remember/2.

ask(Question) :-
  write(Question), write('? '),
  read_string(user_input,"\n","\r",_,Response), Response == "yes",!,
  assertz(remember(Question, Response)).
ask(Question) :-
  assertz(remember(Question, "no")).

go:-
  retractall(remember(_,_)),
  status(Power),
  remember('Power is not working', Response),
  (Response = "no" ->
    mat_issue(Object);
    issue(Object)),
  write('I guess that the problem is: '),
  write(Object), nl.
go:-
  write('I cannot recognize your issue').

Upvotes: 1

Views: 213

Answers (1)

CapelliC
CapelliC

Reputation: 60004

Just for fun, I've done several changes in your code, regarding positive vs negative knowledge, since I feel that asking about the same problem in both positive and negative form is something should be avoided. See if they fit your needs.

issue(fuse) :-
  is_false('Fuse is working').
issue(circuit) :-
  is_true('Fuse is working'),
  is_true('Circuit breaker is tripped').
issue(failure) :-
  is_true('Fuse is working'),
  is_false('Circuit breaker is tripped'),
  is_true('Power network failure').

mat_issue(bulb) :-
  is_false('Bulb is working').
mat_issue(powerswitch) :-
  is_true('Bulb is working'),
  is_false('Power switch is working').
mat_issue(powerswitch) :-
  is_true('Bulb is working'),
  is_true('Power switch is working'),
  is_false('Plug is working').
mat_issue(cord) :-
  is_true('Bulb is working'),
  is_true('Power switch is working'),
  is_true('Plug is working'),
  is_false('Cord is working').
mat_issue(cord) :-
  is_true('Bulb is working'),
  is_true('Power switch is working'),
  is_true('Plug is working'),
  is_true('Cord is working'),
  is_false('Outlet is working').

is_true(X) :- remember(X,A),!,yes(A).
is_true(X) :- ask(X,A),yes(A).
is_false(X) :- \+is_true(X).

yes("yes").
yes("y").

:-dynamic remember/2.

ask(Question,Response) :-
  write(Question), write('? '),
  read_string(user_input,"\n","\r",_,Response),
  assertz(remember(Question,Response)).

go:-
  retractall(remember(_,_)),
  ( is_false('Power is working')
  ->    mat_issue(Object)
  ;     issue(Object)
  ),
  write('I guess that the problem is: '),
  write(Object), nl.
go:-
  write('I cannot recognize your issue').

example session

?- go.
Power is working? y
Fuse is working? y
Circuit breaker is tripped? n
Power network failure? y
I guess that the problem is: failure

Upvotes: 1

Related Questions