0

I am receiving the error stated in the title. Full error:

MaxD = Cone*np.sqrt(SymsX/np.pi)*np.exp((-SymsX/(k*T))) #Define Maxwellian distribution function

AttributeError: 'Mul' object has no attribute 'sqrt'

Here is the code:

from sympy.interactive import printing
printing.init_printing(use_latex = True)
import numpy as np
from sympy import Eq, dsolve, Function, Symbol, symbols
import sympy as sp

EpNaut = 8.854187E-12
u0 = 1.256E-6
k = 1/(4*np.pi*EpNaut)
NumGen = 1000 #How many solution points user wants to generate between 0 and maxen (Higher # the more accurate)
T = 1000 #Temperature in (K)
MaxEn = 7*T*k #Max energy in system
Cone = 2/((k*T)**(3/2)) #Constant infront of the Maxwellian distribution function

SymsX = sp.Symbol('SymsX')
MaxD = Function('MaxD')
PFunction = Function('PFunction')
MaxD = Cone*np.sqrt(SymsX/np.pi)*np.exp((-SymsX/(k*T))) #Define Maxwellian distribution function
PFunction = sp.integrate(MaxD) #Integrate function to get probability-error function

print(PFunction)

I also have an additional question. I sometimes see examples use "from ... import ...". Why is this? Shouldn't just importing the entire library be enough? Is it because using the import command doesn't actually import the entire library but really just the most basic functions?

hpaulj
  • 221,503
  • 14
  • 230
  • 353
