Search code examples
prologunification

Prolog - how to reserve the information when split a variable list?


As a follow up question to my last question (thanks to Patrick),

I have a variable list like this,which is a output from a predicate to_var_list(InputList, X):

X = [_G1426, _G1429, _G1432, 9, _G1438, _G1441].

Now I want split the list by "9", so the result should be like:

 Result = [[_G1426, _G1429, _G1432],[_G1438, _G1441]].

I am using a predicate like this:

split(List, Pivot, Result) :-
    (append(Left, [Pivot|Rest], List)
    -> Result = [Left|Right],
    split(Rest,Pivot,Right);
    Result = [List]).

But this only works for list that is not a variable list, for example:

Y = [1,2,6,9,6,5,9,7,1]

if set the pivot be "9" then the list will be split into

Result = [[1,2,6],[6,5],[7,1]]

But for a variable list as above, apply this predicate will automatically bind every unbounded variable to the pivot, the output lists are ike this:

X = [9,9,9,9,9,9]
Result = [[],[],[],[],[],[],[]]

I know I can split them first then apply to_var_list, but then the relationship that is reserved in the original list X is lost. I need build a constraint model so later I can work on each variable in the list(like set the range of each variable) and finally be able to give out a fix result of list X.

Is there a way to avoid binding the pivot to the variable when doing split?


Solution

  • == will do an equality check without binding:

    ?- X == 9.
    false.
    
    ?- X == Y.
    false.
    
    ?- X == X.
    true.
    
    ?- X = Y, X == Y.
    X = Y.
    

    So you can split as follows:

    split([First|Rest], Pivot, Result) :-
        (First == Pivot ->
            Result = [[], Rest]
        ;
            split(Rest, Pivot, [Left, Right]),
            Result = [[First|Left], Right]
        ).
    

    I only tested this with your test input; since equality check without unification is extra-logical, it may or may not behave correctly in the general case.