def handle_input_move_ctrl(self, direction): # TODO: Handle Toffoli gates. For now, control qubit is assumed to be in ctrl_a variable # with ctrl_b variable reserved for Toffoli gates # TODO: Simplify the logic in this method, including considering not actually ever # placing a TRACE, but rather always dynamically calculating if a TRACE s/b displayed selected_node_gate_part = self.get_selected_node_gate_part() if selected_node_gate_part == node_types.X or \ selected_node_gate_part == node_types.Y or \ selected_node_gate_part == node_types.Z or \ selected_node_gate_part == node_types.H: circuit_grid_node = self.circuit_grid_model.get_node( self.selected_wire, self.selected_column) if 0 <= circuit_grid_node.ctrl_a < self.circuit_grid_model.max_wires: # Gate already has a control qubit so try to move it if direction == MOVE_UP: candidate_wire_num = circuit_grid_node.ctrl_a - 1 if candidate_wire_num == self.selected_wire: candidate_wire_num -= 1 else: candidate_wire_num = circuit_grid_node.ctrl_a + 1 if candidate_wire_num == self.selected_wire: candidate_wire_num += 1 if 0 <= candidate_wire_num < self.circuit_grid_model.max_wires: if self.place_ctrl_qubit( self.selected_wire, candidate_wire_num) == candidate_wire_num: print("control qubit successfully placed on wire ", candidate_wire_num) if direction == MOVE_UP and candidate_wire_num < self.selected_wire: if self.circuit_grid_model.get_node_gate_part( candidate_wire_num + 1, self.selected_column) == node_types.EMPTY: self.circuit_grid_model.set_node( candidate_wire_num + 1, self.selected_column, CircuitGridNode(node_types.TRACE)) elif direction == MOVE_DOWN and candidate_wire_num > self.selected_wire: if self.circuit_grid_model.get_node_gate_part( candidate_wire_num - 1, self.selected_column) == node_types.EMPTY: self.circuit_grid_model.set_node( candidate_wire_num - 1, self.selected_column, CircuitGridNode(node_types.TRACE)) self.update() else: print("control qubit could not be placed on wire ", candidate_wire_num)
def delete_controls_for_gate(self, gate_wire_num, column_num): control_a_wire_num = self.circuit_grid_model.get_node( gate_wire_num, column_num).ctrl_a control_b_wire_num = self.circuit_grid_model.get_node( gate_wire_num, column_num).ctrl_b # Choose the control wire (if any exist) furthest away from the gate wire control_a_wire_distance = 0 control_b_wire_distance = 0 if control_a_wire_num >= 0: control_a_wire_distance = abs(control_a_wire_num - gate_wire_num) if control_b_wire_num >= 0: control_b_wire_distance = abs(control_b_wire_num - gate_wire_num) control_wire_num = -1 if control_a_wire_distance > control_b_wire_distance: control_wire_num = control_a_wire_num elif control_a_wire_distance < control_b_wire_distance: control_wire_num = control_b_wire_num if control_wire_num >= 0: # TODO: If this is a controlled gate, remove the connecting TRACE parts between the gate and the control # ALSO: Refactor with similar code in this method for wire_idx in range(min(gate_wire_num, control_wire_num), max(gate_wire_num, control_wire_num) + 1): print("Replacing wire ", wire_idx, " in column ", column_num) circuit_grid_node = CircuitGridNode(node_types.EMPTY) self.circuit_grid_model.set_node(wire_idx, column_num, circuit_grid_node)
def place_ctrl_qubit(self, gate_wire_num, candidate_ctrl_wire_num): """Attempt to place a control qubit on a wire. If successful, return the wire number. If not, return -1 """ if candidate_ctrl_wire_num < 0 or candidate_ctrl_wire_num >= self.circuit_grid_model.max_wires: return -1 candidate_wire_gate_part = \ self.circuit_grid_model.get_node_gate_part(candidate_ctrl_wire_num, self.selected_column) if candidate_wire_gate_part == node_types.EMPTY or \ candidate_wire_gate_part == node_types.TRACE: circuit_grid_node = self.circuit_grid_model.get_node( gate_wire_num, self.selected_column) circuit_grid_node.ctrl_a = candidate_ctrl_wire_num self.circuit_grid_model.set_node(gate_wire_num, self.selected_column, circuit_grid_node) self.circuit_grid_model.set_node(candidate_ctrl_wire_num, self.selected_column, CircuitGridNode(node_types.EMPTY)) self.update() return candidate_ctrl_wire_num else: print("Can't place control qubit on wire: ", candidate_ctrl_wire_num) return -1
def handle_input_delete(self): selected_node_gate_part = self.get_selected_node_gate_part() print('In handle_input_delete, node_type in selected node is: ', selected_node_gate_part) if selected_node_gate_part == node_types.X or \ selected_node_gate_part == node_types.Y or \ selected_node_gate_part == node_types.Z or \ selected_node_gate_part == node_types.H: self.delete_controls_for_gate(self.selected_wire, self.selected_column) if selected_node_gate_part == node_types.CTRL: gate_wire_num = \ self.circuit_grid_model.get_gate_wire_for_control_node(self.selected_wire, self.selected_column) if gate_wire_num >= 0: self.delete_controls_for_gate( gate_wire_num, self.selected_column ) # for wire_idx in range(min(self.selected_wire, gate_wire_num), # max(self.selected_wire, gate_wire_num) + 1): # print("Replacing wire ", wire_idx, " in column ", self.selected_column) # self.circuit_grid_model.set_node(wire_idx, self.selected_column, node_types.IDEN) elif selected_node_gate_part != node_types.SWAP and \ selected_node_gate_part != node_types.CTRL and \ selected_node_gate_part != node_types.TRACE: circuit_grid_node = CircuitGridNode(node_types.EMPTY) self.circuit_grid_model.set_node(self.selected_wire, self.selected_column, circuit_grid_node) self.update()
def handle_input_delete(self): selected_node_gate_part = self.get_selected_node_gate_part() if ( selected_node_gate_part == node_types.X or selected_node_gate_part == node_types.Y or selected_node_gate_part == node_types.Z or selected_node_gate_part == node_types.H ): self.delete_controls_for_gate(self.selected_wire, self.selected_column) if selected_node_gate_part == node_types.CTRL: gate_wire_num = self.circuit_grid_model.get_gate_wire_for_control_node( self.selected_wire, self.selected_column ) if gate_wire_num >= 0: self.delete_controls_for_gate(gate_wire_num, self.selected_column) elif ( selected_node_gate_part != node_types.SWAP and selected_node_gate_part != node_types.CTRL and selected_node_gate_part != node_types.TRACE ): circuit_grid_node = CircuitGridNode(node_types.EMPTY) self.circuit_grid_model.set_node( self.selected_wire, self.selected_column, circuit_grid_node ) self.update()
def handle_input_ctrl(self): # TODO: Handle Toffoli gates. For now, control qubit is assumed to be in ctrl_a variable # with ctrl_b variable reserved for Toffoli gates selected_node_gate_part = self.get_selected_node_gate_part() if selected_node_gate_part == node_types.X or \ selected_node_gate_part == node_types.Y or \ selected_node_gate_part == node_types.Z or \ selected_node_gate_part == node_types.H: circuit_grid_node = self.circuit_grid_model.get_node(self.selected_wire, self.selected_column) if circuit_grid_node.ctrl_a >= 0: # Gate already has a control qubit so remove it orig_ctrl_a = circuit_grid_node.ctrl_a circuit_grid_node.ctrl_a = -1 self.circuit_grid_model.set_node(self.selected_wire, self.selected_column, circuit_grid_node) # Remove TRACE nodes for wire_num in range(min(self.selected_wire, orig_ctrl_a) + 1, max(self.selected_wire, orig_ctrl_a)): if self.circuit_grid_model.get_node_gate_part(wire_num, self.selected_column) == node_types.TRACE: self.circuit_grid_model.set_node(wire_num, self.selected_column, CircuitGridNode(node_types.EMPTY)) self.update() else: # Attempt to place a control qubit beginning with the wire above if self.selected_wire >= 0: if self.place_ctrl_qubit(self.selected_wire, self.selected_wire - 1) == -1: if self.selected_wire < self.circuit_grid_model.max_wires: if self.place_ctrl_qubit(self.selected_wire, self.selected_wire + 1) == -1: print("Can't place control qubit") self.display_exceptional_condition()
def handle_input_h(self): selected_node_gate_part = self.get_selected_node_gate_part() if selected_node_gate_part == node_types.EMPTY: circuit_grid_node = CircuitGridNode(node_types.H) self.circuit_grid_model.set_node(self.selected_wire, self.selected_column, circuit_grid_node) self.update()
def circuit_from_string(circuit_dimension, gate_string): gate_array = gate_string.split(',') row_max = int(circuit_dimension.split(',')[0]) column_max = int(circuit_dimension.split(',')[1]) circuit_grid_model = CircuitGridModel(row_max, column_max) for i in range(row_max): for j in range(column_max): index = i * column_max + j node = CircuitGridNode(node_types.IDEN) if gate_array[index] == 'X': node = CircuitGridNode(node_types.X) elif gate_array[index] == 'Y': node = CircuitGridNode(node_types.Y) elif gate_array[index] == 'Z': node = CircuitGridNode(node_types.Z) elif gate_array[index] == 'H': node = CircuitGridNode(node_types.H) circuit_grid_model.set_node(i, j, node) circuit = circuit_grid_model.compute_circuit() return circuit
def handle_input_x(self): # Add X gate regardless of whether there is an existing gate # circuit_grid_node = CircuitGridNode(node_types.X) # self.circuit_grid_model.set_node(self.selected_wire, self.selected_column, circuit_grid_node) # Allow deleting using the same key only selected_node_gate_part = self.get_selected_node_gate_part() if selected_node_gate_part == node_types.EMPTY: circuit_grid_node = CircuitGridNode(node_types.X) self.circuit_grid_model.set_node(self.selected_wire, self.selected_column, circuit_grid_node) elif selected_node_gate_part == node_types.X: self.handle_input_delete() self.update()