Same command broadcasts OK from command line, but not in a script - octave

I'm relying on broadcasting in the following element-by-element multiplication of a 2x2x2 matrix by a 1x2 matrix (broadcasting means the smaller matrix is repeated as many times as necessary to match the size of the larger one - see end for more explanation). One command gives a "nonconformant arguments" error when in a script run from the octave command line. But exactly the same command runs fine if typed at the octave command line.
Occasionally, the script doesn't give the error, but I haven't worked out exactly what arrangement the Universe has to be in to avoid the error (see later) -- whatever, running it within a script is as robust as a cheap garden strimmer.
I give a workround below, but I'd like to understand what's behind this error.
Here's my script file mwe_bcast.m:
# Minimum working example of broadcasting an element-by-element multiplication.
# The last line errors when run from octave as a script,
# but not when typed at the octave command line.
clear
test = [0,1;2,3];
test(:,:,2) = 3 - test;
test .*= 2;
factors = [1,2;3,4];
test .*= factors(1,:)
But here's the error when run as a script:
>> mwe_bcast
error: mwe_bcast: .*=: nonconformant arguments (op1 is 2x2x2, op2 is 1x2)
error: called from
mwe_bcast at line 9 column 6
Nonetheless, when I then type the last line at the command line there is no error, and the following output shows that the broadcasting has worked as expected:
>> test .*= factors(1,:)
test =
ans(:,:,1) =
0 4
4 12
ans(:,:,2) =
6 8
2 0
Even weirder: I checked whether this is repeatable after restarting octave. It is and it isn't! Sometimes, if I run the script any amount of times straight after starting octave (after just a cd to the appropriate directory), it runs without errors. But as soon as I edit the script in any way (just changing a comment, and sometimes even just opening it in the octave editor), then re-run the script, I get the error. But, other times, I get the error the first time I run the script after restarting octave.
Workround: I get no error from the script if I don't use the abbreviated assignment (.*=) for this broadcast element-by-element multiplication, i.e. replace the last line with:
test = test .* factors(1,:);
However, just as weirdly, note that the earlier use of .*= in the script to multiply the same matrix by a scalar always works without an error, even though it also relies on broadcasting.
Explanation of broadcasting: Essentially, the last line multiplies the matrix
test(:,:,1) = 0,1
2,3
test(:,:,2) = 3,2
1,0
element-by-element by [1,2] which broadcasts as if it were the matrix:
factors(:,:,1) = 1,2
1,2
factors(:,:,2) = 1,2
1,2
System:
GNU Octave, version 5.2.0
Ubuntu 20.04 LTE
Linux 5.15

Related

Octave eigs() function bugged?

