prologclpb

Building a logical expression from structure data for clpb


I have data in the following form:

:-use_module(library(clpb)).
%inputs are ids that will have an associated boolean value. 
input(i1).
input(i2).
input(i3).
input(i4).
input(i5).
input(i6).
input(i7).
input(i8).
input(i9).
input(i10).
input(i11).
input(i12).
input(i13).
input(i14).
input(i15).
input(i16).
input(i17).
input(i18).
input(i19).
input(i20).
input(i21).
input(i22).
input(i23).

%and_gate(Id,ListOfInputs) the list of inputs can include other AND and/or  OR gates

and_gate(and1,[i1,i2,i3]).
and_gate(and2,[i4,i5,i6]).
and_gate(and3,[and1,and2,or1,or2,i7,i8]).
and_gate(and4,[or3,i9]).
and_gate(and5,[i15,i16,i17]).

%or_gate(Id,ListOfInputs) the list of inputs can include inputs as well as AND and/or OR gates
or_gate(or1,[i10,i11]).
or_gate(or2,[i12,i13]).
or_gate(or3,[or2,i14]).
or_gate(or4,[and5,i18,i19,i20]).

%device(ID,ListOfInputs) the list of inputs can include inputs as well as AND and/or OR gates
device(d1, [and3,and4,or3,or4]).
device(d2,[i21,i22,i23]).

Diagram: https://docs.google.com/drawings/d/10wBpmFxxbDqrlpPVqpkVo_r8I-qcalWAz7Lro9myjMs/edit?usp=sharing

Inputs into a device are also like an AND gate but they are always the 'top' level of the circuit tree. I want to implement a predicate that would result in something like:

?- device_structure(D,OnOFF,Sat,Inputs).
D=d1,
Sat = sat(OnOff =:= *([*([*([V1,V2,V3]),
                          *([V4,V5,V6]),V7,V8,+[V10,V11],+[V12,V13]
                         ]),
                       *([V9,+[V14,+[V12,V13]]]),
                       +[V14,+[V12,V13]],
                       +[*([V15,V16,V17]),V18,V19,V20]])),

Inputs =     [
      input(i1,V1),
      input(i2,V2),
      input(i3,V3),
      input(i4,V4),
      input(i5,V5),
      input(i6,V6),
      input(i7,V7),
      input(i8,V8),
      input(i9,V9),
      input(i10,V10),
      input(i11,V11),
      input(i12,V12),
      input(i13,V13),
      input(i14,V14),
      input(i15,V15),
      input(i16,V16),
      input(i17,V17),
      input(i18,V18),
      input(i19,V19),
      input(i20,V20)
     ]).

And then of course the much simpler structure for d2.

This would allow me to use the clpb library to both give an instantiation of inputs to know which devices are on or off or to find the inputs that need to be on for a device to be on.

However despite numerous attempts I have not been able to build these structures correctly.

The V variables don't need to be named like this but it is important that the variable in the sat statement matches the right input variable.


Solution

  • this seems to work, HTH

    device_structure(D, OnOFF, Sat, Inputs) :-
        device(D, D_in),
        build(D_in, Structure, Inputs),
        Sat = sat(OnOFF =:= *(Structure)).
    
    build([], [], []).
    build([C|Cs], [V|R], Inputs) :-
        input(C),
        build(Cs, R, InputsR),
        inputs([C-V], InputsR, Inputs).
    build([C|Cs], [+(OrStruct)|R], Inputs) :-
        or_gate(C, OrInputs),
        build(OrInputs, OrStruct, Inputs1),
        build(Cs, R, Inputs2),
        inputs(Inputs1, Inputs2, Inputs).
    build([C|Cs], [*(AndStruct)|R], Inputs) :-
        and_gate(C, AndInputs),
        build(AndInputs, AndStruct, Inputs1),
        build(Cs, R, Inputs2),
        inputs(Inputs1, Inputs2, Inputs).
    
    inputs(I1, I2, Inputs) :-
        append(I1, I2, I3),
        sort(I3, Inputs).
    

    Inputs are like [i1-_Var1,...], to get variables you can use pairs_keys_values(InputPairs, _, Inputs).