The purpose of this notebook is to illustrate how to translate a Qubiter English file for a quantum circuit, into a Xanadu Pennylane "qnode"
Next, we will create 2 Qubiter English files and then translate them to Pennylanese
First change your working directory to the qubiter directory in your computer, and add its path to the path environment variable.
import os
import sys
print(os.getcwd())
os.chdir('../../')
print(os.getcwd())
sys.path.insert(0,os.getcwd())
/home/rrtucci/PycharmProjects/qubiter/qubiter/jupyter_notebooks /home/rrtucci/PycharmProjects/qubiter
Next we create a Qubiter English file and its corresponding Picture file.
from qubiter.device_specific.Qubiter_to_PennyLane import *
loaded OneQubitGate, WITHOUT autograd.numpy
file_prefix = "qbtr2penny_test1"
num_qbits = 3
emb = CktEmbedder(num_qbits, num_qbits)
wr = SEO_writer(file_prefix, emb)
wr.write_H(0)
wr.write_X(1)
wr.write_Y(1)
wr.write_Z(1)
wr.write_cnot(0, 1)
wr.write_cz(0, 1)
wr.write_qbit_swap(1, 0)
wr.write_Rx(2, rads=np.pi)
wr.write_Ry(2, rads=np.pi)
wr.write_Rz(2, rads=np.pi)
wr.write_one_qbit_gate(1, OneQubitGate.P_1_phase_fac, [np.pi])
wr.write_Rn(0, rads_list=[np.pi, np.pi, np.pi])
wr.close_files()
wr.print_eng_file(jup=True)
1 | HAD2 AT 0 | 2 | SIGX AT 1 | 3 | SIGY AT 1 | 4 | SIGZ AT 1 | 5 | SIGX AT 1 IF 0T | 6 | SIGZ AT 1 IF 0T | 7 | SWAP 1 0 | 8 | ROTX 180.000000 AT 2 | 9 | ROTY 180.000000 AT 2 | 10 | ROTZ 180.000000 AT 2 | 11 | P1PH 180.000000 AT 1 | 12 | ROTN 180.000000 180.000000 180.000000 AT 0 |
wr.print_pic_file(jup=True)
1 | | | H | 2 | | X | | 3 | | Y | | 4 | | Z | | 5 | | X---@ | 6 | | Z---@ | 7 | | <---> | 8 | Rx | | | 9 | Ry | | | 10 | Rz | | | 11 | | @P | | 12 | | | R |
Next we translate this to a single PennyLane qnode called Turing
aqasm_name = 'PennyL'
qnode_name = 'Turing'
Qubiter_to_PennyLane(file_prefix, num_qbits,
qnode_name,
aqasm_name=aqasm_name,
write_qubiter_files=True)
<qubiter.device_specific.Qubiter_to_PennyLane.Qubiter_to_PennyLane at 0x7f7804847390>
The following 3 files were generated by the constructor just called:
Files 1 and 2 are Qubiter style English and Picture files (they differ from the input English file principally in that they include more NOTA lines).
File 3 is the PennyLane file that we wanted.
This first example has no placeholder variables. It just shows that most PennyLane gates are supported.
Next we create another Qubiter English file and its corresponding Picture file.
file_prefix = "qbtr2penny_test2"
num_qbits = 4
emb = CktEmbedder(num_qbits, num_qbits)
wr = SEO_writer(file_prefix, emb)
wr.write_Rx(2, rads=np.pi/7)
wr.write_Rx(1, rads='#2*.5')
wr.write_Rn(3, rads_list=['#1', '-#1*3', '#2'])
wr.write_Rx(1, rads='-my_fun#2#1')
wr.write_cnot(2, 3)
wr.close_files()
wr.print_eng_file(jup=True)
1 | ROTX 25.714286 AT 2 | 2 | ROTX #2*.5 AT 1 | 3 | ROTN #1 -#1*3 #2 AT 3 | 4 | ROTX -my_fun#2#1 AT 1 | 5 | SIGX AT 3 IF 2T |
wr.print_pic_file(jup=True)
1 | | Rx | | | 2 | | | Rx | | 3 | R | | | | 4 | | | Rx | | 5 | X---@ | | |
Next we translate this to a single PennyLane qnode called Feynman.
This time, the English file uses a placeholder function called my_fun
.
All placeholder functions must be
defined beforehand in a file and the
path to that file must be specified via the variable fun_defs_path
.
In this example, my_fun
is defined in the following file
aqasm_name = 'PennyL'
fun_defs_path = 'qbtr2penny_test2_fun_defs.py'
qnode_name = 'Feynman'
Qubiter_to_PennyLane(file_prefix, num_qbits,
qnode_name,
fun_defs_path,
aqasm_name=aqasm_name,
write_qubiter_files=True)
<qubiter.device_specific.Qubiter_to_PennyLane.Qubiter_to_PennyLane at 0x7f780483eb10>
The following 3 files were generated by the constructor just called:
Files 1 and 2 are Qubiter style English and Picture files (they differ from the input English file principally in that they include more NOTA lines).
File 3 is the PennyLane file that we wanted.
Notice that
defined internally in the qnode. The translating software automatically copies the def of rot() from
the file OneQubitGate.py
where it is defined.
internally in the qnode too. The translating software automatically copies the def of my_fun() from
the file at fun_defs_path
Hermitian
to accept a hamil which is an object of the class QubitOperator from the open-source library OpenFermion.I haven't tested yet whether this qnode works in PennyLane, with Rigetti's hardware and with Tensorflow or PyTorch
This is a particularly demanding test of PennyLane, but I
will consider PennyLane incomplete until and unless it can handle this qnode,
or some alternative that accomplishes the same goals.
Incomplete because I feel this qnode uses features that are possible to code and that most users
of Pennylane will want to have them. Tensorflow's back-propagation should be able to
reach inside the user supplied functions my_fun() and rot(),
although the code defining those functions might need some superficial modifications like replacing the np.
by something else