I have been looking for a good, general design pattern to implement simple mathematical structures where functions have the following properties:
- know which parameters they contain, parameters are "fixed"
- can be called with variable values as arguments
- are defined in terms of other functions, which have the same properties as the aforementioned two.
- prevent repetition of parameter declaration, even if some super functions contain the same parameters as their respective sub-functions.
I found many useful resources but still have some issues.
Mathematical functions can be defined as classes as explained here where parameters are attributes and the __call__
method is used to make the class instances callable with variables as arguments. Here is a simple mathematical structure which is modelled quite well using this approach in python
Mathematical structure
T = c_v*t/(a*h)**2
U = (T**3/(T**3+0.5))
Sample code
class T:
def __init__(self, c_v, a, h):
self.c_v = c_v
self.a = a
self.h = h
def __call__(self, t):
return self.c_v*t/(self.a*self.h)**2
class U(T):
def __call__(self, t):
T = super().__call__(t)
return (T**3/(T**3+0.5) )**(1/6)
The following code will then give a mathematically correct result:
>>> U_func = U(1.5E-7, 0.5, 12)
>>> U_func(100*24*60*60)
This works quite well, but it could be that class U
is dependent on several other function objects. Inheritance here will not work, as all "super" functions implement the same method to do their arithmetic (__call__
). Composition also presents some challenges which I will not get into here. My conclusion is that the above approach will not solve my problem, although it looks nice.
I then did some reading on several patterns like: - Strategy - Factory - Composite
The Composite Pattern showed some promise as it does support tree-structures, I also found out that simple arithmetic is in fact a tree structure as coined by the phrase "Binary Expression Trees". What I am trying to do is related to binary expression trees but is in fact not at the +-/* operator level.
Does anyone understand or identify with what I am trying to achieve? Am I wasting my time here? Is there a one-size fits all design pattern or should I use a combination therewith for this case?