`pint`

is not part of Sage. Here you try to substitute some symbolic variables of a symbolic expression by elements of the `pint`

module. This could only work if you could coerce `pint`

units into the `Symbolic Ring`

. The way to do this is to *define* a coercion between `pint`

units and the Symbolic Ring, you can have a look at the following docs:

This should be easily doable by using the Sage `units`

but i guess it is not what you would like to do since you will lose the consistency checking of `pint`

, for example with Sage `units`

, you can do:

```
sage: units.length.meter + units.time.second
meter + second
```

So perhaps a substitution i not what you would like to do. Perhaps, you should instead create a `.physical_consistency()`

or `.pint()`

(or whatever suitable name) method for symbolic elements, that recurses to the tree of the symbolic expression and make the units replacement from your dictionary.

Note that for powers you will experience some problems because the `.__pow__()`

method is not able to deal with Sage integers:

```
sage: sage: ureg.meter^2
TypeError: Cannot power UnitsContainer by <type 'sage.rings.integer.Integer'>
```

**EDIT** Here is a prototype. The idea is to recursively unfold the symbolic expression and refold it with units:

```
def physical(expr, dico):
r"""
INPUT:
- expr is a symbolic expression.
- dico is a dictionnary that maps symbols to units (possibly with magnitude)
The units are from the pint package, please do `sage -pip install pint` to let this function work.
OUTPUT:
The resulting unit (with magnitude) or raise an error.
"""
op = expr.operator()
dimensionless = (dico.values()[0] / dico.values()[0])
if op:
if op == operator.add:
return sum([is_physical(i, dico) for i in expr.operands()])
elif op == operator.mul:
return prod([is_physical(i, dico) for i in expr.operands()])
elif op == operator.pow: # todo : improve for dimensionless powers, like for log.
return is_physical(expr.operands()[0], dico) ** float(expr.operands()[1])
elif op in [exp, log, cos, sin]: # to enlarge
if is_physical(expr.operands()[0], dico).dimensionality == dimensionless.dimensionality:
return op(is_physical(expr.operands()[0], dico).magnitude) * dimensionless
else:
raise ValueError('The {} can only eat dimensionless numbers.'.format(op))
else:
raise ValueError('I do not know how to deal with {} operator (yet).'.format(op))
else:
if expr.is_symbol():
if expr in dico:
return dico[expr]
else:
raise ValueError('The symbol {} did not get any unit.'.format(expr))
elif expr.is_numeric():
return float(expr) * dimensionless
elif expr in [e, pi]:
return float(expr) * dimensionless
else:
raise ValueError('I do not know how to deal with {} operand (yet).'.format(expr))
```

The reason why i did not use `expr.is__constant()`

, but explicitely list `e`

and `pi`

is because things like `NaN`

are constants, and i am not sure there will not be physical constants (that are not dimensionless). If complex numbers might be involved, it could be better to replace ...

(more)
What are

bandcin the Sage session above that you copy paste?Sorry, forgot the var('a b c') line. I just modified my question accordingly.