def halfadder_gate(variables, vartype=dimod.BINARY, name='HALF_ADDER'): """HALF_ADDER adder constraint.""" variables = tuple(variables) if vartype is dimod.BINARY: configs = frozenset([(0, 0, 0, 0), (0, 1, 1, 0), (1, 0, 1, 0), (1, 1, 0, 1)]) else: # SPIN, vartype is checked by the decorator configs = frozenset([(-1, -1, -1, -1), (-1, +1, +1, -1), (+1, -1, +1, -1), (+1, +1, -1, +1)]) def func(augend, addend, sum_, carry): total = (augend > 0) + (addend > 0) if total == 0: return (sum_ <= 0) and (carry <= 0) elif total == 1: return (sum_ > 0) and (carry <= 0) elif total == 2: return (sum_ <= 0) and (carry > 0) else: raise ValueError("func recieved unexpected values") return Constraint(func, configs, variables, vartype=vartype, name=name)
def and_gate(variables, vartype=dimod.BINARY, name='AND'): """AND gate.""" variables = tuple(variables) if vartype is dimod.BINARY: configurations = frozenset([(0, 0, 0), (0, 1, 0), (1, 0, 0), (1, 1, 1)]) def func(in1, in2, out): return (in1 and in2) == out else: # SPIN, vartype is checked by the decorator configurations = frozenset([(-1, -1, -1), (-1, +1, -1), (+1, -1, -1), (+1, +1, +1)]) def func(in1, in2, out): return ((in1 > 0) and (in2 > 0)) == (out > 0) return Constraint(func, configurations, variables, vartype=vartype, name=name)
def fulladder_gate(variables, vartype=dimod.BINARY, name='FULL_ADDER'): """Full adder. Args: variables (list): Variable labels for the and gate as `[in1, in2, in3, sum, carry]`, where `in1, in2, in3` are inputs to be added and `sum` and 'carry' the resultant outputs. vartype (Vartype, optional, default='BINARY'): Variable type. Accepted input values: * Vartype.SPIN, 'SPIN', {-1, 1} * Vartype.BINARY, 'BINARY', {0, 1} name (str, optional, default='FULL_ADDER'): Name for the constraint. Returns: Constraint(:obj:`.Constraint`): Constraint that is satisfied when its variables are assigned values that match the valid states of a Boolean full adder. Examples: >>> import dwavebinarycsp >>> import dwavebinarycsp.factories.constraint.gates as gates >>> csp = dwavebinarycsp.ConstraintSatisfactionProblem(dwavebinarycsp.BINARY) >>> csp.add_constraint(gates.fulladder_gate(['a', 'b', 'c_in', 'total', 'c_out'], name='FA1')) >>> csp.check({'a': 1, 'b': 0, 'c_in': 1, 'total': 0, 'c_out': 1}) True """ variables = tuple(variables) if vartype is dimod.BINARY: configs = frozenset([(0, 0, 0, 0, 0), (0, 0, 1, 1, 0), (0, 1, 0, 1, 0), (0, 1, 1, 0, 1), (1, 0, 0, 1, 0), (1, 0, 1, 0, 1), (1, 1, 0, 0, 1), (1, 1, 1, 1, 1)]) else: # SPIN, vartype is checked by the decorator configs = frozenset([(-1, -1, -1, -1, -1), (-1, -1, +1, +1, -1), (-1, +1, -1, +1, -1), (-1, +1, +1, -1, +1), (+1, -1, -1, +1, -1), (+1, -1, +1, -1, +1), (+1, +1, -1, -1, +1), (+1, +1, +1, +1, +1)]) def func(in1, in2, in3, sum_, carry): total = (in1 > 0) + (in2 > 0) + (in3 > 0) if total == 0: return (sum_ <= 0) and (carry <= 0) elif total == 1: return (sum_ > 0) and (carry <= 0) elif total == 2: return (sum_ <= 0) and (carry > 0) elif total == 3: return (sum_ > 0) and (carry > 0) else: raise ValueError("func recieved unexpected values") return Constraint(func, configs, variables, vartype=vartype, name=name)
def sat2in4(pos, neg=tuple(), vartype=dimod.BINARY, name='2-in-4'): """Return a 2-in-4 constraint. Args: pos (iterable): An iterable of variable labels. """ pos = tuple(pos) neg = tuple(neg) variables = pos + neg if len(variables) != 4: raise ValueError("") if neg and (len(neg) < 4): # because 2-in-4 sat is symmetric, all negated is the same as none negated const = sat2in4(pos=variables, vartype=vartype) # make one that has no negations for v in neg: const.flip_variable(v) const.name = name # overwrite the name directly return const # we can just construct them directly for speed if vartype is dimod.BINARY: configurations = frozenset([(0, 0, 1, 1), (0, 1, 0, 1), (1, 0, 0, 1), (0, 1, 1, 0), (1, 0, 1, 0), (1, 1, 0, 0)]) else: # SPIN, vartype is checked by the decorator configurations = frozenset([(-1, -1, +1, +1), (-1, +1, -1, +1), (+1, -1, -1, +1), (-1, +1, +1, -1), (+1, -1, +1, -1), (+1, +1, -1, -1)]) def func(a, b, c, d): if a == b: return (b != c) and (c == d) elif a == c: # a != b return b == d else: # a != b, a != c => b == c return a == d return Constraint(func, configurations, variables, vartype=vartype, name=name)
def and_gate(variables, vartype=dimod.BINARY, name='AND'): """AND gate. Args: variables (list): Variable labels for the and gate as `[in1, in2, out]`, where `in1, in2` are inputs and `out` the gate's output. vartype (Vartype, optional, default='BINARY'): Variable type. Accepted input values: * Vartype.SPIN, 'SPIN', {-1, 1} * Vartype.BINARY, 'BINARY', {0, 1} name (str, optional, default='AND'): Name for the constraint. Returns: Constraint(:obj:`.Constraint`): Constraint that is satisfied when its variables are assigned values that match the valid states of an AND gate. Examples: >>> import dwavebinarycsp >>> import dwavebinarycsp.factories.constraint.gates as gates >>> csp = dwavebinarycsp.ConstraintSatisfactionProblem(dwavebinarycsp.BINARY) >>> csp.add_constraint(gates.and_gate(['a', 'b', 'c'], name='AND1')) >>> csp.check({'a': 1, 'b': 0, 'c': 0}) True """ variables = tuple(variables) if vartype is dimod.BINARY: configurations = frozenset([(0, 0, 0), (0, 1, 0), (1, 0, 0), (1, 1, 1)]) def func(in1, in2, out): return (in1 and in2) == out else: # SPIN, vartype is checked by the decorator configurations = frozenset([(-1, -1, -1), (-1, +1, -1), (+1, -1, -1), (+1, +1, +1)]) def func(in1, in2, out): return ((in1 > 0) and (in2 > 0)) == (out > 0) return Constraint(func, configurations, variables, vartype=vartype, name=name)
def xor_gate(variables, vartype=dimod.BINARY, name='XOR'): """XOR constraint.""" variables = tuple(variables) if vartype is dimod.BINARY: configs = frozenset([(0, 0, 0), (0, 1, 1), (1, 0, 1), (1, 1, 0)]) def func(in1, in2, out): return (in1 != in2) == out else: # SPIN, vartype is checked by the decorator configs = frozenset([(-1, -1, -1), (-1, +1, +1), (+1, -1, +1), (+1, +1, -1)]) def func(in1, in2, out): return ((in1 > 0) != (in2 > 0)) == (out > 0) return Constraint(func, configs, variables, vartype=vartype, name=name)
def sat2in4(pos, neg=tuple(), vartype=dimod.BINARY, name='2-in-4'): """Two-in-four (2-in-4) satisfiability. Args: pos (iterable): Variable labels, as an iterable, for non-negated variables of the constraint. Exactly four variables are specified by `pos` and `neg` together. neg (tuple): Variable labels, as an iterable, for negated variables of the constraint. Exactly four variables are specified by `pos` and `neg` together. vartype (Vartype, optional, default='BINARY'): Variable type. Accepted input values: * Vartype.SPIN, 'SPIN', {-1, 1} * Vartype.BINARY, 'BINARY', {0, 1} name (str, optional, default='2-in-4'): Name for the constraint. Returns: Constraint(:obj:`.Constraint`): Constraint that is satisfied when its variables are assigned values that satisfy a two-in-four satisfiability problem. Examples: >>> import dwavebinarycsp >>> import dwavebinarycsp.factories.constraint.sat as sat >>> csp = dwavebinarycsp.ConstraintSatisfactionProblem(dwavebinarycsp.BINARY) >>> csp.add_constraint(sat.sat2in4(['w', 'x', 'y', 'z'], vartype='BINARY', name='sat1')) >>> csp.check({'w': 1, 'x': 1, 'y': 0, 'z': 0}) True """ pos = tuple(pos) neg = tuple(neg) variables = pos + neg if len(variables) != 4: raise ValueError("") if neg and (len(neg) < 4): # because 2-in-4 sat is symmetric, all negated is the same as none negated const = sat2in4(pos=variables, vartype=vartype) # make one that has no negations for v in neg: const.flip_variable(v) const.name = name # overwrite the name directly return const # we can just construct them directly for speed if vartype is dimod.BINARY: configurations = frozenset([(0, 0, 1, 1), (0, 1, 0, 1), (1, 0, 0, 1), (0, 1, 1, 0), (1, 0, 1, 0), (1, 1, 0, 0)]) else: # SPIN, vartype is checked by the decorator configurations = frozenset([(-1, -1, +1, +1), (-1, +1, -1, +1), (+1, -1, -1, +1), (-1, +1, +1, -1), (+1, -1, +1, -1), (+1, +1, -1, -1)]) def func(a, b, c, d): if a == b: return (b != c) and (c == d) elif a == c: # a != b return b == d else: # a != b, a != c => b == c return a == d return Constraint(func, configurations, variables, vartype=vartype, name=name)