Skip to content
Browse files

Add IdentityMorphism.

Having a separate class instead of a flag probably fits better into
SymPy philosophy.  This allows to have Morphism cope without a flag
specifying whether it is an identity or not.  This commit also adds a
different string representation for IdentityMorphism.
  • Loading branch information...
1 parent baf2d46 commit d02283a97691d8a72daa44af8d43cd483d9532a4 @scolobb committed Jun 11, 2012
View
2 sympy/categories/__init__.py
@@ -17,4 +17,4 @@
"""
-from baseclasses import Object, Morphism, Category, Diagram
+from baseclasses import Object, Morphism, IdentityMorphism, Category, Diagram
View
105 sympy/categories/baseclasses.py
@@ -82,7 +82,8 @@ class Morphism(Basic):
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.
+ composition. Identity morphisms are instances of
+ :class:`IdentityMorphism`.
Examples
========
@@ -114,7 +115,10 @@ def __new__(cls, domain, codomain, name="", identity=False):
# The last component of self.args represents the components of
# this morphism.
- return Basic.__new__(cls, domain, codomain, name, identity, [])
+ if identity:
+ return IdentityMorphism(domain, name)
+ else:
+ return Basic.__new__(cls, domain, codomain, name, [])
@property
def domain(self):
@@ -143,7 +147,7 @@ def identity(self):
Is ``True`` if this morphism is known to be an identity
morphism.
"""
- return self.args[3]
+ return False
@property
def components(self):
@@ -163,7 +167,7 @@ def components(self):
True
"""
- components = self.args[4]
+ components = self.args[3]
if not components:
return [self]
else:
@@ -201,17 +205,14 @@ def compose(self, g, new_name=""):
if g.codomain != self.domain:
raise ValueError("Uncomponsable morphisms.")
- if self.identity:
- return g
if g.identity:
return self
# We don't really know whether the new morphism is an identity
# (even if g.domain == self.codomain), so let's suppose it's
# not an identity.
return Basic.__new__(Morphism, g.domain, self.codomain,
- new_name, False, g.components +
- self.components)
+ new_name, g.components + self.components)
def __mul__(self, g):
"""
@@ -287,6 +288,94 @@ def __ne__(self, g):
def __hash__(self):
return hash((self.name, self.domain, self.codomain))
+class IdentityMorphism(Morphism):
+ """
+ An identity morphism.
+
+ An identity morphism is a morphism with equal domain and codomain,
+ which acts as an identity with respect to composition.
+
+ Examples
+ ========
+
+ >>> from sympy.categories import Object, Morphism, IdentityMorphism
+ >>> A = Object("A")
+ >>> B = Object("B")
+ >>> f = Morphism(A, B, "f")
+ >>> id_A = IdentityMorphism(A)
+ >>> f * id_A == f
+ True
+
+ """
+ def __new__(cls, domain, name=""):
+ return Basic.__new__(cls, domain, name)
+
+ @property
+ def domain(self):
+ """
+ Returns the domain of this identity morphism.
+ """
+ return self.args[0]
+
+ @property
+ def codomain(self):
+ """
+ Returns the codomain of this identity morphism.
+ """
+ return self.args[0]
+
+ @property
+ def name(self):
+ """
+ Returns the name of this identity morphism.
+ """
+ return self.args[1]
+
+ @property
+ def identity(self):
+ """
+ Is ``True`` if this morphism is known to be an identity
+ morphism.
+ """
+ return True
+
+ @property
+ def components(self):
+ """
+ Returns the components of this morphisms.
+
+ Since this is an identity morphisms, it always has itself as
+ the only component.
+ """
+ return [self]
+
+ def compose(self, g, new_name=""):
+ """
+ If ``g`` is a morphism with codomain equal to the domain of
+ this identity morphisms, returns ``g``.
+
+ The argument ``new_name`` is not used.
+
+ Examples
+ ========
+
+ >>> from sympy.categories import Object, Morphism, IdentityMorphism
+ >>> A = Object("A")
+ >>> B = Object("B")
+ >>> f = Morphism(A, B, "f")
+ >>> id_A = IdentityMorphism(A)
+ >>> f.compose(id_A) == f
+ True
+
+ """
+ if g.codomain != self.domain:
+ raise ValueError("Uncomponsable morphisms.")
+
+ return g
+
+ def __hash__(self):
+ return hash(self.domain)
+
class Category(Basic):
r"""
An (abstract) category.
View
7 sympy/categories/tests/test_baseclasses.py
@@ -1,4 +1,4 @@
-from sympy.categories import Object, Morphism, Diagram, Category
+from sympy.categories import Object, Morphism, IdentityMorphism, Diagram, Category
from sympy.utilities.pytest import XFAIL, raises
from sympy import FiniteSet, EmptySet, Dict
@@ -87,9 +87,14 @@ def test_morphism():
id_A = Morphism(A, A, identity=True)
id_B = Morphism(B, B, identity=True)
+ assert type(id_A) == IdentityMorphism
+ assert id_A == IdentityMorphism(A, "id_A")
+
assert id_A.identity == True
assert id_A == Morphism(A, A, name="f", identity=True)
+ assert hash(id_A) == hash(Morphism(A, A, name="f", identity=True))
assert id_A != Morphism(A, A, name="f")
+ assert id_A != id_B
assert id_A * id_A == id_A
assert f * id_A == f
View
4 sympy/printing/str.py
@@ -536,6 +536,10 @@ def _print_Morphism(self, morphism):
(component.domain, component.codomain, component.name)
return result[:-3]
+ def _print_IdentityMorphism(self, morphism):
+ return 'IdentityMorphism(%s, "%s")' % \
+ (morphism.domain, morphism.name)
+
def _print_Category(self, category):
return 'Category("%s")' % category.name
View
2 sympy/printing/tests/test_str.py
@@ -481,11 +481,13 @@ def test_categories():
f = Morphism(A, B, "f")
g = Morphism(B, C, "g")
+ id_A = Morphism(A, A, "id_A", identity=True)
K = Category("K")
assert str(A) == 'Object("A")'
assert str(f) == 'Morphism(Object("A"), Object("B"), "f")'
+ assert str(id_A) == 'IdentityMorphism(Object("A"), "id_A")'
assert str(g * f) == 'Morphism(Object("B"), Object("C"), "g") * ' \
'Morphism(Object("A"), Object("B"), "f")'

0 comments on commit d02283a

Please sign in to comment.
Something went wrong with that request. Please try again.