Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 6a35c8b

Browse files
submit test case for legacy cases.
1 parent 244b87f commit 6a35c8b

File tree

10 files changed

+1341
-0
lines changed

10 files changed

+1341
-0
lines changed

‎tests/0.1_qem_and_lib.py‎

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import sys
2+
import os
3+
import matplotlib.pyplot as plt
4+
5+
# Add the directory containing your module to Python's search path
6+
module_path = ".."
7+
sys.path.insert(0, module_path)
8+
9+
import tensorcircuit as tc
10+
from tensorcircuit.cloud.apis import submit_task, get_device, set_provider, set_token
11+
from library.adder import gen_adder_circ
12+
from library.aqft import gen_aqft_circ
13+
from library.bv import gen_bv_circ
14+
from library.grover import gen_grover_circ
15+
from library.qft_adder import qft_adder
16+
from library.uccsd import gen_uccsd
17+
from library.hwea import gen_hwea_circ
18+
19+
set_token(os.getenv("TOKEN"))
20+
shots = 8192
21+
mit = tc.results.rem.ReadoutMit('tianji_s2?o=7')
22+
mit.cals_from_system(13, shots, method='local')
23+
set_provider("tencent")
24+
d = get_device("tianji_s2")
25+
submit_task(
26+
circuit=gen_adder_circ(3),
27+
shots=shots,
28+
device=d
29+
)
30+
submit_task(
31+
circuit=gen_grover_circ(3),
32+
shots=shots,
33+
device=d
34+
)
35+
# submit_task(
36+
# circuit=dynamics_circuit(4, 1.0, 0.1, 3),
37+
# shots=shots,
38+
# device=get_device("tianji_s2"),
39+
# )
40+
submit_task(
41+
circuit=gen_bv_circ(9, 4),
42+
shots=shots,
43+
device=d
44+
)
45+
submit_task(
46+
circuit=gen_uccsd(4),
47+
shots=shots,
48+
device=d
49+
)
50+
qc = qft_adder(3, 2, 5)
51+
print(qc)
52+
submit_task(
53+
circuit=qc,
54+
shots=shots,
55+
device=d
56+
)
57+
submit_task(
58+
circuit=gen_hwea_circ(4, 2),
59+
shots=shots,
60+
device=d
61+
)
62+
submit_task(
63+
circuit=gen_aqft_circ(4),
64+
shots=shots,
65+
device=d
66+
)
67+
print("✅ TEST FILE DONE")

