I'm writing a function that takes 2 lists and creates a polynomial function to later be solved by optimization.
I'm trying to create a string that looks like a function, convert it into a function by using sympy.sympify() and then pass it into optimize.newton().
However it keeps throwing a TypeError "Add" object is not callable while I already think that sympify has correctly returned a function.
I think I'm missing something very basic, maybe there is a function to turn my variable function0 into a function type for scipy to interpret correctly maybe?
def poly_build(coefficient_list, power_list):
'''
coefficient_list & power_list must be iterable objects of the same length, preferably a list
'''
if len (coefficient_list) != len(power_list):
return False
function = ""
for n in range(0, len(coefficient_list)):
if n != len(coefficient_list) - 1:
function += f'{coefficient_list[n]}*x**{power_list[n]} +'
else:
function += f'{coefficient_list[n]}*x**{power_list[n]}'
function0 = (sympy.sympify(function))
function1 = sympy.diff(function0)
function2 = sympy.diff(function1)
return scipy.optimize.newton(function0, 1.5)
A sympy function isn't a Python function as scipy.optimize.newton expects it. To convert:
pyfunction0 = sympy.lambdify(x, function0)
Related
I am trying to write a simple function that converts an input written in LaTeX to a ufunc that can be read by numpy. So far, I'm testing the function by converting \sin(x) to np.sin(x) (ignoring the conversion from {} to (). I'm not that familiar with ufuncs so I keep running into an error when trying to convert the \sin(x) string to the np.sin(x) ufunc for any given x.
import numpy as np
latexEq = input()
def latexMap(latexEq):
if "\sin" in latexEq:
sinLatex = latexEq.replace("\sin", "np.sin")
else:
pass
return sinLatex
npOutput = np.ufunc(latexMap(latexEq))
print(f"f(x)={numpyOutput}")
Similar to how an integer may be converted into a string str(2), I tried enclosed both sinLatex, latexEq, "np.sin", and npOutput but the error I always receive is
TypeError: cannot create 'numpy.ufunc' instances
Any explanation would be appreciated.
So if you just have npOutput = "np.sin" (without the (x)) you can do
# function_name = getattr(module, function_name_string)
npOutput = getattr(np, npOutput.lstrip("np."))
which gives you the function np.sin. The parentheses have to be gone because otherwise it would be a function call, not a function.
Let's assume I have two functions
def seq():
#here I wrote a code that evaluates the mean of a value from a csv file
print(x)#assuming the condition in the above code is true it prints x
seq()
and
def lenn():
p=4
d=#I want this variable to be the value that the 1st function produces
x=d/p
lenn()
One produces an integer and the other uses the output of the 1st function and then divides it with an integer to produce its own output. How do I call the function?
I tried calling the function name but when I tried to divide the function name with an integer it keeps saying that I have a None type. I also tried to put the 1st first function inside the 2nd function but I had the same problem.
How can i solve this?
Don't use print but return (print has no return value, so this defaults to None):
def seq():
return int(input())
def lenn():
p=4
d=seq()
x=d/p
return x
print(lenn())
The problem is that seq does not return the inputted value (x). Anyway, I wouldn't place int(input(x)) in its own function. You can try something like
def lenn():
p=4
d=int(input())
x=d/p
return x
I'm trying to find the maximum of any function f(x) in a certain range and in which x this happens. The arguments of the python function would be (f(x),[a,b]). f(x) being any function and [a,b] the range we will be studying.
For now I've tried a few things but none of them worked. The one I liked the most was a failure because of trying to convert a string onto a float.
def maxf(function,interval):
maxresult = 0
for x in range(interval[0]-1,interval[1]+1):
result=float(function.replace("x",str(x)))
if result >= maxresult:
maxresult = result
maxresultx = x
return maxresult,maxresultx
print(maxf("x**2",[1,3]))
This one returns:
Traceback (most recent call last):
File "main.py", line 10, in <module>
print(maxf("x**2",[1,3]))
File "main.py", line 4, in maxf
result=float(function.replace("x",str(x)))
ValueError: could not convert string to float: '0**2'
I don't know if there is an easier way to do it or how to correct the code so that I can convert that string.
Your problem is that float() accepts a string that already represents a float (eg float("1.23"), not an expression that will result in one (eg float("2**3")). So, you must first evaluate the string.
float(eval("3**2"))
eval() will run any code contained in the string, so don't use it on code you don't trust.
Use this:
def maxf(function,interval):
maxresult = 0
for x in range(interval[0]-1,interval[1]+1):
result=float(function(x))
if result >= maxresult:
maxresult = result
maxresultx = x
return maxresult,maxresultx
print(maxf(lambda x: x**2,[1,3]))
lambda defines a function (an anonymous one) that is passed as parameter, thus maxf can call it as needed.
Python is (also) a functional language, which means that you can use functions as you use ints or floats, etc. A function is just a bunch of callable code, you can associate an identifier to a function or not (just like int values referred by identifiers or as constant in code).
-----EDIT----- suggested by #bacjist
If you don't want to use lambda, then you may define the function as usual:
def f(x):
return x**2
and then call:
print(maxf(f,[1,3]))
The problem is your string is not actually being evaluated. It is just being converted to float so as the error suggests what you are doing is converting "0**2" to float which is not possible what you can do is make use of eval function to evaluate any given string and then compare the result.
You just need to make a small change like this:
result=eval(function.replace("x",str(x)))
This yet not the best way to do this you should use generator there:
def maxf(function,interval):
maxresult = 0
for x in range(interval[0]-1,interval[1]+1):
yield eval(function.replace("x",str(x))), x
print(max(maxf("x**2", [1, 3])))
A more pythonic approach would be using lambda with max function as a key
a_list = [1,3]
max_item = max(a_list, key=lambda x: eval("x**2"))
print(eval("x**2".replace("x", str(max_item))), max_item)
I am trying to create a function, which returns a vector and then integrating it element by element. This is what I have so far
def int1(b):
j = 1
for q in range(0,len(alpha)):
j = j + alpha[q]*(b**q)
p = np.exp(-j);
inu = np.zeros(len(alpha))
for q in range(0,len(alpha)):
inu[q] = np.exp(-j)*(b**q)
return inu
This works if I type something like
print int1(0.1)[2]
However
print sp.integrate.quad(int1(b)[2], 1e-16, 1, epsrel=1e-20)[0]
does not work, or any reasonable variant I can think of. How can I get it to work?
either i get TypeError: 'function' object has no attribute 'getitem' if i leave out the b or ValueError: invalid callable given if I have it in.
The first argument of quad must be a function, something that call be called. Something that you can put (0.1) after and it will make sense. Does int1(b)[2](0.1) make sense? To me neither.
The form quad(int1, 1e-16, 1, epsrel=1e-20)[0] is syntactically correct but quad only allows scalar outputs of the function, so it won't work with your int1. Instead, you need to make a new function that uses int1 but then returns only one of its components. Instead of having another def somewhere, it's better to make such a function right where it is needed, using lambda syntax:
quad(lambda b: int1(b)[2], 1e-16, 1, epsrel=1e-20)[0]
This says: take b, put it in int1, keep the index-2 entry of the returned array.
Is there a keyword in Matlab that is roughly equivalent to None in python?
I am trying to use it to mark an optional argument to a function. I am translating the following Python code
def f(x,y=None):
if y == None:
return g(x)
else:
return h(x,y)
into Matlab
function rtrn = f(x,y)
if y == []:
rtrn = g(x);
else
rtrn = h(x,y);
end;
end
As you can see currently I am using [] as None. Is there a better way to do this?
in your specific case. you may use nargin to determine how many input arguments here provided when calling the function.
from the MATLAB documentation:
The nargin and nargout functions
enable you to determine how many input
and output arguments a function is
called with. You can then use
conditional statements to perform
different tasks depending on the
number of arguments. For example,
function c = testarg1(a, b)
if (nargin == 1)
c = a .^ 2;
elseif (nargin == 2)
c = a + b;
end
Given a single input argument, this
function squares the input value.
Given two inputs, it adds them
together.
NaN while not equivalent, often serves the similar purpose.
nargin is definitely the easiest way of doing it. Also it is usually good practice to validate the number of input argument using nargchk:
function e = testFunc(a,b,c,d)
error( nargchk(2, 4, nargin, 'struct') );
% set default values
if nargin<4, d = 0; end
if nargin<3, c = 0; end
% ..
c = a*b + c*d;
end
... which acts as a way to ensure the correct number of arguments is passed. In this case, a minimum of two arguments are required, with a maximum of four.
If nargchk detects no error, execution resumes normally, otherwise an error is generated. For example, calling testFunc(1) generates:
Not enough input arguments.
UPDATE: A new function was introduced in R2011b narginchk, which replaces the use of the deprecated nargchk+error seen above:
narginchk(2,4);
You can use functions like: exist and isempty to check whether a variable exists and whether it is empty respectively:
if ~exist('c','var') || isempty(c)
c = 10;
end
which allows you to call your function such as: testFunc(1,2,[],4) telling it to use the default value for c but still giving a value for d
You could also use varargin to accept a variable number of arguments.
Finally a powerful way to parse and validate named inputs is to use inputParser
To see examples and other alternatives of passing arguments and setting default values, check out this post and its comments as well.
The equivalent to Python None in MATLAB is string(missing)
To test, type the following in your command window : py.type( string(missing) )
It returns <class 'NoneType'>
MATLAB to python data types documentation here
If you want to pass None into a Python function that you are calling from MATLAB, then you would pass in string(missing). This argument would show up as None in the Python function, for example, if you are detecting for None such as if arg1 == None.