How to implement div and grad in sympy? - python

Playing around a lot with sympy lately, I came up with the problem of calculating divergence and gradient for scalar and vector fields. What I want to do for now is solving the heat equation, i.e.
d/dt u(x,t) - a * lap(u(x,t)) = 0, with lap(x) = (div(grad(x))
on a scalar field. Since I could not find lap, div and grad in sympy.physics.mechanics, I tried to implement them by myself
from sympy import *
from sympy.physics.mechanics import *
o = ReferenceFrame('o')
x,y,z = symbols('x y z')
class div(Function):
#classmethod
def eval(cls, F):
return F.diff(x, o).dot(o.x)+F.diff(y, o).dot(o.y)+F.diff(z, o).dot(o.z)
class grad(Function):
#classmethod
def eval(cls, F):
return o.x * F.diff(x) + o.y * F.diff(y) + o.z * F.diff(z)
f = x**2 + y**3 + z*0.5
print grad(f)
print type(grad(f))
print div(grad(f))
unluckily, this gives
2*x*o.x + 3*y**2*o.y + 0.500000000000000*o.z
Traceback (most recent call last):
File "/home/fortmeier/Desktop/autokernel/autokernel/tools/GenerateCode.py", line 24, in <module>
print div(grad(f))
File "/usr/local/lib/python2.7/dist-packages/sympy/core/cache.py", line 93, in wrapper
r = func(*args, **kw_args)
File "/usr/local/lib/python2.7/dist-packages/sympy/core/function.py", line 368, in __new__
result = super(Function, cls).__new__(cls, *args, **options)
File "/usr/local/lib/python2.7/dist-packages/sympy/core/cache.py", line 93, in wrapper
r = func(*args, **kw_args)
File "/usr/local/lib/python2.7/dist-packages/sympy/core/function.py", line 188, in __new__
args = list(map(sympify, args))
File "/usr/local/lib/python2.7/dist-packages/sympy/core/sympify.py", line 313, in sympify
expr = parse_expr(a, local_dict=locals, transformations=transformations, evaluate=evaluate)
File "/usr/local/lib/python2.7/dist-packages/sympy/parsing/sympy_parser.py", line 757, in parse_expr
return eval_expr(code, local_dict, global_dict)
File "/usr/local/lib/python2.7/dist-packages/sympy/parsing/sympy_parser.py", line 691, in eval_expr
code, global_dict, local_dict) # take local objects in preference
File "<string>", line 1, in <module>
AttributeError: 'Symbol' object has no attribute 'x'
[Finished in 0.3s with exit code 1]
I know that I could do something with the galgebra module, but first I'd like to understand more whats going on here. The question thus is what am I missing?

This looks like a bug in SymPy. sympify(ReferenceFrame('o').x) does not work.

Related

Error using SymPy symbolic integration for a specific set of parameters