Tom
  • 55
  • 6
  • Does this answer your question? [What causes this error (AttributeError: 'Mul' object has no attribute 'cos') in Python?](https://stackoverflow.com/questions/32640759/what-causes-this-error-attributeerror-mul-object-has-no-attribute-cos-in) – Hùng Nguyễn Dec 09 '19 at 03:40
  • 1
    I added some relevant tags. The problem arises from using `sympy` object in a `numpy` function. A beginner should not try to mix `sympy`and `numpy`; that isn't a trivial task. I could go into why it produces an error in this case, but for now it's simpler to just say - don't do it! – hpaulj Dec 09 '19 at 03:42
  • (at)Hung Nguyen I had already looked at that post prior to posting mine and I could see how it works for that instance, but I don't see it work as a general solution because... @hpaulj what if there are operators/constants I wish to use that are only in certain libraries? I will need to mix library usage within the same definitions at some point. Example: sqrt() operator only exists in the np and math libraries and defining functions and symbols can only be handled by functions in the sp library. – Tom Dec 09 '19 at 04:07
  • `sympy` can do `sqrt`, as well as all the transcendentals. – hpaulj Dec 09 '19 at 04:25
  • @hpaulj Alright I wasn't able to locate them on the documentation. I will take a closer look. I assume it is ok still to import multiple libraries for the same script at least so long as the definitions themselves don't use both correct? Because at some point I wish to use both symbolic math (with sympy) and numerical integration (with numpy) in the same script since neither do both of those things. – Tom Dec 09 '19 at 04:34

2 Answers2

0

In an isympy session:

In [1]: import numpy as np                                                      

In [3]: SymsX = Symbol('SymsX')                                                 

In [5]: SymsX/np.pi                 # symbol * float                                                             
Out[5]: 0.318309886183791⋅SymsX

In [6]: SymsX/pi                    # symbol * symbol                            
Out[6]: 
SymsX
─────
  π  

In [7]: sqrt(SymsX/pi)             # sympy sqrt                           
Out[7]: 
  _______
╲╱ SymsX 
─────────
    √π   

In [8]: np.sqrt(SymsX/pi)          # numeric sqrt                                 
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
AttributeError: 'Mul' object has no attribute 'sqrt'

The above exception was the direct cause of the following exception:

TypeError                                 Traceback (most recent call last)
<ipython-input-8-27f855f6b3e2> in <module>
----> 1 np.sqrt(SymsX/pi)

TypeError: loop of ufunc does not support argument 0 of type Mul which has no callable sqrt method

np.sqrt has to first convert its input into a numpy array:

In [10]: np.array(SymsX/np.pi)                                                  
Out[10]: array(0.318309886183791*SymsX, dtype=object)

This is an object dtype array, not a normal numeric one. Given such an array, q numpy ufunc tries to delegate the action to a element method. e.g. (0.31*SymsX).sqrt()

Multiply and addition do work with this object array:

In [11]: 2*_                                                                    
Out[11]: 0.636619772367581⋅SymsX

In [12]: _ + __                                                                 
Out[12]: 0.954929658551372⋅SymsX

These work because the sympy object has the right add and multiply methods:

In [14]: Out[5].__add__                                                         
Out[14]: <bound method Expr.__add__ of 0.318309886183791*SymsX>

In [15]: Out[5]+2*Out[5]                                                        
Out[15]: 0.954929658551372⋅SymsX

===

The sympy.lambdify is the best tool for using sympy and numpy together. Look up its docs.

In this case the SymsX/pi expression can be converted into a numpy expression with:

In [18]: lambdify(SymsX, Out[5],'numpy')                                        
Out[18]: <function _lambdifygenerated(SymsX)>

In [19]: _(23)            # evaluate with `SymsX=23`:                                                                  
Out[19]: 7.321127382227194

In [20]: 23/np.pi                                                               
Out[20]: 7.321127382227186

In [21]: np.sqrt(_19)        # np.sqrt now works on the number                            
Out[21]: 2.7057581899030065

====

The same evaluation in sympy:

In [23]: expr = sqrt(SymsX/pi)                                                  

In [24]: expr                                                                   
Out[24]: 
  _______
╲╱ SymsX 
─────────
    √π   

In [25]: expr.subs(SymsX, 23)                                                   
Out[25]: 
√23
───
 √π

In [27]: _.evalf()                                                              
Out[27]: 2.70575818990300
hpaulj
  • 221,503
  • 14
  • 230
  • 353
0

In a fresh isympy session:

These commands were executed:
>>> from __future__ import division
>>> from sympy import *
>>> x, y, z, t = symbols('x y z t')
>>> k, m, n = symbols('k m n', integer=True)
>>> f, g, h = symbols('f g h', cls=Function)
>>> init_printing()

Documentation can be found at https://docs.sympy.org/1.4/


In [1]: EpNaut = 8.854187E-12 
   ...: u0 = 1.256E-6 
   ...: k = 1/(4*pi*EpNaut) 
   ...: NumGen = 1000  
   ...: T = 1000  
   ...: MaxEn = 7*T*k  
   ...: Cone = 2/((k*T)**(3/2)) 
   ...:  
   ...: SymsX = Symbol('SymsX') 
   ...: MaxD = Function('MaxD') 
   ...: PFunction = Function('PFunction') 
   ...: MaxD = Cone*sqrt(SymsX/pi)*exp((-SymsX/(k*T))) #Define Maxwellian distri
   ...: bution function 
   ...: PFunction = integrate(MaxD) #Integrate function to get probability-error
   ...:  function 
   ...:                                                                         

The result:

In [2]: PFunction                                                               
Out[2]: 
                          ⎛                     _______  -3.5416748e-14⋅π⋅Syms
                      1.0 ⎜  28235229276273.5⋅╲╱ SymsX ⋅ℯ                     
1.33303949775482e-20⋅π   ⋅⎜- ─────────────────────────────────────────────────
                          ⎝                          π                        

X                           ⎛                         _______⎞⎞
    7.50165318945357e+19⋅erf⎝1.88193379267178e-7⋅√π⋅╲╱ SymsX ⎠⎟
─ + ──────────────────────────────────────────────────────────⎟
                                π                             ⎠

In [3]: MaxD                                                                    
Out[3]: 
                      1.0   _______  -3.5416748e-14⋅π⋅SymsX
1.33303949775482e-20⋅π   ⋅╲╱ SymsX ⋅ℯ                      

SymsX is still a symbol, so these are sympy expressions, not numbers.

hpaulj
  • 221,503
  • 14
  • 230
  • 353