Skip to content

Commit 0effe70

Browse files
committed
change platonic udd sequence generator to if-else chain + use numpy to generate
1 parent a165dc8 commit 0effe70

1 file changed

Lines changed: 46 additions & 61 deletions

File tree

qctrlopencontrols/dynamic_decoupling_sequences/predefined.py

Lines changed: 46 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1318,69 +1318,54 @@ def new_platonic_sequence(
13181318
{"sequence": sequence},
13191319
)
13201320

1321-
# The sequences outlined in the cited paper, each sequence is constructed
1322-
# from an Eulerian path on the Cayley graph associated with the relevant
1323-
# point group. Each sequence is constructed of 2 generating operations, in
1324-
# the order specified here.
1325-
# fmt: off
1326-
eulerian_paths = {
1327-
"Dihedral": [0, 1, 0, 1, 1, 0, 1, 0],
1328-
"Tetrahedral": [ 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0],
1329-
"Octahedral": [ 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1 ],
1330-
"Icosahedral": [ 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0 ]
1331-
}
1332-
# fmt: on
1333-
1334-
# The generators assocaited with each point group.
1335-
phi = (np.sqrt(5) + 1) / 2 # golden ratio
1336-
generators = {
1337-
"Dihedral": [
1338-
{"Rabi": np.pi, "Azimuthal": 0, "Detuning": 0}, # rabi, azimuthal, detuning
1339-
{"Rabi": np.pi, "Azimuthal": np.pi / 2, "Detuning": 0},
1340-
],
1341-
"Tetrahedral": [
1342-
{"Rabi": 0, "Azimuthal": 0, "Detuning": 2 * np.pi / 3},
1343-
{
1344-
"Rabi": 4 * np.sqrt(2) * np.pi / 9,
1345-
"Azimuthal": np.pi / 3,
1346-
"Detuning": 2 * np.pi / 9,
1347-
},
1348-
],
1349-
"Octahedral": [
1350-
{"Rabi": 0, "Azimuthal": 0, "Detuning": np.pi / 2},
1351-
{
1352-
"Rabi": 2 * np.sqrt(2 / 3) * np.pi / 3,
1353-
"Azimuthal": np.pi / 4,
1354-
"Detuning": 2 * np.pi / 3 / np.sqrt(3),
1355-
},
1356-
],
1357-
"Icosahedral": [
1358-
{
1359-
"Rabi": 2 * np.pi / 5 / np.sqrt(phi + 2),
1360-
"Azimuthal": 3 * np.pi / 2,
1361-
"Detuning": 2 * np.pi * phi / 5 / np.sqrt(phi + 2),
1362-
},
1363-
{
1364-
"Rabi": 2 * np.pi * (phi - 1) / 3 / np.sqrt(3),
1365-
"Azimuthal": np.pi,
1366-
"Detuning": 2 * np.pi * phi / 3 / np.sqrt(3),
1367-
},
1368-
],
1369-
}
1321+
rabi_rotations, azimuthal_angles, detuning_rotations = None, None, None
1322+
1323+
if sequence == "Dihedral":
1324+
eulerian_path = np.array([0, 1, 0, 1, 1, 0, 1, 0])
1325+
1326+
rabi_rotations = np.ones(eulerian_path.shape[0]) * np.pi
1327+
azimuthal_angles = eulerian_path * np.pi / 2
1328+
detuning_rotations = np.zeros(eulerian_path.shape[0])
1329+
elif sequence == "Tetrahedral":
1330+
eulerian_path = np.array(
1331+
[0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0]
1332+
)
1333+
1334+
rabi_rotations = eulerian_path * 4 * np.sqrt(2) * np.pi / 9
1335+
azimuthal_angles = eulerian_path * np.pi / 3
1336+
detuning_rotations = (
1337+
1 ^ eulerian_path
1338+
) * 2 * np.pi / 3 + eulerian_path * 2 * np.pi / 9
1339+
elif sequence == "Octahedral":
1340+
# fmt:off
1341+
eulerian_path = np.array(
1342+
[ 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1 ]
1343+
)
1344+
# fmt:on
1345+
1346+
rabi_rotations = eulerian_path * 2 * np.sqrt(2 / 3) * np.pi / 3
1347+
azimuthal_angles = eulerian_path * np.pi / 4
1348+
detuning_rotations = (
1349+
1 ^ eulerian_path
1350+
) * np.pi / 2 + eulerian_path * 2 * np.pi / 3 / np.sqrt(3)
1351+
else:
1352+
# fmt:off
1353+
eulerian_path = np.array(
1354+
[ 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0 ]
1355+
)
1356+
# fmt:on
1357+
1358+
phi = (np.sqrt(5) + 1) / 2 # golden ratio
1359+
rabi_rotations = (1 ^ eulerian_path) * 2 * np.pi / 5 / np.sqrt(
1360+
phi + 2
1361+
) + eulerian_path * 2 * np.pi * (phi - 1) / 3 / np.sqrt(3)
1362+
azimuthal_angles = (1 ^ eulerian_path) * 3 * np.pi / 2 + eulerian_path * np.pi
1363+
detuning_rotations = (1 ^ eulerian_path) * 2 * np.pi * phi / 5 / np.sqrt(
1364+
phi + 2
1365+
) + eulerian_path * 2 * np.pi * phi / 3 / np.sqrt(3)
13701366

13711367
# Re-use the CPMG offset function to obtain equally spaced pulses along a certain duration.
1372-
offsets = _carr_purcell_meiboom_gill_offsets(
1373-
duration, len(eulerian_paths[sequence])
1374-
)
1375-
rabi_rotations = np.array(
1376-
[generators[sequence][idx]["Rabi"] for idx in eulerian_paths[sequence]]
1377-
)
1378-
azimuthal_angles = np.array(
1379-
[generators[sequence][idx]["Azimuthal"] for idx in eulerian_paths[sequence]]
1380-
)
1381-
detuning_rotations = np.array(
1382-
[generators[sequence][idx]["Detuning"] for idx in eulerian_paths[sequence]]
1383-
)
1368+
offsets = _carr_purcell_meiboom_gill_offsets(duration, rabi_rotations.shape[0])
13841369

13851370
if pre_post_rotation:
13861371
# Use a pi/2 followed by a -pi/2 X rotation as all the sequences

0 commit comments

Comments
 (0)