I try to write a script that simulates a resistor. It takes 2 arguments for example P and R and it should calculate all missing values of this resistor.
The problem is that I don't want to write every single possible equation for every value. This means I want to write something like (U=RxI, R=U/R, I=U/R , P=UxI) and the script should then complete all equation with the given values for every equation.
For example, something like this:
in R=10
in I=5
out U=R*I
out P=I**2 * R
You can use https://pypi.org/project/Equation/ Packages.
Example
>>> from Equation import Expression
>>> fn = Expression("sin(x+y^2)",["y","x"])
>>> fn
sin((x + (y ^ (2+0j))))
>>> print fn
\sin\left(\left(x + y^{(2+0j)}\right)\right)
>>> fn(3,4)
(0.42016703682664092+0j)
Sympy
Second: https://github.com/sympy/sympy/wiki
Arbitrary precision integers, rationals and floats, as well as symbolic expressions
Simplification (e.g. ( abb + 2bab ) → (3ab^2)), expansion (e.g. ((a+b)^2) → (a^2 + 2ab + b^2)), and other methods of rewriting expressions
Functions (exp, log, sin, ...)
Complex numbers (like exp(Ix).expand(complex=True) → cos(x)+Isin(x))
Taylor (Laurent) series and limits
Differentiation and integration
In vanilla python, there is no solution as general as the one you are looking for.
The typical solution would be to write an algorithm for every option (only given U, only given R) and then logically select which option to execute.
You may also want to consider using a module like SymPy, which has a solver module that may be more up your alley.
I'm writing code for the method to solve this cubic equation. I use python's math library.
(float)(-b+pow(pow(b,3)-27*pow(a,2)*d,1/3))/3*a;
(float)((math.sqrt(delta))/(3*a))*((pow(abs(k)+math.sqrt(pow(k,2)+1),1/3))+(pow(abs(k)-math.sqrt(pow(k,2)+1),1/3)))-(b/(3*a));
Below are pictures of 2 math formulas I need to solve:
A few comments to begin with:
/3*a at the end of your first line does not do what you think it does. Use parentheses!! Parentheses are important. Write / (3 * a) instead.
It's mostly a matter of style, but personally I think A**B is easier to read than pow(A, B) (they are equivalent, as you can see in the documentation).
Note that your code will require b, a, d, Delta and k to be already-existing variables with already-given values. One way to get around that is to encapsulate your code into a function, with these four variables as arguments of the function. Another way to get around that is to use the symbolic expression library sympy.
With these comments in mind, here are two ways to rewrite your first expression and use it in python code. I will let you adapt the second expression yourself.
First way: encapsulating in a function with arguments
def expr1(a,b,d):
numerator = - b + (b**3 - 27*a*a*d)**(1/3)
denominator = 3 * a
return numerator / denominator
print(expr1(2,7,3))
# -0.7219330585463425
Second way: using sympy
Sympy is a library for symbolic calculus. This means we can use it to define symbols, which are basically variables without a value, and then ask it to remember expressions that use these symbols. We are going to use the function sympy.symbols to define our symbols, and expr.subs to evaluate an expression expr by giving values to those symbols. I encourage you to read sympy's documentation.
import sympy
a, b, d = sympy.symbols('a b d')
numerator = - b + (b**3 - 27*a*a*d) ** (1/3)
denominator = 3 * a
expr1 = numerator / denominator
print(expr1)
# (-b + (-27*a**2*d + b**3)**0.333333333333333)/(3*a)
print(expr1.subs([(a,2), (b,7), (d,3)]))
# -0.721933058546343
I think I have encountered a bug of Sympy's evalf() method with substitutions passed.
By accident, I found an expression that evaluates to a wrong value if I replace the variable x by an integer rather than a Float. The funny thing is that this happens only for some values of the precision.
The expression looks somewhat arbitrary, but if I attempt to simplify it further the bug disappears. This is a minimal working example
#!/usr/bin/env python
import sympy
from sympy.abc import x
# Some valid mathematical expression
expr = 1/((x - 9)*(x - 8)*(x - 7)*(x - 4)**2*(x - 3)**3*(x - 2))
def example(prec):
# This is the string 1.( prec-2 zeroes )1
almost1 = '1.'+(prec-2)*'0'+'1'
# We replace the integer 1
res1 = expr.evalf(prec, subs={x:1})
# We replace a Float veeery close to 1
res_almost1 = expr.evalf(prec, subs={x:sympy.Float(almost1,prec)})
return res1, res_almost1
The expected outcome is that the returned tuple should contain similar numbers since 1 and almost1 are very close. However, for some values of prec the result obtained by replacing 1 to expr is zero. (While the one obtained by replacing almost1 is close to the correct one.)
You may ask: "What are the values of prec for which the expression is wrong?". By running the code
wrong = [str(a) for a in range(10,1001) if example(a)[0] == 0]
print(','.join(wrong))
I obtain this seemingly completely random list
11,20,22,29,31,38,40,49,58,67,76,78,85,87,94,96,105,114,123,132,134,141,143,150,152,159,161,170,179,188,190,197,199,206,208,215,217,226,235,244,253,255,262,264,271,273,282,291,300,309,311,318,320,327,329,338,347,356,365,367,374,376,383,385,392,394,403,412,421,423,430,432,439,441,448,450,459,468,477,486,488,495,497,504,506,515,524,533,542,544,551,553,560,562,571,580,589,598,600,607,609,616,618,625,627,636,645,654,663,665,672,674,681,683,692,701,710,719,721,728,730,737,739,748,757,766,775,777,784,786,793,795,802,804,813,822,831,833,840,842,849,851,858,860,869,878,887,896,898,905,907,914,916,925,934,943,952,954,961,963,970,972,981,990,999
I posted it here so see whether I made some blunder in my code, otherwise I plan to post a bug issue on Sympy's github.
I have a program meant to approximate pi using the Chudnovsky Algorithm, but a term in my equation that is very small keeps being rounded to zero.
Here is the algorithm:
import math
from decimal import *
getcontext().prec = 100
pi = Decimal(0.0)
C = Decimal(12/(math.sqrt(640320**3)))
k = 0
x = Decimal(0.0)
result = Decimal(0.0)
sign = 1
while k<10:
r = Decimal(math.factorial(6*k)/((math.factorial(k)**3)*math.factorial(3*k)))
s = Decimal((13591409+545140134*k)/((640320**3)**k))
x += Decimal(sign*r*s)
sign = sign*(-1)
k += 1
result = Decimal(C*x)
pi = Decimal(1/result)
print Decimal(pi)
The equations may be clearer without the "decimal" terms.
import math
pi = 0.0
C = 12/(math.sqrt(640320**3))
k = 0
x = 0.0
result = 0.0
sign = 1
while k<10:
r = math.factorial(6*k)/((math.factorial(k)**3)*math.factorial(3*k))
s = (13591409+545140134*k)/((640320**3)**k)
x += sign*r*s
sign = sign*(-1)
k += 1
result = C*x
pi = 1/result
print pi
The issue is with the "s" variable. For k>0, it always comes to zero. e.g. at k=1, s should equal about 2.1e-9, but instead it is just zero. Because of this all of my terms after the first =0. How do I get python to calculate the exact value of s instead of rounding it down to 0?
Try:
s = Decimal((13591409+545140134*k)) / Decimal(((640320**3)**k))
The arithmetic you're doing is native python - by allowing the Decimal object to perform your division, you should eliminate your error.
You can do the same, then, when computing r.
A couple of comments.
If you are using Python 2.x, the / returns an integer result. If you want a Decimal result, you convert at least one side to Decimal first.
math.sqrt() only return ~16 digits of precision. Since your value for C will only be accurate to ~16 digits, your final result will only be accurate to 16 digits.
If you're doing maths in Python 2.x, you should probably be putting this line into every module:
from __future__ import division
This changes the meaning of the division operator so that it will return a floating point number if needed to give a (closer to) precise answer. The historical behaviour is for x / y to return an int if both x and y are ints, which usually forces the answer to be rounded down.
Returning a float if necessary is generally regarded as a better way to handle division in a language like Python where duck typing is encouraged, since you can just worry about the value of your numbers rather than getting different behaviour for different types.
In Python 3 this is in fact the default, but since old programs relied on the historical behaviour of the division operator it was felt the change was too backwards-incompatible to be made in Python 2. This is why you have to explicitly turn it on with the __future__ import. I would recommend always adding that import in any module that might be doing any mathematics (or just any module at all, if you can be bothered). You'll almost never be upset that it's there, but not having it there has been the cause of a number of obscure bugs I've had to chase.
I feel that the problem with 's' is that all terms are integers, thus you are doing integer maths. A very simple workaround, would be to use 3.0 in the denominator. It only takes one float in the calculation to get a float returned.
I'm trying to code this expression in python but I'm having some difficulty.
This is the code I have so far and wanted some advice.
x = 1x2 vector
mu = 1x2 vector
Sigma = 2x2 matrix
xT = (x-mu).transpose()
sig = Sigma**(-1)
dotP = dot(xT ,sig )
dotdot = dot(dotP, (x-mu))
E = exp( (-1/2) dotdot )
Am I on the right track? Any suggestions?
Sigma ** (-1) isn't what you want. That would raise each element of Sigma to the -1 power, i.e. 1 / Sigma, whereas in the mathematical expression it means the inverse, which is written in Python as np.linalg.inv(Sigma).
(-1/2) dotdot is a syntax error; in Python, you need to always include * for multiplication, or just do - dotdot / 2. Since you're probably using python 2, division is a little wonky; unless you've done from __future__ import division (highly recommended), 1/2 will actually be 0, because it's integer division. You can use .5 to get around that, though like I said I do highly recommend doing the division import.
This is pretty trivial, but you're doing the x-mu subtraction twice where it's only necessary to do once. Could save a little speed if your vectors are big by doing it only once. (Of course, here you're doing it in two dimensions, so this doesn't matter at all.)
Rather than calling the_array.transpose() (which is fine), it's often nicer to use the_array.T, which is the same thing.
I also wouldn't use the name xT; it implies to me that it's the transpose of x, which is false.
I would probably combine it like this:
# near the top of the file
# you probably did some kind of `from somewhere import *`.
# most people like to only import specific names and/or do imports like this,
# to make it clear where your functions are coming from.
import numpy as np
centered = x - mu
prec = np.linalg.inv(Sigma)
E = np.exp(-.5 * np.dot(centered.T, np.dot(prec, centered)))