TypeError: only length-1 arrays can be converted to Python scalars (2)

3

Hello again I am with the same error but in a different place.

Veran I have the following code

import matplotlib.pyplot as plt
import numpy as np

from py_expression_eval import *


def f(exp, var, x0):

    p = Parser()
    p.ops2['^'] = np.power
    result = p.parse(exp).evaluate({var:x0})
    return result

a = 0

b = 4

error = 10

i = 0

while(error>1e-8 and i!=100):

    c = (a + b) / 2
    fa = f('x^3 -2 * x^2 - 1', 'x', a)
    fc = f('x^3 -2 * x^2 - 1', 'x', c)
    if(fc == 0):
        raiz = c
        break
    elif(fa * fc < 0):
        b = c
    else:
        a = c
    raiz = c
    i += 1
    error = abs(fc)
    print("Iteracion",i,". Raiz aproximada:",raiz)
print(raiz)

print(i)

print(f('x^3 -2 * x^2 - 1', 'x',raiz))


x = np.linspace(0, 4, 101)

print(x)

plt.plot(x, f('x^3 -2 * x^2 - 1','x',x))

plt.plot(a, f('x^3 -2 * x^2 - 1', 'x', a), 'or')

plt.grid()

plt.show()

It works perfectly but the problem I had before was the same as the title, a good partner of this site helped me saying the following: It is a common mistake when mixing NumPy arrays and certain native mathematical operations or defined in the standard Python library as math.sqrt ().

In your case the problem originates in the line:

plt.plot(x, f('x^3 -2 * x^2 - 1','x',x))

The problem is interestingly the enhancement operation, which causes the problem because it expects scalars as input parameters but you are passing an array of Numpy:

x = np.linspace(0, 4, 101)

The solution in these cases is usually to replace the problematic function with its equivalent in the Numpyy library, which accepts NumPy arrays as an input parameter. In this case the analog of ^ is numpy.power (), for this you can modify the operator that will use modifying ops2:

parser.ops2['^'] = np.power

and I understood him but when trying to graph with the function

f('x^3 -2 * sin(x^2) - 1','x',x)

the error of the title reappears because of the sin since I imagine that it can not receive a numpy array either and try to solve it by saying that p.ops3['sin'] = np.sin but it tells me that parser does not have an attribute ops3 , or like the one that answered me if I can put ops2 and grab him? How do I name it after parser? I'm sorry to ask this because it's probably very obvious but I'm just learning python:, v

The complete error message is as follows:

  

Traceback (most recent call last):

     

File "C: \ Users \ Daniel \ Desktop \ bisection3.py", line 36, in       plt.plot (x, f ('x ^ 3 -2 * sin (x ^ 2) - 1', 'x', x))

     

File "C: \ Users \ Daniel \ Desktop \ bisection3.py", line 8, in f       result = p.parse (exp) .evaluate ({var: x0})

     

File   "C: \ Users \ Daniel \ AppData \ Local \ Programs \ Python \ Python36-32 \ lib \ site-packages \ py_expression_eval__init __. Py",   line 133, in evaluate       nstack.append (f (n1))

     

TypeError: only length-1 arrays can be converted to Python scalars

    
asked by Daniel V 03.03.2017 в 01:49
source

1 answer

1

Maybe I just needed to explain a bit better where I get op2 , it's actually a Python dictionary belonging to the class Parser where the key is a string as + or ^ and as value has the corresponding function / operation that will be used to resolve the expression, using the library math or methods implemented in the library py_expressions_eval . There are other dictionaries that are used for the same purpose and that you can modify to adapt to your needs, the key is to know where everything is located.

In the case of the sine function, you can find op1 with the key sin and use math.sin to solve As in the previous case you must specify that numpy.sin be used instead to be able to work with arrays as input parameters to the function.

I leave you a list of the dictionaries that are used as attributes in the class Parser to specify the functions used to solve each expression in case you need to modify other operators or functions:

self.ops1 = {
    'sin': math.sin,
    'cos': math.cos,
    'tan': math.tan,
    'asin': math.asin,
    'acos': math.acos,
    'atan': math.atan,
    'sqrt': math.sqrt,
    'log': math.log,
    'abs': abs,
    'ceil': math.ceil,
    'floor': math.floor,
    'round': round,
    '-': self.neg,
    'exp': math.exp,
}

self.ops2 = {
    '+': self.add,
    '-': self.sub,
    '*': self.mul,
    '/': self.div,
    '%': self.mod,
    '^': math.pow,
    ',': self.append,
    '||': self.concat,
    "==": self.equal,
    "!=": self.notEqual,
    ">": self.greaterThan,
    "<": self.lessThan,
    ">=": self.greaterThanEqual,
    "<=": self.lessThanEqual,
    "and": self.andOperator,
    "or": self.orOperator
}

self.functions = {
    'random': random,
    'fac': self.fac,
    'min': min,
    'max': max,
    'pyt': self.pyt,
    'pow': math.pow,
    'atan2': math.atan2,
    'concat':self.concat
}

self.consts = {
    'E': math.e,
    'PI': math.pi,
}

self.values = {
    'sin': math.sin,
    'cos': math.cos,
    'tan': math.tan,
    'asin': math.asin,
    'acos': math.acos,
    'atan': math.atan,
    'sqrt': math.sqrt,
    'log': math.log,
    'abs': abs,
    'ceil': math.ceil,
    'floor': math.floor,
    'round': round,
    'random': self.random,
    'fac': self.fac,
    'exp': math.exp,
    'min': min,
    'max': max,
    'pyt': self.pyt,
    'pow': math.pow,
    'atan2': math.atan2,
    'E': math.e,
    'PI': math.pi
}

It's just a fragment of the library code py_expressions_eval and you can get it in full from pypi or the GitHub repository .

Therefore your code should be something like this:

import matplotlib.pyplot as plt
import numpy as np
from py_expression_eval import *

def f(exp, var, x0):
    p = Parser()
    p.ops2['^'] = np.power
    p.ops1['sin'] = np.sin
    result = p.parse(exp).evaluate({var:x0})
    return result
a = 0
b = 4
error = 10
i = 0
while(error>1e-8 and i!=100):
    c = (a + b) / 2
    fa = f('x^3 -2 * sin(x^2) - 1','x',a)
    fc = f('x^3 -2 * sin(x^2) - 1', 'x', c)
    if(fc == 0):
        raiz = c
        break
    elif(fa * fc < 0):
        b = c
    else:
        a = c
    raiz = c
    i += 1
    error = abs(fc)
    print("Iteracion",i,". Raiz aproximada:",raiz)
print(raiz)
print(i)
print(f('x^3 -2 * sin(x^2) - 1', 'x',raiz))

x = np.linspace(0, 4, 101)
print(x)
plt.plot(x, f('x^3 -2 * sin(x^2) - 1','x',x))
plt.plot(a, f('x^3 -2 * sin(x^2) - 1', 'x', a), 'or')
plt.grid()
plt.show()

Which shows:

    
answered by 03.03.2017 / 08:19
source