‎tests/library/adder.py‎

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
'''
2+
Teague Tomesh - 2/10/2020
3+
4+
Implementation of an n-bit ripple-carry adder.
5+
6+
Based on the specification given in Cuccaro, Draper, Kutin, Moulton.
7+
(https://arxiv.org/abs/quant-ph/0410184v1)
8+
'''
9+
10+
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
11+
import tensorcircuit as tc
12+
from .randinit import qc_randinit
13+
14+
15+
class RCAdder:
16+
"""
17+
An n-bit ripple-carry adder can be generated using an instance of the
18+
RCAdder class by calling the gen_circuit() method.
19+
20+
This adder circuit uses 1 ancilla qubit to add together two values
21+
a = a_(n-1)...a_0 and b = b_(n-1)...a_0
22+
and store their sum
23+
s = s_n...s_0
24+
in the registers which initially held the b value.
25+
26+
The adder circuit uses 2 + binary_len(a) + binary_len(b) qubits.
27+
The initial carry value is stored in the qubit at index = 0.
28+
The binary value of a_i is stored in the qubit at index = 2*i + 2
29+
The binary value of b_i is stored in the qubit at index = 2*i + 1
30+
The high bit, s_n, is stored in the last qubit at index = num_qubits - 1
31+
32+
Attributes
33+
----------
34+
nbits : int
35+
size, in bits, of the numbers the adder can handle
36+
nq : int
37+
number of qubits needed to construct the adder circuit
38+
a, b : int
39+
optional parameters to specify the numbers the adder should add.
40+
Will throw an exception if the length of the bitstring representations
41+
of a or b are greater than nbits.
42+
use_toffoli : bool
43+
Should the toffoli gate be used in the generated circuit or should it
44+
first be decomposed
45+
barriers : bool
46+
should barriers be included in the generated circuit
47+
regname : str
48+
optional string to name the quantum and classical registers. This
49+
allows for the easy concatenation of multiple QuantumCircuits.
50+
qr : QuantumRegister
51+
Qiskit QuantumRegister holding all of the quantum bits
52+
circ : QuantumCircuit
53+
Qiskit QuantumCircuit that represents the uccsd circuit
54+
"""
55+
56+
def __init__(self, nbits=None, a=0, b=0, use_toffoli=False, barriers=False,
57+
measure=False, regname=None):
58+
59+
# number of bits the adder can handle
60+
if nbits is None:
61+
raise Exception('Number of bits must be specified')
62+
else:
63+
self.nbits = nbits
64+
65+
# given nbits, compute the number of qubits the adder will need
66+
# number of qubits = 1 ancilla for the initial carry value
67+
# + 2*nbits to hold both a and b
68+
# + 1 more qubit to hold the high bit, s_n
69+
self.nq = 1 + 2*nbits + 1
70+
71+
# set flags for circuit generation
72+
if len('{0:b}'.format(a)) > nbits or len('{0:b}'.format(b)) > nbits:
73+
raise Exception('Binary representations of a and b must be less than or equal to nbits')
74+
75+
self.a = a
76+
self.b = b
77+
self.use_toffoli = use_toffoli
78+
self.barriers = barriers
79+
self.measure = measure
80+
81+
# create a QuantumCircuit object
82+
if regname is None:
83+
self.qr = QuantumRegister(self.nq)
84+
else:
85+
self.qr = QuantumRegister(self.nq, name=regname)
86+
self.circ = QuantumCircuit(self.qr)
87+
qc_randinit(self.circ)
88+
89+
# add ClassicalRegister if measure is True
90+
if self.measure:
91+
self.cr = ClassicalRegister(self.nq)
92+
self.circ.add_register(self.cr)
93+
94+
95+
def _initialize_value(self, indices, value):
96+
"""
97+
Initialize the qubits at indices to the given value
98+
99+
Parameters
100+
----------
101+
indices : List[int]
102+
List of qubit indices
103+
value : int
104+
The desired initial value
105+
"""
106+
binstr = '{0:b}'.format(value)
107+
for index, val in enumerate(reversed(binstr)):
108+
if val is '1':
109+
self.circ.x(indices[index])
110+
111+
112+
def _toffoli(self, x, y, z):
113+
"""
114+
Implement the toffoli gate using 1 and 2 qubit gates
115+
"""
116+
self.circ.h(z)
117+
self.circ.cx(y,z)
118+
self.circ.tdg(z)
119+
self.circ.cx(x,z)
120+
self.circ.t(z)
121+
self.circ.cx(y,z)
122+
self.circ.t(y)
123+
self.circ.tdg(z)
124+
self.circ.cx(x,z)
125+
self.circ.cx(x,y)
126+
self.circ.t(z)
127+
self.circ.h(z)
128+
self.circ.t(x)
129+
self.circ.tdg(y)
130+
self.circ.cx(x,y)
131+
132+
133+
def _MAJ(self, x, y, z):
134+
"""
135+
Implement the MAJ (Majority) gate described in Cuccaro, Draper, Kutin,
136+
Moulton.
137+
"""
138+
self.circ.cx(z,y)
139+
self.circ.cx(z,x)
140+
141+
if self.use_toffoli:
142+
self.circ.ccx(x,y,z)
143+
else:
144+
# use a decomposed version of toffoli
145+
self._toffoli(x,y,z)
146+
147+
148+
def _UMA(self, x, y, z):
149+
"""
150+
Implement the UMA (UnMajority and Add) gate described in Cuccaro,
151+
Draper, Kutin, Moulton.
152+
"""
153+
self.circ.x(y)
154+
self.circ.cx(x,y)
155+
if self.use_toffoli:
156+
self.circ.ccx(x,y,z)
157+
else:
158+
# use a decomposed version of toffoli
159+
self._toffoli(x,y,z)
160+
self.circ.x(y)
161+
self.circ.cx(z,x)
162+
self.circ.cx(z,y)
163+
164+
165+
def gen_circuit(self):
166+
"""
167+
Create a circuit implementing the ripple-carry adder
168+
169+
Returns
170+
-------
171+
QuantumCircuit
172+
QuantumCircuit object of size self.nq
173+
"""
174+
high_bit_index = self.nq-1
175+
176+
# initialize the a and b registers
177+
a_indices = [2*i+2 for i in range(self.nbits)]
178+
b_indices = [2*i+1 for i in range(self.nbits)]
179+
for index_list, value in zip([a_indices, b_indices], [self.a, self.b]):
180+
self._initialize_value(index_list, value)
181+
182+
# compute the carry bits, c_i, in order using the MAJ ladder
183+
for a_i in a_indices:
184+
self._MAJ(a_i-2, a_i-1, a_i)
185+
186+
# write the final carry bit value to the high bit register
187+
self.circ.cx(a_indices[-1], high_bit_index)
188+
189+
# erase the carry bits in reverse order using the UMA ladder
190+
for a_i in reversed(a_indices):
191+
self._UMA(a_i-2, a_i-1, a_i)
192+
193+
return self.circ
194+
195+
196+
def gen_adder_circ(nbits):
197+
adder = RCAdder(nbits, a=0, b=0)
198+
circ = adder.gen_circuit()
199+
return tc.Circuit.from_qiskit(circ)
200+

