Correct translation of Matlab to Python (CID Distance) - python

This is the Matlab code for Complexity Invariance Distance (Source)
Q and C are 1d-arrays with similar length.
function d = CID(Q, C)
CE_Q = sqrt(sum(diff(Q).^2));
CE_C = sqrt(sum(diff(C).^2));
d = sqrt(sum((Q - C).^2)) * (max(CE_Q,CE_C)/min(CE_Q,CE_C));
This is my pythonic translation:
def cid_dist(Q,C):
import numpy as np
CE_Q = np.sqrt(np.sum(np.diff(Q)**2))
CE_C= np.sqrt(np.sum(np.diff(C)**2))
d = np.sqrt(np.sum((Q - C)**2)) * (np.maximum(CE_Q,CE_C)/np.minimum(CE_Q,CE_C))
return d
Is it correct?

I have tried it in Octave. Both function return identical results.

Related

Looking for some help on an assignment question regarding a function

I'm fairly new to python and i'm working on a problem for a school project. I feel im making progress but i'm not sure what to do next. The question is:
Write a function that takes mass as input and returns its energy equivalent using Einstein’s famous E = mc 2 equation. Test it with at least 3 different mass values. Write the program so that it can take the mass in kilograms as a commandline argument.
import sys
import math
m = float(sys.argv)
c = float(299792458)
def einstein_equation(m, c):
result = m * (math.pow(c, 2))
return result
e = einstein_equation(m, c)
print e
just make it simple man, no need for sys.argv
and no need for math.pow
just:
c = float(7382)
def einstein_equation(m, c):
return m * (c*c)
for _ in range(3):
m = float(input("MASS : "))
e = einstein_equation(m, c)
print (e)
You don't need libary for powering and just add index for sys.argv
import sys
m = int(sys.argv[1])
c = 299792458
print(m*c**2)

solving linear system 6x6 matrix using sympy

