Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from types import SimpleNamespace
- import functools
- class Gate:
- BEHAVIOURS = {
- "NOT": lambda A: not A,
- "OR": lambda A, B: A or B,
- "AND": lambda A,B: A and B,
- "NAND": lambda A,B: not(A and B),
- "NOR": lambda A,B: not(A or B),
- "XOR": lambda A,B: A!=B,
- "XNOR": lambda A,B: A==B,
- "INPUT": lambda A: A
- }
- COSTS = {
- "NOT": 1,
- "OR": 3,
- "AND": 3,
- "NAND": 2,
- "NOR": 2,
- "XOR": 3,
- "XNOR":3,
- "INPUT":0
- }
- def __init__(self,gate_name, childA=None, childB = None):
- if (childA is not None) and (gate_name == "INPUT"):
- raise ValueError("INPUT Gate cannot have children")
- self.behaviour = Gate.BEHAVIOURS[gate_name]
- self.cost= Gate.COSTS[gate_name]
- self.gate_name = gate_name
- self.childA = childA
- self.childB = childB
- def set_state(self,state):
- if self.gate_name != "INPUT":
- raise ValueError("Cannot set_state of any gate but INPUT")
- self.state = state
- def evaluate(self):
- if self.gate_name == "INPUT":
- return self.state
- A_val = self.childA.evaluate()
- if self.childB is not None:
- B_val = self.childB.evaluate()
- return self.behaviour(A_val,B_val)
- return self.behaviour(A_val)
- def caclulate_cost(self):
- if self.gate_name == "INPUT":
- return 0
- total_cost = Gate.COSTS[self.gate_name]
- total_cost += self.childA.calculate_cost()
- if self.childB is not None:
- total_cost += self.childB.calculate_cost()
- return total_cost
- def integer_to_bits(num,pad_until=None):
- bits = []
- while num > 0:
- bits.insert(0,(num % 2) != 0)
- num = num // 2
- if pad_until is not None:
- while len(bits) < pad_until:
- bits.insert(0,False)
- return bits
- VARIABLE_LETTERS = "ABCDWXYZQRST"
- class InputSet(SimpleNamespace):
- def __init__(self, num_inputs):
- super().__init__()
- self.num_inputs = num_inputs
- for idx in range(num_inputs):
- self.__setattr__(VARIABLE_LETTERS[idx],Gate("INPUT"))
- def load_integer(self, num):
- bits = integer_to_bits(num,self.num_inputs)
- for idx in range(self.num_inputs):
- self.__getattribute__(VARIABLE_LETTERS[idx]).set_state(bits[idx])
- def NOT(A):
- return Gate("NOT", A)
- def AND(A,B):
- return Gate("AND", A,B)
- def OR(A,B):
- return Gate("OR", A,B)
- def NAND(A,B):
- return Gate("NAND", A,B)
- def NOR(A,B):
- return Gate("NOR", A,B)
- def XOR(A,B):
- return Gate("XOR", A,B)
- def XNOR(A,B):
- return Gate("XNOR", A,B)
- def VARIADIC_OR(*gates):
- return functools.reduce(XOR,gates)
- def VARIADIC_AND(*gates):
- return functools.reduce(AND,gates)
- problem_inputset = InputSet(4) # A, B, C and D
- #shorthand
- P_IS = problem_inputset
- # B’C’ + A’C’D’ + A’B’C + ACD’ + AB’C’
- ground_truth_circuit = VARIADIC_OR(
- VARIADIC_AND(
- NOT(P_IS.B),
- NOT(P_IS.C)
- ),
- VARIADIC_AND(
- NOT(P_IS.A),
- NOT(P_IS.C),
- NOT(P_IS.D)
- ),
- VARIADIC_AND(
- NOT(P_IS.A),
- NOT(P_IS.B),
- P_IS.C
- ),
- VARIADIC_AND(
- P_IS.A,
- P_IS.C,
- NOT(P_IS.D)
- ),
- VARIADIC_AND(
- P_IS.A,
- NOT(P_IS.B),
- NOT(P_IS.C)
- )
- )
- attempted_simplification_circuit = NOT(
- AND(
- XOR(P_IS.A,P_IS.C),
- NOT(P_IS.B)
- )
- )
- def evaluate_circuit(circuit,inputset):
- def get_line_header(i):
- bits = integer_to_bits(i,inputset.num_inputs)
- return VARIABLE_LETTERS[:inputset.num_inputs] + " == " + "".join([("1" if value else "0") for value in bits]) + " --> "
- max_i = int(2**inputset.num_inputs)
- for i in range(max_i):
- line_header = get_line_header(i)
- inputset.load_integer(i)
- circuit_value = circuit.evaluate()
- print(f"{line_header}{'1' if circuit_value else '0'}")
- print("-----Ground Truth-----")
- evaluate_circuit(ground_truth_circuit,P_IS)
- print("----------")
- print("-----Attempted Simplification-----")
- evaluate_circuit(attempted_simplification_circuit,P_IS)
- print("----------")
- """ Result:
- -----Ground Truth-----
- ABCD == 0000 --> 0
- ABCD == 0001 --> 1
- ABCD == 0010 --> 1
- ABCD == 0011 --> 1
- ABCD == 0100 --> 1
- ABCD == 0101 --> 0
- ABCD == 0110 --> 0
- ABCD == 0111 --> 0
- ABCD == 1000 --> 0
- ABCD == 1001 --> 0
- ABCD == 1010 --> 1
- ABCD == 1011 --> 0
- ABCD == 1100 --> 0
- ABCD == 1101 --> 0
- ABCD == 1110 --> 1
- ABCD == 1111 --> 0
- ----------
- -----Attempted Simplification-----
- ABCD == 0000 --> 1
- ABCD == 0001 --> 1
- ABCD == 0010 --> 0
- ABCD == 0011 --> 0
- ABCD == 0100 --> 1
- ABCD == 0101 --> 1
- ABCD == 0110 --> 1
- ABCD == 0111 --> 1
- ABCD == 1000 --> 0
- ABCD == 1001 --> 0
- ABCD == 1010 --> 1
- ABCD == 1011 --> 1
- ABCD == 1100 --> 1
- ABCD == 1101 --> 1
- ABCD == 1110 --> 1
- ABCD == 1111 --> 1
- ----------
- """
Advertisement
Add Comment
Please, Sign In to add comment