Skip to content

Commit 0db77c6

Browse files
authored
Merge pull request #178 from nwittler/test-update
Update the two qubit test
2 parents fa99e41 + b516ab9 commit 0db77c6

File tree

4 files changed

+323
-402
lines changed

4 files changed

+323
-402
lines changed

c3/libraries/algorithms.py

-2
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,6 @@ def tf_fun():
292292
return result
293293

294294

295-
@algo_reg_deco
296295
def tf_adam(
297296
x_init: np.ndarray,
298297
fun: Callable = None,
@@ -357,7 +356,6 @@ def tf_rmsprop(
357356
raise NotImplementedError("This algorithm is not yet implemented.")
358357

359358

360-
@algo_reg_deco
361359
def tf_adadelta(
362360
x_init: np.ndarray,
363361
fun: Callable = None,

test/conftest.py

+291-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import numpy as np
22
import tensorflow as tf
3+
import copy
4+
import os
5+
import tempfile
36
from typing import Any, Dict, Iterator, Tuple
47
from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister
58
from c3.utils.tf_utils import (
@@ -9,11 +12,28 @@
912
super_to_choi,
1013
tf_project_to_comp,
1114
)
15+
from c3.experiment import Experiment
16+
from c3.model import Model
17+
from c3.libraries.chip import Qubit, Coupling, Drive
18+
from c3.signal.pulse import Envelope, Carrier
19+
from c3.libraries.envelopes import no_drive, gaussian_nonorm
20+
from c3.libraries.hamiltonians import int_XX, x_drive
1221
from c3.parametermap import ParameterMap
22+
from c3.signal.gates import Instruction
1323
from c3.generator.generator import Generator
14-
from c3.generator.devices import Crosstalk
24+
from c3.generator.devices import (
25+
AWG,
26+
Crosstalk,
27+
DigitalToAnalog,
28+
LO,
29+
Mixer,
30+
VoltsToHertz,
31+
)
1532
from c3.libraries.constants import Id, X, Y, Z
1633
from c3.c3objs import Quantity
34+
from c3.optimizers.optimalcontrol import OptimalControl
35+
from c3.libraries.fidelities import unitary_infid_set
36+
from c3.libraries.algorithms import algorithms
1737
from c3.qiskit.c3_gates import RX90pGate, CR90Gate
1838
import pytest
1939

@@ -27,7 +47,7 @@ def get_exp_problem() -> Iterator[Tuple[np.ndarray, np.ndarray]]:
2747
a = np.random.rand(1)
2848
b = np.random.rand(1)
2949
c = np.random.rand(1)
30-
norm = np.sqrt(a ** 2 + b ** 2 + c ** 2)
50+
norm = np.sqrt(a**2 + b**2 + c**2)
3151
# Normalized random coefficients
3252
a = a / norm
3353
b = b / norm
@@ -235,3 +255,272 @@ def get_test_dimensions() -> list:
235255
"""Functions in qt_utils that allow arbitrary numbers of dimensions will be tested for all dimensions in this
236256
list."""
237257
return [3, 5, 10, 50]
258+
259+
260+
@pytest.fixture()
261+
def get_two_qubit_chip() -> Experiment:
262+
"""Setup a two qubit example with pre-optimized gates."""
263+
qubit_lvls = 2
264+
freq_q1 = 5e9
265+
q1 = Qubit(
266+
name="Q1",
267+
desc="Qubit 1",
268+
freq=Quantity(value=freq_q1, min_val=4.995e9, max_val=5.005e9, unit="Hz 2pi"),
269+
hilbert_dim=qubit_lvls,
270+
)
271+
272+
freq_q2 = 5.6e9
273+
q2 = Qubit(
274+
name="Q2",
275+
desc="Qubit 2",
276+
freq=Quantity(value=freq_q2, min_val=5.595e9, max_val=5.605e9, unit="Hz 2pi"),
277+
hilbert_dim=qubit_lvls,
278+
)
279+
280+
coupling_strength = 20e6
281+
q1q2 = Coupling(
282+
name="Q1-Q2",
283+
desc="coupling",
284+
comment="Coupling qubit 1 to qubit 2",
285+
connected=["Q1", "Q2"],
286+
strength=Quantity(
287+
value=coupling_strength, min_val=-1 * 1e3, max_val=200e6, unit="Hz 2pi"
288+
),
289+
hamiltonian_func=int_XX,
290+
)
291+
292+
drive = Drive(
293+
name="d1",
294+
desc="Drive 1",
295+
comment="Drive line 1 on qubit 1",
296+
connected=["Q1"],
297+
hamiltonian_func=x_drive,
298+
)
299+
drive2 = Drive(
300+
name="d2",
301+
desc="Drive 2",
302+
comment="Drive line 2 on qubit 2",
303+
connected=["Q2"],
304+
hamiltonian_func=x_drive,
305+
)
306+
307+
model = Model(
308+
[q1, q2], # Individual, self-contained components
309+
[drive, drive2, q1q2], # Interactions between components
310+
)
311+
312+
model.set_lindbladian(False)
313+
model.set_dressed(True)
314+
315+
sim_res = 100e9 # Resolution for numerical simulation
316+
awg_res = 2e9 # Realistic, limited resolution of an AWG
317+
v2hz = 1e9
318+
319+
generator = Generator(
320+
devices={
321+
"LO": LO(name="lo", resolution=sim_res, outputs=1),
322+
"AWG": AWG(name="awg", resolution=awg_res, outputs=1),
323+
"DigitalToAnalog": DigitalToAnalog(
324+
name="dac", resolution=sim_res, inputs=1, outputs=1
325+
),
326+
"Mixer": Mixer(name="mixer", inputs=2, outputs=1),
327+
"VoltsToHertz": VoltsToHertz(
328+
name="v_to_hz",
329+
V_to_Hz=Quantity(
330+
value=v2hz, min_val=0.9e9, max_val=1.1e9, unit="Hz 2pi/V"
331+
),
332+
inputs=1,
333+
outputs=1,
334+
),
335+
},
336+
chains={
337+
"d1": {
338+
"LO": [],
339+
"AWG": [],
340+
"DigitalToAnalog": ["AWG"],
341+
"Mixer": ["LO", "DigitalToAnalog"],
342+
"VoltsToHertz": ["Mixer"],
343+
},
344+
"d2": {
345+
"LO": [],
346+
"AWG": [],
347+
"DigitalToAnalog": ["AWG"],
348+
"Mixer": ["LO", "DigitalToAnalog"],
349+
"VoltsToHertz": ["Mixer"],
350+
},
351+
},
352+
)
353+
354+
t_final = 7e-9 # Time for single qubit gates
355+
amp = 359e-3 # prev optimized
356+
sideband = 50e6
357+
shift = coupling_strength**2 / (freq_q2 - freq_q1)
358+
gauss_params_single = {
359+
"amp": Quantity(value=amp, min_val=0.1, max_val=0.6, unit="V"),
360+
"t_final": Quantity(
361+
value=t_final, min_val=0.5 * t_final, max_val=1.5 * t_final, unit="s"
362+
),
363+
"sigma": Quantity(
364+
value=t_final / 4, min_val=t_final / 8, max_val=t_final / 2, unit="s"
365+
),
366+
"xy_angle": Quantity(
367+
value=0.0, min_val=-0.5 * np.pi, max_val=2.5 * np.pi, unit="rad"
368+
),
369+
"freq_offset": Quantity(
370+
value=-sideband - shift, min_val=-56 * 1e6, max_val=-48 * 1e6, unit="Hz 2pi"
371+
),
372+
}
373+
374+
gauss_env_single = Envelope(
375+
name="gauss",
376+
desc="Gaussian comp for single-qubit gates",
377+
params=gauss_params_single,
378+
shape=gaussian_nonorm,
379+
)
380+
381+
nodrive_env = Envelope(
382+
name="no_drive",
383+
params={
384+
"t_final": Quantity(
385+
value=t_final, min_val=0.5 * t_final, max_val=1.5 * t_final, unit="s"
386+
)
387+
},
388+
shape=no_drive,
389+
)
390+
391+
lo_freq_q1 = 5e9 + sideband
392+
carrier_parameters = {
393+
"freq": Quantity(value=lo_freq_q1, min_val=4.5e9, max_val=6e9, unit="Hz 2pi"),
394+
"framechange": Quantity(
395+
value=0.0, min_val=-np.pi, max_val=3 * np.pi, unit="rad"
396+
),
397+
}
398+
399+
carr = Carrier(
400+
name="carrier",
401+
desc="Frequency of the local oscillator",
402+
params=carrier_parameters,
403+
)
404+
405+
lo_freq_q2 = 5.6e9 + sideband
406+
carr_2 = copy.deepcopy(carr)
407+
carr_2.params["freq"].set_value(lo_freq_q2)
408+
409+
rx90p_q1 = Instruction(
410+
name="rx90p",
411+
targets=[0],
412+
t_start=0.0,
413+
t_end=t_final,
414+
channels=["d1", "d2"],
415+
params={"use_t_before": True},
416+
)
417+
rx90p_q2 = Instruction(
418+
name="rx90p",
419+
targets=[1],
420+
t_start=0.0,
421+
t_end=t_final,
422+
channels=["d1", "d2"],
423+
params={"use_t_before": True},
424+
)
425+
QId_q1 = Instruction(
426+
name="id",
427+
targets=[0],
428+
t_start=0.0,
429+
t_end=t_final,
430+
channels=["d1", "d2"],
431+
params={"use_t_before": True},
432+
)
433+
QId_q2 = Instruction(
434+
name="id",
435+
targets=[1],
436+
t_start=0.0,
437+
t_end=t_final,
438+
channels=["d1", "d2"],
439+
params={"use_t_before": True},
440+
)
441+
442+
rx90p_q1.add_component(gauss_env_single, "d1")
443+
rx90p_q1.add_component(carr, "d1")
444+
rx90p_q1.add_component(nodrive_env, "d2")
445+
rx90p_q1.add_component(copy.deepcopy(carr_2), "d2")
446+
rx90p_q1.comps["d2"]["carrier"].params["framechange"].set_value(
447+
(-sideband * t_final) * 2 * np.pi % (2 * np.pi)
448+
)
449+
450+
rx90p_q2.add_component(copy.deepcopy(gauss_env_single), "d2")
451+
rx90p_q2.add_component(carr_2, "d2")
452+
rx90p_q2.add_component(nodrive_env, "d1")
453+
rx90p_q2.add_component(copy.deepcopy(carr), "d1")
454+
rx90p_q2.comps["d1"]["carrier"].params["framechange"].set_value(
455+
(-sideband * t_final) * 2 * np.pi % (2 * np.pi)
456+
)
457+
458+
QId_q1.add_component(nodrive_env, "d1")
459+
QId_q1.add_component(copy.deepcopy(carr), "d1")
460+
QId_q1.add_component(nodrive_env, "d2")
461+
QId_q1.add_component(copy.deepcopy(carr_2), "d2")
462+
QId_q2.add_component(copy.deepcopy(nodrive_env), "d2")
463+
QId_q2.add_component(copy.deepcopy(carr_2), "d2")
464+
QId_q2.add_component(nodrive_env, "d1")
465+
QId_q2.add_component(copy.deepcopy(carr), "d1")
466+
467+
Y90p_q1 = copy.deepcopy(rx90p_q1)
468+
Y90p_q1.name = "ry90p"
469+
X90m_q1 = copy.deepcopy(rx90p_q1)
470+
X90m_q1.name = "rx90m"
471+
Y90m_q1 = copy.deepcopy(rx90p_q1)
472+
Y90m_q1.name = "ry90m"
473+
Y90p_q1.comps["d1"]["gauss"].params["xy_angle"].set_value(0.5 * np.pi)
474+
X90m_q1.comps["d1"]["gauss"].params["xy_angle"].set_value(np.pi)
475+
Y90m_q1.comps["d1"]["gauss"].params["xy_angle"].set_value(1.5 * np.pi)
476+
single_q_gates = [QId_q1, rx90p_q1, Y90p_q1, X90m_q1, Y90m_q1]
477+
478+
Y90p_q2 = copy.deepcopy(rx90p_q2)
479+
Y90p_q2.name = "ry90p"
480+
X90m_q2 = copy.deepcopy(rx90p_q2)
481+
X90m_q2.name = "rx90m"
482+
Y90m_q2 = copy.deepcopy(rx90p_q2)
483+
Y90m_q2.name = "ry90m"
484+
Y90p_q2.comps["d2"]["gauss"].params["xy_angle"].set_value(0.5 * np.pi)
485+
X90m_q2.comps["d2"]["gauss"].params["xy_angle"].set_value(np.pi)
486+
Y90m_q2.comps["d2"]["gauss"].params["xy_angle"].set_value(1.5 * np.pi)
487+
single_q_gates.extend([QId_q2, rx90p_q2, Y90p_q2, X90m_q2, Y90m_q2])
488+
489+
pmap = ParameterMap(single_q_gates, generator, model)
490+
491+
pmap.set_opt_map(
492+
[
493+
[["rx90p[0]", "d1", "gauss", "amp"]],
494+
[["rx90p[0]", "d1", "gauss", "freq_offset"]],
495+
[["rx90p[0]", "d1", "gauss", "xy_angle"]],
496+
]
497+
)
498+
return Experiment(pmap)
499+
500+
501+
@pytest.fixture(
502+
params=[
503+
"single_eval",
504+
"tf_sgd",
505+
"lbfgs",
506+
"lbfgs_grad_free",
507+
"cmaes",
508+
"cma_pre_lbfgs",
509+
]
510+
)
511+
def get_OC_optimizer(request, get_two_qubit_chip) -> OptimalControl:
512+
"""Create a general optimizer object with each algorithm with a decorator in the lib."""
513+
exp = get_two_qubit_chip
514+
exp.set_opt_gates(["rx90p[0]"])
515+
logdir = os.path.join(tempfile.TemporaryDirectory().name, "c3logs")
516+
opt = OptimalControl(
517+
dir_path=logdir,
518+
fid_func=unitary_infid_set,
519+
pmap=exp.pmap,
520+
fid_subspace=["Q1", "Q2"],
521+
algorithm=algorithms[request.param],
522+
options={"maxiters": 2} if request.param == "tf_sgd" else {"maxiter": 2},
523+
run_name=f"better_X90_{request.param}",
524+
)
525+
opt.set_exp(exp)
526+
return opt

0 commit comments

Comments
 (0)