i am trying to solve a matrix that has 6x6 matrices as it's entries(elements)
i tried multiplying the inverse of gen to the solution matrix, but i don't trust the correctness of the answer am getting.
from sympy import Eq, solve_linear_system, Matrix,count_ops,Mul,horner
import sympy as sp
a, b, c, d, e,f = sp.symbols('a b c d e f')
ad = Matrix(([43.4,26.5,115,-40.5,52.4,0.921],
[3.78,62.9,127,-67.6,110,4.80],
[41.25,75.0,213,-88.9, 131, 5.88],
[-10.6,-68.4,-120,64.6,-132,-8.49],
[6.5,74.3,121,-72.8,179,29.7],
[1.2,30.7,49.7,-28.7,91,29.9]))
fb= Matrix(([1,0,0,0,0,0],
[0,1,0,0,0,0],
[0,0,1,0,0,0],
[0,0,0,1,0,0],
[0,0,0,0,1,0],
[0,0,0,0,0,1]))
ab = Matrix(([-0.0057],
[0.0006],
[-0.0037],
[0.0009],
[0.0025],
[0.0042]))
az = sp.symbols('az')
bz = sp.symbols('bz')
fz = sp.symbols('fz')
gen = Matrix(([az, fz, 0, 0, 0, 0,bz],
[fz,az,fz,0,0,0,bz],
[0,fz,az,fz,0,0,bz],
[0,0,fz,az,fz,0,bz],
[0,0,0,fz,az,fz,bz],
[0,0,0,0,fz,az,bz]))
answer = solve_linear_system(gen,a,b,c,d,e,f)
first_solution = answer[a]
df = count_ops(first_solution)
print(df,first_solution)
disolved = zip(first_solution.simplify().as_numer_denom(),(1,-1))
dft = Mul(*[horner(b)**e for b,e in disolved])
dff = count_ops(dft)
print(dff,dft)
_1st_solution = dft.subs({az:ad,fz:fb,bz:ab},simultaneous = True).doit()
print(_1st_solution)
when i ran my code it raised sympy.matrices.common.ShapeError
You have to be careful when using horner with expressions containing commutative symbols that are actually noncommutative (in your case because they represent matrices). Your dft expression is
(az**2*bz - bz*fz**2)/(az*(az*(az + fz) - 2*fz**2) - fz**3)
but should maybe be
(az**2 - fz**2)*(az*(az*(az + fz) - 2*fz**2) - fz**3)**(-1)*bz
You would have received a correct expression if you had created the symbols as noncommutative (as shown below).
But you can't use horner with non-commutative symbols, so I just rearranged the expression by hand; you will have to check to see that the ordering is right. As an alternative to doing the factoring by hand you might also try using factor_nc to help you -- but it won't handle horner like expression factoring:
>>> ax, bz, fz = symbols('az bz fz, commutative=False)
>>> (az**2*bz - fz**2*bz)
az**2*bz - fz**2*bz
>>> factor_nc(_)
(az**2 - fz**2)*bz

How to simplify matrix expressions in SymPy?

Consider the following example
import sympy as sy
n = sy.symbols('n')
A = sy.MatrixSymbol("A",n,n)
B = sy.MatrixSymbol("B",n,n)
C = sy.MatrixSymbol("C",n,n)
M = A.inverse()*B.inverse() - A.inverse()*C*B.inverse()
B.inverse()*M.inverse()*A.inverse()
The example prints out B^-1*(A^-1*B^-1 - A^-1*C*B^-1)^-1*A^-1.
Can SymPy simplify the expression to (I-C)^-1? If not, how about any of the intermediate results, like collecting common factors in M?
The work around for this is using string converting on expression:
from sympy import *
n = symbols('n')
A = MatrixSymbol("A",n,n)
B = MatrixSymbol("B",n,n)
C = MatrixSymbol("C",n,n)
M = A.inverse()*B.inverse() - A.inverse()*C*B.inverse()
expression = B.inverse()*M.inverse()*A.inverse()
# convert expression to string then simplify
simplify_expression = simplify(str(expression))
pprint(simplify_expression)
Output:
-1
─────
C - 1

Julia: Products of sequences in a vectorized way

Learning to pass from Python to Julia, I am trying to convert an old code that I have, that is calculating a product of sequence of this expression:
I have two versions of the code in Python, one implemented with for loops, and the other using broadcasting. The for loop version is:
import numpy as np
A = np.arange(1.,5.,1)
G = np.array([[1.,2.],[3.,4.]])
def calcF(G,A):
N = A.size
print A
print N
F = []
for l in range(N):
F.append(G/A[l])
print F[l]
for j in range(N):
if j != l:
F[l]*=((G - A[l])/(G + A[j]))*((A[l] - A[j])/(A[l] + A[j]))
return F
F= calcF(G,A)
print F
And the vectorized version I have learned from a response to my question here, is this function:
def calcF_vectorized(G,A):
# Get size of A
N = A.size
# Perform "(G - A[l])/(G + A[j]))" in a vectorized manner
p1 = (G - A[:,None,None,None])/(G + A[:,None,None])
# Perform "((A[l] - A[j])/(A[l] + A[j]))" in a vectorized manner
p2 = ((A[:,None] - A)/(A[:,None] + A))
# Elementwise multiplications between the previously calculated parts
p3 = p1*p2[...,None,None]
# Set the escaped portion "j != l" output as "G/A[l]"
p3[np.eye(N,dtype=bool)] = G/A[:,None,None]
Fout = p3.prod(1)
# If you need separate arrays just like in the question, split it
return np.array_split(Fout,N)
I tried to naively translate the Python for loops code to Julia:
function JuliacalcF(G,A)
F = Array{Float64}[]
for l in eachindex(A)
push!(F,G/A[l])
println(A[i])
for j in eachindex(A)
if j!=l
F[l]*=((G - A[l])/(G + A[j]))*((A[l] - A[j])/(A[l] + A[j]))
end
end
end
#println(alpha)
return F
end
A = collect(1.0:1.0:5.0)
G = Vector{Float64}[[1.,2.],[3.,4.]]
println(JuliacalcF(G,A))
But is there a way to do it in a smart way as in the numpy broadcasting vectorized version?
Also, take a look at More-Dots and Loop Fusion where vectorization is described with examples.

Solving a mathematical function in Python

I am trying to solve a logarithmic function using Python. I am searching for an irrational number, so I wrote this bisection algorithm:
def racine(x):
a=0
b=x/2
c=(a+b)/2
while a!=b and a<c<b:
if c**2<x:
a=c
else:
b=c
c=(a+b)/2
return a, b
which seems to work, at least for finding irrational roots. However then I have a more complicated function:
ln(P)=A+B/T+C*ln(T)
where P, A, B and C are known constants. Isolating T, there is this:
T==e**((ln(P)-A-B/T)/C)
But this still can't be solved because T is on both sides. Can somebody see the way around it? For now I have this code, which clearly doesn't work.
def temperature(P):
A=18.19
B=-23180
C=-0.8858
T==e**((log(P)-A-B/T)/C)
return racine (T)
Thank you!
The answer should be to use the bisection method again.
a=small estimate
fa = f(a)
b=large estimate
fb = f(b)
while( b-a > 1e-12 ) {
c = (a+b)/2
fc = f(c)
if( fabs(fc) < 1e-12) return c;
if( (fc>0) == (fa>0) ) {
a = c; fa = fc
} else {
b = c; f = fc;
}
return (a+b)/2
For more efficient methods look up the regula falsi method in its Illinois variant.
If you have NumPy installed, you can find the temperature at a given pressure numerically, for example with scipy.optimize.newton. For example,
import numpy as np
from scipy.optimize import newton
A, B, C = 18.19, -23180, -0.8858
fr = lambda T, lnp: (A + B/T + C*np.log(T)) - lnp
def T(p):
return newton(fr, 1000, args=(np.log(p),))
In [1]: p1 = 10
In [2]: T1 = T(p1)
In [3]: T1
Out[3]: 2597.8167133280913
In [4]: np.exp(A + B/T1 + C*np.log(T1)) # check
Out[4]: 10.000000000000002
The initial guess value (here 1000) you might have to customize for your usage: I don't know your units.

Categories