Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
version 0.0
Sgate({sq}, 0) | 0
Dgate(-7.123) | 1
BSgate({theta}) | 0, 1
MeasureFock() | 0
MeasureFock() | 2
"""
)
prog = sf.Program(3)
with prog.context as q:
# the circuit given below is an
# isomorphism of the one provided above
# in circuit, so should validate.
ops.MeasureFock() | q[2]
ops.Dgate(-7.123) | q[1]
ops.Sgate(0.543) | q[0]
ops.BSgate(-0.32) | (q[0], q[1])
ops.MeasureFock() | q[0]
new_prog = prog.compile(target=DummyCircuit())
# no exception should be raised; topology correctly validated
assert len(new_prog) == 5
def test_GBS_compile_ops_after_measure(self):
"""Tests that GBS compilation fails when there are operations following a Fock measurement."""
prog = sf.Program(2)
with prog.context as q:
ops.MeasureFock() | q
ops.Rgate(1.0) | q[0]
with pytest.raises(program.CircuitError, match="Operations following the Fock measurements."):
prog.compile('gbs')
def test_measure_noarg(self):
"""Test measurement with no argument converts"""
# create a test program
prog = Program(1)
with prog.context as q:
ops.MeasureFock() | q[0]
bb = io.to_blackbird(prog)
expected = {"op": "MeasureFock", "modes": [0], "args": [], "kwargs": {}}
assert bb.operations[0] == expected
def test_missing_s2gates(self, tol):
"""Test identity S2gates are inserted when some (but not all)
S2gates are included."""
prog = sf.Program(8)
U = random_interferometer(4)
with prog.context as q:
ops.S2gate(SQ_AMPLITUDE) | (q[1], q[5])
ops.S2gate(SQ_AMPLITUDE) | (q[3], q[7])
ops.Interferometer(U) | (q[0], q[1], q[2], q[3])
ops.Interferometer(U) | (q[4], q[5], q[6], q[7])
ops.MeasureFock() | q
expected = sf.Program(8)
with expected.context as q:
ops.S2gate(0) | (q[0], q[4])
ops.S2gate(SQ_AMPLITUDE) | (q[1], q[5])
ops.S2gate(0) | (q[2], q[6])
ops.S2gate(SQ_AMPLITUDE) | (q[3], q[7])
ops.Interferometer(U) | (q[0], q[1], q[2], q[3])
ops.Interferometer(U) | (q[4], q[5], q[6], q[7])
ops.MeasureFock() | q
res = prog.compile("chip2")
expected = expected.compile("chip2")
assert program_equivalence(res, expected, atol=tol)
def test_GBS_measure_fock_register_order(self):
"""Test that compilation of MeasureFock on multiple modes
sorts the resulting register indices in ascending order."""
prog = sf.Program(4)
with prog.context as q:
ops.S2gate(0.45) | (q[0], q[2])
ops.S2gate(0.45) | (q[0], q[2])
ops.BSgate(0.54, -0.12) | (q[0], q[1])
ops.MeasureFock() | (q[0], q[3], q[2], q[1])
prog = prog.compile("gbs")
last_cmd = prog.circuit[-1]
assert isinstance(last_cmd.op, ops.MeasureFock)
assert [x.ind for x in last_cmd.reg] == list(range(4))
def test_unitaries_do_not_match(self):
"""Test exception raised if the unitary applied to modes [0, 1] is
different to the unitary applied to modes [2, 3]"""
prog = sf.Program(4)
U = random_interferometer(2)
with prog.context as q:
ops.S2gate(0.5) | (q[0], q[2])
ops.S2gate(0.5) | (q[1], q[3])
ops.Interferometer(U) | (q[0], q[1])
ops.Interferometer(U) | (q[2], q[3])
ops.BSgate() | (q[2], q[3])
ops.MeasureFock() | q
with pytest.raises(CircuitError, match="must be identical to interferometer"):
res = prog.compile("chip0")
def test_50_50_BSgate(self, tol):
"""Test 50-50 BSgates correctly compile"""
prog = sf.Program(4)
with prog.context as q:
ops.S2gate(0.5) | (q[0], q[2])
ops.S2gate(0.5) | (q[1], q[3])
ops.BSgate() | (q[0], q[1])
ops.BSgate() | (q[2], q[3])
ops.MeasureFock() | q
res = prog.compile("chip0")
expected = sf.Program(4)
with expected.context as q:
ops.S2gate(0.5, 0) | (q[0], q[2])
ops.S2gate(0.5, 0) | (q[1], q[3])
# corresponds to BSgate() on modes [0, 1]
ops.Rgate(0) | (q[0])
ops.BSgate(np.pi / 4, np.pi / 2) | (q[0], q[1])
ops.Rgate(3 * np.pi / 2) | (q[0])
ops.BSgate(np.pi / 4, np.pi / 2) | (q[0], q[1])
ops.Rgate(3 * np.pi / 4) | (q[0])
ops.Rgate(-np.pi / 4) | (q[1])
#=======================================================================
# here we list different classes of operations for unit testing purposes
zero_args_gates = (Fouriergate,)
one_args_gates = (Xgate, Zgate, Rgate, Pgate, Vgate,
Kgate, CXgate, CZgate, CKgate)
two_args_gates = (Dgate, Sgate, BSgate, MZgate, S2gate)
gates = zero_args_gates + one_args_gates + two_args_gates
channels = (LossChannel, ThermalLossChannel)
simple_state_preparations = (Vacuum, Coherent, Squeezed, DisplacedSqueezed, Fock, Catstate, Thermal) # have __init__ methods with default arguments
state_preparations = simple_state_preparations + (Ket, DensityMatrix)
measurements = (MeasureFock, MeasureHomodyne, MeasureHeterodyne, MeasureThreshold)
decompositions = (Interferometer, BipartiteGraphEmbed, GraphEmbed, GaussianTransform, Gaussian)
#=======================================================================
# exported symbols
__all__ = [cls.__name__ for cls in gates + channels + state_preparations + measurements + decompositions] + shorthands
A, B, C = group_operations(seq, lambda x: isinstance(x, ops.MeasureFock))
raise CircuitError('GBS circuits must contain Fock measurements.')
# there should be only Fock measurements in B
measured = set()
for cmd in B:
if not isinstance(cmd.op, ops.MeasureFock):
raise CircuitError('The Fock measurements are not consecutive.')
# combine the Fock measurements
temp = set(cmd.reg)
if measured & temp:
raise CircuitError('Measuring the same mode more than once.')
measured |= temp
# replace B with a single Fock measurement
B = [Command(ops.MeasureFock(), sorted(list(measured), key=lambda x: x.ind))]
return super().compile(A + B, registers)