I built a calculator for a bio equation, and I think I've narrowed down the source of my problem, which is a natural log I take:
goldman = ((R * T) / F) * cmath.log(float(top_row) / float(bot_row))
print("Membrane potential: " + str(goldman) + "V"
My problem is that it will only display the output in a complex form:
Membrane potential: (0.005100608207126714+0j)V
Is there any way of getting this to print as a floating number? Nothing I've tried has worked.
Complex numbers have a real part and an imaginary part:
>>> c = complex(1, 0)
>>> c
(1+0j)
>>> c.real
1.0
It looks like you just want the real part... so:
print("Membrane potential: " + str(goldman.real) + "V"
Use math.log instead of cmath.log.
Since you don't want the imaginary part of the result, it would be better to use math.log instead of cmath.log. This way, you'll get an error if your input is not in the valid domain for a real log, which is much better than silently giving you meaningless results (for example, if top_row is negative). Also, complex numbered results make no sense for this particular equation.
ie, use:
goldman = ((R * T) / F) * math.log(float(top_row) / float(bot_row))
If you want to just convert it to float value you can do this:
def print_float(x1):
a=x1.real
b=x1.imag
val=a+b
print(val)
ec=complex(2,3)
In this way you can actually get the floating value.
It is simple if you need only real part of the complex number.
goldman = 0.005100608207126714+0j
print(goldman)
(0.005100608207126714+0j)
goldman = float(goldman.real)
print(goldman)
0.005100608207126714
If you need absolute value then use following
goldman = 0.005100608207126714+0j
print(goldman)
(0.005100608207126714+0j)
goldman = float(abs(goldman))
print(goldman)
0.005100608207126714
print(type(goldman))
<class 'float'>
Related
Description of the practical problem:
I have defined many expression using sympy, as in
import sympy as sp
a, b = sp.symbols('a,b', real=True, positive=True)
Xcharles_YclassA_Zregion1 = 1.01 * a**1.01 * b**0.99
Xbob_YclassA_Zregion1 = 1.009999 * a**1.01 * b**0.99
Xbob_YclassA_Zregion2 = 1.009999 * a**1.01 * b**0.99000000001
...
So I have used the names of the expressions to describe options (e.g., charles, bob) within categories (e.g., X).
Now I want a function that takes two strings (e.g., 'Xcharles_YclassA_Zregion1' and 'Xbob_YclassA_Zregion1') and returns its simplified ratio (in this example, 1.00000099009999), so I can quickly check "how different" they are, in terms of result, not in terms of how they are written.
E.g., 2*a and a*2 are the same for my objective.
How can I achieve this?
Notes:
The expressions in the example are hardcoded for the sake of simplicity. But in my actual case they come from a sequence of many other expressions and operations.
Not all combinations of options for all categories would exist. E.g., Xcharles_YclassA_Zregion2 may not exist. Actually, if I were to write a table for existing expression names, it would be sparsely filled.
I guess rewriting my code using dict to store the table might solve my problem. But I would have to modify a lot of code for that.
Besides the practical aspects of my objective, I don't know if there is any formal difference between Symbol (which is a specific class) and expression. From the sources I read (e.g., this) I did not arrive to a conclusion. This understanding may help in solving the question.
TL;DR - What I tried
I aimed at something like
def verify_ratio(vstr1, vstr2):
"""Compare the result of two different computations of the same quantity"""
ratio = sp.N(sp.parsing.sympy_parser.parse_expr(vstr1)) / sp.parsing.sympy_parser.parse_expr(vstr2)
print(vstr1 + ' / ' + vstr2, '=', sp.N(ratio))
return
This did not work.
Code below shows why
import sympy as sp
a, b = sp.symbols('a,b', real=True, positive=True)
expr2 = 1.01 * a**1.01 * b**0.99
print(type(expr2), '->', expr2)
expr2b = sp.parsing.sympy_parser.parse_expr('expr2')
print(type(expr2b), '->', expr2b)
expr2c = sp.N(sp.parsing.sympy_parser.parse_expr('expr2'))
print(type(expr2c), '->', expr2c)
#print(sp.N(sp.parsing.sympy_parser.parse_expr('expr2')))
expr2d = sp.sympify('expr2')
print(type(expr2d), '->', expr2d)
with output
<class 'sympy.core.mul.Mul'> -> 1.01*a**1.01*b**0.99
<class 'sympy.core.symbol.Symbol'> -> expr2
<class 'sympy.core.symbol.Symbol'> -> expr2
<class 'sympy.core.symbol.Symbol'> -> expr2
I need something that takes the string 'expr2' and returns the expression 1.01 * a**1.01 * b**0.99.
None of my attempts achieved the objective.
Questions or links which did not help (at least for me):
From string to sympy expression
https://docs.sympy.org/latest/tutorials/intro-tutorial/basic_operations.html
https://docs.sympy.org/latest/modules/parsing.html
https://docs.sympy.org/latest/modules/core.html#sympy.core.sympify.sympify
https://docs.sympy.org/latest/tutorials/intro-tutorial/manipulation.html
If, when parsing, you want to use the expression that has been mapped to a variable you have to pass the dictionary that python uses to keep track of those mappings, i.e. locals()
>>> from sympy.abc import x
>>> from sympy import sympify, parse_expr
>>> y = x + 2
>>> sympify('y')
y
>>> sympify('y', locals=locals())
x + 2
>>> parse_expr('y', local_dict=locals())
x + 2
As suggested by Oscar Benjamin from the Sympy Google group, eval does the job
def verify_ratio(vstr1, vstr2):
"""Compare the result of two different computations of the same quantity"""
print(vstr1 + ' / ' + vstr2, '=', eval(vstr1 + ' / ' + vstr2))
return
What shows this would work is
>>> import sys
>>> import sympy as sp
>>> a, b = sp.symbols('a,b', real=True, positive=True)
>>> a is eval('a')
True
In my case, all expressions and symbols I am using in vstr1 and vstr2 are global.
If nesting within other functions, I might need to pass further parameters to verify_ratio, as in the solution by smichr.
I'm in the middle of a big (and frankly quite hard) project so while this is my first interrogation, it probably won't be the last. Also : english is not my first langage so 'Sorry for bad english' and I'm writing this on my phone so 'Sorry for bad formating'.
Ok so : I'm trying to implement the General Number Field Sieve in Python, and I'm, at least for now, heavily relying on sympy.
Here is a peice of code where I'm struggling. In the code below, gpc(N,m) is a float list.
From sympy import Poly
From sympy.abc import x
g = Poly(gpc(N,m), x) [*]
However, when I do that, I get a polynomial over the domain RR and I would very much like to switch this to another domain D (where D will end up being ZZ['x'] but I would like this function to be general)
I'm aware of the fact that I can slightly modify [*] in
g = Poly(gpc(N,m), x, domain = D)
to get what I want. However, this wouldn't be enough. Somewhere else in my code, I need to be able to change the domain of an already constructed polynomial, and this solution wouldn't help.
When I lookep it up, I found the change_ring method so I tried this :
f = g.change_ring(D)
However, upon execution, I get the error message :
'Poly' object has no attribute 'change_ring'
So I guess that this function don't exist.
Does anyone knows how to change the domain of a polynomial ?
Thanks a lot !
It looks like creating a new Poly instance is the best approach; there are a few class methods that could help (take a look at the Poly.from_* class methods)
For example:
from sympy import Poly
from sympy.abc import x, a
g = Poly(x**3 + a*x*2 - 5*x + 6, x)
print(g) # Poly(x**3 + (2*a - 5)*x + 6, x, domain='ZZ[a]')
f = Poly.from_poly(g, *g.gens, domain='ZZ[a, b]')
print(f) # Poly(x**3 + (2*a - 5)*x + 6, x, domain='ZZ[a,b]')
I also wonder if rationalizing your floats at some point might help - see e.g. nsimplify.
I have a set of 4 simultaneous equations:
0.059z = x
0.06w = y
z+w = 8093
x+y = 422
All the solutions I've found so far seem to be for equations that have all the variables present in each equation, then convert to matrices and use the solve function.
Is there an easier way to do this in R or Python using the equations in their original form?
Also, how can I ensure that only positive numbers are returned in the solution?
Hope this makes sense...many thanks for the help
You can use sympy for this:
from sympy import symbols, linsolve, Eq
x,y,z,w = symbols('x y z w')
linsolve([Eq(0.059*z, x), Eq(0.06*w, y), Eq(z+w, 8093), Eq(x+y, 422)], (x, y, z, w))
Output:
Regarding your comments about negative values - there is only one solution to the system of equations, and it has negative values for y and w. If there was more than one solution, sympy would return them, and you could filter the solutions from there to only positive values.
In R, maybe you try it like below:
library(rootSolve)
library(zeallot)
model <- function(v){
c(x,y,z,w) %<-% v
return(c(0.059*z-x, 0.06*w-y, z+w-8093, x+y-422))
}
res <- multiroot(f = model, start = c(0,0,0,0))
then you can get the solution res as
> res
[1] 3751.22 -3329.22 63580.00 -55487.00
there are a few things going on here. first as CDJB notes: if there were any positive solutions then sympy would find them. I searched for those numbers and found this paper which suggests you should be using 7088 instead of 8093. we can do a quick sanity check:
def pct(value):
return f"{value:.1%}"
print(pct(422 / 8093)) # ~5.2%
print(pct(422 / 7088)) # ~6.0%
confirming that you're going to struggle averaging ~5.9% and ~6.0% towards ~5.2%, and explaining the negative solutions in the other answers. further, these are presumably counts so all your variables also need to be whole numbers.
once this correct denominator is used, I'd comment that there are many solutions (11645 by my count) e.g:
cases = [1, 421]
pop = [17, 7071]
rates = [pct(c / p) for c, p in zip(cases, pop)]
gives the appropriate output, as does:
cases = [2, 420]
pop = [34, 7054]
this is because the data was rounded to two decimal places. you probably also don't want to use either of the above, they're just the first two valid solutions I got.
we can define a Python function to enumerate all solutions:
from math import floor, ceil
def solutions(pop, cases, rate1, rate2, err):
target = (pct(rate1), pct(rate2))
for pop1 in range(1, pop):
pop2 = pop - pop1
c1_lo = ceil(pop1 * (rate1 - err))
c1_hi = floor(pop1 * (rate1 + err))
for c1 in range(c1_lo, c1_hi+1):
c2 = cases - c1
if (pct(c1 / pop1), pct(c2 / pop2)) == target:
yield c1, c2, pop1, pop2
all_sols = list(solutions(7088, 422, 0.059, 0.060, 0.0005))
which is where I got my count of 11645 above from.
not sure what to suggest with this, but you could maybe do a bootstrap to see how much your statistic varies with different solutions. another option would be to do a Bayesian analysis which would let you put priors over the population sizes and hence cut this down a lot.
We are working on a big mathematical project with a lot of long equations and derivatives, which are produced by Wolfram Mathematica. We have more than 1000 very long equations.
Master program is written in Java and Mathematica is only used for generating equations. Our goal is to transform "Mathematica" form to "Java" form of equation. Then we can copy/paste generated code directly to "Java" code.
So for example we have short equation in Mathematica form:
Sqrt[((Cos[R]*X1 - X2)^2 + (Sin[R]*Y1 - Y2)^2)/S^2]/S
And we want to have it in Java form, so this is expected result:
Math.sqrt((Math.pow(Math.cos(R) * X1 - X2, 2) + Math.pow(Math.sin(R) * Y1 - Y2, 2)) / Math.pow(S, 2)) / S
Here is short python script, which manages some functions:
E = "Sqrt[((Cos[R]*X1 - X2)^2 + (Sin[R]*Y1 - Y2)^2)/S^2]/S"
E = E.replace("[", "(") # Replaces Square brackets with normal brackets
E = E.replace("]", ")") # Replaces Square brackets with normal brackets
E = E.replace("*", " * ") # Add some spaces for easier reading
E = E.replace("/", " / ") # Add some spaces for easier reading
E = E.replace("Cos", "Math.cos") # Change "Mathematica" cos to "Java" cos
E = E.replace("Sin", "Math.sin") # Change "Mathematica" sin to "Java" sin
E = E.replace("Sqrt", "Math.sqrt") # Change "Mathematica" SQRT to "Java" SQRT
# Converting Power function is missing here... This is a must :)
print(E)
Above code produces:
Math.sqrt(((Math.cos(R) * X1 - X2)^2 + (Math.sin(R) * Y1 - Y2)^2) / S^2) / S
The problem is that we didn't find any solution for power function. We wanted to use python regex, but we cannot find any proper solution. The problem is that power function has to take everything within brackets, so for example:
(Math.cos(R) * X1 - X2)^2 >>>> Math.pow(Math.cos(R) * X1 - X2, 2)
I hope that somebody has a quick and fancy solution. Otherwise I will need to take some time and write a long and "dirty" script, which will take care of this problem.
Thanks for your help :)
Your regex search could be somethig like this:
import re
E = "(Math.cos(R) * X1 - X2)^2"
regex = re.compile(r'\((.*)\)\^(\d)')
match = regex.match(E)
new_E = "Math.pow(%s, %s)" % (match.group(1), match.group(2))
print(new_E) # Math.pow(Math.cos(R) * X1 - X2, 2)
The way it works is by searching for anything inside parenthesis, followed by ^n, being n a digit from 0 to 9.
I hope you can adapt this to be as generalized as you need it to be.
I tried something using mathematica's fullform[] function which turns a^b into Power[a,b]. Then I changed the Power[a,b] to some arbitrary function e.g PowerJ[a,b] using find and replace. Then I could change back to input stlye to return the formula to a form with has "*,+" etc. I was then able to use your code above to change the PowerJ[a,b] to Math.pow[a,b].
Given a numpy array like this:
prob= [[ -1.77244641 -3.89116659 -4.92632753 -8.04921303
-9.05286957]]
I wish to write them in a file separated by commas and reduce the decimal place to 4.
This is what I have tried:
for pk in prob:
jk=' '.join(str(b) for b in pk)
f.write("("+ "%.4f" %jk + ")")
f.write("\t")
q=map(float, jk.split(','))
This however doesn't accept the decimal limiting logic and gives me an error saying float argument required no string.. I am trying to extract the probabilities and write them like this:
(-1.7724, -3.8911, -4.9263, -8.0492, -9.0528)
You need to do the formatting on each string, not on the joined string. Another thing: you said comma-separated, but you used a space to join them. Here is what your program should look like:
for pk in prob:
jk = ','.join(["%.4f" % b for b in pk])
f.write("(" + jk + ")" + "\t")
Your q = map(float, pk.split(',')) line is really useless since pk is already storing all of the floats.
I think your prob like this:
prob=numpy.array([[ -1.77244641 , -3.89116659 ,-4.92632753, -8.04921303,
-9.05286957]])
And I changed your code like this:
for pk in prob:
jk=', '.join("%.4f"%b for b in pk)
jk="("+jk+")"+"\t"
f.write(jk)