Note: I have already accepted the answer from Izaak van Dongen above. This answer is to provide context for the question for those that may be interested.
I was reading a book on SDEs and I asked a question on the measure theory presentation of probability space. There are a large number of structural definitions involved. I wanted to use SymPy to organize them and present the type signatures in something mimicking Axiom style.
To do this pleasantly in Python 3 and SymPy I needed a few things:
- A way of dynamically enforcing function signatures.
- A way of pretty-printing complex algebraic type signatures (this question).
I started implementing the definitions. To check that they were organized correctly, I asked
With that in hand, and the above solution for the pretty-printing, the following few definitions give the style of my solution (without quoting the whole thing which is about 85 definitions):
import sympy as sp # I am at version 1.6.1
from typen import strict_type_hints, enforce_type_hints
from traits.api import Array, Either, Enum, Instance, Int, Str, Tuple
class Concept(sp.Expr):
def __init__(self, name, value):
self.name = name
self.value = value
def _latex(self, printer=None):
return f"{self.name}:\\ \\text{{{self.__class__.__name__}}}"
class NonemptySet(Concept):
def __init__(self, name, value):
if value==sp.S.EmptySet:
raise ValueError("Set must not be empty")
super().__init__(name, value)
def _latex(self, printer=None):
return self.name
class Reals(NonemptySet):
@strict_type_hints
def __init__(self):
self.name = sp.symbols('\\Re')
super().__init__(self.name,sp.Reals)
def _latex(self, printer=None):
return self.name
class SampleSpace (NonemptySet):
pass
class Algebra(NonemptySet):
@strict_type_hints
def __init__(self,
name: sp.Symbol,
Ω: SampleSpace,
A: Either(NonemptySet, sp.Symbol)):
self.Ω=Ω
super().__init__(name, A)
def _latex(self, printer=None):
math=str(self.name).replace('$','')
math2 = self.Ω._latex(printer)
return f"{math}:\\ \\text{{{self.__class__.__name__} on }} ({math2})"
class Algebra(Algebra):
@strict_type_hints
def __init__(self, name: sp.Symbol, Ω: SampleSpace, A: Algebra):
self.Ω=Ω
super().__init__(name, Ω, A)
class EventSpace(Algebra):
@strict_type_hints
def __init__(self, name: sp.Symbol, Ω: SampleSpace, A: Algebra):
super().__init__(name, Ω, A)
class AdditiveFunction(Concept):
@strict_type_hints
def __init__(self,
name: sp.core.function.UndefinedFunction,
Ω: SampleSpace,
A: Algebra,
f: sp.core.function.UndefinedFunction):
self.Ω = Ω
self.A = A
super().__init__(name, f)
def _latex(self, printer=None):
math2 = self.A._latex(printer)
return f"{self.name}: {self.A.name} \\to \\Re \\ \\text{{{self.__class__.__name__} on }} {math2}"
and so on. Any comments or suggestions on a more "SymPy-thonic" way of improving the above sketch would be greatly appreciated.