I used symbolic integration to find the numerical values of the following series of (similar) integrals, because the functions appear to be slow convergent, and numerical methods so far result in values quite different from the symbolic calculation (no matter what relative and absolute tolerance I tried):
from sympy import *
import numpy as np
a1 = 1001
a2 = 1001
a3 = 951
Delta = lambda s: ((a1**2+s)**Rational(1, 2))*((a2**2+s)**Rational(1, 2))*((a3**2+s)**Rational(1, 2))
s = Symbol('s')
I1 = re(N(2*np.pi*a1*a2*a3*integrate(1/((a1**2 + s) * Delta(s)), (s, 0, oo))))
I2 = re(N(2*np.pi*a1*a2*a3*integrate(1/((a2**2 + s) * Delta(s)), (s, 0, oo))))
I3 = re(N(2*np.pi*a1*a2*a3*integrate(1/((a3**2 + s) * Delta(s)), (s, 0, oo))))
The integration works for most values of a1, a2, a3. However, by mere chance, I found a set of values that results in errors : a1 = 1001, a2 = 1001, a3 = 951. With the following error:
python3 test.py
Traceback (most recent call last):
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/core/assumptions.py", line 454, in getit
return self._assumptions[fact]
KeyError: 'zero'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/core/assumptions.py", line 454, in getit
return self._assumptions[fact]
KeyError: 'extended_real'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/core/assumptions.py", line 454, in getit
return self._assumptions[fact]
KeyError: 'finite'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "test.py", line 14, in <module>
I1 = re(N(2*np.pi*a1*a2*a3*integrate(1/((a1**2 + s) * Delta(s)), (s, 0, oo))))
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/integrals/integrals.py", line 1571, in integrate
return integral.doit(**doit_flags)
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/integrals/integrals.py", line 581, in doit
ret = try_meijerg(function, xab)
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/integrals/integrals.py", line 553, in try_meijerg
res = meijerint_definite(function, x, a, b)
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/integrals/meijerint.py", line 1860, in meijerint_definite
res = _meijerint_definite_2(f, x)
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/integrals/meijerint.py", line 1969, in _meijerint_definite_2
res = _meijerint_definite_3(g, x)
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/integrals/meijerint.py", line 1981, in _meijerint_definite_3
res = _meijerint_definite_4(f, x)
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/integrals/meijerint.py", line 2060, in _meijerint_definite_4
res += C*_int0oo(f1_, f2_, x)
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/integrals/meijerint.py", line 1305, in _int0oo
return meijerg(a1, a2, b1, b2, omega/eta)/eta
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/core/decorators.py", line 266, in _func
return func(self, other)
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/core/decorators.py", line 136, in binary_op_wrapper
return func(self, other)
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/core/expr.py", line 266, in __truediv__
return Mul(self, denom)
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/core/cache.py", line 72, in wrapper
retval = cfunc(*args, **kwargs)
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/core/operations.py", line 85, in __new__
c_part, nc_part, order_symbols = cls.flatten(args)
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/core/mul.py", line 266, in flatten
if not a.is_zero and a.is_Rational:
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/core/assumptions.py", line 458, in getit
return _ask(fact, self)
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/core/assumptions.py", line 513, in _ask
_ask(pk, obj)
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/core/assumptions.py", line 501, in _ask
a = evaluate(obj)
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/core/expr.py", line 912, in _eval_is_extended_negative
return self._eval_is_extended_positive_negative(positive=False)
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/core/expr.py", line 870, in _eval_is_extended_positive_negative
if self.is_extended_real is False:
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/core/assumptions.py", line 458, in getit
return _ask(fact, self)
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/core/assumptions.py", line 513, in _ask
_ask(pk, obj)
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/core/assumptions.py", line 501, in _ask
a = evaluate(obj)
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/core/expr.py", line 846, in _eval_is_positive
finite = self.is_finite
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/core/assumptions.py", line 458, in getit
return _ask(fact, self)
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/core/assumptions.py", line 513, in _ask
_ask(pk, obj)
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/core/assumptions.py", line 513, in _ask
_ask(pk, obj)
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/core/assumptions.py", line 501, in _ask
a = evaluate(obj)
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/core/expr.py", line 909, in _eval_is_extended_positive
return self._eval_is_extended_positive_negative(positive=True)
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/core/expr.py", line 875, in _eval_is_extended_positive_negative
n2 = self._eval_evalf(2)
File "/opt/anaconda3/lib/python3.7/site-packages/sympy/functions/special/hyper.py", line 690, in _eval_evalf
v = mpmath.meijerg(ap, bq, z, r)
File "/opt/anaconda3/lib/python3.7/site-packages/mpmath/functions/hypergeometric.py", line 1058, in meijerg
return ctx.hypercomb(h, a+b, **kwargs)
File "/opt/anaconda3/lib/python3.7/site-packages/mpmath/functions/hypergeometric.py", line 127, in hypercomb
[ctx.rgamma(b) for b in beta_s] + \
File "/opt/anaconda3/lib/python3.7/site-packages/mpmath/functions/hypergeometric.py", line 224, in hyper
elif q == 0: return ctx._hyp1f0(a_s[0][0], z)
File "/opt/anaconda3/lib/python3.7/site-packages/mpmath/ctx_mp_python.py", line 1035, in f_wrapped
retval = f(ctx, *args, **kwargs)
File "/opt/anaconda3/lib/python3.7/site-packages/mpmath/functions/hypergeometric.py", line 271, in _hyp1f0
return (1-z) ** (-a)
File "<string>", line 9, in __pow__
File "/opt/anaconda3/lib/python3.7/site-packages/mpmath/libmp/libelefun.py", line 339, in mpf_pow
reciprocal_rnd[rnd]), -tman, prec, rnd)
File "/opt/anaconda3/lib/python3.7/site-packages/mpmath/libmp/libmpf.py", line 1073, in mpf_pow_int
return mpf_div(fone, inverse, prec, rnd)
File "/opt/anaconda3/lib/python3.7/site-packages/mpmath/libmp/libmpf.py", line 960, in mpf_div
raise ZeroDivisionError
ZeroDivisionError
I do not understand the cause for error with this specific set of values, and would like to find a way to work around it, either through numerical or analytical integration.
Curiously, parameter values that are quite close does not cause any errors. For example, the following two sets work perfectly fine:
a1 = 1018, a2 = 1018, a3 = 917
a1 = 984, a2 = 984, a3 = 984
I would add that closed form solution treating a1, a2, a3 as unknowns do not exist. But closed form solutions do exist when replacing a1, a2, a3 with numerical values. The problem being that for my need I need to try different combinations of a1, a2, a3 values thousands of times.
There is a bug somewhere. It fails trying to numerically evaluate this:
meijerg(((0, -1), ()), ((-1/2, 0), ()), 904401*exp_polar(0)/1002001)
I'm not sure if that's an invalid expression coming from a bug in the symbolic integration routine or if the bug is in mpmath for not being able to evaluate it.
That code is itself called as part of the assumptions which are cached. The same error does not get reraised if you run the same code repeatedly within the same process. On the third run I get the answers:
In [4]: I1 = re(N(2*np.pi*a1*a2*a3*integrate(1/((a1**2 + s) * Delta(s)), (s, 0, oo))))
...: I2 = re(N(2*np.pi*a1*a2*a3*integrate(1/((a2**2 + s) * Delta(s)), (s, 0, oo))))
...: I3 = re(N(2*np.pi*a1*a2*a3*integrate(1/((a3**2 + s) * Delta(s)), (s, 0, oo))))
In [5]: I1, I2, I3
Out[5]: (4.10232880720189, 4.10232880720189, 4.3617129999554)
Note that numerical evaluation of the integral itself in sympy gives the exact same answers e.g. (use Integral rather than integrate):
In [7]: expr = 2*pi*a1*a2*a3*Integral(1/((a1**2 + s) * Delta(s)), (s, 0, oo))
In [8]: expr
Out[8]:
∞
⌠
⎮ 1
1905805902⋅π⋅⎮ ───────────────────────────── ds
⎮ ____________ 2
⎮ ╲╱ s + 904401 ⋅(s + 1002001)
⌡
0
In [9]: expr.evalf()
Out[9]: 4.10232880720189
If you need to do this many times then I would suggest using evalf rather than integrate.

