1
votes

I'm working on SWI-Prolog.

Given the following key-value-pairs list:

List = [pair(key1,1), pair(key2,1), pair(key3,_G1), pair(key4,-_G1), pair(key5,- -_G1)]

Note: in this case the only free variable is G1, but there may be more than 1 free variables.

The value of the pair (Key,Value) may be set to 1.

Otherwise it belongs to the group {Var, -Var, - -Var, - - -Var, ... , - - - ... -Var}

I want to unify Var with the value 1.

Is there any elegant way to do it without parsing the Value?

I tried the numbervars predicate but it will only write letters to the variables.

I also got a working predicate that solves it, but I'm looking for a more elegant way.

fixFreeVars([]).
fixFreeVars([kvp(_,X)|KVPs]) :-
   fixFreeVar(X),!,
   fixFreeVars(KVPs).

fixFreeVar(X) :- var(X), X = 1.
fixFreeVar(-X) :- fixFreeVar(X).
fixFreeVar(X) :- nonvar(X).

Any suggestions?

1
Why do you permit minus (-) as operator but no other operators? This looks odd to me.false

1 Answers

3
votes

Several ways to do it. One compact solution would be:

fix_free_variables(Term) :-
    term_variables(Term, Variables),
    findall(1, member(1, Variables), Variables).

Example calls:

?- fix_free_variables([pair(key1,1), pair(key2,1), pair(key3,_G1), pair(key4,-_G1), pair(key5,- -_G1)]).
_G1 = 1.

?- fix_free_variables([pair(key1,1), pair(key2,1), pair(key3,_G1), pair(key4,-_G2), pair(key5,- -_G3)]).
_G1 = _G2, _G2 = _G3, _G3 = 1.

Both term_variables/2 and findall/3 are standard built-in predicates. member/2 is usually available either as a built-in predicate or as a library predicate.