Guest User

Untitled

a guest
Nov 22nd, 2022
36
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.23 KB | None | 0 0
  1. from types import SimpleNamespace
  2. import functools
  3.  
  4. class Gate:
  5.    
  6.     BEHAVIOURS = {
  7.         "NOT": lambda A:  not A,
  8.         "OR": lambda A, B: A or B,
  9.         "AND": lambda A,B: A and B,
  10.         "NAND": lambda A,B: not(A and B),
  11.         "NOR": lambda A,B: not(A or B),
  12.         "XOR": lambda A,B: A!=B,
  13.         "XNOR": lambda A,B: A==B,
  14.         "INPUT": lambda A: A
  15.     }
  16.    
  17.    
  18.     COSTS = {
  19.         "NOT": 1,
  20.         "OR": 3,
  21.         "AND": 3,
  22.         "NAND": 2,
  23.         "NOR": 2,
  24.         "XOR": 3,
  25.         "XNOR":3,
  26.         "INPUT":0
  27.     }
  28.    
  29.     def __init__(self,gate_name, childA=None, childB = None):
  30.        
  31.         if (childA is not None) and (gate_name == "INPUT"):
  32.             raise ValueError("INPUT Gate cannot have children")
  33.        
  34.         self.behaviour = Gate.BEHAVIOURS[gate_name]
  35.         self.cost= Gate.COSTS[gate_name]
  36.         self.gate_name = gate_name
  37.         self.childA = childA
  38.         self.childB = childB
  39.        
  40.     def set_state(self,state):
  41.        
  42.         if self.gate_name != "INPUT":
  43.             raise ValueError("Cannot set_state of any gate but INPUT")
  44.        
  45.         self.state = state
  46.    
  47.     def evaluate(self):
  48.        
  49.         if self.gate_name == "INPUT":
  50.             return self.state
  51.            
  52.         A_val = self.childA.evaluate()
  53.         if self.childB is not None:
  54.             B_val = self.childB.evaluate()
  55.             return self.behaviour(A_val,B_val)
  56.         return self.behaviour(A_val)
  57.        
  58.     def caclulate_cost(self):
  59.        
  60.         if self.gate_name == "INPUT":
  61.             return 0
  62.            
  63.         total_cost = Gate.COSTS[self.gate_name]
  64.        
  65.         total_cost += self.childA.calculate_cost()
  66.        
  67.         if self.childB is not None:
  68.             total_cost += self.childB.calculate_cost()
  69.            
  70.         return total_cost
  71.        
  72. def integer_to_bits(num,pad_until=None):
  73.     bits = []
  74.     while num > 0:
  75.         bits.insert(0,(num % 2) != 0)
  76.         num = num // 2
  77.     if pad_until is not None:
  78.         while len(bits) < pad_until:
  79.             bits.insert(0,False)
  80.     return bits
  81.  
  82.  
  83. VARIABLE_LETTERS = "ABCDWXYZQRST"
  84.  
  85. class InputSet(SimpleNamespace):
  86.  
  87.     def __init__(self, num_inputs):
  88.         super().__init__()
  89.         self.num_inputs = num_inputs
  90.         for idx in range(num_inputs):
  91.             self.__setattr__(VARIABLE_LETTERS[idx],Gate("INPUT"))
  92.  
  93.     def load_integer(self, num):
  94.         bits = integer_to_bits(num,self.num_inputs)
  95.         for idx in range(self.num_inputs):
  96.             self.__getattribute__(VARIABLE_LETTERS[idx]).set_state(bits[idx])
  97.  
  98. def NOT(A):
  99.     return Gate("NOT", A)    
  100. def AND(A,B):
  101.     return Gate("AND", A,B)
  102. def OR(A,B):
  103.     return Gate("OR", A,B)
  104. def NAND(A,B):
  105.     return Gate("NAND", A,B)
  106. def NOR(A,B):
  107.     return Gate("NOR", A,B)
  108. def XOR(A,B):
  109.     return Gate("XOR", A,B)
  110. def XNOR(A,B):
  111.     return Gate("XNOR", A,B)
  112.  
  113. def VARIADIC_OR(*gates):
  114.     return functools.reduce(XOR,gates)
  115.  
  116. def VARIADIC_AND(*gates):
  117.     return functools.reduce(AND,gates)
  118.  
  119. problem_inputset = InputSet(4) # A, B, C and D
  120.  
  121. #shorthand
  122. P_IS = problem_inputset
  123.  
  124. # B’C’ + A’C’D’ + A’B’C + ACD’ + AB’C’
  125. ground_truth_circuit =  VARIADIC_OR(
  126.     VARIADIC_AND(
  127.         NOT(P_IS.B),
  128.         NOT(P_IS.C)
  129.     ),
  130.     VARIADIC_AND(
  131.         NOT(P_IS.A),
  132.         NOT(P_IS.C),
  133.         NOT(P_IS.D)
  134.     ),
  135.     VARIADIC_AND(
  136.         NOT(P_IS.A),
  137.         NOT(P_IS.B),
  138.         P_IS.C
  139.     ),
  140.     VARIADIC_AND(
  141.         P_IS.A,
  142.         P_IS.C,
  143.         NOT(P_IS.D)
  144.     ),
  145.     VARIADIC_AND(
  146.         P_IS.A,
  147.         NOT(P_IS.B),
  148.         NOT(P_IS.C)
  149.     )
  150. )
  151.  
  152. attempted_simplification_circuit = NOT(
  153.     AND(
  154.         XOR(P_IS.A,P_IS.C),
  155.         NOT(P_IS.B)
  156.     )
  157. )
  158.  
  159. def evaluate_circuit(circuit,inputset):
  160.  
  161.     def get_line_header(i):
  162.         bits = integer_to_bits(i,inputset.num_inputs)
  163.         return VARIABLE_LETTERS[:inputset.num_inputs] + " == " + "".join([("1" if value else "0") for value in bits]) + " --> "
  164.        
  165.     max_i = int(2**inputset.num_inputs)
  166.  
  167.     for i in range(max_i):
  168.         line_header = get_line_header(i)
  169.         inputset.load_integer(i)
  170.         circuit_value = circuit.evaluate()
  171.         print(f"{line_header}{'1' if circuit_value else '0'}")
  172.  
  173. print("-----Ground Truth-----")
  174. evaluate_circuit(ground_truth_circuit,P_IS)      
  175. print("----------")
  176. print("-----Attempted Simplification-----")
  177. evaluate_circuit(attempted_simplification_circuit,P_IS)      
  178. print("----------")
  179.  
  180. """ Result:
  181. -----Ground Truth-----
  182. ABCD == 0000 --> 0
  183. ABCD == 0001 --> 1
  184. ABCD == 0010 --> 1
  185. ABCD == 0011 --> 1
  186. ABCD == 0100 --> 1
  187. ABCD == 0101 --> 0
  188. ABCD == 0110 --> 0
  189. ABCD == 0111 --> 0
  190. ABCD == 1000 --> 0
  191. ABCD == 1001 --> 0
  192. ABCD == 1010 --> 1
  193. ABCD == 1011 --> 0
  194. ABCD == 1100 --> 0
  195. ABCD == 1101 --> 0
  196. ABCD == 1110 --> 1
  197. ABCD == 1111 --> 0
  198. ----------
  199. -----Attempted Simplification-----
  200. ABCD == 0000 --> 1
  201. ABCD == 0001 --> 1
  202. ABCD == 0010 --> 0
  203. ABCD == 0011 --> 0
  204. ABCD == 0100 --> 1
  205. ABCD == 0101 --> 1
  206. ABCD == 0110 --> 1
  207. ABCD == 0111 --> 1
  208. ABCD == 1000 --> 0
  209. ABCD == 1001 --> 0
  210. ABCD == 1010 --> 1
  211. ABCD == 1011 --> 1
  212. ABCD == 1100 --> 1
  213. ABCD == 1101 --> 1
  214. ABCD == 1110 --> 1
  215. ABCD == 1111 --> 1
  216. ----------
  217.  
  218. """
  219.  
  220.    
  221.  
  222.  
Advertisement
Add Comment
Please, Sign In to add comment