def read_config(self, filepath: str) -> None: """ Load a file and parse it to create a ParameterMap object. Parameters ---------- filepath : str Location of the configuration file """ with open(filepath, "r") as cfg_file: cfg = hjson.loads(cfg_file.read()) for key, gate in cfg.items(): if "mapto" in gate.keys(): instr = copy.deepcopy(self.instructions[gate["mapto"]]) instr.name = key for drive_chan, comps in gate["drive_channels"].items(): for comp, props in comps.items(): for par, val in props["params"].items(): instr.comps[drive_chan][comp].params[par].set_value(val) else: instr = Instruction( name=key, t_start=0.0, t_end=gate["gate_length"], channels=list(gate["drive_channels"].keys()), ) for drive_chan, comps in gate["drive_channels"].items(): for comp, props in comps.items(): ctype = props.pop("c3type") instr.add_component( comp_lib[ctype](name=comp, **props), chan=drive_chan ) self.instructions[key] = instr self.__initialize_parameters()
def fromdict(self, cfg: dict) -> None: for key, gate in cfg.items(): if "mapto" in gate.keys(): instr = copy.deepcopy(self.instructions[gate["mapto"]]) instr.name = key for drive_chan, comps in gate["drive_channels"].items(): for comp, props in comps.items(): for par, val in props["params"].items(): instr.comps[drive_chan][comp].params[ par].set_value(val) else: instr = Instruction( name=key, t_start=0.0, t_end=gate["gate_length"], channels=list(gate["drive_channels"].keys()), ) for drive_chan, comps in gate["drive_channels"].items(): for comp, props in comps.items(): ctype = props.pop("c3type") instr.add_component(comp_lib[ctype](name=comp, **props), chan=drive_chan) self.instructions[key] = instr self.__initialize_parameters()
def test_set_unitary() -> None: propagators = {"rxp": X, "ryp": Y} instructions = {"rxp": Instruction("rxp"), "ryp": Instruction("ryp")} goal = unitary_infid_set( propagators=propagators, instructions=instructions, index=[0], dims=[2], n_eval=136, ) almost_equal(goal, 0)
def test_set_states() -> None: propagators = {"rxp": X, "ryp": Y} instructions = {"rxp": Instruction("rxp"), "ryp": Instruction("ryp")} psi_0 = np.array([[1], [0]]) goal = state_transfer_infid_set( propagators=propagators, instructions=instructions, index=[0], dims=[2], psi_0=psi_0, n_eval=136, ) almost_equal(goal, 0)
def test_crosstalk() -> None: generator = Generator( devices={ "LO": lo, "AWG": awg, "DigitalToAnalog": dac, "Response": resp, "Mixer": mixer, "VoltsToHertz": v_to_hz, "crosstalk": xtalk, }, chains={ "d1": ["LO", "AWG", "DigitalToAnalog", "Response", "Mixer", "VoltsToHertz"], "d2": ["LO", "AWG", "DigitalToAnalog", "Response", "Mixer", "VoltsToHertz"], }, ) RX90p_q1 = Instruction( name="RX90p", t_start=0.0, t_end=t_final, channels=["d1", "d2"] ) RX90p_q1.add_component(gauss_env_single, "d1") RX90p_q1.add_component(carr, "d1") gauss_params_single_2 = { "amp": Quantity(value=0, min_val=-0.4, max_val=0.6, unit="V"), "t_final": Quantity( value=t_final, min_val=0.5 * t_final, max_val=1.5 * t_final, unit="s" ), "sigma": Quantity( value=t_final / 4, min_val=t_final / 8, max_val=t_final / 2, unit="s" ), "xy_angle": Quantity( value=0.0, min_val=-0.5 * np.pi, max_val=2.5 * np.pi, unit="rad" ), "freq_offset": Quantity( value=-sideband - 3e6, min_val=-56 * 1e6, max_val=-52 * 1e6, unit="Hz 2pi" ), "delta": Quantity(value=-1, min_val=-5, max_val=3, unit=""), } gauss_env_single_2 = Envelope( name="gauss", desc="Gaussian comp for single-qubit gates", params=gauss_params_single_2, shape=env_lib.gaussian_nonorm, ) RX90p_q1.add_component(gauss_env_single_2, "d2") RX90p_q1.add_component(carr, "d2") full_signal = generator.generate_signals(RX90p_q1) assert ( full_signal["d1"]["values"].numpy() == full_signal["d2"]["values"].numpy() ).all()
def fromdict(self, cfg: dict) -> None: for key, gate in cfg.items(): if "mapto" in gate.keys(): instr = copy.deepcopy(self.instructions[gate["mapto"]]) instr.name = key for drive_chan, comps in gate["drive_channels"].items(): for comp, props in comps.items(): for par, val in props["params"].items(): instr.comps[drive_chan][comp].params[ par].set_value(val) else: # TODO: initialize directly by using the constructor. instr = Instruction(ideal=[[1]]) # Set ideal to mute warning instr.from_dict(gate, name=key) self.instructions[key] = instr self.__initialize_parameters()
def test_signal_generation() -> None: t_final = 7e-9 # Time for single qubit gates sideband = 50e6 * 2 * np.pi gauss_params_single = { 'amp': Quantity(value=0.5, min_val=0.4, max_val=0.6, unit="V"), 't_final': Quantity(value=t_final, min_val=0.5 * t_final, max_val=1.5 * t_final, unit="s"), 'sigma': Quantity(value=t_final / 4, min_val=t_final / 8, max_val=t_final / 2, unit="s"), 'xy_angle': Quantity(value=0.0, min_val=-0.5 * np.pi, max_val=2.5 * np.pi, unit='rad'), 'freq_offset': Quantity(value=-sideband - 3e6 * 2 * np.pi, min_val=-56 * 1e6 * 2 * np.pi, max_val=-52 * 1e6 * 2 * np.pi, unit='Hz 2pi'), 'delta': Quantity(value=-1, min_val=-5, max_val=3, unit="") } gauss_env_single = Envelope(name="gauss", desc="Gaussian comp for single-qubit gates", params=gauss_params_single, shape=envelopes['gaussian_nonorm']) carrier_parameters = { 'freq': Quantity(value=5e9 * 2 * np.pi, min_val=4.5e9 * 2 * np.pi, max_val=6e9 * 2 * np.pi, unit='Hz 2pi'), 'framechange': Quantity(value=0.0, min_val=-np.pi, max_val=3 * np.pi, unit='rad') } carr = Carrier(name="carrier", desc="Frequency of the local oscillator", params=carrier_parameters) X90p_q1 = Instruction(name="X90p", t_start=0.0, t_end=t_final, channels=["d1"]) X90p_q1.add_component(gauss_env_single, "d1") X90p_q1.add_component(carr, "d1") gen.generate_signals(X90p_q1)
def test_signal_generation() -> None: t_final = 7e-9 # Time for single qubit gates sideband = 50e6 * 2 * np.pi gauss_params_single = { "amp": Quantity(value=0.5, min_val=0.4, max_val=0.6, unit="V"), "t_final": Quantity( value=t_final, min_val=0.5 * t_final, max_val=1.5 * t_final, unit="s" ), "sigma": Quantity( value=t_final / 4, min_val=t_final / 8, max_val=t_final / 2, unit="s" ), "xy_angle": Quantity( value=0.0, min_val=-0.5 * np.pi, max_val=2.5 * np.pi, unit="rad" ), "freq_offset": Quantity( value=-sideband - 3e6 * 2 * np.pi, min_val=-56 * 1e6 * 2 * np.pi, max_val=-52 * 1e6 * 2 * np.pi, unit="Hz 2pi", ), "delta": Quantity(value=-1, min_val=-5, max_val=3, unit=""), } gauss_env_single = Envelope( name="gauss", desc="Gaussian comp for single-qubit gates", params=gauss_params_single, shape=envelopes["gaussian_nonorm"], ) carrier_parameters = { "freq": Quantity( value=5e9 * 2 * np.pi, min_val=4.5e9 * 2 * np.pi, max_val=6e9 * 2 * np.pi, unit="Hz 2pi", ), "framechange": Quantity( value=0.0, min_val=-np.pi, max_val=3 * np.pi, unit="rad" ), } carr = Carrier( name="carrier", desc="Frequency of the local oscillator", params=carrier_parameters, ) rx90p_q1 = Instruction(name="rx90p", t_start=0.0, t_end=t_final, channels=["d1"]) rx90p_q1.add_component(gauss_env_single, "d1") rx90p_q1.add_component(carr, "d1") gen.generate_signals(rx90p_q1)
def create_IQ(self, instr: Instruction, chan: str) -> dict: """ Construct the in-phase (I) and quadrature (Q) components of the signal. These are universal to either experiment or simulation. In the xperiment these will be routed to AWG and mixer electronics, while in the simulation they provide the shapes of the instruction fields to be added to the Hamiltonian. Parameters ---------- channel : str Identifier for the selected drive line. components : dict Separate signals to be combined onto this drive line. t_start : float Beginning of the signal. t_end : float End of the signal. Returns ------- dict Waveforms as I and Q components. """ ts = self.create_ts(instr.t_start, instr.t_end, centered=True) self.ts = ts signal, norm = instr.get_awg_signal(chan, ts, options={self.__options: True}) self.amp_tot = norm self.signal[chan] = { "inphase": signal["inphase"], "quadrature": signal["quadrature"], "ts": ts, } return self.signal[chan]
desc="Gaussian comp for single-qubit gates", params=gauss_params_single, shape=env_lib.gaussian_nonorm, ) lo_freq_q1 = 5e9 + sideband carrier_parameters = { "freq": Quantity(value=lo_freq_q1, min_val=4.5e9, max_val=6e9, unit="Hz 2pi"), "framechange": Quantity(value=0.0, min_val=-np.pi, max_val=3 * np.pi, unit="rad"), } carr = Carrier( name="carrier", desc="Frequency of the local oscillator", params=carrier_parameters ) RX90p_q1 = Instruction(name="RX90p", t_start=0.0, t_end=t_final, channels=["d1"]) RX90p_q1.add_component(gauss_env_single, "d1") RX90p_q1.add_component(carr, "d1") tstart = RX90p_q1.t_start tend = RX90p_q1.t_end chan = "d1" with open("test/generator_data.pickle", "rb") as filename: data = pickle.load(filename) @pytest.mark.unit def test_LO() -> None: lo_sig = lo.process(RX90p_q1, "d1") assert (
def quick_setup(self, filepath: str) -> None: """ Load a quick setup file and create all necessary components. Parameters ---------- filepath : str Location of the configuration file """ with open(filepath, "r") as cfg_file: cfg = hjson.loads(cfg_file.read()) model = Model() model.read_config(cfg["model"]) gen = Generator() gen.read_config(cfg["generator"]) single_gate_time = cfg["single_qubit_gate_time"] v2hz = cfg["v2hz"] instructions = [] sideband = cfg.pop("sideband", None) for gate_name, props in cfg["single_qubit_gates"].items(): target_qubit = model.subsystems[props["target_qubit"]] instr = Instruction( name=gate_name, t_start=0.0, t_end=single_gate_time, channels=[target_qubit.drive_line], ) instr.quick_setup( target_qubit.drive_line, target_qubit.params["freq"].get_value() / 2 / np.pi, single_gate_time, v2hz, sideband, ) instructions.append(instr) for gate_name, props in cfg["two_qubit_gates"].items(): qubit_1 = model.subsystems[props["qubit_1"]] qubit_2 = model.subsystems[props["qubit_2"]] instr = Instruction( name=gate_name, t_start=0.0, t_end=props["gate_time"], channels=[qubit_1.drive_line, qubit_2.drive_line], ) instr.quick_setup( qubit_1.drive_line, qubit_1.params["freq"].get_value() / 2 / np.pi, props["gate_time"], v2hz, sideband, ) instr.quick_setup( qubit_2.drive_line, qubit_2.params["freq"].get_value() / 2 / np.pi, props["gate_time"], v2hz, sideband, ) instructions.append(instr) self.pmap = ParameterMap(instructions, generator=gen, model=model)
def setup_pmap() -> ParameterMap: t_final = 7e-9 # Time for single qubit gates sideband = 50e6 lo_freq = 5e9 + sideband # ### MAKE GATESET gauss_params_single = { 'amp': Quantity(value=0.45, min_val=0.4, max_val=0.6, unit="V"), 't_final': Quantity(value=t_final, min_val=0.5 * t_final, max_val=1.5 * t_final, unit="s"), 'sigma': Quantity(value=t_final / 4, min_val=t_final / 8, max_val=t_final / 2, unit="s"), 'xy_angle': Quantity(value=0.0, min_val=-0.5 * np.pi, max_val=2.5 * np.pi, unit='rad'), 'freq_offset': Quantity(value=-sideband - 0.5e6, min_val=-53 * 1e6, max_val=-47 * 1e6, unit='Hz 2pi'), 'delta': Quantity(value=-1, min_val=-5, max_val=3, unit="") } gauss_env_single = Envelope(name="gauss", desc="Gaussian comp for single-qubit gates", params=gauss_params_single, shape=envelopes.gaussian_nonorm) nodrive_env = Envelope(name="no_drive", params={ 't_final': Quantity(value=t_final, min_val=0.5 * t_final, max_val=1.5 * t_final, unit="s") }, shape=envelopes.no_drive) carrier_parameters = { 'freq': Quantity(value=lo_freq, min_val=4.5e9, max_val=6e9, unit='Hz 2pi'), 'framechange': Quantity(value=0.0, min_val=-np.pi, max_val=3 * np.pi, unit='rad') } carr = Carrier(name="carrier", desc="Frequency of the local oscillator", params=carrier_parameters) X90p = Instruction(name="X90p", t_start=0.0, t_end=t_final, channels=["d1"]) QId = Instruction(name="Id", t_start=0.0, t_end=t_final, channels=["d1"]) X90p.add_component(gauss_env_single, "d1") X90p.add_component(carr, "d1") QId.add_component(nodrive_env, "d1") QId.add_component(copy.deepcopy(carr), "d1") QId.comps['d1']['carrier'].params['framechange'].set_value( (-sideband * t_final) % (2 * np.pi)) Y90p = copy.deepcopy(X90p) Y90p.name = "Y90p" X90m = copy.deepcopy(X90p) X90m.name = "X90m" Y90m = copy.deepcopy(X90p) Y90m.name = "Y90m" Y90p.comps['d1']['gauss'].params['xy_angle'].set_value(0.5 * np.pi) X90m.comps['d1']['gauss'].params['xy_angle'].set_value(np.pi) Y90m.comps['d1']['gauss'].params['xy_angle'].set_value(1.5 * np.pi) parameter_map = ParameterMap(instructions=[QId, X90p, Y90p, X90m, Y90m]) gateset_opt_map = [[("X90p", "d1", "gauss", "amp"), ("Y90p", "d1", "gauss", "amp"), ("X90m", "d1", "gauss", "amp"), ("Y90m", "d1", "gauss", "amp")], [("X90p", "d1", "gauss", "delta"), ("Y90p", "d1", "gauss", "delta"), ("X90m", "d1", "gauss", "delta"), ("Y90m", "d1", "gauss", "delta")], [("X90p", "d1", "gauss", "freq_offset"), ("Y90p", "d1", "gauss", "freq_offset"), ("X90m", "d1", "gauss", "freq_offset"), ("Y90m", "d1", "gauss", "freq_offset")], [("Id", "d1", "carrier", "framechange")]] parameter_map.set_opt_map(gateset_opt_map) return parameter_map
def quick_setup(self, cfg) -> None: """ Load a quick setup cfg and create all necessary components. Parameters ---------- cfg : Dict Configuration options """ model = Model() model.read_config(cfg["model"]) gen = Generator() gen.read_config(cfg["generator"]) single_gate_time = cfg["single_qubit_gate_time"] v2hz = cfg["v2hz"] instructions = [] sideband = cfg.pop("sideband", None) for gate_name, props in cfg["single_qubit_gates"].items(): target_qubit = model.subsystems[props["qubits"]] instr = Instruction( name=props["name"], targets=[model.names.index(props["qubits"])], t_start=0.0, t_end=single_gate_time, channels=[target_qubit.drive_line], ) instr.quick_setup( target_qubit.drive_line, target_qubit.params["freq"].get_value() / 2 / np.pi, single_gate_time, v2hz, sideband, ) instructions.append(instr) for gate_name, props in cfg["two_qubit_gates"].items(): qubit_1 = model.subsystems[props["qubit_1"]] qubit_2 = model.subsystems[props["qubit_2"]] instr = Instruction( name=gate_name, targets=[ model.names.index(props["qubit_1"]), model.names.index(props["qubit_2"]), ], t_start=0.0, t_end=props["gate_time"], channels=[qubit_1.drive_line, qubit_2.drive_line], ) instr.quick_setup( qubit_1.drive_line, qubit_1.params["freq"].get_value() / 2 / np.pi, props["gate_time"], v2hz, sideband, ) instr.quick_setup( qubit_2.drive_line, qubit_2.params["freq"].get_value() / 2 / np.pi, props["gate_time"], v2hz, sideband, ) instructions.append(instr) self.pmap = ParameterMap(instructions, generator=gen, model=model)
unit="s"), "freq_offset": Qty(value=0, min_val=-50 * 1e6, max_val=50 * 1e6, unit="Hz 2pi"), "xy_angle": Qty(value=0, min_val=-0.5 * np.pi, max_val=2.5 * np.pi, unit="rad"), } flux_env = Envelope( name="flux", desc="Flux bias for tunable coupler", params=flux_params, shape=envelopes["flattop_cut"], ) instr1 = Instruction( name="instr1", t_start=0.0, t_end=cphase_time, channels=["Qubit1"], ) instr2 = Instruction( name="instr2", t_start=0.0, t_end=cphase_time, channels=["Qubit2"], ) instr1.add_component(copy.deepcopy(flux_env), "Qubit1") instr1.add_component(copy.deepcopy(carr_q1), "Qubit1") instr2.add_component(flux_env, "Qubit2") instr2.add_component(carr_q1, "Qubit2")
def test_save_and_load(): global instr, pmap instr = Instruction() instr.from_dict(hjson.loads(instr_dict_str, object_pairs_hook=hjson_decode)) pmap = ParameterMap(model=model, generator=generator, instructions=[instr]) test_extended_pulse()
def setup_pmap() -> ParameterMap: t_final = 7e-9 # Time for single qubit gates sideband = 50e6 lo_freq = 5e9 + sideband # ### MAKE GATESET gauss_params_single = { "amp": Quantity(value=0.45, min_val=0.4, max_val=0.6, unit="V"), "t_final": Quantity(value=t_final, min_val=0.5 * t_final, max_val=1.5 * t_final, unit="s"), "sigma": Quantity(value=t_final / 4, min_val=t_final / 8, max_val=t_final / 2, unit="s"), "xy_angle": Quantity(value=0.0, min_val=-0.5 * np.pi, max_val=2.5 * np.pi, unit="rad"), "freq_offset": Quantity(value=-sideband - 0.5e6, min_val=-53 * 1e6, max_val=-47 * 1e6, unit="Hz 2pi"), "delta": Quantity(value=-1, min_val=-5, max_val=3, unit=""), } gauss_env_single = Envelope( name="gauss", desc="Gaussian comp for single-qubit gates", params=gauss_params_single, shape=envelopes.gaussian_nonorm, ) nodrive_env = Envelope( name="no_drive", params={ "t_final": Quantity(value=t_final, min_val=0.5 * t_final, max_val=1.5 * t_final, unit="s") }, shape=envelopes.no_drive, ) carrier_parameters = { "freq": Quantity(value=lo_freq, min_val=4.5e9, max_val=6e9, unit="Hz 2pi"), "framechange": Quantity(value=0.0, min_val=-np.pi, max_val=3 * np.pi, unit="rad"), } carr = Carrier( name="carrier", desc="Frequency of the local oscillator", params=carrier_parameters, ) RX90p = Instruction(name="RX90p", t_start=0.0, t_end=t_final, channels=["d1"]) QId = Instruction(name="Id", t_start=0.0, t_end=t_final, channels=["d1"]) RX90p.add_component(gauss_env_single, "d1") RX90p.add_component(carr, "d1") QId.add_component(nodrive_env, "d1") QId.add_component(copy.deepcopy(carr), "d1") QId.comps["d1"]["carrier"].params["framechange"].set_value( (-sideband * t_final) % (2 * np.pi)) RY90p = copy.deepcopy(RX90p) RY90p.name = "RY90p" RX90m = copy.deepcopy(RX90p) RX90m.name = "RX90m" RY90m = copy.deepcopy(RX90p) RY90m.name = "RY90m" RY90p.comps["d1"]["gauss"].params["xy_angle"].set_value(0.5 * np.pi) RX90m.comps["d1"]["gauss"].params["xy_angle"].set_value(np.pi) RY90m.comps["d1"]["gauss"].params["xy_angle"].set_value(1.5 * np.pi) parameter_map = ParameterMap( instructions=[QId, RX90p, RY90p, RX90m, RY90m]) gateset_opt_map = [ [ ("RX90p", "d1", "gauss", "amp"), ("RY90p", "d1", "gauss", "amp"), ("RX90m", "d1", "gauss", "amp"), ("RY90m", "d1", "gauss", "amp"), ], [ ("RX90p", "d1", "gauss", "delta"), ("RY90p", "d1", "gauss", "delta"), ("RX90m", "d1", "gauss", "delta"), ("RY90m", "d1", "gauss", "delta"), ], [ ("RX90p", "d1", "gauss", "freq_offset"), ("RY90p", "d1", "gauss", "freq_offset"), ("RX90m", "d1", "gauss", "freq_offset"), ("RY90m", "d1", "gauss", "freq_offset"), ], [("Id", "d1", "carrier", "framechange")], ] parameter_map.set_opt_map(gateset_opt_map) return parameter_map
params={"t_final": Qty(t_final, "s")}, shape=envelopes.rect, ) carrier_parameters = { "freq": Qty(value=lo_freq_q1, min_val=1.5e9, max_val=6e9, unit="Hz 2pi"), "framechange": Qty(value=0.0, min_val=-np.pi, max_val=3 * np.pi, unit="rad"), } carr = Carrier(name="carrier", desc="Frequency of the local oscillator", params=carrier_parameters) rectangle = Instruction(name="Rectangle", t_start=0.0, t_end=t_final, channels=["d1"]) rectangle.add_component(rect, "d1") rectangle.add_component(carr, "d1") @pytest.mark.unit def test_AWG_phase_shift() -> None: phase = 0.5 rect.params["freq_offset"] = Qty(0, "Hz 2pi") rect.params["xy_angle"] = Qty(phase, "pi") sigs = generator.generate_signals(rectangle) correct_signal = np.cos(2 * np.pi * lo_freq_q1 * sigs["d1"]["ts"] + phase * np.pi) print(sigs["d1"]["values"])