📚 The CoCalc Library - books, templates and other resources
License: OTHER
#1# Copyright 2019 the original author or authors.2#3# Licensed under the Apache License, Version 2.0 (the "License");4# you may not use this file except in compliance with the License.5# You may obtain a copy of the License at6#7# http://www.apache.org/licenses/LICENSE-2.08#9# Unless required by applicable law or agreed to in writing, software10# distributed under the License is distributed on an "AS IS" BASIS,11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12# See the License for the specific language governing permissions and13# limitations under the License.14#15import numpy as np16from qiskit import QuantumCircuit, QuantumRegister17from . import circuit_node_types as node_types181920class CircuitGridModel():21"""Grid-based model that is built when user interacts with circuit"""22def __init__(self, max_wires, max_columns):23self.max_wires = max_wires24self.max_columns = max_columns25self.nodes = np.empty((max_wires, max_columns),26dtype = CircuitGridNode)27self.latest_computed_circuit = None2829def __str__(self):30retval = ''31for wire_num in range(self.max_wires):32retval += '\n'33for column_num in range(self.max_columns):34# retval += str(self.nodes[wire_num][column_num]) + ', '35retval += str(self.get_node_gate_part(wire_num, column_num)) + ', '36return 'CircuitGridModel: ' + retval3738def set_node(self, wire_num, column_num, circuit_grid_node):39# First, embed the wire and column locations in the node40circuit_grid_node.wire_num = wire_num41circuit_grid_node.column_num = column_num42self.nodes[wire_num][column_num] = circuit_grid_node4344# self.nodes[wire_num][column_num] = \45# CircuitGridNode(circuit_grid_node.node_type,46# circuit_grid_node.radians,47# circuit_grid_node.ctrl_a,48# circuit_grid_node.ctrl_b,49# circuit_grid_node.swap)5051# TODO: Decide whether to protect as shown below52# if not self.nodes[wire_num][column_num]:53# self.nodes[wire_num][column_num] = CircuitGridNode(node_type, radians)54# else:55# print('Node ', wire_num, column_num, ' not empty')5657def get_node(self, wire_num, column_num):58return self.nodes[wire_num][column_num]5960def get_node_gate_part(self, wire_num, column_num):61requested_node = self.nodes[wire_num][column_num]62if requested_node and requested_node.node_type != node_types.EMPTY:63# Node is occupied so return its gate64return requested_node.node_type65else:66# Check for control nodes from gates in other nodes in this column67nodes_in_column = self.nodes[:, column_num]68for idx in range(self.max_wires):69if idx != wire_num:70other_node = nodes_in_column[idx]71if other_node:72if other_node.ctrl_a == wire_num or other_node.ctrl_b == wire_num:73return node_types.CTRL74elif other_node.swap == wire_num:75return node_types.SWAP7677return node_types.EMPTY7879def get_gate_wire_for_control_node(self, control_wire_num, column_num):80"""Get wire for gate that belongs to a control node on the given wire"""81gate_wire_num = -182nodes_in_column = self.nodes[:, column_num]83for wire_idx in range(self.max_wires):84if wire_idx != control_wire_num:85other_node = nodes_in_column[wire_idx]86if other_node:87if other_node.ctrl_a == control_wire_num or \88other_node.ctrl_b == control_wire_num:89gate_wire_num = wire_idx90# print("Found gate: ",91# self.get_node_gate_part(gate_wire_num, column_num),92# " on wire: " , gate_wire_num)93return gate_wire_num9495def get_rotation_gate_nodes(self):96rot_gate_nodes = []97for column_num in range(self.max_columns):98for wire_num in range(self.max_wires):99node = self.nodes[wire_num][column_num]100if node and node.ctrl_a == -1:101if node.node_type == node_types.X or \102node.node_type == node_types.Y or \103node.node_type == node_types.Z:104rot_gate_nodes.append(node)105return rot_gate_nodes106107108def compute_circuit(self):109qr = QuantumRegister(self.max_wires, 'q')110qc = QuantumCircuit(qr)111112# Add a column of identity gates to protect simulators from an empty circuit113qc.iden(qr)114115for column_num in range(self.max_columns):116for wire_num in range(self.max_wires):117node = self.nodes[wire_num][column_num]118if node:119if node.node_type == node_types.IDEN:120# Identity gate121qc.iden(qr[wire_num])122elif node.node_type == node_types.X:123if node.radians == 0:124if node.ctrl_a != -1:125if node.ctrl_b != -1:126# Toffoli gate127qc.ccx(qr[node.ctrl_a], qr[node.ctrl_b], qr[wire_num])128else:129# Controlled X gate130qc.cx(qr[node.ctrl_a], qr[wire_num])131else:132# Pauli-X gate133qc.x(qr[wire_num])134else:135# Rotation around X axis136qc.rx(node.radians, qr[wire_num])137elif node.node_type == node_types.Y:138if node.radians == 0:139if node.ctrl_a != -1:140# Controlled Y gate141qc.cy(qr[node.ctrl_a], qr[wire_num])142else:143# Pauli-Y gate144qc.y(qr[wire_num])145else:146# Rotation around Y axis147qc.ry(node.radians, qr[wire_num])148elif node.node_type == node_types.Z:149if node.radians == 0:150if node.ctrl_a != -1:151# Controlled Z gate152qc.cz(qr[node.ctrl_a], qr[wire_num])153else:154# Pauli-Z gate155qc.z(qr[wire_num])156else:157if node.ctrl_a != -1:158# Controlled rotation around the Z axis159qc.crz(node.radians, qr[node.ctrl_a], qr[wire_num])160else:161# Rotation around Z axis162qc.rz(node.radians, qr[wire_num])163elif node.node_type == node_types.S:164# S gate165qc.s(qr[wire_num])166elif node.node_type == node_types.SDG:167# S dagger gate168qc.sdg(qr[wire_num])169elif node.node_type == node_types.T:170# T gate171qc.t(qr[wire_num])172elif node.node_type == node_types.TDG:173# T dagger gate174qc.tdg(qr[wire_num])175elif node.node_type == node_types.H:176if node.ctrl_a != -1:177# Controlled Hadamard178qc.ch(qr[node.ctrl_a], qr[wire_num])179else:180# Hadamard gate181qc.h(qr[wire_num])182elif node.node_type == node_types.SWAP:183if node.ctrl_a != -1:184# Controlled Swap185qc.cswap(qr[node.ctrl_a], qr[wire_num], qr[node.swap])186else:187# Swap gate188qc.swap(qr[wire_num], qr[node.swap])189190self.latest_computed_circuit = qc191return qc192193194class CircuitGridNode():195"""Represents a node in the circuit grid"""196def __init__(self, node_type, radians=0.0, ctrl_a=-1, ctrl_b=-1, swap=-1):197self.node_type = node_type198self.radians = radians199self.ctrl_a = ctrl_a200self.ctrl_b = ctrl_b201self.swap = swap202self.wire_num = -1203self.column_num = -1204205def __str__(self):206string = 'type: ' + str(self.node_type)207string += ', radians: ' + str(self.radians) if self.radians != 0 else ''208string += ', ctrl_a: ' + str(self.ctrl_a) if self.ctrl_a != -1 else ''209string += ', ctrl_b: ' + str(self.ctrl_b) if self.ctrl_b != -1 else ''210return string211212213