def to_blackbird(prog, version="1.0"): """Convert a Strawberry Fields Program to a Blackbird Program. Args: prog (Program): the Strawberry Fields program version (str): Blackbird script version number Returns: blackbird.BlackbirdProgram: """ bb = blackbird.BlackbirdProgram(name=prog.name, version=version) # TODO not sure if this makes sense: the program has *already been* compiled using this target if prog.target is not None: # set the target bb._target["name"] = prog.target # set the run options if prog.run_options: bb._target["options"].update(prog.run_options) if prog.backend_options: bb._target["options"].update(prog.backend_options) # fill in the quantum circuit for cmd in prog.circuit: op = {"kwargs": {}, "args": []} op["op"] = cmd.op.__class__.__name__ op["modes"] = [i.ind for i in cmd.reg] if "Measure" in op["op"]: # special case to take into account 'select' keyword argument if cmd.op.select is not None: op["kwargs"]["select"] = cmd.op.select if cmd.op.p: # argument is quadrature phase op["kwargs"]["phi"] = cmd.op.p[0] if op["op"] == "MeasureFock": # special case to take into account 'dark_counts' keyword argument if cmd.op.dark_counts is not None: op["kwargs"]["dark_counts"] = cmd.op.dark_counts else: for a in cmd.op.p: if sfpar.par_is_symbolic(a): # SymPy object, convert to string a = str(a) op["args"].append(a) bb._operations.append(op) return bb
def to_blackbird(prog: Program, version: str = "1.0") -> blackbird.BlackbirdProgram: """Convert a Strawberry Fields Program to a Blackbird Program. Args: prog (Program): the Strawberry Fields program version (str): Blackbird script version number Returns: blackbird.BlackbirdProgram: """ bb = blackbird.BlackbirdProgram(name=prog.name, version=version) bb._modes = set(prog.reg_refs.keys()) isMeasuredParameter = lambda x: isinstance(x, sfpar.MeasuredParameter) # not sure if this makes sense: the program has *already been* compiled using this target if prog.target is not None: # set the target bb._target["name"] = prog.target # set the run options if prog.run_options: bb._target["options"].update(prog.run_options) if prog.backend_options: bb._target["options"].update(prog.backend_options) # fill in the quantum circuit for cmd in prog.circuit: op = {"kwargs": {}, "args": []} op["op"] = cmd.op.__class__.__name__ op["modes"] = [i.ind for i in cmd.reg] if "Measure" in op["op"]: # special case to take into account 'select' keyword argument if cmd.op.select is not None: op["kwargs"]["select"] = cmd.op.select if cmd.op.p: # argument is quadrature phase op["args"] = cmd.op.p if op["op"] == "MeasureFock": # special case to take into account 'dark_counts' keyword argument if cmd.op.dark_counts is not None: op["kwargs"]["dark_counts"] = cmd.op.dark_counts else: for a in cmd.op.p: if sfpar.par_is_symbolic(a): # SymPy object, convert to string if any(map(isMeasuredParameter, a.free_symbols)): # check if there are any measured parameters in `a` a = blackbird.RegRefTransform(a) else: a = str(a) op["args"].append(a) # If program is a TDMProgram then add the looped-over arrays to the # blackbird program. `prog.loop_vars` are symbolic parameters (e.g. # `{p0}`), which should be replaced with `p.name` (e.g. `p0`) inside the # Blackbird operation (keyword) arguments. if isinstance(prog, TDMProgram): for p in prog.loop_vars: for i, ar in enumerate(op["args"]): if str(p) == str(ar): op["args"][i] = p.name for k, v in op["kwargs"].items(): if str(p) == str(v): op["kwargs"][k] = p.name bb._operations.append(op) # add the specific "tdm" metadata to the Blackbird program if isinstance(prog, TDMProgram): bb._type["name"] = "tdm" bb._type["options"].update({ "temporal_modes": prog.timebins, }) bb._var.update({ f"{p.name}": np.array([prog.tdm_params[i]]) for i, p in enumerate(prog.loop_vars) }) return bb
def to_blackbird(prog, version="1.0"): """Convert a Strawberry Fields Program to a Blackbird Program. Args: prog (Program): the Strawberry Fields program version (str): Blackbird script version number Returns: blackbird.BlackbirdProgram: """ bb = blackbird.BlackbirdProgram(name=prog.name, version=version) if prog.backend is not None: # set the target bb._target["name"] = prog.backend # fill in the quantum circuit for cmd in prog.circuit: op = {"kwargs": {}, "args": []} op["op"] = cmd.op.__class__.__name__ op["modes"] = [i.ind for i in cmd.reg] if "Measure" in op["op"]: # special case to take into account 'select' keyword argument if cmd.op.select is not None: op["kwargs"]["select"] = cmd.op.select if cmd.op.p: # argument is quadrature phase op["kwargs"]["phi"] = cmd.op.p[0].x else: if cmd.op.p is not None: for a in cmd.op.p: # check if reg ref transform if isinstance(a.x, RegRefTransform): # if a.x.func_str is not None: # TODO: will not satisfy all use cases # as the RegRefTransform string cannot be checked # to determine if it is a valid function for serialization! # # Possible solutions: # # * Use SymPy to represent functions, as # SymPy provides methods for converting to # Python functions as well as serialization # # * Don't allow classical processing of measurements # on remote backends # # op["args"].append(a.x.func_str) # else: raise ValueError( "The RegRefTransform in operation {} " "is not supported by Blackbird.".format(cmd.op)) # else: op["args"].append(a.x) bb._operations.append(op) return bb