Skip to content

Commit 85754b7

Browse files
committed
Revert "simplify gaugeopt in the non-LS case"
This reverts commit 6e9ccb1.
1 parent 6ced5a3 commit 85754b7

File tree

1 file changed

+51
-40
lines changed

1 file changed

+51
-40
lines changed

pygsti/algorithms/gaugeopt.py

Lines changed: 51 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -587,24 +587,45 @@ def _mock_objective_fn(v):
587587
else:
588588
# non-least-squares case where objective function returns a single float
589589
# and (currently) there's no analytic jacobian
590+
dim = int(_np.sqrt(mxBasis.dim))
591+
if n_leak > 0:
592+
B = _tools.leading_dxd_submatrix_basis_vectors(dim - n_leak, dim, mxBasis)
593+
"""
594+
^ Need to do something else.
595+
596+
In a leakage-friendly basis the operation matrices can be partitioned as
597+
[comp , semileak1]
598+
[semileak2, fulleak ].
599+
Instead of projecting only on to comp, we want to keep everything
600+
except fullleak. ... But I don't think we can implement that just by
601+
pre-multiplying by a projector.
602+
603+
I think this distinction might not be significant under certain idealized
604+
assumptions, but small deviations from those conditions (which are certain
605+
to happen in practice) might make it matter.
606+
"""
607+
P = B @ B.T.conj()
608+
if _np.linalg.norm(P.imag) > 1e-12:
609+
raise ValueError()
610+
else:
611+
P = P.real
612+
transform_mx_arg = (P, None)
613+
# ^ The semantics of this tuple are defined by the frobeniusdist function
614+
# in the ExplicitOpModelCalc class. There are intended semantics for
615+
# the second element of the tuple, but those aren't implemented yet so
616+
# for now I'm setting the second entry to None. -- Riley
617+
else:
618+
transform_mx_arg = (_np.eye(mxBasis.dim), None)
590619

591-
assert target_model is not None
592620
assert gates_metric != "frobeniustt"
593621
assert spam_metric != "frobeniustt"
622+
assert spam_metric == gates_metric
623+
metric = spam_metric
624+
# assert spam_metric == gates_metric
594625
# ^ Erik and Corey said these are rarely used. I've removed support for
595626
# them in this codepath (non-LS optimizer) in order to make it easier to
596627
# read my updated code for leakage-aware metrics. It wouldn't be hard to
597628
# add support back, but I just want to keep things simple. -- Riley
598-
assert spam_metric == gates_metric
599-
metric = spam_metric
600-
601-
dim = int(_np.sqrt(mxBasis.dim))
602-
B = _tools.leading_dxd_submatrix_basis_vectors(dim - n_leak, dim, mxBasis)
603-
P = B @ B.T.conj()
604-
assert _np.linalg.norm(P.imag) <= 1e-12
605-
P = P.real
606-
607-
log = []
608629

609630
def _objective_fn(gauge_group_el, oob_check):
610631
mdl = _transform_with_oob_check(model, gauge_group_el, oob_check)
@@ -620,35 +641,25 @@ def _objective_fn(gauge_group_el, oob_check):
620641
spamPenaltyVec = _spam_penalty(mdl, spam_penalty_factor, mdl.basis)
621642
ret += _np.sum(spamPenaltyVec)
622643

644+
assert target_model is not None
645+
"""
646+
Leakage-aware metric supported, per implementation in mdl.frobeniusdist.
647+
Refer to how mdl.frobeniusdist handles the case when transform_mx_arg
648+
is a tuple in order to understand how the leakage-aware metric is defined.
649+
650+
Idea: raise an error if mxBasis isn't leakage-friendly.
651+
PROBLEM: if we're deep in the code then we end up needing to be
652+
working in a basis that has the identity matrix as its
653+
first element. The leakage-friendly basis doesn't even
654+
have the identity matrix as an element, let alone the first element
655+
656+
TODO: dig into function calls below and see where we can
657+
access the mxBasis object. (I'm sure we can.)
658+
Looks like it isn't accessible within ExplicitOpModelCalc objects.
659+
It's most definitely available in ExplicitOpModel.
660+
"""
623661
if "frobenius" in metric:
624-
d = 0
625-
nSummands = 0.0
626-
for opLabel, gate in mdl.operations.items():
627-
wt = item_weights.get(opLabel, opWeight)
628-
gate_mx = gate.to_dense()
629-
other_mx = target_model.operations[opLabel].to_dense()
630-
delta = gate_mx - other_mx
631-
delta = delta @ P
632-
val = _np.linalg.norm(delta.flatten())
633-
d += wt * val**2
634-
nSummands += wt * (gate.dim)**2
635-
636-
for lbl, rhoV in mdl.preps.items():
637-
wt = item_weights.get(lbl, spamWeight)
638-
d += wt * rhoV.frobeniusdist_squared(target_model.preps[lbl], None, None)
639-
nSummands += wt * rhoV.dim
640-
641-
for lbl, Evec in mdl.effects.items():
642-
wt = item_weights.get(lbl, spamWeight)
643-
evec = Evec.to_dense()
644-
other = target_model.effects[lbl].to_dense()
645-
delta = evec - other
646-
delta = delta @ P
647-
val = _np.linalg.norm(delta.flatten())
648-
d += wt * val**2
649-
nSummands += wt * Evec.dim
650-
651-
val = _np.sqrt(d / nSummands)
662+
val = mdl.frobeniusdist(target_model, transform_mx_arg, item_weights)
652663
if "squared" in metric:
653664
val = val ** 2
654665
ret += val
@@ -696,7 +707,7 @@ def _objective_fn(gauge_group_el, oob_check):
696707
else:
697708
raise ValueError("Invalid metric: %s" % metric)
698709
# end _objective_fn
699-
710+
700711
_jacobian_fn = None
701712

702713
return _objective_fn, _jacobian_fn

0 commit comments

Comments
 (0)