def test_gate_noarg(self): """Test gate with no argument converts""" # create a test program prog = Program(1) with prog.context as q: ops.Vac | q[0] bb = io.to_blackbird(prog) expected = {"op": "Vacuum", "modes": [0], "args": [], "kwargs": {}} assert bb.operations[0] == expected
def test_measure_noarg(self): """Test measurement with no argument converts""" # create a test program prog = Program(1) with prog.context as q: ops.Measure | q[0] bb = io.to_blackbird(prog) expected = {"op": "MeasureFock", "modes": [0], "args": [], "kwargs": {}} assert bb.operations[0] == expected
def test_gate_arg(self): """Test gate with argument converts""" # create a test program prog = Program(2) with prog.context as q: ops.Sgate(0.54, 0.324) | q[1] bb = io.to_blackbird(prog) expected = {"op": "Sgate", "modes": [1], "args": [0.54, 0.324], "kwargs": {}} assert bb.operations[0] == expected
def test_tdm_program(self): prog = TDMProgram(2) with prog.context([1, 2], [3, 4], [5, 6]) as (p, q): ops.Sgate(0.7, 0) | q[1] ops.BSgate(p[0]) | (q[0], q[1]) ops.Rgate(p[1]) | q[1] ops.MeasureHomodyne(p[2]) | q[0] bb = io.to_blackbird(prog) assert bb.operations[0] == { 'kwargs': {}, 'args': [0.7, 0], 'op': 'Sgate', 'modes': [1] } assert bb.operations[1] == { 'kwargs': {}, 'args': ['p0', 0.0], 'op': 'BSgate', 'modes': [0, 1] } assert bb.operations[2] == { 'kwargs': {}, 'args': ['p1'], 'op': 'Rgate', 'modes': [1] } assert bb.operations[3] == { 'kwargs': { 'phi': 'p2' }, 'args': [], 'op': 'MeasureHomodyne', 'modes': [0] } assert bb.programtype == { 'name': 'tdm', 'options': { 'temporal_modes': 2 } } assert list(bb._var.keys()) == ["p0", "p1", "p2"] assert np.all(bb._var["p0"] == np.array([[1, 2]])) assert np.all(bb._var["p1"] == np.array([[3, 4]])) assert np.all(bb._var["p2"] == np.array([[5, 6]])) assert bb.modes == [0, 1]
def test_tdm_program(self): """Test TDM program converts properly""" prog = TDMProgram(2) with prog.context([1, 2], [3, 4], [5, 6]) as (p, q): ops.Sgate(0.7, 0) | q[1] ops.BSgate(p[0]) | (q[0], q[1]) ops.Rgate(p[1]) | q[1] ops.MeasureHomodyne(p[2]) | q[0] bb = io.to_blackbird(prog) assert bb.operations[0] == { "kwargs": {}, "args": [0.7, 0], "op": "Sgate", "modes": [1] } assert bb.operations[1] == { "kwargs": {}, "args": ["p0", 0.0], "op": "BSgate", "modes": [0, 1], } assert bb.operations[2] == { "kwargs": {}, "args": ["p1"], "op": "Rgate", "modes": [1] } assert bb.operations[3] == { "kwargs": {}, "args": ["p2"], "op": "MeasureHomodyne", "modes": [0], } assert bb.programtype == { "name": "tdm", "options": { "temporal_modes": 2 } } assert list(bb._var.keys()) == ["p0", "p1", "p2"] assert np.all(bb._var["p0"] == np.array([[1, 2]])) assert np.all(bb._var["p1"] == np.array([[3, 4]])) assert np.all(bb._var["p2"] == np.array([[5, 6]])) assert bb.modes == {0, 1}
def test_measured_par_str(self): """Test a MeasuredParameter with some transformations converts properly""" prog = Program(2) with prog.context as q: ops.Sgate(0.43) | q[0] ops.MeasureX | q[0] ops.Zgate(2 * pf.sin(q[0].par)) | q[1] bb = io.to_blackbird(prog) expected = { "op": "Zgate", "modes": [1], "args": ["2*sin(q0)"], "kwargs": {} } assert bb.operations[-1] == expected
def test_two_mode_gate(self): """Test two mode gate converts""" prog = Program(4) with prog.context as q: ops.BSgate(0.54, -0.324) | (q[3], q[0]) bb = io.to_blackbird(prog) expected = { "op": "BSgate", "modes": [3, 0], "args": [0.54, -0.324], "kwargs": {}, } assert bb.operations[0] == expected
def test_decomposition_operation_not_compiled(self): """Test decomposition operation""" # create a test program prog = Program(4) with prog.context as q: ops.Interferometer(U) | q bb = io.to_blackbird(prog) expected = { "op": "Interferometer", "modes": [0, 1, 2, 3], "args": [U], "kwargs": {}, } assert bb.operations[0] == expected
def test_measure_arg(self): """Test measurement with argument converts""" # create a test program prog = Program(1) with prog.context as q: ops.MeasureHomodyne(0.43) | q[0] bb = io.to_blackbird(prog) expected = { "op": "MeasureHomodyne", "modes": [0], "args": [], "kwargs": {"phi": 0.43}, } assert bb.operations[0] == expected
def test_measure_darkcounts(self): """Test measurement with dark counts""" # create a test program prog = Program(1) with prog.context as q: ops.MeasureFock(dark_counts=2) | q[0] bb = io.to_blackbird(prog) expected = { "op": "MeasureFock", "modes": [0], "args": [], "kwargs": {"dark_counts": [2]}, } assert bb.operations[0] == expected
def test_measured_par_str(self): """Test a MeasuredParameter with some transformations converts properly""" prog = Program(2) with prog.context as q: ops.Sgate(0.43) | q[0] ops.MeasureX | q[0] ops.Zgate(2 * pf.sin(q[0].par)) | q[1] bb = io.to_blackbird(prog) assert bb.operations[-1]["op"] == "Zgate" assert bb.operations[-1]["modes"] == [1] assert isinstance(bb.operations[-1]["args"][0], blackbird.RegRefTransform) assert bb.operations[-1]["args"][0].func_str == "2*sin(q0)" assert bb.operations[-1]["args"][0].regrefs == [0] assert bb.operations[-1]["kwargs"] == {}
def test_gate_kwarg(self): """Test gate with keyword argument converts""" # create a test program prog = Program(2) with prog.context as q: ops.Dgate(np.abs(0.54 + 0.324j), np.angle(0.54 + 0.324j)) | q[1] bb = io.to_blackbird(prog) # Note: due to how SF stores quantum commands with the Parameter class, # all kwargs get converted to positional args internally. expected = { "op": "Dgate", "modes": [1], "args": [np.abs(0.54 + 0.324j), np.angle(0.54 + 0.324j)], "kwargs": {}, } assert bb.operations[0] == expected
def test_free_par_str(self): """Test a FreeParameter with some transformations converts properly""" prog = Program(2) r, alpha = prog.params('r', 'alpha') with prog.context as q: ops.Sgate(r) | q[0] ops.Zgate(3 * pf.log(-alpha)) | q[1] bb = io.to_blackbird(prog) assert bb.operations[0] == { "op": "Sgate", "modes": [0], "args": ['{r}', 0.0], "kwargs": {} } assert bb.operations[1] == { "op": "Zgate", "modes": [1], "args": ['3*log(-{alpha})'], "kwargs": {} }
def create_job(self, target: str, program: Program, run_options: dict = None) -> Job: """Creates a job with the given circuit. Args: target (str): the target device program (strawberryfields.Program): the quantum circuit run_options (Dict[str, Any]): Runtime arguments for the program execution. If provided, overrides the value stored in the given ``program``. Returns: strawberryfields.api.Job: the created job """ # Serialize a blackbird circuit for network transmission bb = to_blackbird(program) bb._target["name"] = target bb._target["options"] = run_options circuit = bb.serialize() path = "/jobs" response = requests.post(self._url(path), headers=self._headers, json={"circuit": circuit}) if response.status_code == 201: job_id = response.json()["id"] if self._verbose: self.log.info("Job %s was successfully submitted.", job_id) return Job( id_=job_id, status=JobStatus(response.json()["status"]), connection=self, ) raise RequestFailedError("Failed to create job: {}".format( self._format_error_message(response)))
def run_async(self, program: Program, *, compile_options=None, recompile=False, **kwargs) -> xcc.Job: """Runs a non-blocking remote job. In the non-blocking mode, a ``xcc.Job`` object is returned immediately, and the user can manually refresh the status and check for updated results of the job. Args: program (strawberryfields.Program): the quantum circuit compile_options (None, Dict[str, Any]): keyword arguments for :meth:`.Program.compile` recompile (bool): Specifies if ``program`` should be recompiled using ``compile_options``, or if not provided, the default compilation options. Keyword Args: shots (Optional[int]): The number of shots for which to run the job. If this argument is not provided, the shots are derived from the given ``program``. Returns: xcc.Job: the created remote job """ # get the specific chip to submit the program to compile_options = compile_options or {} kwargs.update(self._backend_options) device = self.device compiler_name = compile_options.get("compiler", device.default_compiler) program_is_compiled = program.compile_info is not None if program_is_compiled and not recompile: # error handling for program compilation: # program was compiled but recompilation was not allowed by the # user if program.compile_info and ( program.compile_info[0].target != device.target or program.compile_info[0]._spec != device._spec): compile_target = program.compile_info[0].target # program was compiled for a different device raise ValueError("Cannot use program compiled with " f"{compile_target} for target {self.target}. " 'Pass the "recompile=True" keyword argument ' f"to compile with {compiler_name}.") if not program_is_compiled: # program is not compiled msg = f"Compiling program for device {device.target} using compiler {compiler_name}." self.log.info(msg) program = program.compile(device=device, **compile_options) elif recompile: # recompiling program if compile_options: msg = f"Recompiling program for device {device.target} using the specified compiler options: {compile_options}." else: msg = f"Recompiling program for device {device.target} using compiler {compiler_name}." self.log.info(msg) program = program.compile(device=device, **compile_options) elif program.compile_info[1][0] == "X": # validating program msg = ( f"Program previously compiled for {device.target} using {program.compile_info[1]}. " f"Validating program against the Xstrict compiler.") self.log.info(msg) program = program.compile(device=device, compiler="Xstrict") # Update and filter the run options if provided. # Forwarding the boolean `crop` run option to the hardware will result in undesired # behaviour as og-tdm also uses that keyword arg, hence it is removed. temp_run_options = {**program.run_options, **kwargs} skip_run_keys = ["crop"] run_options = { key: temp_run_options[key] for key in temp_run_options.keys() - skip_run_keys } if "shots" not in run_options: raise ValueError("Number of shots must be specified.") # Serialize a Blackbird circuit for network transmission bb = to_blackbird(program) bb._target["options"] = run_options circuit = bb.serialize() connection = self.connection job = xcc.Job.submit( connection=connection, name=program.name, target=self.target, circuit=circuit, language=f"blackbird:{bb.version}", ) return job