How can I avoid numba error with recursion?

I have setup a function that iterates over combinations of chars to form strings.
It is recursive to itself, the recursive call looks like that:
testG(charNum - 1, arr2)
But when i call the entire function, I get this error:
>>> testSpeedGPU()
Traceback (most recent call last):
File "<pyshell#9>", line 1, in <module>
testSpeedGPU()
File "F:\Script Projects#\HASHFinder.py", line 90, in testSpeedGPU
testG(4, [''])
File "D:\Python\lib\site-packages\numba\cuda\dispatcher.py", line 40, in __call__
return self.compiled(*args, **kws)
File "D:\Python\lib\site-packages\numba\cuda\compiler.py", line 758, in __call__
kernel = self.specialize(*args)
File "D:\Python\lib\site-packages\numba\cuda\compiler.py", line 769, in specialize
kernel = self.compile(argtypes)
File "D:\Python\lib\site-packages\numba\cuda\compiler.py", line 784, in compile
kernel = compile_kernel(self.py_func, argtypes,
File "D:\Python\lib\site-packages\numba\core\compiler_lock.py", line 32, in _acquire_compile_lock
return func(*args, **kwargs)
TypeError: compile_kernel() got an unexpected keyword argument 'boundscheck'
Here is the function's body:
#jit(target ="cuda")
def testG(charNum, inpArray) -> null:
if charNum == 1:
arr2 = []
for s in range(len(inpArray)):
for i in range(len(alp)):
arr2.append(alp[i] + inpArray[s])
return
else:
print("more than 1")
arr2 = []
for s in range(len(inpArray)):
for i in range(len(alp)):
arr2.append(alp[i] + inpArray[s])
testG(charNum - 1, arr2)
I think it does have to do with the recursion but I really dont know.
Thanks for your help!
PS: The function works when not marked with #jit(target="cuda")

Python vestigial parameter and uncallable function

import numpy as np
from scipy.optimize import fsolve
from scipy.integrate import quad
import matplotlib.pyplot as plt
Rgas = 8.31446261815324 #Pa*m**3/mol*K
def Peng_Robinson_EOS(P,V,T,Tc,Pc,ω):
a = (1+(0.37464+1.54226*ω-0.26992*ω**2)*(1-(T/Tc)**(1/2)))**2*Rgas**2*Tc**2/Pc #Pa*m**3
b = 0.07780 * Rgas*Tc/Pc
return P + a/((V+(1-np.sqrt(2))*b)*(V+(1+np.sqrt(2)))) - Rgas*T/(V-b)
def PR_Psat(T,Tc,Pc,ω,V,Pguess = 100000):
def integral_diff (Pguess,T,Tc,Pc,ω,V):
def Psat_integrand (V,Pguess,T,Tc,Pc,ω):
integrand1 = fsolve(Peng_Robinson_EOS(Pguess,V,T,Tc,Pc,ω),Pguess)
integrand2 = Pguess
integrand = integrand1-integrand2
return integrand
Vl = fsolve(Psat_integrand(V,Pguess,T,Tc,Pc,ω),0)
Vv_guess = Rgas*T/Pguess
Vv = fsolve(Psat_integrand(V,Pguess,T,Tc,Pc,ω),Vv_guess)
Vinf_guess = (Vl + Vv)/2
Vinf = fsolve(Psat_integrand(V,Pguess,T,Tc,Pc,ω),Vinf_guess)
left = quad(Psat_integrand(V,Pguess,T,Tc,Pc,ω),Vl,Vinf)[0]
right = quad(Psat_integrand(V,Pguess,T,Tc,Pc,ω),Vinf,Vv)[0]
diff = left + right
return diff
Psat = fsolve(integral_diff(Pguess,T,Tc,Pc,ω,V),Pguess)
return Psat
There are two issues with this code.
1: in theory, PR_Psat should not depend on V, since all values of V used in calculation are found via fsolve. However, because Peng_Robinson_EOS depends on V, it Python won't let it be ignored in enclosing functions. Is there a way to eliminate the need to "specify" V?
from an earlier version (before V was a parameter of all functions), to demonstrate:
runfile('...', wdir='...')
Traceback (most recent call last):
File "<ipython-input-4-0875bc6411e8>", line 1, in <module>
runfile('...', wdir='...')
File "...\lib\site-packages\spyder\utils\site\sitecustomize.py", line 705, in runfile
execfile(filename, namespace)
File "...\lib\site-packages\spyder\utils\site\sitecustomize.py", line 102, in execfile
exec(compile(f.read(), filename, 'exec'), namespace)
File "...", line 40, in <module>
print(PR_Psat(300,647.1,22055000,0.345))
File "...", line 37, in PR_Psat
Psat = fsolve(integral_diff(Pguess,T,Tc,Pc,ω),Pguess)
File "...", line 25, in integral_diff
Vl = fsolve(Psat_integrand(V,Pguess,T,Tc,Pc,ω),0)
NameError: name 'V' is not defined
2: It seems that Peng_Robinson is not being treated as a callable function, but rather as a float. I'm not sure what is causing this.
runfile('...', wdir='...')
Traceback (most recent call last):
File "<ipython-input-13-0875bc6411e8>", line 1, in <module>
runfile('...', wdir='...')
File "C:\Users\Spencer\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 705, in runfile
execfile(filename, namespace)
File "...\lib\site-packages\spyder\utils\site\sitecustomize.py", line 102, in execfile
exec(compile(f.read(), filename, 'exec'), namespace)
File "...", line 42, in <module>
print(PR_Psat(300,647.1,22055000,0.345,1))
File "...", line 39, in PR_Psat
Psat = fsolve(integral_diff(Pguess,T,Tc,Pc,ω,V),Pguess)
File "...", line 27, in integral_diff
Vl = fsolve(Psat_integrand(V,Pguess,T,Tc,Pc,ω),0)
File "...", line 23, in Psat_integrand
integrand1 = fsolve(Peng_Robinson_EOS(Pguess,V,T,Tc,Pc,ω),Pguess)
File "...\lib\site-packages\scipy\optimize\minpack.py", line 148, in fsolve
res = _root_hybr(func, x0, args, jac=fprime, **options)
File "...\lib\site-packages\scipy\optimize\minpack.py", line 214, in _root_hybr
shape, dtype = _check_func('fsolve', 'func', func, x0, args, n, (n,))
File "...\lib\site-packages\scipy\optimize\minpack.py", line 27, in _check_func
res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
TypeError: 'numpy.float64' object is not callable
In theory, Peng_Robinson_EOS should, if plotted as P(V) with constant T, produce a cubic regression. The goal of PR_Psat is to find the value of P for which the integrals between P and the cubic regression cancel. (Hence, integral_diff being plugged into fsolve)
To summarize the questions,
1) Is there a way to eliminate the need for V in PR_Psat?
2) Why is Peng_Robinson_EOS being flagged as an un-callable numpy.float64 object?
The problem was a syntax error. Arguments for fsolve and quad were placed wrong. To fix both problems, I moved the args to the back. For example,
incorrect:
Vv = fsolve(Psat_integrand(V,Pguess,T,Tc,Pc,ω),Vv_guess)
correct:
Vv = fsolve(Psat_integrand,Vv_guess,args=(Pguess,T,Tc,Pc,ω))
The reason Peng_Robinson_EOS is being called a numpy.float64 is because with the syntax of the code in the question the program is evaluated before being passed to the solver.
Also, with proper syntax, V is no longer an issue.
def PR_Psat(T,Tc,Pc,ω,Pguess = 1000):
def integral_diff (Pguess,T,Tc,Pc,ω):
def Psat_integrand (V,Pguess,T,Tc,Pc,ω):
integrand1 = fsolve(Peng_Robinson_EOS,Pguess,args=(V,T,Tc,Pc,ω))
integrand2 = Pguess
integrand = integrand1-integrand2
return integrand
Vl = fsolve(Psat_integrand,0,args=(Pguess,T,Tc,Pc,ω))
Vv_guess = Rgas*T/Pguess
Vv = fsolve(Psat_integrand,Vv_guess,args=(Pguess,T,Tc,Pc,ω))
Vinf_guess = (Vl + Vv)/2
Vinf = fsolve(Psat_integrand,Vinf_guess,args=(Pguess,T,Tc,Pc,ω))
left = quad(Psat_integrand,Vl,Vinf,args=(Pguess,T,Tc,Pc,ω))[0]
right = quad(Psat_integrand,Vinf,Vv,args=(Pguess,T,Tc,Pc,ω))[0]
diff = left + right
return diff
Psat = fsolve(integral_diff,Pguess,args=(T,Tc,Pc,ω))
return Psat

