Modelling losses in squeezed states with a beam splitter

Hello!

I want to simulate a lossy channel for squeezed states. For this, I am using the Beam Splitter (BS) gate in strawberry fields (SF) (We can model lossy channel with ‘t’ transmittance by using a t/(1-t) BS, and inserting vacuum as one of the inputs).

As by default, the input state in SF is a vacuum state, I am using the S gate in one of the arms to initialise it with a Squeezed state. Let’s say, I am using a 50/50 beam splitter for modelling a 50% lossy channel. I am using the following code:

prog = sf.Program(2)
with prog.context as q:
    # Preparing with input squeezed state
    Sgate(0.6931) |  q[0]     # Var(X) = 0.25 for r (squeezing parameter) = 0.6931
    BSgate()      | (q[0], q[1])
    MeasureX      |  q[1]      # Measuring X quadrature

# Initializing the engine
eng = sf.Engine(backend="gaussian")    

# Executing the program with the engine
# The circuit is executed 1000 times and the results for the measurement of X quadrature for each run is stored in the array x
x = []

for i in range(1000):
    results = eng.run(prog)
    x.append(np.round(results.samples,2))

# Print Var(X)
print(np.round(np.var(x),3))

Now, according to my calculations the Var(X) should be 0.625 in both the arms. But instead, I am getting V(X) = 0.25 for q[0] (same as the input) and infinity (a very high number ) for q[1].

It is only when I am explicitly initialising q[1] with the Vacuum state, I am getting the expected result of Var(X) = 0.625 for both q[0] and q[1] after passing through the beam splitter.

prog = sf.Program(2)
with prog.context as q:
    # Preparing with input squeezed state
    Sgate(0.6931) |  q[0]     # Var(X) = 0.25 for r (squeezing parameter) = 0.6931
    Vac           |  q[1]
    BSgate()      | (q[0], q[1])
    MeasureX      |  q[1]      # Measuring X quadrature

I cannot understand why this discrepancy is coming. Technically, I should get the same result with both the approaches, if the initial state is always a vacuum state.

Python ver: 3.12.2
SF version: 0.23.0

Hi @Cheeranjiv_Pandey , welcome to the Forum!

The issue here is that you’re running the program again and again without resetting the engine so, while the first time the state is indeed the vacuum, in successive iterations it isn’t.

All you need is add eng.reset() in the line after eng.run(prog). Check out the docs for reset here to see an example.

By the way, since you want to use a loss channel you might want to look at sf.ops.LossChannel too.

I hope this helps!

Thank you very much for your reply. This really helped!

1 Like