XOR linear equation system solver in Python

Question:

I have n rows and n+1 columns matrix and need to construct such system
For example matrix is

x4 x3 x2 x1 result
1  1  0  1  0
1  0  1  0  1
0  1  0  1  1
1  0  1  1  0

Then equation will be (+ is XOR)

x4+x3+x1=0
x4+x2=1
x3+x1=1
x4+x2+x1=0

I need to return answer as list of x1,…..
How can we do it in python?

Asked By: noone

||

Answers:

Learn Gauss, can be also used for XOR. Then write a gauss python program

Answered By: Drem Edys

You could make use of the Python interface pyz3 of Microsoft’s Z3 solver:

from z3 import *

def xor2(a, b):
    return Xor(a, b)

def xor3(a, b, c):
    return Xor(a, Xor(b, c))

#  define Boolean variables
x1 = Bool('x1')
x2 = Bool('x2')
x3 = Bool('x3')
x4 = Bool('x4')

s = Solver()

#  every equation is expressed as one constraint
s.add(Not(xor3(x4, x3, x1)))
s.add(xor2(x4, x2))
s.add(xor2(x3, x1))
s.add(Not(xor3(x4, x2, x1)))

#  solve and output results
print(s.check())
print(s.model())

Result:

sat
[x3 = False, x2 = False, x1 = True, x4 = True]

You can install the package as:

python -m pip install z3-solver

Alternative solution

You could also make use of the Python wrapper of the SAT solver cryptominisat. This solver has built-in capability to solve a system of xor clauses. The comments explain how to install the necessary Python package pycryptosat.
The problem to be solved is expressed as array of variable lists and xor results. There are certainly more elegant ways to store such problems.
The solver returns a (potentially long) tuple of truth values, one for every variable.

#
#  How to install pycryptosat, the python wrapper of cryptominisat?
#  ================================================================
#  For Windows:
#  Download pycryptosat binary .whl from
#  https://www.lfd.uci.edu/~gohlke/pythonlibs/#pycryptosat
#  Python38Scripts>pip install pycryptosat-0.6.1.1-cp38-cp38-win_amd64.whl
#
#  Note: It is essential that the downloaded wheel file fits your installed ptyhon version
#        In my case cp38 for python 3.8 and 64 bits.
#        Otherwise, the pip install will abort with failure
#
#  For Unix, a simple "pip install pycroptosat" should suffice

import pycryptosat
from pycryptosat import Solver 

s = Solver(threads=1)

var_names = ["x4", "x3", "x2", "x1"]
var_id = [4, 3, 2, 1]
dic_id_name = {id: var_names[index] for index, id in enumerate(var_id)}

problem = [
    #  x4 x3 x2 x1 result
    [[1, 1, 0, 1], 0],
    [[1, 0, 1, 0], 1],
    [[0, 1, 0, 1], 1],
    [[1, 0, 1, 1], 0]
  ]

#  Translate problem into set of xor clauses
for xor in problem:
    clause = [var_id[index] for index, value in enumerate(xor[0]) if value == 1]
    rhs = (xor[1] == 1)
    #  add_xor_clause() expects a list of variable IDs as first parameter.
    #  Second parameter is the right-hand-side of the xor expression.
    #  print(f"xor clause {clause} {rhs}")
    s.add_xor_clause(clause, rhs)

sat, solution = s.solve()
    
print(f"sat: {sat}")

if (sat):
    print(f"solution:")
    for id, name in sorted(dic_id_name.items(), key=lambda x:x[1]):
        print(f"{name} = {solution[id]}")
else:
    print("No solution. Sorry!")

Resulting output:

sat: True
solution:
x1 = True
x2 = False
x3 = False
x4 = True
Answered By: Axel Kemper
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.