units tests
I just stumbled over a problem again that I reported years ago in sage-devel, but perhaps someone here can help. I am still after the quick and dirty way for using the existing units package in sage to test symbolic equations for consistent units. This is currently not possible because units are treated as conventional variables, meaning that:
units.x.y - units.x.y
0
The only thing that really stops me right now is that I don't know how to get it to return:
units.x.y + units.x.y
units.x.y
units.x.y - units.x.y
units.x.y
Is there an easy way to write a function or create a subclass that would do that while keeping the rest (multiplication, division, exponents etc.) the way it is?
UPDATE: A modification of the first answer by tmonteil does part of the job:
class MYExp(sage.symbolic.expression.Expression):
def __sub__(self,other):
if self.convert() == other.convert():
return self
else:
raise TypeError('Subtraction of non-matching units')
def __add__(self,other):
if self.convert() == other.convert():
return self
else:
raise TypeError('Sum of non-matching units')
def __mul__(self,other):
return MYExp(SR, super(MYExp, self).__mul__(other))
def __div__(self,other):
return MYExp(SR, super(MYExp, self).__div__(other))
def __pow__(self,other):
return MYExp(SR, super(MYExp, self).__pow__(other))
U = lambda x: MYExp(SR,x)
for s in units.length.trait_names():
globals()[s] = U(getattr(units.length,s))
Now this works:
type(meter*2)
class '__main__.MYExp'
But this does not:
type(2*meter)
type 'sage.symbolic.expression.Expression'
Similar for division. Is there a way to somehow modify the above to make any expressions involving MYExp return a MYExp, rather than just those expressions that start with MYExp?
This was explained at the end of my answer : if you want
2*meter
lead to aMYExp
expression, you have to define a coercion.Adding reverse multiplication and division did the trick (see my proposed solution below). Defining coercions seems outside my area of comfort.