]> gitweb.michael.orlitzky.com - sage.d.git/commitdiff
mjo/clan/clan.py: new method _test_leftreg_trace_is_ip()
authorMichael Orlitzky <michael@orlitzky.com>
Fri, 10 Apr 2026 13:11:48 +0000 (09:11 -0400)
committerMichael Orlitzky <michael@orlitzky.com>
Fri, 10 Apr 2026 13:11:48 +0000 (09:11 -0400)
This is the second (and last) axiom of a clan.

mjo/clan/clan.py

index c724eb29cd1dabfdf224ffd80faad93ee6e6e75d..645f33f662f638cc894a53b5d4689edfd50f345b 100644 (file)
@@ -154,6 +154,69 @@ class Clan(CombinatorialFreeModule):
 
         return result
 
+
+    def _test_leftreg_trace_is_ip(self):
+        r"""
+        Check that the trace of ``(x*y).leftreg()`` defines
+        an inner product on ``x,y``. This is the second axiom
+        of a clan.
+
+        SETUP::
+
+            sage: from mjo.clan.random import random_clan
+
+        EXAMPLES::
+
+            sage: C = random_clan()              # long time
+            sage: C._test_leftreg_trace_is_ip()  # long time
+            True
+
+        """
+        def f(x,y):
+            # The purported inner product
+            return (x*y).leftreg().trace()
+
+        def check_linear_in_x(x,y):
+            a = self.base_ring().random_element()
+            z = self.random_element()
+            return f(a*x + z, y) == a*f(x,y) + f(z,y)
+
+        def check_linear_in_y(x,y):
+            a = self.base_ring().random_element()
+            z = self.random_element()
+            return f(x, a*y + z) == a*f(x,y) + f(x,z)
+
+        def check_symmetric(x,y):
+            return f(x,y) == f(y,x)
+
+        def check_positive_definite(x):
+            norm2_x = f(x,x)
+            return (norm2_x >= 0) and ((norm2_x == 0) == (x == 0))
+
+        def check_all(x,y):
+            return all([
+                check_linear_in_x(x,y),
+                check_linear_in_y(x,y),
+                check_symmetric(x,y),
+                check_positive_definite(x+y),
+                check_positive_definite(x-y),
+                check_positive_definite(x*y),
+            ])
+
+        # Check the basis...
+        b = self.basis()
+        result = all( check_all(b[i], b[j])
+                      for j in b.keys()
+                      for i in b.keys() )
+
+        # And some random elements for good measure
+        xs = ( self.random_element() for _ in range(10) )
+        ys = ( self.random_element() for _ in range(10) )
+        result |= all( check_all(x, y) for x in xs for y in ys )
+
+        return result
+
+
     def _test_leftreg_eigenvalues(self):
         r"""
         Check the leftreg-eigenvalues-are-real axiom of this clan.