attempt to autogen 3sat
This commit is contained in:
parent
b6f54b2db4
commit
31b9b3640c
101
3sat.py
Normal file
101
3sat.py
Normal file
@ -0,0 +1,101 @@
|
||||
import inspect
|
||||
import itertools
|
||||
import random
|
||||
|
||||
from grover import classical_func_search
|
||||
|
||||
|
||||
class X(object):
|
||||
""""""
|
||||
|
||||
def __init__(self, i):
|
||||
self.i = i
|
||||
|
||||
|
||||
class SAT(object):
|
||||
def __init__(self, predicates=3):
|
||||
self.and_clauses = []
|
||||
self.and_clauses_funcs = []
|
||||
self.predicates = predicates
|
||||
|
||||
def or_(self, or_clauses):
|
||||
def inner_or_(params):
|
||||
for or_clause in or_clauses:
|
||||
yes_no, var = or_clause[0], or_clause[1].i - 1
|
||||
if yes_no(params[var]):
|
||||
return True
|
||||
return False
|
||||
|
||||
return inner_or_
|
||||
|
||||
def and_(self, and_clauses):
|
||||
def inner_and_(params):
|
||||
for and_clause in and_clauses:
|
||||
if and_clause(params):
|
||||
return False
|
||||
return True
|
||||
|
||||
return inner_and_
|
||||
|
||||
def yes(self, x):
|
||||
return x
|
||||
|
||||
def no(self, x):
|
||||
return not x
|
||||
|
||||
def generate(self, ands=1):
|
||||
params = [X(i) for i in range(1, self.predicates + 1)]
|
||||
|
||||
def or_clause(or_clauses):
|
||||
def inner_or_clause(params):
|
||||
return self.or_(or_clauses)(params)
|
||||
|
||||
return inner_or_clause
|
||||
|
||||
for _ in range(ands):
|
||||
or_clauses = list(zip(random.choices([self.yes, self.no], k=3), random.sample(params, k=3)))
|
||||
self.and_clauses.append(or_clauses)
|
||||
self.and_clauses_funcs.append(or_clause(or_clauses))
|
||||
|
||||
def inner_generate(args):
|
||||
return self.and_(self.and_clauses_funcs)(args)
|
||||
|
||||
self.inner = inner_generate
|
||||
|
||||
def __call__(self, args):
|
||||
self.inner(args)
|
||||
|
||||
def show(self):
|
||||
for j, _or_clause in enumerate(self.and_clauses):
|
||||
for i, predicate in enumerate(_or_clause):
|
||||
if i == 0:
|
||||
print("( ", end='')
|
||||
trueness, var = predicate
|
||||
if trueness == self.yes:
|
||||
print("x_{}".format(var.i), end='')
|
||||
else:
|
||||
print("¬x_{}".format(var.i), end='')
|
||||
if i + 1 != len(_or_clause):
|
||||
print(" ∨ ", end='')
|
||||
if j + 1 != len(self.and_clauses):
|
||||
print(" ) ∧ ")
|
||||
else:
|
||||
print(" )")
|
||||
|
||||
|
||||
def classical_3sat(func):
|
||||
# Generate all possible true/false tupples for the 3-sat problem
|
||||
input_range = list(itertools.product([True, False], repeat=func.predicates))
|
||||
random.shuffle(input_range)
|
||||
return classical_func_search(func, input_range)
|
||||
|
||||
|
||||
def main():
|
||||
gen_3sat = SAT(predicates=6)
|
||||
gen_3sat.generate(ands=1)
|
||||
gen_3sat.show()
|
||||
print(classical_3sat(gen_3sat))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
9
compiler.py
Normal file
9
compiler.py
Normal file
@ -0,0 +1,9 @@
|
||||
from lib_q_computer_math import s
|
||||
|
||||
|
||||
def int_to_state(i):
|
||||
return s("|{}>".format(bin(i)))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(int_to_state(42))
|
45
grover.py
Normal file
45
grover.py
Normal file
@ -0,0 +1,45 @@
|
||||
# http://twistedoakstudios.com/blog/Post2644_grovers-quantum-search-algorithm
|
||||
import inspect
|
||||
import itertools
|
||||
import random
|
||||
from pprint import pprint
|
||||
|
||||
|
||||
def classical_func_search(func, input_range):
|
||||
"""Grover’s algorithm takes a function, searches through
|
||||
the implicit list of possible inputs to that function, and
|
||||
returns inputs that causes the function to return true.
|
||||
"""
|
||||
rv = []
|
||||
for i, params in enumerate(input_range):
|
||||
result = func(params)
|
||||
if result:
|
||||
rv.append(params)
|
||||
return rv
|
||||
|
||||
|
||||
def _3sat(x1, x2, x3):
|
||||
# https://cstheory.stackexchange.com/questions/38538/oracle-construction-for-grovers-algorithm
|
||||
# 3-SAT from here: https://qiskit.org/textbook/ch-applications/satisfiability-grover.html
|
||||
return (not x1 or not x2 or not x3) and \
|
||||
(x1 or not x2 or x3) and \
|
||||
(x1 or x2 or not x3) and \
|
||||
(x1 or not x2 or not x3) and \
|
||||
(not x1 or x2 or x3)
|
||||
|
||||
|
||||
def classical_3sat(func):
|
||||
# Generate all possible true/false tupples for the 3-sat problem
|
||||
sig = inspect.signature(func)
|
||||
params = sig.parameters
|
||||
input_range = list(itertools.product([True, False], repeat=len(params)))
|
||||
random.shuffle(input_range)
|
||||
return classical_func_search(func, input_range)
|
||||
|
||||
|
||||
def main():
|
||||
pprint(classical_3sat(_3sat))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -48,7 +48,7 @@ class Matrix(object):
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, Complex):
|
||||
return bool(np.allclose(self.m, other))
|
||||
elif isinstance(other, TwoQubitPartial):
|
||||
elif isinstance(other, PartialQubit):
|
||||
return False
|
||||
return np.allclose(self.m, other.m)
|
||||
|
||||
@ -291,16 +291,16 @@ class State(Vector):
|
||||
# [0, 0, 1, 1, 0, 0, 1, 1]
|
||||
partial_measurement_of_qbit = [int(b[qubit_n - 1]) for b in bin_repr]
|
||||
# [0, 1, 4, 5]
|
||||
indexes_for_p_0 = [i for i, index in enumerate(partial_measurement_of_qbit) if index==0]
|
||||
indexes_for_p_0 = [i for i, index in enumerate(partial_measurement_of_qbit) if index == 0]
|
||||
weights_0 = [self.get_prob(j) for j in indexes_for_p_0]
|
||||
choices_0 = [format_str.format(i) for i in indexes_for_p_0]
|
||||
measurement_result = random.choices(choices_0, weights_0)[0][qubit_n-1]
|
||||
measurement_result = random.choices(choices_0, weights_0)[0][qubit_n - 1]
|
||||
# TODO: Verify if this is the correct collapse to lower dimension after partial measurement
|
||||
# https://www.youtube.com/watch?v=MG_9JWsrKtM&list=PL1826E60FD05B44E4&index=16
|
||||
normalization_factor = np.sqrt(np.sum([self.m[i][0] for i in indexes_for_p_0]))
|
||||
# TODO: This can be 0...
|
||||
self.m = [
|
||||
[(self.m[i][0]**2)/normalization_factor] for i in indexes_for_p_0
|
||||
[(self.m[i][0] ** 2) / normalization_factor] for i in indexes_for_p_0
|
||||
]
|
||||
return measurement_result
|
||||
|
||||
@ -555,7 +555,7 @@ class HermitianOperator(LinearTransformation, HermitianMatrix):
|
||||
# np.kron(np.outer(_0.m, _0.m), np.eye(2)) + np.kron(np.outer(_1.m, _1.m), X.m)
|
||||
# _0.x(_0) * Matrix(I.m) + _1.x(_1) * Matrix(X.m)
|
||||
|
||||
class TwoQubitPartial(object):
|
||||
class PartialQubit(object):
|
||||
def __init__(self, rpr):
|
||||
self.rpr = rpr
|
||||
self.operator = None
|
||||
@ -564,12 +564,12 @@ class TwoQubitPartial(object):
|
||||
return str("-{}-".format(self.rpr))
|
||||
|
||||
|
||||
C_partial = TwoQubitPartial("C")
|
||||
x_partial = TwoQubitPartial("x")
|
||||
C_partial = PartialQubit("C")
|
||||
x_partial = PartialQubit("x")
|
||||
|
||||
|
||||
class TwoQubitOperator(UnitaryOperator):
|
||||
def __init__(self, m: ListOrNdarray, A: TwoQubitPartial, B: TwoQubitPartial,
|
||||
def __init__(self, m: ListOrNdarray, A: PartialQubit, B: PartialQubit,
|
||||
A_p: UnitaryOperator, B_p: UnitaryOperator, *args, **kwargs):
|
||||
super().__init__(m, *args, **kwargs)
|
||||
A.operator, B.operator = self, self
|
||||
@ -697,11 +697,23 @@ H = UnitaryOperator([[1 / np.sqrt(2), 1 / np.sqrt(2)],
|
||||
[1 / np.sqrt(2), -1 / np.sqrt(2)], ],
|
||||
name="H")
|
||||
|
||||
CNOT = TwoQubitOperator([[1, 0, 0, 0],
|
||||
[0, 1, 0, 0],
|
||||
[0, 0, 0, 1],
|
||||
[0, 0, 1, 0], ],
|
||||
C_partial, x_partial, I, X)
|
||||
CNOT = TwoQubitOperator([
|
||||
[1, 0, 0, 0],
|
||||
[0, 1, 0, 0],
|
||||
[0, 0, 0, 1],
|
||||
[0, 0, 1, 0],
|
||||
], C_partial, x_partial, I, X)
|
||||
|
||||
# TOFFOLLI_GATE = ThreeQubitOperator([
|
||||
# [1, 0, 0, 0, 0, 0, 0, 0],
|
||||
# [0, 1, 0, 0, 0, 0, 0, 0],
|
||||
# [0, 0, 1, 0, 0, 0, 0, 0],
|
||||
# [0, 0, 0, 1, 0, 0, 0, 0],
|
||||
# [0, 0, 0, 0, 1, 0, 0, 0],
|
||||
# [0, 0, 0, 0, 0, 1, 0, 0],
|
||||
# [0, 0, 0, 0, 0, 0, 0, 1],
|
||||
# [0, 0, 0, 0, 0, 0, 1, 0],
|
||||
# ], C_partial, C_partial, x_partial, I, I, X)
|
||||
|
||||
|
||||
def assert_raises(exception, msg, callable, *args, **kwargs):
|
||||
@ -1037,7 +1049,7 @@ class QuantumCircuit(object):
|
||||
self.add_row(row_data)
|
||||
|
||||
def compose_quantum_state(self, step):
|
||||
partials = [op for op in step if isinstance(op, TwoQubitPartial)]
|
||||
partials = [op for op in step if isinstance(op, PartialQubit)]
|
||||
# TODO: No more than 1 TwoQubitGate **OR** UnitaryOperator can be used in a step
|
||||
for partial in partials:
|
||||
two_qubit_op = partial.operator
|
||||
@ -1096,8 +1108,8 @@ class QuantumProcessor(object):
|
||||
self.reset()
|
||||
|
||||
def compose_quantum_state(self, step):
|
||||
if any([type(s) is TwoQubitPartial for s in step]):
|
||||
two_qubit_gates = filter(lambda s: type(s) is TwoQubitPartial, step)
|
||||
if any([type(s) is PartialQubit for s in step]):
|
||||
two_qubit_gates = filter(lambda s: type(s) is PartialQubit, step)
|
||||
state = []
|
||||
for two_qubit_gate in two_qubit_gates:
|
||||
two_qubit_gate.operator.verify_step(step)
|
||||
|
Loading…
Reference in New Issue
Block a user