def test_parameter_arithmetic(self, p, q): """Test parameter arithmetic works as expected,""" pp = FreeParameter("x") qq = FreeParameter("y") pp.val = p qq.val = q binary_arithmetic(pp, qq, p, q)
def test_par_is_symbolic(self, r): """Recognizing symbolic parameters.""" p = FreeParameter("x") q = MeasuredParameter(RegRef(0)) assert not par_is_symbolic(r) assert par_is_symbolic(pf.sin(r)) assert par_is_symbolic(q) assert par_is_symbolic(p) assert par_is_symbolic(pf.sin(p)) assert par_is_symbolic(p + r) assert par_is_symbolic(p - r) assert par_is_symbolic(p * r) assert par_is_symbolic(p / r) assert par_is_symbolic(p**r) assert par_is_symbolic(p - p) # no simplification # object array with symbols a = np.array([[0.1, 3, 0], [0.3, 2, p], [1, 2, 4]]) assert a.dtype == object assert par_is_symbolic(a) # object array, no symbols a = np.array([[0.1, 3, 0], [0.3, 2, 0], [1, 2, 4]], dtype=object) assert a.dtype == object assert not par_is_symbolic(a) # float array, no symbols a = np.array([[0.1, 3, 0], [0.3, 2, 0], [1, 2, 4]]) assert a.dtype != object assert not par_is_symbolic(a) assert par_is_symbolic(pf.sin(a))
def test_par_evaluate_dtype_TF(self, p, dtype): """Test the TF parameter evaluation works when a dtype is provided""" pytest.importorskip("tensorflow", minversion="2.0") import tensorflow as tf x = FreeParameter("x") x.val = tf.Variable(p) res = par_evaluate(x, dtype=dtype) assert res.dtype is tf.as_dtype(dtype)
def test_symbolic_p0(self, cls): """Decompositions cannot have a symbolic p[0].""" x = FreeParameter("x") with pytest.raises( TypeError, match= "first parameter of a Decomposition is a square matrix, and cannot be symbolic", ): cls(x)
def test_raw_parameter_printing(self): """Raw printing of parameter expressions.""" c = MeasuredParameter(RegRef(1)) d = FreeParameter("x") assert str(c) == "q1" assert str(d) == "{x}" assert str(0.1234567 * d) == "0.1234567*{x}" assert str(np.array([0, 1, -3, 0.987654]) * d) == "[0 1.0*{x} -3.0*{x} 0.987654*{x}]" assert str(pf.exp(1 + c) / d ** 2) == "exp(q1 + 1)/{x}**2"
def test_par_str(self): """String representations of parameters.""" a = 0.1234567 b = np.array([0, 0.987654]) c = MeasuredParameter(RegRef(1)) d = FreeParameter('x') assert par_str(a) == '0.1235' # rounded to 4 decimals assert par_str(b) == '[0. 0.9877]' assert par_str(c) == 'q1' assert par_str(d) == '{x}' assert par_str(b * d) == '[0 0.987654*{x}]' # not rounded to 4 decimals due to Sympy's internal settings (object array!)
def test_tdm_program(self): """Test converting a tdm bb_script to a TDMProgram""" bb_script = textwrap.dedent("""\ name None version 1.0 type tdm (temporal_modes=3) int array p0 = 1, 2 int array p1 = 3, 4 int array p2 = 5, 6 Sgate(0.7, 0) | 1 BSgate(p0, 0.0) | [0, 1] Rgate(p1) | 1 MeasureHomodyne(phi=p2) | 0 """) bb = blackbird.loads(bb_script) prog = io.to_program(bb) assert isinstance(prog, TDMProgram) assert len(prog) == 4 assert prog.circuit assert prog.circuit[0].op.__class__.__name__ == "Sgate" assert prog.circuit[0].op.p[0] == 0.7 assert prog.circuit[0].op.p[1] == 0 assert prog.circuit[0].reg[0].ind == 1 assert prog.circuit[1].op.__class__.__name__ == "BSgate" assert prog.circuit[1].op.p[0] == FreeParameter("p0") assert prog.circuit[1].op.p[1] == 0.0 assert prog.circuit[1].reg[0].ind == 0 assert prog.circuit[1].reg[1].ind == 1 assert prog.circuit[2].op.__class__.__name__ == "Rgate" assert prog.circuit[2].op.p[0] == FreeParameter("p1") assert prog.circuit[2].reg[0].ind == 1 assert prog.circuit[3].op.__class__.__name__ == "MeasureHomodyne" assert prog.circuit[3].op.p[0] == FreeParameter("p2") assert prog.circuit[3].reg[0].ind == 0 assert prog.concurr_modes == 2 assert prog.timebins == 2 assert prog.spatial_modes == 1 assert prog.free_params == { "p0": FreeParameter("p0"), "p1": FreeParameter("p1"), "p2": FreeParameter("p2"), } assert all(prog.tdm_params[0] == np.array([1, 2])) assert all(prog.tdm_params[1] == np.array([3, 4])) assert all(prog.tdm_params[2] == np.array([5, 6]))
def test_par_str(self): """String representations of parameters.""" a = 0.1234567 b = np.array([0, 0.987654]) c = MeasuredParameter(RegRef(1)) d = FreeParameter("x") assert par_str(a) == "0.1235" # rounded to 4 decimals assert par_str(b) == "[0. 0.9877]" assert par_str(c) == "q1" assert par_str(d) == "{x}" assert ( par_str(b * d) == "[0 0.987654*{x}]" ) # not rounded to 4 decimals due to Sympy's internal settings (object array!)
def test_tdm_program(self): """Test converting a TDM XIR program to a TDMProgram""" xir_prog = xir.Program() xir_prog.add_statement(xir.Statement("Sgate", [0.7, 0], (1,))) xir_prog.add_statement(xir.Statement("BSgate", ["p0", 0.0], (0, 1))) xir_prog.add_statement(xir.Statement("Rgate", ["p1"], (1,))) xir_prog.add_statement(xir.Statement("MeasureHomodyne", {"phi": "p2"}, (0,))) xir_prog.add_constant("p0", [1, 2]) xir_prog.add_constant("p1", [3, 4]) xir_prog.add_constant("p2", [5, 6]) xir_prog.add_option("_type_", "tdm") xir_prog.add_option("N", [2]) xir_prog.add_option("shots", 3) sf_prog = io.to_program(xir_prog) assert isinstance(sf_prog, TDMProgram) assert sf_prog.run_options == {"shots": 3} assert len(sf_prog) == 4 assert sf_prog.circuit assert sf_prog.circuit[0].op.__class__.__name__ == "Sgate" assert sf_prog.circuit[0].op.p[0] == 0.7 assert sf_prog.circuit[0].op.p[1] == 0 assert sf_prog.circuit[0].reg[0].ind == 1 assert sf_prog.circuit[1].op.__class__.__name__ == "BSgate" assert sf_prog.circuit[1].op.p[0] == FreeParameter("p0") assert sf_prog.circuit[1].op.p[1] == 0.0 assert sf_prog.circuit[1].reg[0].ind == 0 assert sf_prog.circuit[1].reg[1].ind == 1 assert sf_prog.circuit[2].op.__class__.__name__ == "Rgate" assert sf_prog.circuit[2].op.p[0] == FreeParameter("p1") assert sf_prog.circuit[2].reg[0].ind == 1 assert sf_prog.circuit[3].op.__class__.__name__ == "MeasureHomodyne" assert sf_prog.circuit[3].op.p[0] == FreeParameter("p2") assert sf_prog.circuit[3].reg[0].ind == 0 assert sf_prog.concurr_modes == 2 assert sf_prog.timebins == 2 assert sf_prog.spatial_modes == 1 assert sf_prog.free_params == { "p0": FreeParameter("p0"), "p1": FreeParameter("p1"), "p2": FreeParameter("p2"), } assert all(sf_prog.tdm_params[0] == np.array([1, 2])) assert all(sf_prog.tdm_params[1] == np.array([3, 4])) assert all(sf_prog.tdm_params[2] == np.array([5, 6]))
def test_par_regref_deps(self): """RegRef dependencies of parameters.""" r = [RegRef(k) for k in range(2)] R0 = set([r[0]]) R = set(r) s = 0.4 x = FreeParameter("x") p = MeasuredParameter(r[0]) q = MeasuredParameter(r[1]) assert par_regref_deps(s) == set() assert par_regref_deps(x) == set() assert par_regref_deps(p) == R0 assert par_regref_deps(s * p) == R0 assert par_regref_deps(x * p) == R0 assert par_regref_deps(p + q) == R assert par_regref_deps(s * p + q**x) == R
def test_par_evaluate(self, p): x = FreeParameter("x") with pytest.raises(ParameterError, match="unbound parameter with no default value"): par_evaluate(x) # val only x.val = p assert np.all(par_evaluate(x) == p) # default only x.val = None x.default = p assert np.all(par_evaluate(x) == p) # both val and default x.val = p x.default = 0.0 assert np.all(par_evaluate(x) == p)
def test_parameter_unary_negation(self, p): """Test unary negation works as expected.""" pp = FreeParameter("x") pp.val = p assert par_evaluate(-p) == pytest.approx(-p) assert par_evaluate(-pp) == pytest.approx(-p)
def test_parameter_right_literal_arithmetic(self, p, q): """Test parameter arithmetic works as expected.""" pp = FreeParameter("x") pp.val = p binary_arithmetic(pp, q, p, q)
def test_parameter_left_literal_arithmetic(self, p, q): """Test parameter arithmetic works as expected.""" qq = FreeParameter("x") qq.val = q binary_arithmetic(p, qq, p, q)
def test_par_evaluate_dtype_numpy(self, p, dtype): """Test the numpy parameter evaluation works when a dtype is provided""" x = FreeParameter("x") x.val = p res = par_evaluate(x, dtype=dtype) assert res.dtype.type is dtype
def test_tdm_program_script(self, use_floats): """Test converting a TDM XIR script to a TDMProgram""" xir_script = inspect.cleandoc( """ options: _type_: tdm; N: [2, 3]; end; constants: p0: [pi, 3*pi/2, 0]; p1: [1, 0.5, pi]; p2: [0, 0, 0]; end; Sgate(0.123, pi/4) | [2]; BSgate(p0, 0.0) | [1, 2]; Rgate(p1) | [2]; // test a gate that takes in an array Ket([1, 0, 0]) | [0, 1]; MeasureHomodyne(phi: p0) | [0]; MeasureFock | [2]; """ ) xir_prog = xir.parse_script(xir_script, eval_pi=True, use_floats=use_floats) print(xir_prog.options) sf_prog = io.to_program(xir_prog) assert isinstance(sf_prog, TDMProgram) assert len(sf_prog) == 6 assert sf_prog.circuit assert sf_prog.circuit[0].op.__class__.__name__ == "Sgate" assert sf_prog.circuit[0].op.p[0] == 0.123 assert sf_prog.circuit[0].op.p[1] == np.pi / 4 assert sf_prog.circuit[0].reg[0].ind == 2 assert sf_prog.circuit[1].op.__class__.__name__ == "BSgate" assert sf_prog.circuit[1].op.p[0] == FreeParameter("p0") assert sf_prog.circuit[1].op.p[1] == 0.0 assert sf_prog.circuit[1].reg[0].ind == 1 assert sf_prog.circuit[1].reg[1].ind == 2 assert sf_prog.circuit[2].op.__class__.__name__ == "Rgate" assert sf_prog.circuit[2].op.p[0] == FreeParameter("p1") assert sf_prog.circuit[2].reg[0].ind == 2 assert sf_prog.circuit[3].op.__class__.__name__ == "Ket" assert np.array_equal(sf_prog.circuit[3].op.p[0], [1, 0, 0]) assert sf_prog.circuit[3].reg[0].ind == 0 assert sf_prog.circuit[3].reg[1].ind == 1 assert sf_prog.circuit[4].op.__class__.__name__ == "MeasureHomodyne" assert sf_prog.circuit[4].op.p[0] == FreeParameter("p0") assert sf_prog.circuit[4].reg[0].ind == 0 assert sf_prog.circuit[5].op.__class__.__name__ == "MeasureFock" assert sf_prog.circuit[5].op.p == [] assert sf_prog.circuit[5].reg[0].ind == 2 assert sf_prog.concurr_modes == 5 assert sf_prog.timebins == 3 assert sf_prog.spatial_modes == 2 assert sf_prog.free_params == { "p0": FreeParameter("p0"), "p1": FreeParameter("p1"), "p2": FreeParameter("p2"), } assert all(sf_prog.tdm_params[0] == np.array([np.pi, 3 * np.pi / 2, 0])) assert all(sf_prog.tdm_params[1] == np.array([1, 0.5, np.pi])) assert all(sf_prog.tdm_params[2] == np.array([0, 0, 0]))