scipy.minimize error : setting an array element with a sequence

I want to estimate parameters 'k,ru,sigma' that maximumize the function 'func'
('ru' means r upperba)
The'func'formula is compex, so I want to upload the image to show this fomula, but i have no enough reputation.
import numpy as np
sigma,k,ru=0.01,0.001,5
p0=np.array([[0.01,0.01,6]])
p=np.array([[sigma,k,ru]])
def func(p,r):
T=91/365
y=1/(np.sqrt(2*(np.pi)*p[0]**2/(2*p[1])*(1-np.exp(-(2*p[1]*T)))))*np.exp((r-p[2]-np.exp(-(p[1]*T))*(r-p[2]))**2/(p[0]**2/((-4)*p[1])*(1-np.exp(-(2*p[1]*T)))))
return -y
from scipy.optimize import minimize
r=np.array([[1.45,2.5,2.6,1.67,1.2]])
# r has 1350 datas like this
res=minimize(func,p0,args=(r))
Traceback (most recent call last):
File "<ipython-input-9-b94a05d2ede8>", line 1, in <module>
res=minimize(func,p0,args=(r))
File "C:\Users\hyun su\Anaconda3\lib\site-packages\scipy\optimize\_minimize.py", line 419, in minimize
return _minimize_bfgs(fun, x0, args, jac, callback, **options)
File "C:\Users\hyun su\Anaconda3\lib\site-packages\scipy\optimize\optimize.py", line 837, in _minimize_bfgs
gfk = myfprime(x0)
File "C:\Users\hyun su\Anaconda3\lib\site-packages\scipy\optimize\optimize.py", line 282, in function_wrapper
return function(*(wrapper_args + args))
File "C:\Users\hyun su\Anaconda3\lib\site-packages\scipy\optimize\optimize.py", line 616, in approx_fprime
return _approx_fprime_helper(xk, f, epsilon, args=args)
File "C:\Users\hyun su\Anaconda3\lib\site-packages\scipy\optimize\optimize.py", line 556, in _approx_fprime_helper
grad[k] = (f(*((xk + d,) + args)) - f0) / d[k]
ValueError: setting an array element with a sequence.
How can i solve this?
func here takes in a vector but it must be a scalar function of one or more variables as indicated in the scipy.optimize.minimize doc

