新手用Prolog实现命题逻辑求解器,异或功能遇问题
Hey there! Let's work through that XOR issue you're facing with your propositional logic solver. Your current implementation has a subtle problem tied to how Prolog handles unification and negation as failure—let's break it down and fix it.
The Problem with Your Current XOR Implementation
Your existing code:
xor(X,Y) :- not(X=Y).
Works sometimes for concrete boolean values (like xor(true,false) returns true), but falls apart when dealing with unbound variables. Here's why:
- When
XandYare unbound,X=Ysucceeds (Prolog unifies the two variables into one), sonot(X=Y)fails. That means a query likexor(X,Y)won't return any valid boolean pairs, which isn't what we expect from a propositional logic solver. - Relying on
not/1(negation as failure) for boolean logic can also lead to unexpected behavior in complex queries, since it's not equivalent to pure logical negation—it only checks if a goal can't be proven.
Two Solid Fixes for XOR
Option 1: Explicit Fact-Based Definition
The most straightforward way to define XOR is to explicitly state the two valid boolean pairs where it holds true:
xor(true, false). xor(false, true).
This is efficient, easy to read, and behaves exactly as expected:
- Concrete queries like
xor(true, true)will correctly fail (returnfalse), whilexor(true,false)succeeds. - Queries with unbound variables like
xor(X,Y)will return both valid pairs:X=true, Y=falseandX=false, Y=true.
Option 2: Reuse Your Existing Logic Predicates
If you prefer to build XOR using the boolean operations you already have (and/2, or/2, not/1), you can use the standard logical definition of XOR: either X or Y is true, but not both. Translated to Prolog:
xor(X, Y) :- and(or(X, Y), not(and(X, Y))).
This leverages your existing code, so it integrates seamlessly with the rest of your solver. It will behave identically to the fact-based version for both concrete values and unbound variables.
Test It Out
Try these queries to verify the fix works:
?- xor(true, true). % Should return false (no solution) ?- xor(true, false). % Should return true ?- xor(X, Y). % Should return X=true,Y=false; X=false,Y=true
Quick side note: Your implies2/3 predicate looks cut off—if you're trying to define P → (¬Q ∨ R), the full code would be:
implies2(P,Q,R) :- implies(P, or(not(Q), R)).
内容的提问来源于stack exchange,提问作者Roberto Sepúlveda Bravo

