The word "Placeholder" is used in Qubiter (we are in good company, Tensorflow uses this word in the same way) to mean a variable for which we delay/postpone assigning a numerical value (evaluating it) until a later time. In the case of Qubiter, it is useful to define gates with placeholders standing for angles. One can postpone evaluating those placeholders until one is ready to call the circuit simulator, and then pass the values of the placeholders as an argument to the simulator’s constructor. Placeholders of this type can be useful, for example, with quantum neural nets (QNNs). In some QNN algorithms, the circuit gate structure is fixed but the angles of the gates are varied many times, gradually, trying to lower a cost function each time.
In Qubiter, legal variable names must be of form
#3
or-#3
or#3*.5
or
-#3*.5
where 3 can be replaced by any non-negative int, and .5 can
be replaced by anything that can be an argument of float() without
throwing an exception. In this example, the 3 that follows the hash
character is called the variable number
NEW! (functional placeholder variables)
Now legal variable names can ALSO be of the form my_fun#1#2
or
-my_fun#1#2
, where
might be any number > 0 of hash variables. Thus, there need not always be precisely 2 hash variables as in the example.
my_fun
can be replaced by the name of any function with one ormore input floats (2 inputs in the example), as long as the first character of the function's name is a lower case letter.
The strings
my_fun#1#2
or-my_fun#1#2
indicate than one wants to
use for the angle being replaced, the values of my_fun(#1, #2)
or
-my_fun(#1, #2)
, respectively, where the inputs #1 and #2 are
floats standing for radians and the output is also a float standing
for radians.
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
We begin by writing a simple circuit with 4 qubits. As usual, the following code will
write an English and a Picture file in the io_folder
directory. Note that some
angles have been entered into the write() Python functions as legal
variable names instead of floats. In the English file, you will see those legal
names where the numerical values of those angles would have been.
from qubiter.SEO_writer import *
from qubiter.SEO_reader import *
from qubiter.EchoingSEO_reader import *
from qubiter.SEO_simulator import *
loaded OneQubitGate, WITHOUT autograd.numpy
num_qbits = 4
file_prefix = 'placeholder_test'
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_Rx(1, rads='my_fun1#2')
wr.write_Rn(3, rads_list=['#1', '-#1*3', '#3'])
wr.write_Rx(1, rads='-my_fun2#2#1')
wr.write_cnot(2, 3)
wr.close_files()
The following 2 files were just written:
Simply by creating an object of the class SEO_reader with the flag write_log
set equal to True, you can create a log file which contains
encountered in the English file
rdr = SEO_reader(file_prefix, num_qbits, write_log=True)
The following log file was just written:
Next, let us create two functions that will be used for the functional placeholders
def my_fun1(x):
return x*.5
def my_fun2(x, y):
return x + y
Partial Substitution
This creates new files
with #1=30
, #2=60
, 'my_fun1'->my_fun1
,
but #3
and 'my_fun2'
still undecided
vman = PlaceholderManager(eval_all_vars=False,
var_num_to_rads={1: np.pi/6, 2: np.pi/3},
fun_name_to_fun={'my_fun1': my_fun1})
wr = SEO_writer(file_prefix + '_eval01', emb)
EchoingSEO_reader(file_prefix, num_qbits, wr,
vars_manager=vman)
<qubiter.EchoingSEO_reader.EchoingSEO_reader at 0x7f08b0036d50>
The following 2 files were just written:
The following code runs the simulator after substituting
#1=30
, #2=60
, #3=90
, 'my_fun1'->my_fun1
, 'my_fun2'->my_fun2
vman = PlaceholderManager(
var_num_to_rads={1: np.pi/6, 2: np.pi/3, 3: np.pi/2},
fun_name_to_fun={'my_fun1': my_fun1, 'my_fun2': my_fun2}
)
sim = SEO_simulator(file_prefix, num_qbits, verbose=False,
vars_manager=vman)
StateVec.describe_st_vec_dict(sim.cur_st_vec_dict)
*********branch= pure total probability of state vector (=one if no measurements)= 1.000000 dictionary with key=qubit, value=(Prob(0), Prob(1)) {0: (1.0, -0.0), 1: (0.75, 0.25), 2: (0.811745, 0.188255), 3: (0.623513, 0.376487)}