# Gas Law Symbolic Equation Anonymous

# Definitions v3

#Main Tank Pressure[Pascals]
#Pp=1013529.32
#Tank Volume[m^3]
Vt=0.0013929
#Moles of Air
#n= 0
#Gas Constant
r=8.3144621
#Ambient Temperature[Kelvin][70F]
t= 294.261
eng5= [solve(Pp*Vt == n*r*t,n) for Pp in np.arange(103421.359,1013529,6895.75729)]


Why does this say:

TypeError: The first argument must be a symbolic expression or a list of
symbolic expressions.


I have the variables defined elsewhere[Pp =var('Pp')] but I'm not sure why this won't work. Thanks

edit retag close merge delete

Sort by » oldest newest most voted The first step in debugging is to look to see what the first argument actually is. I'm assuming that you did n = var("n") or something at some point. So we can get the first element:

sage: Pps = np.arange(103421.359,1013529,6895.75729)
sage: Pps
103421.359
sage: Pp = Pps
sage: Pp * Vt
144.05561095109999
sage: Pp * Vt == n
False
sage: Pp * Vt == n*r*t
False


.. and we see that Sage is automatically evaluating the expression, and since it can't prove that it's true -- which is good, because it's not true in general -- it's saying that it's False.

Ultimately this is because

sage: type(Pp)
<type 'numpy.float64'>


Pp is a numpy float, which doesn't interact too well with the Sage types. As soon as the __eq__ method of the float is called, the game's over. You can work around this in some fragile ways, such as flipping the order:

sage: n*r*t == Pp*Vt
2446.62193200810*n == 144.055610951
sage: solve(n*r*t == Pp*Vt, n)
[n == (52361895020038/889307677165161)]


But a better and more robust way would be to avoid getting numpy involved at all, and stick with Sage-native objects. For example, you can use srange and sxrange:

srange(start, end=None, step=1, universe=None, check=True, include_endpoint=False, endpoint_tolerance=1e-05)
Return list of numbers a, a+step, ..., a+k*step,
where a+k*step < b and a+(k+1)*step >= b over
exact rings, and makes a best attempt for inexact rings
(see note below).


which would give:

sage: s = srange(103421.359,1013529,6895.75729)
sage: len(s)
132
sage: s[:5]
[103421.359000000, 110317.116290000, 117212.873580000, 124108.630870000, 131004.388160000]


and then

sage: eng5= [solve(Pp*Vt == n*r*t,n) for Pp in srange(103421.359,1013529,6895.75729)]
sage: len(eng5)
132
sage: eng5[:3]
[[n == (52361895020038/889307677165161)], [n == (56778965120683/904048017111831)], [n == (74168281138961/1111449736506101)]]


Short version: don't use numpy unless you need to, and here you don't.

more

Could you elaborate on when one might use srange, xrange or np.arange? Why did someone request using np.arange on this problem: http://ask.sagemath.org/question/1725/unexpected-solve-errors I see that srange() works there, but xrange() does not. Is it because srange and np.arange both generate a list output, but xrange does it dynamically? Thanks for the clarification!

xrange is a Python lazy range (the "x" means "lazy" for historical reasons), and yields Python ints. They don't have a lot of the Sage special methods, and dividing int(5) by int(2) gives 2 (truncating division) rather than the fraction 5/2. You also can't use it with floats. srange -- the "S" stands for "Sage" -- handles lots of different kinds of Sage objects. See also the  [1, 1.5, .., 10] syntax. np.arange is seldom useful in Sage, but is really useful in standard Python, because Python doesn't have a builtin "range" that works with non-integers. Does that make sense?