I am making a script where you can input a, b and c into the quadratic formula and it will give you the answer.
It says that b is not defined when I run it.
from cmath import sqrt
qf = lambda a, b, c: (-b-cmath.sqrt((b**2) - (4*a*c)))/(2*a), (-b+cmath.sqrt((b**2) - (4*a*c)))/(2*a)
a, b, c = input('Enter a, b and c with spaces in between the values \n').split()
a = float(a) ; b = float(b) ; c = float(c)
Print(qf(a, b,c)
Traceback (most recent call last):
File "/storage/emulated/0/Download/.last_tmp.py", line 2, in
qf = lambda a, b, c: (-b-cmath.sqrt((b2) - (4*a*c)))/(2*a), (-b+cmath.sqrt((b2) - (4*a*c)))/(2*a)
NameError: name 'b' is not defined
Check this out:
from math import sqrt
def get_roots(a, b, c):
if a == 0:
raise ZeroDivisionError('Not a quadratic equation')
val = b ** 2 - 4 * a * c
if val < 0:
raise Exception('Imaginary Roots')
val = sqrt(val)
root1 = (-b - val) / (2 * a)
root2 = (-b + val) / (2 * a)
return root1, root2
a, b, c = input('Enter a, b and c with spaces in between the values \n').split()
a, b, c = float(a), float(b), float(c)
print(get_roots(a,b,c))
Lambda functions can only return one thing so you need to group your outputs into either a tuple or a list by adding an enclosing () or []. The python parser is getting to:
qf = lambda a, b, c: (-b-sqrt((b**2) - (4*a*c)))/(2*a)
and assuming the lambda function is over. It then begins reading:
, (-b+sqrt((b**2) - (4*a*c)))/(2*a)
and tries to interpret -b in the global scope (where it doesn't exist) this gives you your name error. If you were to get rid of all the variables and for a moment pretend the second result of the quadratic formula was always 0, you'd get a tuple with the first element being a lambda function and the second being the integer 0
>>>qf = lambda a, b, c: [(-b-sqrt((b**2) - (4*a*c)))/(2*a),0
>>>qf
(<function <lambda> at 0x000002B44EF72F28>, 0)
This doesn't quite get what you're after, because you want a single function rather than a tuple of two separate functions to compute each root separately.
Here's what it'd look like if you want the lambda to return a list:
qf = lambda a, b, c: [(-b-sqrt((b**2) - (4*a*c)))/(2*a), (-b+sqrt((b**2) - (4*a*c)))/(2*a)]
Related
I was attempting to exemplify python lambda expressions with the well-known formula for triangle's area. Given the three sides a, b, and c and the semi perimeter s as (a+b+c)/2, the area is square root of (s * (s-a) * (s-b) * (s-c)). So, I wrote the python code:
s = lambda a, b, c : (a + b + c)/2 #Line 1
area_tri = lambda a, b, c : (s(a,b,c) * (s(a,b,c)-a) * (s(a,b,c)-b) * \
(s(a,b,c)*c)) ** 0.5
area_tri(1, 2, 3)
The statement computing area_tri has to compute s(a, b, c) four times. So, I thought if I could write something like:
semi = s
after Line 1 and replace every occurrence of s(a,b,c) with semi in the area_tri computation statement. But, it would produce an error that a, b and c are unknown symbols. Is there an error-free alternative?
After python3.8, you can use walrus operator:=:
area_tri = lambda a, b, c: ((semi := s(a, b, c)) * (semi - a) * (semi - b) * (semi - c)) ** 0.5
For earlier versions, the best way is to define a function:
def area_tri(a, b, c):
semi = s(a, b, c)
return (semi * (semi - a) * (semi - b) * (semi - c)) ** 0.5
I'm trying to implement the multivariate chain rule using python, when I try to substitute one of the elements using the built-in sympy function expr.subs() I won't get an answer.
The exercise goes as follows:
Compute df/dx of the following function using the chain rule:
a = x^2
b = exp(a)
c = a + b
d = log(c)
e = sin(c)
f = d + e
And this is the code:
a, b, c, d, e, f = sym.symbols('a b c d e f')
f = d + e
dfd = sym.diff(f, d)
dfe = sym.diff(f, e)
df = sym.Matrix([[dfd, dfe]])
d = sym.log(c)
e = sym.sin(c)
ddc = sym.diff(d)
dde = sym.diff(e)
dd = sym.Matrix([[ddc],[dde]])
dfdd = df#dd
c = a + b
dca = sym.diff(c, a)
dcb = sym.diff(c, b)
dc = sym. Matrix([[dca, dcb]])
dfdc = dfdd#dc
a = x**2
b = sym.exp(a)
result = dfdc.subs(c, (a + b))
result
The result the function .subs() doesn't substitute anything and I don't know why, I tried substituting it using other ways to write the function, like:
dfdc.subs({c : (a + b)})
dfdc.subs(c, a + b)
And even tried to just substitute it for an integer to see it that would work and neither does it.
What am I doing wrong?
The c in your dfdc expression was created before you set c=a+b. So it still appears as c in dfdc. However, by the time you want to do your subs, the c symbol is declared as c=a+b, and so your substitute really reads
dfdc.subs(a+b, a+b)
And that does nothing.
In order to really use c there, do
dfdc.subs(sym.Symbol('c'), a+b)
I have a small module written as:
Contents of psychometrics.py
def prob3pl(theta, D = 1.7, a, b, c):
result = c + (1 - c) / (1 + np.exp(-D * a * (theta - b)))
return(result)
def gpcm(theta, d, score, a, D=1.7):
Da = D * a
result = np.exp(np.sum(Da * (theta - d[0:score]))) / np.sum(np.exp(np.cumsum(Da * (theta - d))))
return(result)
if __name__ == '__main__':
gpcm(theta, d, score, a, D=1.7)
prob3pl(theta, D = 1.7, a, b, c)
Now using the python interpret I do the following:
import psychometrics as py
import numpy as np
py.prob3pl(0, a = 1, b= 0, c=0)
However, when running this yields
>>> py.prob3pl(0,a=1,b=0,c=0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: prob3pl() missing 1 required positional argument: 'D'
When I copy and paste the function into the interpreter it runs using the default value of D = 1 but when importing that isn't happening.
What error am I making such that the default value for D is not recognized when I import the module?
Thank you
Your code has syntax error -
SyntaxError: non-default argument follows default argument
Therefore, kindly change function prob3pl() as
def prob3pl(theta, a, b, c, D = 1.7):
result = c + (1 - c) / (1 + np.exp(-D * a * (theta - b)))
return(result)
Reason - In python function declaration, there should not be any non-default argument after any default argument. as D=1.7 here
Simple question on how to link (or string together) multiple functions that depend on each other. I have the following example function (in Jupyter):
### First function
def function_one():
## process one
a = "one" + "two"
print(a)
## process two
b = "red" + "blue"
print(b)
## process three
c = "this" + "sucks"
print(c)
return a, b, c
### Second function
def function_two(a, b, c):
## process four
d = a + b
print(d)
## process five
e = b + c
print(e)
## process six
f = a + c
print(f)
return d, e, f
### Third function
def function_three():
g = a + b + c + d + e + f
print(g)
return g
### Calling functions
initial = function_one()
second = function_two(initial)
third = ... #I can't get past the following error to even link this function in
The first function works when called, but when I try to send that data downstream to the second function, I get this error:
onetwo
redblue
thissucks
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-10-7c5562b97c86> in <module>
1 initial = function_one()
----> 2 second = function_two(initial)
TypeError: function_two() missing 2 required positional arguments: 'b' and 'c'
How do I remedy this?
When returning multiple objects, you are actually returning a tuple. Ex:
>>> def foo():
>>> return 1, 2, 3
>>> type(foo())
<class 'tuple'>
So, right now the whole tuple is treated as argument a and hence b and c are missing. In order to pass that on as 3 separate arguments, you need to unpack that tuple:
initial = function_one()
second = function_two(*initial)
third = function_three(*initial, *second)
Assign the return values to variables then pass it to the second function:
a, b, c = function_one()
function_two(a, b, c)
For your third function you need it to accept parameters as well
def function_three(a, b, c, d, e, f):
g = a + b + c + d + e + f
print(g)
return g
Then putting it all together:
a, b, c = function_one()
d, e, f = function_two(a, b, c)
g = function_three(a, b, c, d, e, f)
I have three variables called a, b and c, each of these can assume a different value defined in a range. I'd like to create a function that tests every possible variable value and gives me their best combination for the output 'f'.
a = list(range(1, 10, 2))
b = list(range(5, 8, 1))
c = list(range(1, 3, 1))
def all_combinations (a, b, c):
#something
f = a + (b * a) - (c*(a ^ b))
return BEST a, b, c for my f
it's possible to do it ? what is the best way to do it?
You can use itertools.product() to get all the possible combinations of a, b, and c.
Then calculate your formula for each unique combination of a b c, keep track of the result, and if the result is better than the previous best, save the current values of a b c.
import itertools
def all_combinations (alist, blist, clist):
best_a = 0
best_b = 0
best_c = 0
best_f = 0
for a,b,c in itertools.product(alist, blist, clist):
f = a + (b * a) - (c*(a ^ b))
if f > best_f: # use your own definition of "better"
best_a = a
best_b = b
best_c = c
best_f = f
return best_a, best_b, best_c
First of all, you said I have three variables called a, b and c, each of these can assume a different value defined in a range. Note that the variables in your code are actually equal to three lists of integers, not three integers.
The naive algorithm to test all possible combinations is 3 nested for loops. Here I assume that by "best" you mean "maximum value":
def all_combinations (list1, list2, list3):
best_f, best_a, best_b, best_c = None, None, None, None
for a in list1:
for b in list2:
for c in list3:
f = a + (b * a) - (c*(a ^ b))
# here you have to define what f being "better" than best_f means:
if not f or f > best_f:
best_f = f
best_a = a
best_b = b
best_c = c
return best_a, best_b, best_c
If you're sure those are the only values you want to test, then the following will work. Otherwise you might want to look into scipy.optimize.
from itertools import product
import numpy as np
parameters = list(product(a, b, c))
results = [my_fun(*x) for x in parameters]
print(parameters[np.argmax(results)])
obviously replace np.argmax with np.argmin if you want to minimize the function