LU decomposition without pivoting in JULIA - matlab

Trying to rewrite the lu_nopivot from this answer https://stackoverflow.com/a/41151228 into JULIA and use only one loop.
The julia code I wrote
using LinearAlgebra
function lu_nopivot(A)
n = size(A, 1)
L = Matrix{eltype(A)}(I, n, n)
U = copy(A)
for k = 1:n
L[k+1:n,k] = U[k+1:n,k] / U[k,k]
U[k+1:n,:] = U[k+1:n,:] - L[k+1:n,k]*U[k,:]
end
return L, U
end
But calling the function
L, U = lu_nopivot(A) gives an error MethodError: no method matching *(::Vector{Float64}, ::Vector{Float64}) on L[k+1:n,k]*U[k,:]. Any reason why this is?

The problem is that when you do U[k, :], even though you're extracting out a row, what you get back is a column vector. So L[k+1:n,k]*U[k,:] becomes an attempt to multiply a column vector by a column vector.
One way to get a row vector aka a 1 x N Matrix in Julia (though I don't know if this is the idiomatic way) is to do U[k:k, :] instead:
U[k+1:n,:] = U[k+1:n,:] - L[k+1:n,k] * U[k:k,:]
Note however that Julia's implementation of lu already has a no-pivot option:
Pivoting can be turned off by passing
pivot = NoPivot().
julia> M = rand(1.0:100.0, 3, 3)
3×3 Matrix{Float64}:
71.0 50.0 23.0
82.0 63.0 37.0
96.0 28.0 5.0
julia> L, U = lu_nopivot(M); # after the above k:k change has been made
julia> L
3×3 Matrix{Float64}:
1.0 0.0 0.0
1.15493 1.0 0.0
1.35211 -7.53887 1.0
julia> U
3×3 Matrix{Float64}:
71.0 50.0 23.0
0.0 5.25352 10.4366
0.0 0.0 52.5818
julia> lu(M, NoPivot())
LU{Float64, Matrix{Float64}}
L factor:
3×3 Matrix{Float64}:
1.0 0.0 0.0
1.15493 1.0 0.0
1.35211 -7.53887 1.0
U factor:
3×3 Matrix{Float64}:
71.0 50.0 23.0
0.0 5.25352 10.4366
0.0 0.0 52.5818
Using this is likely more performant, and more robust too (eg. your current implementation cannot handle matrices of eltype Int, since L and U are given the same type as the input but will need to contain Floats).

Related

Swift Double.remainder(dividingBy:) returning negative value

let num = 32.0
Double(num).remainder(dividingBy: 12.0)
I'm getting -4?..instead of 8.0...it's subtracting 12.0 from 8.0
how do i fix this?
Please, read the documentation carefully:
For two finite values x and y, the remainder r of dividing x by y satisfies x == y * q + r, where q is the integer nearest to x / y. If x / y is exactly halfway between two integers, q is chosen to be even. Note that q is not x / y computed in floating-point arithmetic, and that q may not be representable in any available integer type.
(emphasis mine)
You want to use truncatingRemainder(dividingBy:) instead:
let num = 32.0
let value = Double(num)
.truncatingRemainder(dividingBy: 12)
print(value) // 8
remainder(dividingBy:)is not the modulus function.
In real division 32.0/12.0 = 2.666666.... The remainder(dividingBy:) function defines the nearest integer to that result as q: in this case 3. So we write:
32.O = q * 12 + r
With q being an integer, and r a Double.
32.0 = 3 * 12.0 + r ⇒ r = - 4.0
The remainder r, as defined by this function, is -4.0.

Why is exponential integrator method giving poor results?

//u' + Au = g(t,u) can be solved by exponential integrators also
//Following snippet is for exp INtegrators
A = -full(Strang(11))
A[end,1]=1;A[1,end]=1;
g(t,u) = 2-u
u0 = zeros(11);u0[6]=1
nsteps = 1000
tmax = 10.0
h = tmax/nsteps
u = u0
t = 0
for k in 1:nsteps
u = expm(-h*A)*u + h*((expm(-h*A)-1)\(-h*A))*g(t,u)
t = k*h
end
//this is for euler's method
for k in 1:nsteps
u += h*(A*u + h*g(t,u))
t = k*h
end
Why are they giving poor results?
The method is exploding very badly, it should converge to [1.99]*11 , or something like that?
Is there any mistake while implementing Exp Integrator?
The test problem is a singular matrix. A better test is the setup:
using SpecialMatrices
A = -full(Strang(11))
g(t,u) = 2-u
u = zeros(11);u[6]=1
nsteps = 10000
tmax = 1.0
h = tmax/nsteps
t = 0
Using this, fix the h in the Euler to get (notice there's an extra h, my bad:
u = zeros(11);u[6]=1
for k in 1:nsteps
u += h*(A*u + g(t,u))
t = k*h
end
#show u
u = [0.93573,1.19361,1.26091,1.29627,1.34313,1.37767,1.34313,1.29627,1.26091,1.19361,0.93573]
But to find out what's wrong, start looking at numbers. What happens A=0? Well, we know that phi(z) = (e^z - 1)/z. By L'Hopital's rule, phi(z) -> 1 as z->0. Therefore, in order for our implementation to have the same behavior, we have to have that same result. But let's check what happens:
expm(zeros(5,5))
5×5 Array{Float64,2}:
1.0 0.0 0.0 0.0 0.0
0.0 1.0 0.0 0.0 0.0
0.0 0.0 1.0 0.0 0.0
0.0 0.0 0.0 1.0 0.0
0.0 0.0 0.0 0.0 1.0
Notice that this gives the identity matrix. So think about the limit: if the bottom is going to zero... how can this be constant? We must have that the top is going to zero... so the top is going to I.
And that's the moment of clarity: the author meant 1 in the field that you're in. So for a matrix input, 1=I. When you realize that, you fix the code:
# Norsett-Euler
u = zeros(11);u[6]=1
for k in 1:nsteps
u = expm(h*A)*u + ((expm(h*A)-I)/A)*g(t,u)
t = k*h
end
#show u
u = [0.935722,1.1936,1.26091,1.29627,1.34313,1.37768,1.34313,1.29627,1.26091,1.1936,0.935722]
Moral of the story: for programming mathematics, you also have to debug your math.
Edit
Get a more efficient form one step at a time. First, try and force another varphi term:
# Norsett-Euler
u = zeros(11);u[6]=1
for k in 1:nsteps
u = (I + A*(expm(h*A)-I)/A)*u + ((expm(h*A)-I)/A)*g(t,u)
t = k*h
end
#show u
Now gather:
# Norsett-Euler
u = zeros(11);u[6]=1
for k in 1:nsteps
u = u + ((expm(h*A)-I)/A)*(A*u + g(t,u))
t = k*h
end
#show u
This is the efficient form of the method you were trying to write. Then you can cache the operator since A is constant:
# Norsett-Euler
u = zeros(11);u[6]=1
phi1 = ((expm(h*A)-I)/A)
for k in 1:nsteps
u = u + phi1*(A*u + g(t,u))
t = k*h
end
#show u
The exponential Euler-Rosenbrock step should be for u'=Lu+g(t,u)
u = expm(h*L)*u + ((expm(h*L)-1)/L)*g(t,u)
Note that the inverted matrix is L (in Matlab A/B == A*inv(B) and A\B == inv(A)*B), and there is no naked h in the formula. In your case, L = -A.
An alternative method to split off the exponential part has is as follows. Set u(t) = exp(-t*A)*v(t) which translates into the differential equation
exp(-t*A)*v'(t) = g(t,exp(-t*A)*v((t))
Now apply the forward Euler step for v
v(t+h) = v(t) + h * exp(t*A)*g(t,exp(-t*A)*v((t))
which translated back into terms in u gives
u(t+h) = exp(-(t+h)*A)*v(t+h)
= exp(-h*A) * ( u(t) + h * g(t,u(t)) )
This should equally result in a first order method.

How to insert vector of ones to Matrix?

I've a vector and a matrix:
1
1
0 0
0 0
I want to prepend the vector to matrix to produce :
1 0 0
1 0 0
I have so far :
val dv = DenseVector(1.0,1.0);
val dm = DenseMatrix.zeros[Double](2,2)
Reading the API : http://www.scalanlp.org/api/breeze/#breeze.linalg.DenseMatrix
and both these docs :
https://github.com/scalanlp/breeze/wiki/Quickstart https://github.com/scalanlp/breeze/wiki/Linear-Algebra-Cheat-Sheet
But this operation does not appear to be available ?
Is there a method/function to prepend a vector of ones to a Matrix ?
Another option here. Firstly convert the DenseVector to a 2X1 matrix and then use the DenseMatrix.horzcat() method:
val newMat = DenseMatrix.horzcat(new DenseMatrix(2,1,dv.toArray), dm)
# breeze.linalg.DenseMatrix[Double] = 1.0 0.0 0.0
# 1.0 0.0 0.0
newMat.rows
# 2
newMat.cols
# 3
You can make a function to create your dense matrix with a column of ones prepended:
def prependOnesColumn[V](original: DenseMatrix[V]): DenseMatrix[V] = {
val ones = DenseMatrix.ones(original.rows, 1)
val dataWithOnes = ones.data ++ original.data
DenseMatrix.create(original.rows, original.cols + 1, dataWithOnes)
}

Cholesky Decomposition

I am trying to generate some random standard normal variables and correlate them
In particular I want:
where is the vector I want to simulate, and the given covariance matrix.
I am doing the following in matlab:
Simulate a vector of uncorrelated Gaussian random variables,
then find a square root of , i.e. a matrix such that .
Then the target vector is given by
Here is my matlab code:
N = 500000
u_1 = normrnd(zeros(N,1),1);
u_2 = normrnd(zeros(N,1),1);
u_3 = normrnd(zeros(N,1),1);
u_4 = normrnd(zeros(N,1),1);
rv = [u_1 '; u_2'; u_3'; u_4'];
VarCov = [1 -0.87 0.0 -0.6;
-0.87 1 0.0 0.0;
0.0 0.0 1 0.0
-0.6 0.0 0.0 1];
ch = chol(VarCov);
result = ch * rv;
However the chol(VarCov) is giving an error saying that the matrix is not positive semi definite.

MATLAB : Get k random subscripts with condition from a Matrix

I'd like get k random subscripts from A to be used in a C++ program with currently load data from a file given a set of subscripts.
I've a MxN matrix A with double values and a Mx1 matrix B with integers from 0 to 20.
How could i get k random subscripts from A with a condition from B ? In example, given:
A = [ 0.25 0.25 0.25 0.25
0.18 0.18 0.18 0.18
0.36 0.36 0.36 0.36
0.51 0.51 0.51 0.51 ]
B = [ 0
1
2
1 ]
I'm trying to get k = 1 random row subscript i from A if B(i) == 1. So, I'm looking for i == 1 or i == 4.
I've tried first create a logical index as:
idx = B == 1;
And then, get from A the elements with that condition as follow:
r = A( idx, : );
And finally, do a permutation in r to in order to get k rows:
randperm( size(r) )
But I'm stuck now as I do not know how to translate the permutation to the matrix A.
I'm also trying to understand the function [I,J] = ind2sub(siz,IND) but no idea right now how to join the subscripts with the randon permutation. Moreover, the results of randperm( size(r) ) are related to the size of r.
So, How could i get k random subscripts from A with a condition from B ? The idea is use the subscripts in a C++ program as input parameters
You can get the relevant row numbers as follows:
nrs=1:length(idx);
nrs=nrs(idx);
Now to permute them:
nrs_permidx = randperm(length(nrs))
permuted = nrs(nrs_permidx)
And I guess you can take it from here.