Skip to content

Conversation

@cxzhong
Copy link
Contributor

@cxzhong cxzhong commented Nov 19, 2025

Solutions

This fixes #40780
Add an explicit check in _element_constructor_ to handle vectors directly using from_vector() before attempting to use self._assoc(x):

def _element_constructor_(self, x):
    if isinstance(x, list) and len(x) == 2:
        return self(x[0])._bracket_(self(x[1]))
    
    # Check if x is a vector from the module to avoid infinite recursion
    try:
        if hasattr(x, 'parent') and x.parent() == self.module():
            return self.from_vector(x)
    except (AttributeError, NotImplementedError):
        pass
    
    return self.element_class(self, self._assoc(x))

📝 Checklist

  • The title is concise and informative.
  • The description explains in detail what this PR is about.
  • I have linked a relevant issue or discussion.
  • I have created tests covering the changes.
  • I have updated the documentation and checked the documentation preview.

The Infinite Loop Cycle

The infinite recursion occurs in the following cycle:

1. gl(vector) 
   ↓
2. LieAlgebraFromAssociative._element_constructor_(vector)
   ↓
3. self._assoc(vector)  # _assoc is a MatrixSpace
   ↓
4. MatrixSpace.__call__(vector)
   ↓
5. Uses coercion: VectorSpace → LieAlgebra → MatrixSpace
   ↓
6. Back to step 1: gl(vector)

Detailed Breakdown

  1. Morphism Construction Context:

    • When creating a morphism via gl.morphism({e:e for e in gl.gens()}), the morphism code (in morphism.py) computes brackets to extend the spanning set
    • It calls domain.bracket(spanning_set[i], spanning_set[j]) where spanning_set contains vectors
  2. Bracket Computation:

    • The bracket method in lie_algebras.py line 290:
      return self(lhs)._bracket_(self(rhs))
    • This attempts to convert vectors (lhs, rhs) to Lie algebra elements by calling self(vector)
  3. Element Constructor Issue:

    • LieAlgebraFromAssociative._element_constructor_ (line 1246) was:
      return self.element_class(self, self._assoc(x))
    • When x is a vector, it calls self._assoc(vector)
  4. Coercion Map Problem:

    • self._assoc is a MatrixSpace
    • There exists a composite coercion map:
      VectorSpace → LieAlgebra → MatrixSpace
      
    • This map was registered when LiftMorphismToAssociative was set up as a coercion
  5. The Loop Closes:

    • MatrixSpace(vector) uses the coercion map
    • First step: VectorSpace → LieAlgebra calls gl(vector)
    • This triggers _element_constructor_ again with the same vector
    • The cycle repeats infinitely

⌛ Dependencies

@cxzhong cxzhong requested a review from mantepse November 19, 2025 09:18
@cxzhong cxzhong added the t: bug label Nov 19, 2025
@cxzhong cxzhong requested a review from orlitzky November 19, 2025 14:36
True
Test that morphisms can be constructed (this used to fail with
RecursionError)::
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could use :exc:`RecursionError` here to create a link in the docs

Test that morphisms can be constructed (this used to fail with
RecursionError)::
sage: gl = lie_algebras.gl(QQ, 2)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one might be better in a TESTS:: block since it doesn't demonstrate the element constructor directly

try:
if hasattr(x, 'parent') and x.parent() == self.module():
return self.from_vector(x)
except (AttributeError, NotImplementedError):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can these two errors really happen? We check for the .parent attribute before using it, and then we check that x belongs to a module before calling from_vector() on it...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

creating a morphism of the lie algebra gl_n enters (probably infinite) recursion

2 participants