I am trying to rotate some seismic data held in a numpy nd-array. This array has dimensions (N-receiver, M-sources,3-source_channels, 3-receiver channels, K-time channels).
I know how to set up the rotation if applied to a single time stamp (t_i) over a single receiver & single source station. The actual Z, R, T, N, E, notation isn't important for the general problem, just know that the transformation is defined like so:
In python, for a single timestamp I'd probably code up something like:
import numpy as np
a = 50.0 # example alpha
b = 130 # example beta
a_rotation = np.asarray([[1,0,0],[0,np.cos(a),np.sin(a)],[0,-np.sin(a),np.cos(a)]])
b_rotation = np.asarray([[1,0,0],[0,-np.cos(b),-np.sin(b)],[0,np.sin(b),-np.cos(b)]])
# pretend the zn's are actual float data
single_timeslice_data = np.asarray([[zz,zn,ze],[nz,nn,ne],[ez,en,ee]])
# operation w numpy matrix rotation
rotated_channels = a_rotation # single_timeslice_data # b_rotation
So my question is twofold:
How do I apply this matrix product with numpy over all timesteps?
ex: (3 x 3) * (3 x 3 x K) * (3 x 3)
How do I do this matrix product with numpy when there may be an arbitrary number of other dimensions?
ex: (3 x 3) * (N x M x 3 x 3 x K) * (3 x 3)
1)
(3 x 3) * (3 x 3 * K) * (3 * 3) = (3 x 3 x K)
np.einsum('ab,bcK,cd->adK', Arr1, Arr2, Arr3)
2)
(3 x 3) * (N x M x 3 x 3 x K) * (3 x 3) = (N x M x 3 x 3 x K)
np.einsum('ab,NMbcK,cd->NMadK', Arr1, Arr2, Arr3)
Related
The number π can be calculated with the following infinite series sum:
I want to define a Haskell function roughlyPI that, given a natural number k, calculates the series sum from 0 to the k value.
Example: roughlyPi 1000 (or whatever) => 3.1415926535897922
What I did was this (in VS Code):
roughlyPI :: Double -> Double
roughlyPI 0 = 2
roughlyPI n = e1/e2 + (roughlyPI (n-1))
where
e1 = 2**(n+1)*(factorial n)**2
e2 = factorial (2*n +1)
factorial 0 = 1
factorial n = n * factorial (n-1)
but it doesn't really work....
*Main> roughlyPI 100
NaN
I don't know what's wrong. I'm new to Haskell, by the way.
All I really want is to be able to type in a number that will give me PI at the end. It can't be that hard...
As mentioned in the comments, we need to avoid large divisions and instead intersperse smaller divisions within the factorials. We use Double for representing PI but even Double has its limits. For instance 1 / 0 == Infinity and (1 / 0) / (1 / 0) == Infinity / Infinity == NaN.
Luckily, we can use algebra to simplify the formula and hopefully delay the blowup of our Doubles. By dividing within our factorial the numbers don't grow too unwieldy too quickly.
This solution will calculate roughlyPI 1000, but it fails on 1023 with NaN because 2 ^ 1024 :: Double == Infinity. Note how each iteration of fac has a division as well as a multiplication to help keep the numbers from blowing up. If you are trying to approximate PI with a computer, I believe there are better algorithms, but I tried to keep it as conceptually close to your attempt as possible.
roughlyPI :: Integer -> Double
roughlyPI 0 = 2
roughlyPI k = e + roughlyPI (k - 1)
where
k' = fromIntegral k
e = 2 ** (k' + 1) * fac k / (2 * k' + 1)
where
fac 1 = 1 / (k' + 1)
fac p = (fromIntegral p / (k' + fromIntegral p)) * fac (p - 1)
We can do better than having a blowup of Double after 1000 by doing computations with Rationals then converting to Double with realToFrac (credit to #leftaroundabout):
roughlyPI' :: Integer -> Double
roughlyPI' = realToFrac . go
where
go 0 = 2
go k = e + go (k - 1)
where
e = 2 ^ (k + 1) * fac k / (2 * fromIntegral k + 1)
where
fac 1 = 1 % (k + 1)
fac p = (p % (k + p)) * fac (p - 1)
For further reference see Wikipedia page on approximations of PI
P.S. Sorry for the bulky equations, stackoverflow does not support LaTex
First note that your code actually works:
*Main> roughlyPI 91
3.1415926535897922
The problem, as was already said, is that when you try to make the approximation better, the factorial terms become too big to be representable in double-precision floats. The simplest – albeit somewhat brute-force – way to fix that is to do all the computation in rational arithmetic instead. Because numerical operations in Haskell are polymorphic, this works with almost the same code as you have, only the ** operator can't be used since that allows fractional exponents (which are in general irrational). Instead, you should use integer exponents, which is anyway the conceptually right thing. That requires a few fromIntegral:
roughlyPI :: Integer -> Rational
roughlyPI 0 = 2
roughlyPI n = e1/e2 + (roughlyPI (n-1))
where
e1 = 2^(n+1)*fromIntegral (factorial n^2)
e2 = fromIntegral . factorial $ 2*n + 1
factorial 0 = 1
factorial n = n * factorial (n-1)
This now works also for much higher degrees of approximation, although it takes a long time to carry around the giant fractions involved:
*Main> realToFrac $ roughlyPI 1000
3.141592653589793
The way to go in such cases is to calculate the ratio of consecutive terms and calculate the terms by rolling multiplications of the ratios:
-- 1. -------------
pi1 n = Sum { k = 0 .. n } T(k)
where
T(k) = 2^(k+1)(k!)^2 / (2k+1)!
-- 2. -------------
ts2 = [ 2^(k+1)*(k!)^2 / (2k+1)! | k <- [0..] ]
pis2 = scanl1 (+) ts2
pi2 n = pis2 !! n
-- 3. -------------
T(k) = 2^(k+1)(k!)^2 / (2k+1)!
T(k+1) = 2^(k+2)((k+1)!)^2 / (2(k+1)+1)!
= T(k) 2 (k+1)^2 / (2k+2) (2k+3)
= T(k) (k+1)^2 / ( k+1) (2k+3)
= T(k) (k+1) / (k+1 + k+2)
= T(k) / (1 + (k+2)/(k+1))
= T(k) / (2 + 1 /(k+1))
-- 4. -------------
ts4 = scanl (/) 2 [ 2 + 1/(k+1) | k <- [0..]] :: [Double]
pis4 = scanl1 (+) ts4
pi4 n = pis4 !! n
This way we share and reuse the calculations as much as possible. This leads to the most efficient code, hopefully leading to the smallest cumulative numerical error. The formula also turned out to be exceptionally simple, and could even be simplified further as ts5 = scanl (/) 2 [ 2 + recip k | k <- [1..]].
Trying it out:
> pis2 = scanl1 (+) $ [ fromIntegral (2^(k+1))*fromIntegral (product[1..k])^2 /
fromIntegral (product[1..(2*k+1)]) | k <- [0..] ] :: [Double]
> take 8 $ drop 30 pis2
[3.1415926533011587,3.141592653447635,3.141592653519746,3.1415926535552634,
3.141592653572765,3.1415926535813923,3.141592653585647,3.141592653587746]
> take 8 $ drop 90 pis2
[3.1415926535897922,3.1415926535897922,NaN,NaN,NaN,NaN,NaN,NaN]
> take 8 $ drop 30 pis4
[3.1415926533011587,3.141592653447635,3.141592653519746,3.1415926535552634,
3.141592653572765,3.1415926535813923,3.141592653585647,3.141592653587746]
> take 8 $ drop 90 pis4
[3.1415926535897922,3.1415926535897922,3.1415926535897922,3.1415926535897922,
3.1415926535897922,3.1415926535897922,3.1415926535897922,3.1415926535897922]
> pis4 !! 1000
3.1415926535897922
I've got a math equation that I want to visually record the substitution of.
The equation is y = h * f(t + h, h + f(t, h)), where f(x, y) = x + y - 1
I want to substitute f into y, such that I get:
y = h * f(t + h, h + (t + h - 1))
y = h * (t + h + h + (t + h - 1) - 1)
I've had issues with replace not allowing me to do multi-parameter substitution
I don't have much code, since I'm not sure how to implement it
from sympy import *
f = Function('f')(x, y)
eqn = h * f(t + h, h + f(t, h))
Thanks
sympy.Function is used for declaring undefined functions but in your case the function is known.
The following code seems to work fine over here
from sympy import *
x,y,t,h = symbols('x y t h')
def f(x,y):
return x + y - 1
y = h * f(t+h,h+f(t,h))
y = expand(y)
display(y)
The role of the expand function was to work out the outer multiplication by h in the definition of y.
You can run it in a Jupyter notebook or as an alternative use the print or display function, I get the following result:
Extending average's answer -- Their solution works perfectly if the function is known.
To make it work for a function that's input from the user, you need to do this:
function = input()
def f(x, y, evaluate = False):
eqn = sympify(function)
if evaluate:
eqn = eqn.subs([("x", x), ("y", y)])
return eqn
y = h + f(h, t, True)
This way, if the user inputs "x ** y" for f, y will expand to h + h ** t
magnitude :: Floating a => [a] -> a
magnitude = sqrt . mag
where mag [] = 0
mag (x:xs) = x^2 + mag xs
This is supposed to square every element in the list, then take their sum and then take the square root. Fair enough, but how does this recursive function work, when it only adds x to the list xs ?
but how does this recursive function work, when it only adds x to the list xs?
x is the head (first element) of the list, and it uses recursion on the tail xs.
So for example for a list [1,4,2,5], it obtain the sum with:
mag [1,4,2,5]
= 1 ^ 2 + mag [4,2,5]
= 1 + mag [4,2,5]
= 1 + (4 ^ 2 + mag [2,5])
= 1 + (16 + mag [2,5])
= 1 + (16 + (2 ^ 2 + mag [5]))
= 1 + (16 + (4 + mag [5]))
= 1 + (16 + (4 + (5 ^ 2 + mag [])))
= 1 + (16 + (4 + (25 + mag [])))
= 1 + (16 + (4 + (25 + 0)))
= 1 + (16 + (4 + 25))
= 1 + (16 + 29)
= 1 + 45
= 46
The magnitude is defined as sqrt . mag, this is equivalent to \x -> sqrt (mag x). This thus means that we first calculate the sum of squares of x with mag x, and then calculate the square root of that result.
This is supposed to square every element in the list, then take their sum
This is done by the local function, mag.
mag [] = 0
mag (x:xs) = x^2 + mag xs
If the list is empty, the sum of squares is 0. If it is non-empty, it is the square of the first element plus the sum of squares of the remainder of the list.
and then take the square root.
This is done by magnitude. Its definition is equivalent to
magnitude xs = sqrt (mag xs)
But we use function composition, .,
magnitude xs = (sqrt.mag) xs
and pointfree style (omitting the xs since it appears on both the left and right side) for brevity
magnitude = sqrt.mag
Why does GHCi give incorrect answer below?
GHCi
λ> ((-20.24373193905347)^12)^2 - ((-20.24373193905347)^24)
4.503599627370496e15
Python3
>>> ((-20.24373193905347)**12)**2 - ((-20.24373193905347)**24)
0.0
UPDATE
I would implement Haskell's (^) function as follows.
powerXY :: Double -> Int -> Double
powerXY x 0 = 1
powerXY x y
| y < 0 = powerXY (1/x) (-y)
| otherwise =
let z = powerXY x (y `div` 2)
in if odd y then z*z*x else z*z
main = do
let x = -20.24373193905347
print $ powerXY (powerXY x 12) 2 - powerXY x 24 -- 0
print $ ((x^12)^2) - (x ^ 24) -- 4.503599627370496e15
Although my version doesn't appear any more correct than the one provided below by #WillemVanOnsem, it strangely gives the correct answer for this particular case at least.
Python is similar.
def pw(x, y):
if y < 0:
return pw(1/x, -y)
if y == 0:
return 1
z = pw(x, y//2)
if y % 2 == 1:
return z*z*x
else:
return z*z
# prints 0.0
print(pw(pw(-20.24373193905347, 12), 2) - pw(-20.24373193905347, 24))
Short answer: there is a difference between (^) :: (Num a, Integral b) => a -> b -> a and (**) :: Floating a => a -> a -> a.
The (^) function works only on integral exponents. It will normally make use of an iterative algorithm that will each time check if the power is divisible by two, and divide the power by two (and if non-divisible multiply the result with x). This thus means that for 12, it will perform a total of six multiplications. If a multiplication has a certain rounding-off error, that error can "explode". As we can see in the source code, the (^) function is implemented as:
(^) :: (Num a, Integral b) => a -> b -> a
x0 ^ y0 | y0 < 0 = errorWithoutStackTrace "Negative exponent"
| y0 == 0 = 1
| otherwise = f x0 y0
where -- f : x0 ^ y0 = x ^ y
f x y | even y = f (x * x) (y `quot` 2)
| y == 1 = x
| otherwise = g (x * x) (y `quot` 2) x -- See Note [Half of y - 1]
-- g : x0 ^ y0 = (x ^ y) * z
g x y z | even y = g (x * x) (y `quot` 2) z
| y == 1 = x * z
| otherwise = g (x * x) (y `quot` 2) (x * z) -- See Note [Half of y - 1]
The (**) function is, at least for Floats and Doubles implemented to work on the floating point unit. Indeed, if we take a look at the implementation of (**), we see:
instance Floating Float where
-- …
(**) x y = powerFloat x y
-- …
This thus redirect to the powerFloat# :: Float# -> Float# -> Float# function, which will, normally be linked to the corresponding FPU operation(s) by the compiler.
If we use (**) instead, we obtain zero as well for a 64-bit floating point unit:
Prelude> (a**12)**2 - a**24
0.0
We can for example implement the iterative algorithm in Python:
def pw(x0, y0):
if y0 < 0:
raise Error()
if y0 == 0:
return 1
return f(x0, y0)
def f(x, y):
if (y % 2 == 0):
return f(x*x, y//2)
if y == 1:
return x
return g(x*x, y // 2, x)
def g(x, y, z):
if (y % 2 == 0):
return g(x*x, y//2, z)
if y == 1:
return x*z
return g(x*x, y//2, x*z)
If we then perform the same operation, I get locally:
>>> pw(pw(-20.24373193905347, 12), 2) - pw(-20.24373193905347, 24)
4503599627370496.0
Which is the same value as what we get for (^) in GHCi.
I wrote a program which calculates the integral of the probability density function of the lognormal distribution.
I want it to be able to calculate the nth moments of the pdf too. But if I modify my code I get this error. It works properly before I add *(x^(M))
Function riemanint(n, a, b)
Dim h, i, x
h = (b - a) / n
x = a - h / 2
For i = 1 To n
x = x + h
s = s + f(x, ev, var, PI, M) * h
Next
riemanint = s
End Function
Function f(x, ev, var, PI, M)
PI = Application.WorksheetFunction.PI()
ev = Range("D2")
var = Range("E2")
M = Range("F2")
f = (((1 / (x * ((2 * PI) ^ 0.5) * var)) * Exp((-(Log(x) - ev) ^ 2) / (2 * var * var)))) * (x^(M))
End Function