qmath very strange AttributeError

I'm trying to use qmath, a quaternion lib.
this
from qmath import qmathcore
a = qmathcore.quaternion([1,2,3,4])
print a.conj()
gives me such traceback
Traceback (most recent call last):
File "*******/q_test.py", line 25, in <module>
print str(a.conj())
File "*******/venv/lib/python2.7/site-packages/qmath/qmathcore.py", line 788, in conj
return self.real() - self.imag()
File "*******/venv/lib/python2.7/site-packages/qmath/qmathcore.py", line 762, in imag
return self - self.real()
File "*******/venv/lib/python2.7/site-packages/qmath/qmathcore.py", line 522, in __sub__
self -= other
File "*******/venv/lib/python2.7/site-packages/qmath/qmathcore.py", line 407, in __isub__
self.other = quaternion(other)
File "*******/venv/lib/python2.7/site-packages/qmath/qmathcore.py", line 81, in __init__
self.q = q.q
AttributeError: quaternion instance has no attribute 'q'
but in docs they said, that this must work:
def conj(self):
"""
Returns the conjugate of the quaternion
>>> import qmathcore
>>> a = qmathcore.quaternion([1,2,3,4])
>>> a.conj()
(1.0-2.0i-3.0j-4.0k)
>>> a = qmathcore.hurwitz([1,2,3,4])
>>> a.conj()
(1-2i-3j-4k)
"""
return self.real() - self.imag()
what is this?
qmathcore.py fails its own doctest with a newer (1.9) numpy.
Adding this test to quatereon()
elif isinstance(q,float) or isinstance(q,int): # accept np.float64
self.q = 1.0 * np.array([q,0.,0.,0.])
allows qmath.quaternion([1,2,3,4]).imag() (and conj).
The quaternion method is using a lot of type(q)==xxx tests. isinstance() is a more robust test. Also it ends with a else:pass, and thus doesn't catch q values that it can't handle.
After correcting some import errors, the qmathcore doctest runs fine.

Categories