Permalink
Browse files

Implement identity morphisms.

A Morphism can now be defined to be an identity.  Identity morphisms are
defined not to influence composition.  All identity morphisms of one and
the same object are equal.
  • Loading branch information...
1 parent c9b027b commit fa74c0952e2b66b946b388e7d3f3f00cfdc291df @scolobb committed Jun 6, 2012
Showing with 46 additions and 3 deletions.
  1. +32 −2 sympy/categories/baseclasses.py
  2. +14 −1 sympy/categories/tests/test_baseclasses.py
@@ -73,6 +73,11 @@ class Morphism(Basic):
codomains). The names of such composed morphisms are not taken in
consideration at comparison.
+ Morphisms with the same domain and codomain can be defined to be
+ identity morphisms. Identity morphisms with the same (co)domains
+ are equal. Identity morphisms are identities with respect to
+ composition.
+
Examples
========
@@ -92,16 +97,29 @@ class Morphism(Basic):
Morphism(Object("B"), Object("C"), "g") *
Morphism(Object("A"), Object("B"), "f")
+ >>> id_A = Morphism(A, A, identity=True)
+ >>> id_A == Morphism(A, A, identity=True)
+ True
+
+ >>> f * id_A == f
+ True
+
"""
- def __new__(cls, domain, codomain, name=""):
- new_morphism = Basic.__new__(cls, domain, codomain, name)
+ def __new__(cls, domain, codomain, name="", identity=False):
+ new_morphism = Basic.__new__(cls, domain, codomain, name, identity)
new_morphism.domain = domain
new_morphism.codomain = codomain
new_morphism.name = name
new_morphism.components = [new_morphism]
+ new_morphism.identity = identity
+
+ if identity and (domain != codomain):
+ raise ValueError(
+ "identity morphisms must have the same domain and codomain")
+
return new_morphism
def compose(self, g, new_name=""):
@@ -138,6 +156,11 @@ def compose(self, g, new_name=""):
if g.codomain != self.domain:
return None
+ if self.identity:
+ return g
+ if g.identity:
+ return self
+
composite = Morphism(g.domain, self.codomain, new_name)
composite.components = g.components + self.components
@@ -184,6 +207,13 @@ def flatten(self, new_name=""):
return Morphism(self.domain, self.codomain, new_name)
def __eq__(self, g):
+ if self.identity and g.identity:
+ # All identities are equal.
+ return self.domain == g.domain
+ elif self.identity or g.identity:
+ # One of the morphisms is an identity, but not both.
+ return False
+
if (len(self.components) == 1) and (len(g.components) == 1):
# We are comparing two simple morphisms.
if (not self.name) or (not g.name):
@@ -1,5 +1,5 @@
from sympy.categories import Object, Morphism, Diagram
-from sympy.utilities.pytest import XFAIL
+from sympy.utilities.pytest import XFAIL, raises
from sympy import FiniteSet, EmptySet
def test_object():
@@ -77,6 +77,19 @@ def test_morphism():
assert hash(f) == hash(Morphism(A, B, "f"))
+ id_A = Morphism(A, A, identity=True)
+ id_B = Morphism(B, B, identity=True)
+
+ assert id_A.identity == True
+ assert id_A == Morphism(A, A, name="f", identity=True)
+ assert id_A != Morphism(A, A, name="f")
+
+ assert id_A * id_A == id_A
+ assert f * id_A == f
+ assert id_B * f == f
+
+ raises(ValueError, lambda: Morphism(A, B, identity=True))
+
@XFAIL
def test_diagram():
A = Object("A")

0 comments on commit fa74c09

Please sign in to comment.