‎tests/library/aqft.py‎

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
import math
2+
import numpy as np
3+
import tensorcircuit as tc
4+
from .randinit import qc_randinit
5+
6+
class QFT:
7+
"""
8+
Class which generates the circuit to perform the Quantum Fourier
9+
Transform (or its inverse) as described in Mike & Ike Chapter 5.
10+
11+
(Michael A Nielsen and Isaac L Chuang. Quantum computation and quantum
12+
information (10th anniv. version), 2010.)
13+
14+
For another example see Figure 1 of Daniel E Browne 2007 New J. Phys. 9 146
15+
16+
A QFT or iQFT circuit can be generated with a given instance of the
17+
QFT class by calling the gen_circuit() method.
18+
19+
Attributes
20+
----------
21+
width : int
22+
number of qubits
23+
inverse : bool
24+
Set to true to generate the inverse quantum fourier transform
25+
kvals : bool
26+
optional parameter that will change the angle of the controlled
27+
rotations so that when the circuit is printed it will display
28+
the same k values that are shown in Mike & Ike Chpt 5, Fig 5.1
29+
(NOTE: the generated circuit will no longer be valid! This is
30+
for visualization purposes only.)
31+
barriers : bool
32+
should barriers be included in the generated circuit
33+
measure : bool
34+
should a classical register & measurement be added to the circuit
35+
regname : str
36+
optional string to name the quantum and classical registers. This
37+
allows for the easy concatenation of multiple QuantumCircuits.
38+
qr : QuantumRegister
39+
Qiskit QuantumRegister holding all of the quantum bits
40+
cr : ClassicalRegister
41+
Qiskit ClassicalRegister holding all of the classical bits
42+
circ : QuantumCircuit
43+
Qiskit QuantumCircuit that represents the uccsd circuit
44+
"""
45+
46+
def __init__(self, width, approximation_degree, inverse=False, kvals=False, barriers=True,
47+
measure=False, regname=None):
48+
49+
# number of qubits
50+
self.nq = width
51+
self.approximation_degree = approximation_degree
52+
53+
# set flags for circuit generation
54+
self.inverse = inverse
55+
self.kvals = kvals
56+
self.barriers = barriers
57+
self.measure = measure
58+
59+
# create a QuantumCircuit object
60+
self.circ = tc.Circuit(self.nq)
61+
qc_randinit(self.circ)
62+
63+
64+
def reg_qft(self):
65+
"""
66+
Implement the QFT on self.circ
67+
68+
j ranges from 0 -> nq-1
69+
k ranges from j+1 -> nq-1
70+
71+
For each j qubit, a controlled cu1 gate is applied with target=j,
72+
control=k (for each k).
73+
74+
cu1 = 1 0
75+
0 e^(2pi*i / 2^(k-j+1))
76+
"""
77+
78+
# CPHASE gate decompostion
79+
def cu1(circ, theta, j, k):
80+
circ.RZ(k, theta=theta)
81+
circ.cnot(j, k)
82+
circ.RZ(k, theta=-theta/2)
83+
circ.cnot(j, k)
84+
circ.RZ(k, theta=-theta/2)
85+
circ.RZ(j, theta=-theta/2)
86+
87+
for j in range(self.nq):
88+
self.circ.H(j)
89+
for k in range(j+1,self.nq):
90+
if k-j+1<=self.approximation_degree:
91+
cu1(self.circ, (2*np.pi)/(2**(k-j+1)), j, k)
92+
93+
94+
95+
def gen_circuit(self):
96+
"""
97+
Create a circuit implementing the UCCSD ansatz
98+
99+
Given the number of qubits and parameters, construct the
100+
ansatz as given in Whitfield et al.
101+
102+
Returns
103+
-------
104+
QuantumCircuit
105+
QuantumCircuit object of size nq with no ClassicalRegister and
106+
no measurements
107+
"""
108+
self.reg_qft()
109+
110+
return self.circ
111+
112+
113+
def gen_aqft_circ(full_circ_size, approximation_degree=None):
114+
if not approximation_degree:
115+
approximation_degree=int(math.log(full_circ_size,2)+1)
116+
full_circ = QFT(full_circ_size, approximation_degree).gen_circuit()
117+
return full_circ

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /