Reputation: 17
I am having the following issue in a Prolog program. The mathematical formulation of the problem is as follows:
Let Entanglements = the set of structures of the form entanglement(Symbol, Index, PosX, PosY), where Symbol is a character, Index an integer, and PosX and PosY variables (bound or unbound). For all entanglement(Symbol, Index, PosX, PosY) in Entanglements, with one of the two variables PosX or PosY bound and the other unbound, bind the unbound variable to Symbol.
After that, let RemEntanglements = all entanglement(Symbol, Index, PosX, PosY) in Entanglements with at least one of PosX and PosY bound.
Question: Given the set Entanglements, what are the Remaining Entanglements (RemEntanglements)?
My code does not function as intended. Could you give a hint as to what I ought to change?
function(Entanglements, RemEntanglements) :-
findall(entanglement(Symbol, Index, PosX, PosY),
(member(entanglement(Symbol, Index, PosX, PosY), Entanglements),
(var(PosX), nonvar(PosY), PosX = Symbol;
var(PosY), nonvar(PosX), PosY = Symbol)),
Changed),
findall(entanglement(Symbol1, Index1, PosX1, PosY1),
(member(entanglement(Symbol1, Index1, PosX1, PosY1),Entanglements),
(var(PosX1);
var(PosY1))),
RemEntanglements).
Test query:
test(RemEntanglements) :-
function([entanglement('0',2,'X',P3),
entanglement('X',3,P3,P1), entanglement('0',4,P6,P7)],
RemEntanglements).
This query should work as follows: 1) Bind P3 to '0', given that entanglement('0',2,'X',P3) has one bound variable and an unbound one
2) RemEntanglements = [entanglement('X',3,'0',P1), entanglement('0',4,P6,P7)]
, given that P3 was already bound to the '0' symbol, but the others are still unbound.
The answer I got:
[entanglement('0', 2, 'X', _G11664), entanglement('X', 3, _G11655, _G11656), entanglement('X', 3, _G11647, _G11648), entanglement('0', 4, _G11639, _G11640), entanglement('0', 4, _G11631, _G11632)]
Thank you in advance!
Upvotes: 1
Views: 4126
Reputation: 60004
I think you're using the wrong predicate: findall(Template,Goal,List) it's a list generator, and works - abstractly - instancing Template in Goal, then copies Template in List. Then any binding in Goal will be undone among executions.
Then I would write in this way
function(Entanglements, RemEntanglements) :-
maplist(instance, Entanglements),
include(one_bound, Entanglements, RemEntanglements).
instance(entanglement(Symbol, _Index, PosX, PosY)) :-
( ( var(PosX), nonvar(PosY) )
-> PosX = Symbol
; ( var(PosY), nonvar(PosX) )
-> PosY = Symbol
; true
).
one_bound(entanglement(_Symbol, _Index, PosX, PosY)) :-
nonvar(PosX) ; nonvar(PosY).
test(RemEntanglements) :-
function([ entanglement('0',2,'X',P3),
entanglement('X',3, P3,_),
entanglement('0',4, _,_)],
RemEntanglements).
that yields
?- test(L).
L = [entanglement('0', 2, 'X', '0'), entanglement('X', 3, '0', 'X')].
Upvotes: 1
Reputation:
The way it is written now, you should at least get rid of singleton variables. They almost always point to an error in the logic of your predicate. For one, you are binding variables in the first findall
(to Changed
) and then using the original list in the second findall
, which is clearly not your intention.
The singleton variables in your test however should be unbound, you can start their names with an underscore to silence the warning.
Upvotes: 1