Running Octave 6.3.0 for Windows. I need to get the smallest eigenvalue of some matrix.eigs(A,1,"sm") is supposed to do that, but I often get wrong results with singular matrices.
eigs(A) (which returns all the the first 6 eigenvalues/vectors) is correct (at least at the machine precision):
>> A = [[1 1 1];[1 1 1];[1 1 1]]
A =
1 1 1
1 1 1
1 1 1
>> [v lambda flag] = eigs(A)
v =
0.5774 -0.3094 -0.7556
0.5774 -0.4996 0.6458
0.5774 0.8091 0.1098
lambda =
Diagonal Matrix
3.0000e+00 0 0
0 -4.5198e-16 0
0 0 -1.5831e-17
flag = 0
But eigs(A,1,"sm") is not:
>> [v lambda flag] = eigs(A,1,"sm")
warning: eigs: 'A - sigma*B' is singular, indicating sigma is exactly an eigenvalue so convergence is not guaranteed
warning: called from
eigs at line 298 column 20
warning: matrix singular to machine precision
warning: called from
eigs at line 298 column 20
warning: matrix singular to machine precision
warning: called from
eigs at line 298 column 20
warning: matrix singular to machine precision
warning: called from
eigs at line 298 column 20
warning: matrix singular to machine precision
warning: called from
eigs at line 298 column 20
v =
-0.7554
0.2745
0.5950
lambda = 0.4322
flag = 0
Not only the returned eigenvalue is wrong, but the returned flag is zero, indicating that every went right in the function...
Is it a wrong usage of eigs() (but from the doc I can't see what is wrong) or a bug?
EDIT: if not a bug, at least a design issue... No problem either when requesting the 2 smallest values instead of the smallest value alone.
>> eigs(A,2,"sm")
ans =
-1.7700e-17
-5.8485e-16
EDIT 2: the eigs() function in Matlab online just runs fine and return the correct results (at the machine precision)
>> A=ones(3)
A =
1 1 1
1 1 1
1 1 1
>> [v lambda flag] = eigs(A,1,"smallestabs")
v =
-0.7556
0.6458
0.1098
lambda =
-1.5831e-17
flag =
0
After more tests and investigations I think I can answer that yes, Octave eigs() has some flaw.
eigs(A,1,"sm") likely uses the inverse power iteration method, that is repeatedly solving y=A\x, then x=y, starting with an arbitrary x vector. Obviously there's a problem if A is singular. However:
Matlab eigs() runs fine in such case, and returns the correct eigenvalue (at the machine precision). I don't know what it does, maybe adding a tiny value on the diagonal if the matrix is detected as singular, but it does something better (or at least different) than Octave.
If for some (good or bad) reason Octave's algorithm cannot handle a singular matrix, then this should be reflected in the 3rd return argument ("flag"). Instead, it is always zero as if everything went OK.
eigs(A,1,"sm") is actually equivalent to eigs(A,1,0), and the more general syntax is eigs(A,1,sigma), which means "find the closest eigenvalue to sigma, and the associated eigenvector". For this, the inverse power iteration method is applied with the matrix A-sigma*I. Problem: if sigma is already an exact eigenvalue this matrix is singular by definition. Octave eigs() fails in this case, while Matlab eigs() succeeds. It's kind of weird to have a failure when one knows in advance the exact eigenvalue, or sets it by chance. So the right thing to do in Octave is to test if (A-sigma.I) is singular, and if yes add a tiny value to sigma: eigs(A,1,sigma+eps*norm(A)). Matlab eigs() probably does something like that.

tricontour is not compatible with matlab version, or octave clabel

I need to draw and label contours of data given on a Delaunay grid. The function tricontour, part of the apparently no longer supported plot pkg, cannot do this, because the function returns a single argument (h):
pkg load plot
nx=ny=11;
[x,y]=ndgrid(linspace(-1,1,nx),linspace(-1,1,ny));
xp=[x(:),y(:)];
tp=[1,2,nx+1;nx+2,nx+1,2];
tp=kron(tp,ones(ny-1,1))+kron(ones(size(tp)),(0:ny-2)'*nx);
tp=kron(tp,ones(nx-1,1))+kron(ones(size(tp)),(0:nx-2)');
G=xp(:,1)+xp(:,2);
h=tricontour(tp,xp(:,1),xp(:,2),G,[-1:.5:1],'b');
[h]=clabel(c,h,[-4:2:6])
This MWE fails with
error: 'c' undefined near line 10 column 12
error: called from
Testricontourlabel at line 10 column 4
The matlab version of this function returns both c and h, and so is compatible with the matlab version of clabel.
Any ideas for a work around?

How do I fix an error with dataaspectratio not being finite in Octave?

I'm writing a simple script that iterates some data and plots the result. It was working fine. Then I zoomed in on the plot. After doing that, every time I try to run it I get the error
error: set: "dataaspectratio" must be finite
whether I use plot() or pcolor(). I found from a search that I can check the data aspect ratio with daspect() and the answer is [4 2 1] which looks finite to me. Even if I close and restart this error persists and won't let me plot anything, even a simple thing from the command line. Or a graph comes up with no y axis. How can I fix this?
The full error trying to run my file logistic.m is:
logistic
error: set: "dataaspectratio" must be finite
error: called from
__plt__>__plt2vv__ at line 495 column 10
__plt__>__plt2__ at line 242 column 14
__plt__ at line 107 column 18
plot at line 223 column 10
logistic at line 8 column 1
error: set: "dataaspectratio" must be finite
Here's the full script that I used:
R=linspace(0,4,100);
for j=1:100
r=R(j);
X=linspace(0,1,100);
for i=1:1000
X=r*(X-X.*X);
endfor
plot(R,X);
hold on;
endfor
Just now, after starting Octave again, this problem went away. A while later it came back. All I did was zoom into a plot that I made. The plot window still comes up the first time, but it's just a horizontal line with no axes. After that, the plot window doesn't even come up.

How do I fix the index error in my Octave code?

I'm having issues with the index for my code. I'm trying to create a code on Octave for the power method (vector iteration) and the error: 'x(4): out of bound 3' keeps popping up at line 6.
A=[6,-2,2,4;0,-4,2,2;0,0,2,-5;0,0,0,-3]
b=[12;10;-9;-3]
n=4
for i=rows(A):-1:1
for j=i+1:rows(A)
x(i)=[b(i)-A(i,j)*x(j)]/A(i,i); #error: 'x(4): out of bound 3'
endfor
endfor
x
In the following line, note that you have x appearing twice; the first seeks to assign to it, but the second simply tries to access its value:
x(i) = [ b(i) - A(i,j) * x(j) ] / A(i,i);
⬑ assignment ⬑ access
Assigning to an index that doesn't exist (yet) is absolutely fine; octave will simply fill in the intervening values with 'zeroes'. E.g.
>> clear x
>> x(3) = 1 % output: x = [0, 0, 1]
However, trying to access an index which doesn't exist yet is an error, since there's nothing there to access. This results in an "out of bound" error (and, in its error message, octave is kind enough to tell you what the last legitimate index is that you can access in that particular array).
Therefore, this is an error:
>> clear x
>> x(3) = 1 % output: x = [0, 0, 1]
>> 1 + x(4) % output: error: x(4): out of bound 3
Now going back to your specific code, you are trying to access something that doesn't exist yet. The reason it doesn't exist yet, is that you have set up your for loops such that j will achieve a higher value than i at a particular step, such that you are trying to access x(j), which does not exist yet, in order to assign it to x(i), where i < j. Therefore this results in an out of bounds error (you are trying to access index j when you only have up to i available).
In your particular case, octave informs you that this happened when j was 4, and i was 3.
PS: I will echo #HansHirse's implied warning here, that you should always pay attention to your variables, and clear them appropriately in your scripts, especially if you plan to run it many times. Never use a variable that you haven't defined (or cleared) beforehand. Otherwise, x here may not be undefined when you run your script, say, a second time. This leads to all sorts of problems, e.g., your code works but for the wrong reasons, and then fails to work again when you run it the next day and x is now undefined. In this particular example, if you had an x in your workspace which had the right number of elements in it, your code would "work" but produce the wrong result, and you wouldn't know any better.

octave runs ok but plot is not displayed?

HI there
I am using Octave 2.3.4 with a plot command. I am new at Octave. This plot does not display for some reason. Here is my M file sample:
1;
clear all;
%%%%%%%%% parameters setting %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
r=0.01; %risk free rate
S0=50; %underlying price 1
%create an implied volatiltiy surface using below parameters:
basevol=0.25; %implied volatility at time t=0 and in center of strike axis
skewT=-0.001; %icrease in vol for one unit increase in maturity
v1=0.1; %defines how much a smile is raised at left end from base vol
v3=0.2; %defines how much a smile is raised at right end from base vol
nK=100; %no. of strike steps
nT=10; %no. of time steps
Tmax=1; %maximum value in time axis
Kmin=1; %minimum value in strike price axis
Kmax=150; %maximum value of strike price axis
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
dt=Tmax/(nT-1);
Tvec=0:dt:1;
dk=(Kmax-Kmin)/(nK-1);
Kvec=Kmin:dk:Kmax;
Tvec=Tvec';
Kvec=Kvec';
nK=size(Kvec,1);
nT=size(Tvec,1);
dvolT=ones(nK,nT)*(skewT*dt);
dvolT=cumsum(dvolT,2);
SmileVec=GetSmile(Kvec,v1,0,v3);
dvolK=ones(nK,nT);
dvolK=repmat(SmileVec,1,nT);
ImpliedVolSurface=ones(nK,nT)*basevol+dvolT+dvolK;
%use formula mentioned by John Elder in "Hedging for Financial Derivatives"
%this formula gives local volatility using implied volatility
function ret=GetLocalVolSurface(ImpliedVolSurface, S, r, Kvec, Tvec)
[m,n]=size(ImpliedVolSurface);
LocalVolSurface=zeros(m,n);
dk=Kvec(2)-Kvec(1);
dt=Tvec(2)-Tvec(1);
x=ImpliedVolSurface;
for i=3:m-2, %loop over strikes
for j=1:n-1, %loop over time steps
dv_dk=(x(i+1,j)-x(i-1,j))/(2*dk);
dv2_dk2=(x(i-1,j)-2*x(i,j)+x(i+1,j))/(dk*dk);
dv_dt=(x(i,j+1)-x(i,j))/dt;
K=Kvec(i);
T=Tvec(j+1);
rT=T^0.5;
sig=x(i,j);
h1=(log(S/K)+r*T+0.5*sig*sig*T)/(sig*rT);
numer=sig*sig + 2*T*sig*dv_dt + 2*r*K*T*sig*dv_dk;
denom=(1+K*h1*rT*dv_dk)^2 + K*K*T*sig*sig*(dv2_dk2-h1*dv_dk*dv_dk*rT);
LocalVolSurface(i,j)=(numer/denom)^0.5;
end
end
ret=LocalVolSurface;
endfunction
LocalVol_Surface=GetLocalVolSurface(ImpliedVolSurface,S0,r,Kvec,Tvec);
AsyImplVols=zeros(nK,1);
T=Tvec(nT-1);
F=S0*exp(r*T);
for i=3:nK-2,
% use formula sigBS(F,K)=sigLoc( (F+K)/2 )
K=Kvec(i);
lookupK=(F+K)/2;
kdiff=abs(Kvec-lookupK); %try to find nearest point in grid
kidx=min(find(kdiff==min(kdiff)));
if ( (kidx > 3) && (kidx < nK-2) ),
AsyImplVols(i)=LocalVol_Surface(kidx);
else
AsyImplVols(i) = NaN;
end
end
figure(1);
plot(Kvec(3:nK-2),[ImpliedVolSurface(3:nK-2,nT-1) LocalVol_Surface(3:nK-2,nT-1) AsyImplVols(3:nK-2)]);
When I run in Octave with no error, the plot is never displayed. It does include gnuplot 1.0.1 which I understand does the graph? Is there something I am not doing or missing? I am also running this on Windows 2003 Server.
Thanks
I got the answer here. Octave by default uses fltk for plotting etc, which is failing to work, using gnuplot works here. Just add below lines to .octaverc file in your home directory.
graphics_toolkit("gnuplot")
So that every time octave starts it will set the default package for plotting to gnuplot
I do know that's an old question but since I ran into quite the same error yesterday, maybe this can help someone else, too:
According to the Octave wiki pages, there seems to be a problem with plotting and the "oct2mat"-library. For me, the problem was solved after I ran this at the octave command prompt:
pkg rebuild -noauto oct2mat
and restarted octave. When you need to use "oct2mat", type:
pkg load oct2mat
Hope that helps!
I get the same problem installing on a windows 7 64 bit laptop (HP 630) with intel graphics. Every time you plot, it fails to do anything, but if you plot again, it shows up. It's some kind of refresh bug. It's annoying, but if you plot twice, the second time it works.
I am wondering if it is some kind of double buffering bug, because it works correctly on my own laptop running windows 7 with a dedicated graphics card.
In any case, try plotting twice in a row, I'll bet it works, and please let me know what the machine and video card are, because I've reported this to octave development.