Octave: "'ncx2cdf' undefined" error - octave

I'm trying to run a M-file from octave but I get this error:
Octave evaluation error: 'ncx2cdf' undefined

Apparently the non-central chi-square distribution is simply defined as 1 minus the Marcum Q function. The signal package at octave-forge provides an implementation for this function (seemingly compatible with matlab).
Therefore you could presumably write your own ncx2cdf function simply as follows:
function Out = myncx2cdf (X, V, Delta)
Out = 1 - marcumq (sqrt (Delta), sqrt (X), V/2);
end
Confirmed in matlab:
>> X = randi(100, [1,20]); V = 4; Delta = 10;
>> ncx2cdf(X, V, Delta)
ans =
1.0000 0.9410 0.9999 1.0000 1.0000 1.0000 1.0000 0.5549 0.6093 0.9410 1.0000 0.9410 1.0000 0.9279 1.0000 0.9920 0.8183 0.9410 1.0000 0.9997
>> 1 - marcumq(sqrt(Delta), sqrt(X), V/2)
ans =
1.0000 0.9410 0.9999 1.0000 1.0000 1.0000 1.0000 0.5549 0.6093 0.9410 1.0000 0.9410 1.0000 0.9279 1.0000 0.9920 0.8183 0.9410 1.0000 0.9997
Octave session for the same X, V, and Delta:
octave:34> pkg load signal
octave:35> 1 - marcumq(sqrt(Delta), sqrt(X), V/2)
ans =
1.00000 0.94105 0.99988 1.00000 1.00000 1.00000 0.99996 0.55492 0.60929 0.94105 1.00000 0.94105 1.00000 0.92793 1.00000 0.99203 0.81831 0.94105 1.00000 0.99972
Note that the degrees of freedom parameter V is restricted to even values with this implementation; if you'd like to use odd degrees of freedom too, e.g. 5, this could be interpolated from the result for V=4 and V=6 (this seems to work well in practice).

