How to fix: "anonymous function bodies must be single expressions" error on Octave - octave

I am trying to make a function in Octave where you give octave a function f(x,y) as a string, a change in X, a change in Y, a starting point, and the size of a matrix, the function will create a matrix populated with the values of f(x,y) at each point in the matrix.
This is for an application that displays a 3d graph, using the matrix to map each value to a block
# funcStr: The function whose Z values are being calculated
# dx: the change in x that each block in the x direction represents
# dy: the change in y that each block in the y direction represents
# startPt: the point (in an array of x, y) that center block represents
# res: the side length (in blocks) of the plane
pkg load symbolic
syms x y
function[zValues] = calculateZValues(funcStr, dx, dy, startPt, res)
zValues = zeros(res);
eqn = #(x, y) inline(funcStr);
startX = startPt{1};
startY = startPt{2};
for yOffset = 1:res
for xOffset = 1:res
xCoord = startX + dx * xOffset;
yCoord = startY + dy * yOffset;
zValues(res * yOffset + xOffset) = double(subs(eqn, #(x, y), {xCoord, yCoord}));
endfor
endfor
endfunction
The error I am getting is:
>> calculateZValues("x*y", 1, 1, {0,0}, 10)
parse error near line 20 of file /home/rahul/Documents/3dGraph/graph/calculateZValues.m
anonymous function bodies must be single expressions
>>> zValues(res * yOffset + xOffset) = double(subs(eqn, #(x, y), {xCoord, yCoord}));
I have no idea what the issue is. I have replaced the #(x,y) part with {x,y} in the line referenced by the error but it says nothing or it raises an error about the function subs not being declared. I have also tried moving the pkg and syms lines above the function header

Related

Octave, The secant method

I am trying to implement the secant method using Octave, and in particular I made a function called secant("function","x0","x1","tolerance"). I used the while-loop for calculate the root of a function and I think the problem is in the loop.
But the result that I get, it is not what I expect. The correct answer is x=0,49438.
My code is the following:
tol = 10.^(-5); # tolerance
x0 = 0.4; # initial point
x1 = 0.6; # initial point
syms x;
fun = #(x) exp(sin(x)) - 2/(1+x.^2); # f(x) = exp(sin(x)) - 2/(1+x^2)
fprintf("Function f(x)\n");
fun
fprintf("\n");
fprintf("initial points: %f\n",x0,x1);
function[raiz,errel,niter] = secant(fun,x0,x1,tol)
niter = 0; # steps number
errel = []; # the vector of relative errors
y0 = fun(x0); # f(x0)
y1 = fun(x1); # f(x1)
ra = 0.0; # ra is the variable of the function's root
while abs(ra-x1)>= tol
niter += 1;
ra = x1 - ((x1-x0)./(y1-y0)).*y0; # formula of the secant method
if abs((ra-x1))<tol
raiz = ra;
return;
endif
x0 = x1; y0 = y1; x1 = ra;
y1 = fun(ra);
errel(niter) = abs(ra-x1)/abs(ra); # Calcule of relative error
endwhile
if abs((ra-x1)/ra)<tol
fprintf ('The method is over\n');
fprintf ('\n');
endif
raiz = ra;
endfunction
[r,er,tot] = secant(fun,x0,x1,tol)
I appreciate the help you can give me
It makes little sense to use the secant root in the loop condition. At first it is not defined, and inside the loop it is shifted into the support points for the next secant. Note that at the end ra and x1 contain the same value, making the loop condition trivial, in a wrong way.
Next, the secant has the equation
y(x) = y1 + (y1-y0)/(x1-x0)*(x-x_1)
check that with this formula y(x0)=y0 and y(x1)=y1. Thus the secant root is to be found at
x = x1 - (x1-x0)/(y1-y0)*y1
Finally, at no point are symbolic expressions used, defining x as symbolic variable is superfluous.
The break-out test inside the loop is also redundant and prevents a coherent state after the loop. Just remove it and remember that x1 contains the last approximation.
With all this I get an execution log as follows:
Function f(x)
fun =
#(x) exp (sin (x)) - 2 / (1 + x .^ 2)
initial points: 0.400000
initial points: 0.600000
The method is over
r = 0.494379048216965
er =
2.182723270633349e-01 3.747373180587413e-03 5.220701832080676e-05 1.899377363987941e-08
tot = 4

How to correctly calculate a nonlinear function and plot its graph in Octave?

Goal: Plot the graph using a non-linear function.
Function and graph
This is my first time working at Octave. To plot the graph, I need to calculate a function in the range Fx (0.1 ... 10).
I tried to implement this by looping the function through the for loop, writing the results to an array (x-axis - Fn, y-axis - function value), then loading the arrays into the plot() function.
Fn = 1
Ln = 5
Q = 0.5
function retval = test (Fn, Ln, Q)
# Fn squared (for common used)
Fn = Fn^2
# Node A + Node B
nodeA = Fn * (Ln - 1)
nodeB = (Ln * Fn - 1)^2 + Fn * (Fn - 1)^2 * (Ln - 1)^2 * Q^2
nodeB = sqrt(nodeB)
# Result
result = nodeA / nodeB
retval = result
return;
endfunction
frequencyArray = {}
gainArray = {}
fCount = 1
gCount = 1
for i = 0:0.5:5
# F
Fn = i
frequencyArray{fCount} = Fn
fCount = fCount + 1
# G
gainArray{gCount} = test(Fn, Ln, Q)
gCount = gCount + 1
end
plot(frequencyArray, gainArray);
As a result, I get an error about the format of the arrays.
>> plot(frequencyArray, gainArray);
error: invalid value for array property "xdata"
error: __go_line__: unable to create graphics handle
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
In addition to the error, I believe that these tasks are solved in more correct ways, but I did not quite understand what to look for.
Questions:
Did I choose the right way to solve the problem? Are there any more elegant ways?
How can I fix this error?
Thank you!
If I have correctly interpreted what you are trying to do, the following should work. Firstly, you need to use the term-by-term versions of all arithmetic operators that act on Fn. These are the same as the normal operators except preceded by a dot. Next, you need to put Fn equal to a vector containing the x-values of all the points you wish to plot and put Q equal to a vector containing the values of Q for which you want to draw curves. Use a for-loop to loop through the values of Q and plot a single curve in each iteration of the loop. You don't need a loop to plot each curve because Octave will apply your "test" function to the whole Fn vector and return the result as a vector of the same size. To plot the curves on a log axis, use the function "semilogx(x, y)" insetad of "plot(x, y)". To make the plots appear on the same figure, rather than separate ones put "hold on" before the loop and "hold off" afterwards. You used cell arrays instead of vectors in your for-loop, which the plotting functions don't accept. Also, you don't need an explicit return statement in an Octave function.
The following code produces a set of curves that look like the ones in the figure you pasted in your question:
Ln = 5
function result = test (Fn, Ln, Q)
# Fn squared (for common used)
Fn = Fn.^2;
# Node A + Node B
nodeA = Fn .* (Ln - 1);
nodeB = (Ln .* Fn .- 1).^2 + Fn .* (Fn .- 1).^2 .* (Ln - 1)^2 * Q^2;
nodeB = sqrt(nodeB);
# Result
result = nodeA ./ nodeB;
endfunction
Fn = linspace(0.1, 10, 500);
Q = [0.1 0.2 0.5 0.8 1 2 5 8 10];
hold on
for q = Q
K = test(Fn, Ln, q);
semilogx(Fn, K);
endfor
hold off

How to solve the Error: x undefined in octave

I was trying to plot data.
Firstly, I have load the data from a file
data = load('ex1data1.txt'); % read comma separated data
X = data(:, 1); y = data(:, 2);
m = length(y); % number of training examples
Then i have called the function plotData
function figure=plotData(x, y)
figure; % open a new figure window
if(is_vector(x) && is_vector(y))
figure=plot(x,y,'rx',MarkerSize,10);
xlabel('Profit in $10,000s');
ylabel('Population of city in 10,000s');
endif
endfunction
But Iam getting an error. which says:
x is undefined
Thank you in advance.
The problem is in the following statement:
X = data(:, 1); y = data(:, 2);
you have defined X variable but when you call
plotData(x, y)
you are using lowercase X
I think if change the statement: plotData(X, y) will solve your problem

Use the same plot for different subfunctions

I am calling a functions recursively and I want them all to draw in the same plot. When i try to create a handler and pass it on with the parameters I get the following error:
??? Error using ==> set Invalid handle object.
Error in ==> triangle at 23
set(h, 'xdata', [x1,x3], 'ydata', [y1,y3]);
Before calling my function I've created a handler and set my preferences:
h = plot([0,1],[0,0]);
set(h, 'erasemode', 'none');
triangle(0,0,1,0,10,0,h)
This is my function:
function triangle(x1,y1,x2,y2, deepth , n,h)
%Paints a equilateral triangle for two given Points
if depth > n
shg
clf reset
%vector
v_12 = [x2-x1;y2-y1];
%rotate vector
g_uz = [0.5,-sqrt(3)/2;sqrt(3)/2, 0.5];
p = g_uz * v_12;
x3 = p(1) + x1;
y3 = p(2) + y1;
axis([-10 10 -10 10]);
axis off
drawnow
set(h, 'xdata', [x1,x3], 'ydata', [y1,y3]);
drawnow
set(h, 'xdata', [x2,x3], 'ydata', [y2,y3]);
drawnow
v_13 = [x3-x1,y3-y1];
v_23 = [x3-x2,y3-y2];
% 1-3 triangle
triangle(x1+v_13(1)/3,y1 + v_13(1)/3, x1+ 2*v_13(1)/3,y1 + 2*v_13(1)/3, tiefe, n+1 );
end
Do you know any solutions? How can I Plot in an object form a function i called?
The clf on line 6 clears the figure, removing the line that you want to use as your graphic output.
Remove that line and see if it works.
Try using hold all. It lets you plot new lines in the figure without clearing existing lines.
figure
hold all
triangle(...)
Inside your function just call plot.
plot(x, y)
plot(x, z)

How can I find the smallest difference between two angles around a point?

Given a 2D circle with 2 angles in the range -PI -> PI around a coordinate, what is the value of the smallest angle between them?
Taking into account that the difference between PI and -PI is not 2 PI but zero.
An Example:
Imagine a circle, with 2 lines coming out from the center, there are 2 angles between those lines, the angle they make on the inside aka the smaller angle, and the angle they make on the outside, aka the bigger angle.
Both angles when added up make a full circle. Given that each angle can fit within a certain range, what is the smaller angles value, taking into account the rollover
This gives a signed angle for any angles:
a = targetA - sourceA
a = (a + 180) % 360 - 180
Beware in many languages the modulo operation returns a value with the same sign as the dividend (like C, C++, C#, JavaScript, full list here). This requires a custom mod function like so:
mod = (a, n) -> a - floor(a/n) * n
Or so:
mod = (a, n) -> (a % n + n) % n
If angles are within [-180, 180] this also works:
a = targetA - sourceA
a += (a>180) ? -360 : (a<-180) ? 360 : 0
In a more verbose way:
a = targetA - sourceA
a -= 360 if a > 180
a += 360 if a < -180
x is the target angle. y is the source or starting angle:
atan2(sin(x-y), cos(x-y))
It returns the signed delta angle. Note that depending on your API the order of the parameters for the atan2() function might be different.
If your two angles are x and y, then one of the angles between them is abs(x - y). The other angle is (2 * PI) - abs(x - y). So the value of the smallest of the 2 angles is:
min((2 * PI) - abs(x - y), abs(x - y))
This gives you the absolute value of the angle, and it assumes the inputs are normalized (ie: within the range [0, 2π)).
If you want to preserve the sign (ie: direction) of the angle and also accept angles outside the range [0, 2π) you can generalize the above. Here's Python code for the generalized version:
PI = math.pi
TAU = 2*PI
def smallestSignedAngleBetween(x, y):
a = (x - y) % TAU
b = (y - x) % TAU
return -a if a < b else b
Note that the % operator does not behave the same in all languages, particularly when negative values are involved, so if porting some sign adjustments may be necessary.
An efficient code in C++ that works for any angle and in both: radians and degrees is:
inline double getAbsoluteDiff2Angles(const double x, const double y, const double c)
{
// c can be PI (for radians) or 180.0 (for degrees);
return c - fabs(fmod(fabs(x - y), 2*c) - c);
}
See it working here:
https://www.desmos.com/calculator/sbgxyfchjr
For signed angle:
return fmod(fabs(x - y) + c, 2*c) - c;
In some other programming languages where mod of negative numbers are positive, the inner abs can be eliminated.
I rise to the challenge of providing the signed answer:
def f(x,y):
import math
return min(y-x, y-x+2*math.pi, y-x-2*math.pi, key=abs)
For UnityEngine users, the easy way is just to use Mathf.DeltaAngle.
Arithmetical (as opposed to algorithmic) solution:
angle = Pi - abs(abs(a1 - a2) - Pi);
I absolutely love Peter B's answer above, but if you need a dead simple approach that produces the same results, here it is:
function absAngle(a) {
// this yields correct counter-clock-wise numbers, like 350deg for -370
return (360 + (a % 360)) % 360;
}
function angleDelta(a, b) {
// https://gamedev.stackexchange.com/a/4472
let delta = Math.abs(absAngle(a) - absAngle(b));
let sign = absAngle(a) > absAngle(b) || delta >= 180 ? -1 : 1;
return (180 - Math.abs(delta - 180)) * sign;
}
// sample output
for (let angle = -370; angle <= 370; angle+=20) {
let testAngle = 10;
console.log(testAngle, "->", angle, "=", angleDelta(testAngle, angle));
}
One thing to note is that I deliberately flipped the sign: counter-clockwise deltas are negative, and clockwise ones are positive
There is no need to compute trigonometric functions. The simple code in C language is:
#include <math.h>
#define PIV2 M_PI+M_PI
#define C360 360.0000000000000000000
double difangrad(double x, double y)
{
double arg;
arg = fmod(y-x, PIV2);
if (arg < 0 ) arg = arg + PIV2;
if (arg > M_PI) arg = arg - PIV2;
return (-arg);
}
double difangdeg(double x, double y)
{
double arg;
arg = fmod(y-x, C360);
if (arg < 0 ) arg = arg + C360;
if (arg > 180) arg = arg - C360;
return (-arg);
}
let dif = a - b , in radians
dif = difangrad(a,b);
let dif = a - b , in degrees
dif = difangdeg(a,b);
difangdeg(180.000000 , -180.000000) = 0.000000
difangdeg(-180.000000 , 180.000000) = -0.000000
difangdeg(359.000000 , 1.000000) = -2.000000
difangdeg(1.000000 , 359.000000) = 2.000000
No sin, no cos, no tan,.... only geometry!!!!
A simple method, which I use in C++ is:
double deltaOrientation = angle1 - angle2;
double delta = remainder(deltaOrientation, 2*M_PI);