src/compose.py

changeset 12
a0d61ac3719e
parent 3
c3a4f4bb87f7
--- a/src/compose.py	Mon Jun 29 00:20:42 2026 +0300
+++ b/src/compose.py	Sun Oct 04 13:02:26 2026 -0500
@@ -43,6 +43,8 @@
     def __init__(self, f, op):
         self.f = f
         self.op = op
+        self.override_lipschitz = None
+        self.override_lipschitz_pair = None
 
     def apply(self, *args):
         return self.f.apply(self.op.apply(*args))
@@ -93,7 +95,9 @@
         on ∇F. The function `diff_chain_lipschitz_factor` should return the Lipschitz factor divided by $M$: we obtain $M$ through the `diff_bound` on $F$.
         """
 
-        if hasattr(self.op, "opnorm"):
+        if self.override_lipschitz is not None:
+            return self.override_lipschitz
+        elif hasattr(self.op, "opnorm"):
             return self.f.diff_lipschitz_factor() * self.op.opnorm() ** 2
         else:
             mdf = self.f.diff_bound()
@@ -113,6 +117,9 @@
         there is no special handling of linear opeartors.
         """
 
+        if self.override_lipschitz_pair is not None:
+            return self.override_lipschitz_pair
+
         mdf = self.f.diff_bound()
 
         lda1, lda2 = self.op.diff_chain_lipschitz_factor_pair()
@@ -151,3 +158,31 @@
     #         raise Exception("Linear operators have unbounded range")
     #     else:
     #         return xbound
+
+
+class ScaleAuxStepHack:
+    """
+    This hack only scale the differential, to get different step length parameters wrt. k and c,
+    without rescaling the variables themselves. Essentially it amounts to computing the gradient wrt.
+    different inner products.
+    """
+
+    def __init__(self, scale):
+        self.scale = scale
+
+    def apply(self, x):
+        # μ, (k, (c1, c2)) = x
+        # sck, scc = self.scale
+        # return μ, (k * sck, (c1 * scc, c2 * scc))
+        return x
+
+    def diff_adjdir(self, j, _x, apply_result=None):
+        dμ, (dk, (dc1, dc2)) = j
+        sck, scc = self.scale
+        return dμ, (dk * sck, (dc1 * scc, dc2 * scc))
+
+    def opnorm(self, *args):
+        return 1
+
+    def diff_bound(self):
+        return 1

mercurial