1- from qiskit import IBMQ
21from qiskit import BasicAer as Aer
32from qiskit import ClassicalRegister , QuantumRegister , QuantumCircuit
43from qiskit import execute
87from matplotlib .patches import Circle , Rectangle
98import copy
109from ipywidgets import widgets
11- from IPython .display import display , clear_output
12-
13- try :
14- IBMQ .load_accounts ()
15- except :
16- pass
10+ from IPython .display import display , clear_output
1711
1812class run_game ():
1913 # Implements a puzzle, which is defined by the given inputs.
@@ -43,7 +37,9 @@ def __init__(self,initialize, success_condition, allowed_gates, vi, qubit_names,
4337 shots=1024
4438 Number of shots used to to calculate expectation values.
4539 mode='circle'
46- Either the standard 'Hello Quantum' visualization can be used (with mode='circle') or the alternative line based one (mode='line').
40+ Either the standard 'Hello Quantum' visualization can be used (with mode='circle'), or the extended one (mode='y') or the alternative line based one (mode='line').
41+ y_boxes = False
42+ Whether to show expectation values involving y.
4743 verbose=False
4844 """
4945
@@ -79,6 +75,9 @@ def get_success(required_gates):
7975 for gate in required_gates [qubit ]:
8076 success = success and (required_gates [qubit ][gate ]== 0 )
8177 return success
78+
79+ def show_circuit ():
80+ gates = get_total_gate_list
8281
8382 def get_command (gate ,qubit ):
8483 # For a given gate and qubit, return the string describing the corresoinding Qiskit string.
@@ -96,6 +95,9 @@ def get_command(gate,qubit):
9695 elif gate in ['ry(pi/4)' ,'ry(-pi/4)' ]:
9796 real_command = 'grid.qc.ry(' + '-' * (gate == 'ry(-pi/4)' )+ 'np.pi/4,grid.qr[' + qubit + '])'
9897 clean_command = 'qc.ry(' + '-' * (gate == 'ry(-pi/4)' )+ 'np.pi/4,' + qubit_name + ')'
98+ elif gate in ['rx(pi/4)' ,'rx(-pi/4)' ]:
99+ real_command = 'grid.qc.rx(' + '-' * (gate == 'rx(-pi/4)' )+ 'np.pi/4,grid.qr[' + qubit + '])'
100+ clean_command = 'qc.rx(' + '-' * (gate == 'rx(-pi/4)' )+ 'np.pi/4,' + qubit_name + ')'
99101 elif gate in ['cz' ,'cx' ,'swap' ]:
100102 real_command = 'grid.qc.' + gate + '(grid.qr[' + '0' * (qubit == '1' )+ '1' * (qubit == '0' )+ '],grid.qr[' + qubit + '])'
101103 clean_command = 'qc.' + gate + '(' + other_name + ',' + qubit_name + ')'
@@ -105,7 +107,10 @@ def get_command(gate,qubit):
105107 bloch = [None ]
106108
107109 # set up initial state and figure
108- grid = pauli_grid (backend = backend ,shots = shots ,mode = mode )
110+ if mode == 'y' :
111+ grid = pauli_grid (backend = backend ,shots = shots ,mode = 'circle' ,y_boxes = True )
112+ else :
113+ grid = pauli_grid (backend = backend ,shots = shots ,mode = mode )
109114 for gate in initialize :
110115 eval ( get_command (gate [0 ],gate [1 ])[0 ] )
111116
@@ -147,8 +152,8 @@ def get_command(gate,qubit):
147152
148153 boxes = widgets .VBox ([gate ,qubit ,action ])
149154 display (boxes )
150- if vi [ 1 ] :
151- print ('\n Your quantum program so far\n ' )
155+ if qubit_names == { '0' : 'q[0]' , '1' : 'q[1]' } :
156+ print ('\n Your quantum program so far: \n \n q = QuantumRegister(2) \n b = ClassicalRegister(2) \n qc = QuantumCircuit(q,b) \n ' )
152157 self .program = []
153158
154159 def given_gate (a ):
@@ -202,8 +207,8 @@ def given_action(c):
202207 else :
203208 command = get_command (q_gate ,q01 )
204209 eval (command [0 ])
205- if vi [ 1 ]:
206- print (command [1 ])
210+ if qubit_names in [{ '0' : 'q[0]' , '1' : 'q[1]' },{ '0' : 'A' , '1' : 'B' } ]:
211+ print (' ' + command [1 ])
207212 self .program .append ( command [1 ] )
208213 if required_gates [q01 ][gate .value ]> 0 :
209214 required_gates [q01 ][gate .value ] -= 1
@@ -225,24 +230,41 @@ def given_action(c):
225230 qubit .observe (given_qubit )
226231 action .observe (given_action )
227232
233+ def get_circuit (puzzle ):
234+
235+ q = QuantumRegister (2 ,'q' )
236+ b = ClassicalRegister (2 ,'b' )
237+ qc = QuantumCircuit (q ,b )
238+
239+ for line in puzzle .program :
240+ eval (line )
228241
242+ return qc
243+
229244class pauli_grid ():
230245 # Allows a quantum circuit to be created, modified and implemented, and visualizes the output in the style of 'Hello Quantum'.
231246
232- def __init__ (self ,backend = Aer .get_backend ('qasm_simulator' ),shots = 1024 ,mode = 'circle' ):
247+ def __init__ (self ,backend = Aer .get_backend ('qasm_simulator' ),shots = 1024 ,mode = 'circle' , y_boxes = False ):
233248 """
234249 backend=Aer.get_backend('qasm_simulator')
235250 Backend to be used by Qiskit to calculate expectation values (defaults to local simulator).
236251 shots=1024
237252 Number of shots used to to calculate expectation values.
238253 mode='circle'
239- Either the standard 'Hello Quantum' visualization can be used (with mode='circle') or the alternative line based one (mode='line').
254+ Either the standard 'Hello Quantum' visualization can be used (with mode='circle') or the alternative line based one (mode='line').
255+ y_boxes=True
256+ Whether to display full grid that includes Y expectation values.
240257 """
241258
242259 self .backend = backend
243260 self .shots = shots
244-
245- self .box = {'ZI' :(- 1 , 2 ),'XI' :(- 2 , 3 ),'IZ' :( 1 , 2 ),'IX' :( 2 , 3 ),'ZZ' :( 0 , 3 ),'ZX' :( 1 , 4 ),'XZ' :(- 1 , 4 ),'XX' :( 0 , 5 )}
261+
262+ self .y_boxes = y_boxes
263+ if self .y_boxes :
264+ self .box = {'ZI' :(- 1 , 2 ),'XI' :(- 3 , 4 ),'IZ' :( 1 , 2 ),'IX' :( 3 , 4 ),'ZZ' :( 0 , 3 ),'ZX' :( 2 , 5 ),'XZ' :(- 2 , 5 ),'XX' :( 0 , 7 ),
265+ 'YY' :(0 ,5 ), 'YI' :(- 2 ,3 ), 'IY' :(2 ,3 ), 'YZ' :(- 1 ,4 ), 'ZY' :(1 ,4 ), 'YX' :(1 ,6 ), 'XY' :(- 1 ,6 ) }
266+ else :
267+ self .box = {'ZI' :(- 1 , 2 ),'XI' :(- 2 , 3 ),'IZ' :( 1 , 2 ),'IX' :( 2 , 3 ),'ZZ' :( 0 , 3 ),'ZX' :( 1 , 4 ),'XZ' :(- 1 , 4 ),'XX' :( 0 , 5 )}
246268
247269 self .rho = {}
248270 for pauli in self .box :
@@ -278,51 +300,62 @@ def __init__(self,backend=Aer.get_backend('qasm_simulator'),shots=1024,mode='cir
278300
279301
280302 def get_rho (self ):
281- # Runs the circuit specified by self.qc and determines the expectation values for 'ZI', 'IZ', 'ZZ', 'XI', 'IX', 'XX', 'ZX' and 'XZ'.
303+ # Runs the circuit specified by self.qc and determines the expectation values for 'ZI', 'IZ', 'ZZ', 'XI', 'IX', 'XX', 'ZX' and 'XZ' (and the ones with Ys too if needed).
304+
305+ if self .y_boxes :
306+ corr = ['ZZ' ,'ZX' ,'XZ' ,'XX' ,'YY' ,'YX' ,'YZ' ,'XY' ,'ZY' ]
307+ ps = ['X' ,'Y' ,'Z' ]
308+ else :
309+ corr = ['ZZ' ,'ZX' ,'XZ' ,'XX' ]
310+ ps = ['X' ,'Z' ]
282311
283- bases = ['ZZ' ,'ZX' ,'XZ' ,'XX' ]
284312 results = {}
285- for basis in bases :
313+ for basis in corr :
286314 temp_qc = copy .deepcopy (self .qc )
287315 for j in range (2 ):
288316 if basis [j ]== 'X' :
289317 temp_qc .h (self .qr [j ])
318+ elif basis [j ]== 'Y' :
319+ temp_qc .sdg (self .qr [j ])
320+ temp_qc .h (self .qr [j ])
290321 temp_qc .barrier (self .qr )
291322 temp_qc .measure (self .qr ,self .cr )
292323 job = execute (temp_qc , backend = self .backend , shots = self .shots )
293324 results [basis ] = job .result ().get_counts ()
294325 for string in results [basis ]:
295326 results [basis ][string ] = results [basis ][string ]/ self .shots
296-
327+
297328 prob = {}
298329 # prob of expectation value -1 for single qubit observables
299330 for j in range (2 ):
300- for p in ['X' ,'Z' ]:
331+
332+ for p in ps :
301333 pauli = {}
302- for pp in 'IXZ' :
334+ for pp in [ 'I' ] + ps :
303335 pauli [pp ] = (j == 1 )* pp + p + (j == 0 )* pp
304336 prob [pauli ['I' ]] = 0
305- for basis in [pauli ['X' ],pauli ['Z' ]]:
337+ for ppp in ps :
338+ basis = pauli [ppp ]
306339 for string in results [basis ]:
307340 if string [(j + 1 )% 2 ]== '1' :
308- prob [pauli ['I' ]] += results [basis ][string ]/ 2
341+ prob [pauli ['I' ]] += results [basis ][string ]/ (2 + self .y_boxes )
342+
309343 # prob of expectation value -1 for two qubit observables
310- for basis in [ 'ZZ' , 'ZX' , 'XZ' , 'XX' ] :
344+ for basis in corr :
311345 prob [basis ] = 0
312346 for string in results [basis ]:
313347 if string [0 ]!= string [1 ]:
314348 prob [basis ] += results [basis ][string ]
315349
316350 for pauli in prob :
317351 self .rho [pauli ] = 1 - 2 * prob [pauli ]
318-
319352
320353 def update_grid (self ,rho = None ,labels = False ,bloch = None ,hidden = [],qubit = True ,corr = True ,message = "" ):
321354 """
322355 rho = None
323356 Dictionary of expectation values for 'ZI', 'IZ', 'ZZ', 'XI', 'IX', 'XX', 'ZX' and 'XZ'. If supplied, this will be visualized instead of the results of running self.qc.
324- labels = None
325- Dictionary of strings for 'ZI', 'IZ', 'ZZ', 'XI', 'IX', 'XX', 'ZX' and 'XZ' that are printed in the corresponding boxes.
357+ labels = False
358+ Determines whether basis labels are printed in the corresponding boxes.
326359 bloch = None
327360 If a qubit name is supplied, and if mode='line', Bloch circles are displayed for this qubit
328361 hidden = []
@@ -387,7 +420,7 @@ def add_line(line,pauli_pos,pauli):
387420 self .lines [pauli ]['w' ] = plt .plot ( [a [0 ],b [0 ]], [a [1 ],b [1 ]], color = (1.0 ,1.0 ,1.0 ), lw = lw )
388421 self .lines [pauli ]['b' ] = plt .plot ( [b [0 ],c [0 ]], [b [1 ],c [1 ]], color = (0.0 ,0.0 ,0.0 ), lw = lw )
389422 return coord
390-
423+
391424 l = 0.9 # line length
392425 r = 0.6 # circle radius
393426 L = 0.98 * np .sqrt (2 ) # box height and width
@@ -442,11 +475,14 @@ def add_line(line,pauli_pos,pauli):
442475 self .bottom .set_text (message )
443476
444477 if labels :
445- for pauli in box :
446- plt .text (self .box [pauli ][0 ]- 0.05 ,self .box [pauli ][1 ]- 0.85 , pauli )
478+ for pauli in self . box :
479+ plt .text (self .box [pauli ][0 ]- 0.18 ,self .box [pauli ][1 ]- 0.85 , pauli )
447480
448- self .ax .set_xlim ([- 3 ,3 ])
449- self .ax .set_ylim ([0 ,6 ])
481+ if self .y_boxes :
482+ self .ax .set_xlim ([- 4 ,4 ])
483+ self .ax .set_ylim ([0 ,8 ])
484+ else :
485+ self .ax .set_xlim ([- 3 ,3 ])
486+ self .ax .set_ylim ([0 ,6 ])
450487
451- self .fig .canvas .draw ()
452-
488+ self .fig .canvas .draw ()
0 commit comments