Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

📚 The CoCalc Library - books, templates and other resources

132929 views
License: OTHER
1
#
2
# Copyright 2019 the original author or authors.
3
#
4
# Licensed under the Apache License, Version 2.0 (the "License");
5
# you may not use this file except in compliance with the License.
6
# You may obtain a copy of the License at
7
#
8
# http://www.apache.org/licenses/LICENSE-2.0
9
#
10
# Unless required by applicable law or agreed to in writing, software
11
# distributed under the License is distributed on an "AS IS" BASIS,
12
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
# See the License for the specific language governing permissions and
14
# limitations under the License.
15
#
16
import numpy as np
17
from qiskit import QuantumCircuit, QuantumRegister
18
from . import circuit_node_types as node_types
19
20
21
class CircuitGridModel():
22
"""Grid-based model that is built when user interacts with circuit"""
23
def __init__(self, max_wires, max_columns):
24
self.max_wires = max_wires
25
self.max_columns = max_columns
26
self.nodes = np.empty((max_wires, max_columns),
27
dtype = CircuitGridNode)
28
self.latest_computed_circuit = None
29
30
def __str__(self):
31
retval = ''
32
for wire_num in range(self.max_wires):
33
retval += '\n'
34
for column_num in range(self.max_columns):
35
# retval += str(self.nodes[wire_num][column_num]) + ', '
36
retval += str(self.get_node_gate_part(wire_num, column_num)) + ', '
37
return 'CircuitGridModel: ' + retval
38
39
def set_node(self, wire_num, column_num, circuit_grid_node):
40
# First, embed the wire and column locations in the node
41
circuit_grid_node.wire_num = wire_num
42
circuit_grid_node.column_num = column_num
43
self.nodes[wire_num][column_num] = circuit_grid_node
44
45
# self.nodes[wire_num][column_num] = \
46
# CircuitGridNode(circuit_grid_node.node_type,
47
# circuit_grid_node.radians,
48
# circuit_grid_node.ctrl_a,
49
# circuit_grid_node.ctrl_b,
50
# circuit_grid_node.swap)
51
52
# TODO: Decide whether to protect as shown below
53
# if not self.nodes[wire_num][column_num]:
54
# self.nodes[wire_num][column_num] = CircuitGridNode(node_type, radians)
55
# else:
56
# print('Node ', wire_num, column_num, ' not empty')
57
58
def get_node(self, wire_num, column_num):
59
return self.nodes[wire_num][column_num]
60
61
def get_node_gate_part(self, wire_num, column_num):
62
requested_node = self.nodes[wire_num][column_num]
63
if requested_node and requested_node.node_type != node_types.EMPTY:
64
# Node is occupied so return its gate
65
return requested_node.node_type
66
else:
67
# Check for control nodes from gates in other nodes in this column
68
nodes_in_column = self.nodes[:, column_num]
69
for idx in range(self.max_wires):
70
if idx != wire_num:
71
other_node = nodes_in_column[idx]
72
if other_node:
73
if other_node.ctrl_a == wire_num or other_node.ctrl_b == wire_num:
74
return node_types.CTRL
75
elif other_node.swap == wire_num:
76
return node_types.SWAP
77
78
return node_types.EMPTY
79
80
def get_gate_wire_for_control_node(self, control_wire_num, column_num):
81
"""Get wire for gate that belongs to a control node on the given wire"""
82
gate_wire_num = -1
83
nodes_in_column = self.nodes[:, column_num]
84
for wire_idx in range(self.max_wires):
85
if wire_idx != control_wire_num:
86
other_node = nodes_in_column[wire_idx]
87
if other_node:
88
if other_node.ctrl_a == control_wire_num or \
89
other_node.ctrl_b == control_wire_num:
90
gate_wire_num = wire_idx
91
# print("Found gate: ",
92
# self.get_node_gate_part(gate_wire_num, column_num),
93
# " on wire: " , gate_wire_num)
94
return gate_wire_num
95
96
def get_rotation_gate_nodes(self):
97
rot_gate_nodes = []
98
for column_num in range(self.max_columns):
99
for wire_num in range(self.max_wires):
100
node = self.nodes[wire_num][column_num]
101
if node and node.ctrl_a == -1:
102
if node.node_type == node_types.X or \
103
node.node_type == node_types.Y or \
104
node.node_type == node_types.Z:
105
rot_gate_nodes.append(node)
106
return rot_gate_nodes
107
108
109
def compute_circuit(self):
110
qr = QuantumRegister(self.max_wires, 'q')
111
qc = QuantumCircuit(qr)
112
113
# Add a column of identity gates to protect simulators from an empty circuit
114
qc.iden(qr)
115
116
for column_num in range(self.max_columns):
117
for wire_num in range(self.max_wires):
118
node = self.nodes[wire_num][column_num]
119
if node:
120
if node.node_type == node_types.IDEN:
121
# Identity gate
122
qc.iden(qr[wire_num])
123
elif node.node_type == node_types.X:
124
if node.radians == 0:
125
if node.ctrl_a != -1:
126
if node.ctrl_b != -1:
127
# Toffoli gate
128
qc.ccx(qr[node.ctrl_a], qr[node.ctrl_b], qr[wire_num])
129
else:
130
# Controlled X gate
131
qc.cx(qr[node.ctrl_a], qr[wire_num])
132
else:
133
# Pauli-X gate
134
qc.x(qr[wire_num])
135
else:
136
# Rotation around X axis
137
qc.rx(node.radians, qr[wire_num])
138
elif node.node_type == node_types.Y:
139
if node.radians == 0:
140
if node.ctrl_a != -1:
141
# Controlled Y gate
142
qc.cy(qr[node.ctrl_a], qr[wire_num])
143
else:
144
# Pauli-Y gate
145
qc.y(qr[wire_num])
146
else:
147
# Rotation around Y axis
148
qc.ry(node.radians, qr[wire_num])
149
elif node.node_type == node_types.Z:
150
if node.radians == 0:
151
if node.ctrl_a != -1:
152
# Controlled Z gate
153
qc.cz(qr[node.ctrl_a], qr[wire_num])
154
else:
155
# Pauli-Z gate
156
qc.z(qr[wire_num])
157
else:
158
if node.ctrl_a != -1:
159
# Controlled rotation around the Z axis
160
qc.crz(node.radians, qr[node.ctrl_a], qr[wire_num])
161
else:
162
# Rotation around Z axis
163
qc.rz(node.radians, qr[wire_num])
164
elif node.node_type == node_types.S:
165
# S gate
166
qc.s(qr[wire_num])
167
elif node.node_type == node_types.SDG:
168
# S dagger gate
169
qc.sdg(qr[wire_num])
170
elif node.node_type == node_types.T:
171
# T gate
172
qc.t(qr[wire_num])
173
elif node.node_type == node_types.TDG:
174
# T dagger gate
175
qc.tdg(qr[wire_num])
176
elif node.node_type == node_types.H:
177
if node.ctrl_a != -1:
178
# Controlled Hadamard
179
qc.ch(qr[node.ctrl_a], qr[wire_num])
180
else:
181
# Hadamard gate
182
qc.h(qr[wire_num])
183
elif node.node_type == node_types.SWAP:
184
if node.ctrl_a != -1:
185
# Controlled Swap
186
qc.cswap(qr[node.ctrl_a], qr[wire_num], qr[node.swap])
187
else:
188
# Swap gate
189
qc.swap(qr[wire_num], qr[node.swap])
190
191
self.latest_computed_circuit = qc
192
return qc
193
194
195
class CircuitGridNode():
196
"""Represents a node in the circuit grid"""
197
def __init__(self, node_type, radians=0.0, ctrl_a=-1, ctrl_b=-1, swap=-1):
198
self.node_type = node_type
199
self.radians = radians
200
self.ctrl_a = ctrl_a
201
self.ctrl_b = ctrl_b
202
self.swap = swap
203
self.wire_num = -1
204
self.column_num = -1
205
206
def __str__(self):
207
string = 'type: ' + str(self.node_type)
208
string += ', radians: ' + str(self.radians) if self.radians != 0 else ''
209
string += ', ctrl_a: ' + str(self.ctrl_a) if self.ctrl_a != -1 else ''
210
string += ', ctrl_b: ' + str(self.ctrl_b) if self.ctrl_b != -1 else ''
211
return string
212
213