camel
camel

Reputation: 135

prolog reasoning about constraints

I'm trying to use Prolog to reason about constraints and then query the knowledgebase to pass these constraints on to a solver (can't use clpfd).

%a first example would be constrainsquare(Row,Col,Val)
constrainsquare(1,1,3).
constrainsquare(1,2,2).

and I can then query all constraints using something like bagof/3. This is not statisfactory because I also want to be able to write

 constrainsquare(3,4,8):-constrainsquare(3,3,7).

The ability to say that if the solution has a 7 at position 3,3; it necessarily has an 8 at position 3,4. Now you can no longer gather all constraints using something like bagof/3.

How would you do this ideomatically in prolog?

Note that I cannot simply do

constrainsquare(L) :-
  member(cs(1,1,3),L),
  member(cs(1,2,2),L),
  member(cs(3,4,8),L),
  member(cs(3,3,7),L).

because I'm receiving new facts about the solution periodically and cannot alter existing facts.

At the moment I'm thinking about using a list of constraints and doing something like

info(cell(1,1,3)).
info(cell(1,2,2)).
constrainsquare(I,[I]).
partialinfo(cell(3,4,8),cell(3,3,7)).
....

and then query it by running bagoff to obtain [cell(1,1,3)],[cell(1,2,2)]... and then folding/appending to [cell(1,1,3),cell(1,2,2)] but this feels a bit 'meh'. I want to know the "proper" way.

Upvotes: 0

Views: 127

Answers (1)

lurker
lurker

Reputation: 58324

Let's suppose you had query, we'll call it Q, that you wished to run on a set of hypothetical facts. We'll call the set of facts, Facts. You could write a predicate which would run the query on those facts dynamically as follows:

what_if_query(Q, Facts) :-
    maplist(assertz, Facts),
    call(Q),
    maplist(retract, Facts).

If Q takes one argument for results, R, then we could write:

what_if_query(Q, Facts, R) :-
    maplist(assertz, Facts),
    call(Q, R),
    maplist(retract, Facts).

Then, if you had a list of scenarios of facts, you could write:

what_if_scenarios(Scenarios, Q, Results) :-
    maplist(what_if_query(Q), Scenarios, Results).

A "fact" can be any assertable Prolog term, and so could also be a rule: (Head :- P1, P2, ..., Pn). For example, your list of "facts" could be:

[cs(1,1,3), cs(1,2,2), (cs(3,4,8) :- cs(3,3,7))]

Upvotes: 1

Related Questions