What is the proper use of the “select” option inside the MeasureHomodyne() function?
Hey @saurabh-shringarpure! Welcome to the forum !
The select
argument is optional — its default value is None
, meaning that it’s completely bypassed and not used by default. However, if you specify a value here, it means that when you perform a homodyne measurement you are asking for a post-selection of specific measurement results. I.e., you’re filtering out values from random sampling — no selection — that you don’t want except for one.
Here is an example that you can play around with!
import strawberryfields as sf
from strawberryfields.ops import *
prog = sf.Program(2)
eng = sf.Engine("gaussian")
with prog.context as q:
S2gate(1) | (q[0], q[1])
# interchange the following lines to see behaviour of select
#MeasureHomodyne(0, select=3) | q[0]
MeasureHomodyne(0) | q[0]
samples = eng.run(prog).samples
print(samples)
Hope this helps!
Can it select a range of values instead of just one?
I don’t think so, unfortunately! Is this detrimental to your code / research?
Oh, I see. Thank you. Yes, I would like that feature for my research.
It might be best for us to seek an alternate approach. Are you able to share your research endeavours and/or code? We might be able to show you a way around this!
import strawberryfields as sf
from strawberryfields.ops import *
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
from matplotlib import cm
prog = sf.Program(2)
eng = sf.Engine("bosonic")
theta = np.arccos(np.sqrt(0.5)) # arccos of the transmittivity of the beamsplitter
# Options for the postselection window
start = 0.1
stop = 0.2
with prog.context as q:
sf.ops.Catstate(2) | q[0]
sf.ops.Vacuum() | q[1]
sf.ops.BSgate(theta,0) | (q[0], q[1])
MeasureHomodyne(0, select = [start, stop]) | q[1] #Need to use a postselection window here. Accept all values between start and stop.
state = eng.run(prog).state
# We now plot it
xvec = np.linspace(-8, 8, 201)
W = state.wigner(mode = 0, xvec = xvec, pvec = xvec)
Wp = np.round(W.real, 4)
scale = np.max(Wp.real)
nrm = mpl.colors.Normalize(-scale, scale)
plt.axes().set_aspect("equal")
plt.contourf(xvec, xvec, Wp, 60, cmap=cm.RdBu, norm=nrm)
plt.xlabel(r"q (units of $\sqrt{\hbar}$)", fontsize=15)
plt.ylabel(r"p (units of $\sqrt{\hbar}$)", fontsize=15)
plt.show()
Thank you @isaacdevlugt I am looking for an application similar to the one shown here. This code doesn’t work as the ‘select’ option in MeasureHomodyne() takes a single value input.
I’m not sure that I see an alternative besides just running your circuit twice as follows :
import strawberryfields as sf
from strawberryfields.ops import *
import numpy as np
prog1 = sf.Program(2)
prog2 = sf.Program(2)
eng = sf.Engine("bosonic")
theta = np.arccos(np.sqrt(0.5)) # arccos of the transmittivity of the beamsplitter
# Options for the postselection window
start = 0.1
stop = 0.2
with prog1.context as q:
sf.ops.Catstate(2) | q[0]
sf.ops.Vacuum() | q[1]
sf.ops.BSgate(theta,0) | (q[0], q[1])
MeasureHomodyne(0, select = start) | q[1] #Need to use a postselection window here. Accept all values between start and stop.
state1 = eng.run(prog).state
with prog2.context as q:
sf.ops.Catstate(2) | q[0]
sf.ops.Vacuum() | q[1]
sf.ops.BSgate(theta,0) | (q[0], q[1])
MeasureHomodyne(0, select = stop) | q[1] #Need to use a postselection window here. Accept all values between start and stop.
state2 = eng.run(prog).state
print(state1, state2)
I’ll tag @Sebastian_Duque_Mesa here just in case I’m missing something.
Yep — just confirmed with Sebastián. Looks like this is the way to do it (two separate programs).
Thank you @isaacdevlugt @Sebastian_Duque_Mesa for your answer. However, I would like to accept all the values in between ‘start’ and ‘stop’ as well. The measurement operator needs to be \propto \int_{\text{start}}^{\text{stop}}{dx|x\rangle\langle x|}. The result should be just one quantum state in the unmeasured mode. Can this be done?
Unfortunately no . This would entail giving multiple select
values to MeasureHomodyne
, which isn’t a feature.