here is a easy implementation of non-central chi square distribution:
function f = ncx2pdf(x, n, lambda, term = 32)
f = exp(-lambda/2) * arrayfun(#(x) sum_expression([0:term],x,n,lambda), x);
function t = sum_expression(j,v,n,l)
# j is vector, v is scalar.
numerator = (l/2).^j .* v.^(n/2+j-1) * exp(-v/2);
denominator = factorial(j) .* 2.^(n/2+j) .* gamma(n/2+j);
t = sum(numerator ./ denominator);
end
end
here is the function file , put it in your octave path.

Related

How to deduce left-hand side matrix from vector?

Suppose I have the following script, which constructs a symbolic array, A_known, and a symbolic vector x, and performs a matrix multiplication.
clc; clearvars
try
pkg load symbolic
catch
error('Symbolic package not available!');
end
syms V_l k s0 s_mean
N = 3;
% Generate left-hand-side square matrix
A_known = sym(zeros(N));
for hI = 1:N
A_known(hI, 1:hI) = exp(-(hI:-1:1)*k);
end
A_known = A_known./V_l;
% Generate x vector
x = sym('x', [N 1]);
x(1) = x(1) + s0*V_l;
% Matrix multiplication to give b vector
b = A_known*x
Suppose A_known was actually unknown. Is there a way to deduce it from b and x? If so, how?
Til now, I only had the case where x was unknown, which normally can be solved via x = b \ A.
Mathematically, it is possible to get a solution, but it actually has infinite solutions.
Example
A = magic(5);
x = (1:5)';
b = A*x;
A_sol = b*pinv(x);
which has
>> A
A =
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
but solves A as A_sol like
>> A_sol
A_sol =
3.1818 6.3636 9.5455 12.7273 15.9091
3.4545 6.9091 10.3636 13.8182 17.2727
4.4545 8.9091 13.3636 17.8182 22.2727
3.4545 6.9091 10.3636 13.8182 17.2727
3.1818 6.3636 9.5455 12.7273 15.9091

Find integer solution to formula

Given two vectors of candidates:
x = [1 3 5];
y = [1 2 3 4];
I want to find which candidates satisfy an equation or formula. This is what I want to do:
f = x + y - 6;
solve f;
And then, it spits out the solutions:
5 1
3 3
If it matters, I am actually using Octave, not MatLab because I don't have a Windows machine. I know that I can do this with a for loop:
for i=x
for j=y
if i+j-6==0
disp([i j]);
end
end
This is a trivial example. I am looking for a solution that will handle much larger examples.
Solving such equations per "brute force" is generally a bad idea but here you go:
x = [1 3 5];
y = [1 2 3 4];
## build grid (also works for n vars)
[xx, yy] = ndgrid (x, y);
## anonymous function
f = #(x,y) abs(x + y - 6) < 16*eps
## true?
t = f (xx, yy);
## build result
[xx(t) yy(t)]

Failing to solve a simple ODE with Octave

I am new to Octave, so I am trying to make some simple examples work before moving onto more complex projects.
I am trying to resolve the ODE dy/dx = a*x+b, but without success. Here is the code:
%Funzione retta y = a*x + b. Ingressi: vettore valori t; coefficienti a,b
clear all;
%Inizializza argomenti
b = 1;
a = 1;
x = ones(1,20);
function y = retta(a, x, b) %Definisce funzione
y = ones(1,20);
y = a .* x .+ b;
endfunction
%Calcola retta
x = [-10:10];
a = 2;
b = 2;
r = retta(a, x, b)
c = b;
p1 = (a/2)*x.^2+b.*x+c %Sol. analitica di dy/dx = retta %
plot(x, r, x, p1);
% Risolve eq. differenziale dy/dx = retta %
y0 = b; x0 = 0;
p2 = lsode(#retta, y0, x)
And the output is:
retta3code
r =
-18 -16 -14 -12 -10 -8 -6 -4 -2 0 2 4 6 8 10 12 14 16 18 20 22
p1 =
Columns 1 through 18:
82 65 50 37 26 17 10 5 2 1 2 5 10 17 26 37 50 65
Columns 19 through 21:
82 101 122
error: 'b' undefined near line 9 column 16
error: called from:
error: retta at line 9, column 4
error: lsode: evaluation of user-supplied function failed
error: lsode: inconsistent sizes for state and derivative vectors
error: /home/fabio/octave_file/retta3code.m at line 21, column 4
So, the function retta works properly the first time, but it fails when used in lsode.
Why does that happen? What needs to be changed to make the code work?
Somehow you still miss some important parts of the story. To solve an ODE y'=f(y,x) you need to define a function
function ydot = f(y,x)
where ydot has the same dimensions as y, both have to be vectors, even f they are of dimension 1. x is a scalar. For some traditional reason, lsode (a FORTRAN code used in multiple solver packages) prefers the less used order (y,x), in most text books and other solvers you find the order (x,y).
Then to get solution samples ylist over sample points xlist you call
ylist = lsode("f", y0, xlist)
where xlist(1) is the initial time.
The internals of f are independent of the sample list list and what size it has. It is a separate issue that you can use multi-evaluation to compute the exact solution with something like
yexact = solexact(xlist)
To pass parameters, use anonymous functions, like in
function ydot = f(y,x,a,b)
ydot = [ a*x+b ]
end
a_val = ...
b_val = ...
lsode(#(y,x) f(y,x,a_val, b_val), y0, xlist)
The code as modified below works, but I'd prefer to be able to define the parameters a and b out of the function and then pass them to rdot as arguments.
x = [-10,10];
a = 1;
b = 0;
c = b;
p1 = (a/2).*(x.^2)+b.*x+c %Sol. analitica di dy/dx = retta %
function ydot = rdot(ydot, x)
a = 1;
b = 0;
ydot = ones(1,21);
ydot = a.*x .+ b;
endfunction
y0 = p1(1); x0 = 0;
p2 = lsode("rdot", y0, x, x0)'
plot(x, p1, "-k", x, p2, ".r");

Vectorization of feature scaling

I want to feature scale a matrix (X) with 2 columns. I am using mean normalization, and I wrote the following lines in Octave:
X_norm = X
mu = mean(X);
sigma = std(X);
X_norm(:,1) = (X_norm(:,1) .- mu(:,1)) ./ sigma(:,1);
X_norm(:,2) = (X_norm(:,2) .- mu(:,2)) ./ sigma(:,2);
Can you please let me know a cleaner way to vectorize these calculation?
I checked my code by comparing with the result from zscore(X) and they matched - i.e. a sum(X_norm - zscore(X)) returned me 0 0.
I am constrained to not use zscore(), and hence the question.
Sample data as follows:
2104 3
1600 3
2400 3
1416 2
3000 4
1985 4
1534 3
1427 3
1380 3
1494 3
1940 4
2000 3
1890 3
4478 5
1268 3
2300 4
1320 2
1236 3
2609 4
3031 4
1767 3
1888 2
1604 3
1962 4
3890 3
1100 3
1458 3
2526 3
2200 3
2637 3
You could simply do:
X_norm = (X .- mean(X,1)) ./ std(X,0,1);
During cross validation faced zero division issue.
This worked for me.
mu = mean(X);
X_norm = X - mu;
sigma = std(X);
% Skip zero div
sigmaZeroIdx = sigma == 0;
sigma(1,sigmaZeroIdx) = 1;
X_norm = X_norm ./ sigma;
I think you could apply a for loop for N size of features.
X_norm = X;
mu = zeros(1, size(X, 2));
sigma = zeros(1, size(X, 2));
for iter = 1:num_iters;
mu(1,iter) = mean(X_norm(:,iter));
X_norm(:,iter) = X_norm(:,iter) .- mu(1,iter);
sigma(1,iter) = std(X_norm(:,iter));
X_norm(:,iter) = X_norm(:,iter) ./ mu(1,iter);
end

how to plot function in scilab

I have 2 functions here:
function y=f(x)
y=(x*%e^x)-cos(x);
endfunction
function c=regulafalsi(f, x0, x1, tol)
i=1;
n(1)=100;
if f(x0)*f(x1) < 0
a(1)=x0;
b(1)=x1;
c(1)=a(1)-f(a(1))*(b(1)-a(1))/(f(b(1))-f(a(1)));
printf('i.\t\t a\t\t c\t\t b\t\t f(c)\t Galat \n');
printf('%2d \t %11.4f \t %11.4f \t %11.4f \t %11.4f \n',i,a(i),c(i),b(i),f(c(i)));
while abs(n(i))>=tol,
if f(a(i))*f(c(i))< 0
a(i+1)=a(i);
b(i+1)=c(i);
end
if f(a(i))*f(c(i))> 0
a(i+1)=c(i);
b(i+1)=b(i);
end
c(i+1)=a(i+1)-f(a(i+1))*(b(i+1)-a(i+1))/(f(b(i+1))-f(a(i+1)));
n(i+1)=abs((c(i+1)-c(i))/(c(i+1)));
printf('%2d \t %11.4f \t %11.4f \t %11.4f \t %11.4f \t %7.4f \n',i+1,a(i+1),c(i+1),b(i+1),f(c(i+1)),n(i+1));
i=i+1;
end
else
printf(' ');
end
endfunction
How to plot those function?
I tried plot(y,c) not working.
You have two Scilab functions but only the first of them represents a mathematical function that could be plotted. The second one is a root-finding procedure which outputs some numerical data; it's not meant to be fed into plot command.
To plot function f, you can do the following (e.g., at the end of your script, or in command window)
x = linspace(0,1)
plot(x,f(x))
Here 0, 1 are the endpoints of the interval on which to plot. The linspace command creates an array of numbers distributed over that interval, which is fed into f and then the result into plot.
In order for this to work, you will need to adjust your formula for f slightly:
function y=f(x)
y=(x.*exp(x))-cos(x);
endfunction
The dot before * indicates the multiplication is to be done component wise. This allows this function to process arrays of numbers at once.
Your root-finding function (the method of false position, apparently) works fine. For example, executed with
regulafalsi(f,0,1,0.01)
it returns
i. a c b f(c) Galat
1 0.0000 0.3147 1.0000 -0.5199
2 0.3147 0.4467 1.0000 -0.2035 0.2956
3 0.4467 0.4940 1.0000 -0.0708 0.0957
4 0.4940 0.5099 1.0000 -0.0236 0.0312
5 0.5099 0.5152 1.0000 -0.0078 0.0102
6 0.5152 0.5169 1.0000 -0.0025 0.0033
The root around 0.516 has been found.