Piecewise functions in the Octave symbolic package? - octave

Unlike Matlab, Octave Symbolic has no piecewise function. Is there a work around? I would like to do something like this:
syms x
y = piecewise(x0, 1)
Relatedly, how does one get pieces of a piecewise function? I ran the following:
>> int (exp(-a*x), x, 0, t)
And got the following correct answer displayed and stored in a variable:
t for a = 0
-a*t
1 e
- - ----- otherwise
a a
But now I would like to access the "otherwise" part of the answer so I can factor it. How do I do that?
(Yes, I can factor it in my head, but I am practicing for when more complicated expressions come along. I am also only really looking for an approach using symbolic expressions -- even though in any single case numerics may work fine, I want to understand the symbolic approach.)
Thanks!

Matlab's piecewise function seems to be fairly new (introduced in 2016b), but it basically just looks like a glorified ternary operator. Unfortunately I don't have 2016 to check if it performs any checks on the inputs or not, but in general you can recreate a 'ternary' operator in octave by indexing into a cell using logical indexing. E.g.
{#() return_A(), #() return_B(), #() return_default()}([test1, test2, true]){1}()
Explanation:
Step 1: You put all the values of interest in a cell array. Wrap them in function handles if you want to prevent them being evaluated at the time of parsing (e.g. if you wanted the output of the ternary operator to be to produce an error)
Step 2: Index this cell array using logical indexing, where at each index you perform a logical test
Step 3: If you need a 'default' case, use a 'true' test for the last element.
Step 4: From the cell (sub)array that results from above, select the first element and 'run' the resulting function handle. Selecting the first element has the effect that if more than one tests succeed, you only pick the first result; given the 'default' test will always succeed, this also makes sure that this is not picked unless it's the first and only test that succeeds (which it does so by default).
Here are the above steps implemented into a function (appropriate sanity checks omitted here for brevity), following the same syntax as matlab's piecewise:
function Out = piecewise (varargin)
Conditions = varargin(1:2:end); % Select all 'odd' inputs
Values = varargin(2:2:end); % Select all 'even' inputs
N = length (Conditions);
if length (Values) ~= N % 'default' case has been provided
Values{end+1} = Conditions{end}; % move default return-value to 'Values'
Conditions{end} = true; % replace final (ie. default) test with true
end
% Wrap return-values into function-handles
ValFuncs = cell (1, N);
for n = 1 : N; ValFuncs{n} = #() Values{n}; end
% Grab funhandle for first successful test and call it to return its value
Out = ValFuncs([Conditions{:}]){1}();
end
Example use:
>> syms x t;
>> F = #(a) piecewise(a == 0, t, (1/a)*exp(-a*t)/a);
>> F(0)
ans = (sym) t
>> F(3)
ans = (sym)
-3⋅t
ℯ
─────
9

Related

Is using base case variable in a recursive function important?

I'm currently learning about recursion, it's pretty hard to understand. I found a very common example for it:
function factorial(N)
local Value
if N == 0 then
Value = 1
else
Value = N * factorial(N - 1)
end
return Value
end
print(factorial(3))
N == 0 is the base case. But when i changed it into N == 1, the result is still remains the same. (it will print 6).
Is using the base case important? (will it break or something?)
What's the difference between using N == 0 (base case) and N == 1?
That's just a coincidence, since 1 * 1 = 1, so it ends up working either way.
But consider the edge-case where N = 0, if you check for N == 1, then you'd go into the else branch and calculate 0 * factorial(-1), which would lead to an endless loop.
The same would happen in both cases if you just called factorial(-1) directly, which is why you should either check for > 0 instead (effectively treating every negative value as 0 and returning 1, or add another if condition and raise an error when N is negative.
EDIT: As pointed out in another answer, your implementation is not tail-recursive, meaning it accumulates memory for every recursive functioncall until it finishes or runs out of memory.
You can make the function tail-recursive, which allows Lua to treat it pretty much like a normal loop that could run as long as it takes to calculate its result:
local function factorial(n, acc)
acc = acc or 1
if n <= 0 then
return acc
else
return factorial(n-1, acc*n)
end
return Value
end
print(factorial(3))
Note though, that in the case of factorial, it would take you way longer to run out of stack memory than to overflow Luas number data type at around 21!, so making it tail-recursive is really just a matter of training yourself to write better code.
As the above answer and comments have pointed out, it is essential to have a base-case in a recursive function; otherwise, one ends up with an infinite loop.
Also, in the case of your factorial function, it is probably more efficient to use a helper function to perform the recursion, so as to take advantage of Lua's tail-call optimizations. Since Lua conveniently allows for local functions, you can define a helper within the scope of your factorial function.
Note that this example is not meant to handle the factorials of negative numbers.
-- Requires: n is an integer greater than or equal to 0.
-- Effects : returns the factorial of n.
function fact(n)
-- Local function that will actually perform the recursion.
local function fact_helper(n, i)
-- This is the base case.
if (i == 1) then
return n
end
-- Take advantage of tail calls.
return fact_helper(n * i, i - 1)
end
-- Check for edge cases, such as fact(0) and fact(1).
if ((n == 0) or (n == 1)) then
return 1
end
return fact_helper(n, n - 1)
end

Octave keeps giving results from function although not asked

I created a function in Octave for which I, at this moment, only want one of the possible outputs displayed. The code:
function [pi, time, numiter] = PageRank(pi0,H,v,n,alpha,epsilon);
rowsumvector=ones(1,n)*H';
nonzerorows=find(rowsumvector);
zerorows=setdiff(1:n,nonzerorows); l=length(zerorows);
a=sparse(zerorows,ones(l,1),ones(l,1),n,1);
k=0;
residual=1;
pi=pi0;
tic;
while (residual >= epsilon)
prevpi=pi;
k=k+1;
pi=alpha*pi*H + (alpha*(pi*a)+1-alpha)*v;
residual = norm(pi-prevpi,1);
end
pi;
numiter=k
time=toc;
endfunction
Now I only want numiter returned, but it keeps giving me back pi as well, no matter whether I delete pi;, or not.
It returns it in the following format:
>> PageRank(pi0,H,v,length(H),0.9,epsilon)
numiter = 32
ans =
0.026867 0.157753 0.026867 0.133573 0.315385
To me it seems strange that the pi is not given with its variable, but merely as an ans.
Any suggestions?
I know the Octave documentation for this is not very extensive, but perhaps it gives enough hints to understand that how you think about output variables is wrong.
The call
PageRank(pi0,H,v,length(H),0.9,epsilon)
returns a single output argument, it is equivalent to
ans = PageRank(pi0,H,v,length(H),0.9,epsilon)
ans is always the implied output argument if none is explicitly given. ans will be assigned the value of pi, the first output argument of your function. The variable pi (nor time, nor numiter) in your workspace will be modified or assigned to. These are the names of local variables inside your function.
To obtain other output variables, do this:
[out1,out2,out3] = PageRank(pi0,H,v,length(H),0.9,epsilon)
Now, the variable out1 will be assigned the value that pi had inside your function. out2 will contain the value of time, and out3 the value of numiter,
If you don't want the first two output arguments, and only want the third one, do this:
[~,~,out3] = PageRank(pi0,H,v,length(H),0.9,epsilon)
The ~ indicates to Octave that you want to ignore that output argument.

How to solve a second order differential equation on Scilab?

I need to solve this differential equation using Runge-Kytta 4(5) on Scilab:
The initial conditions are above. The interval and the h-step are:
I don't need to implement Runge-Kutta. I just need to solve this and plot the result on the plane:
I tried to follow these instructions on the official "Scilab Help":
https://x-engineer.org/graduate-engineering/programming-languages/scilab/solve-second-order-ordinary-differential-equation-ode-scilab/
The suggested code is:
// Import the diagram and set the ending time
loadScicos();
loadXcosLibs();
importXcosDiagram("SCI/modules/xcos/examples/solvers/ODE_Example.zcos");
scs_m.props.tf = 5000;
// Select the solver Runge-Kutta and set the precision
scs_m.props.tol(6) = 6;
scs_m.props.tol(7) = 10^-2;
// Start the timer, launch the simulation and display time
tic();
try xcos_simulate(scs_m, 4); catch disp(lasterror()); end
t = toc();
disp(t, "Time for Runge-Kutta:");
However, it is not clear for me how I can change this for the specific differential equation that I showed above. I have a very basic knowledge of Scilab.
The final plot should be something like the picture bellow, an ellipse:
Just to provide some mathematical context, this is the differential equation that describes the pendulum problem.
Could someone help me, please?
=========
UPDATE
Based on #luizpauloml comments, I am updating this post.
I need to convert the second-order ODE into a system of first-order ODEs and then I need to write a function to represent such system.
So, I know how to do this on pen and paper. Hence, using z as a variable:
OK, but how do I write a normal script?
The Xcos is quite disposable. I only kept it because I was trying to mimic the example on the official Scilab page.
To solve this, you need to use ode(), which can employ many methods, Runge-Kutta included. First, you need to define a function to represent the system of ODEs, and Step 1 in the link you provided shows you what to do:
function z = f(t,y)
//f(t,z) represents the sysmte of ODEs:
// -the first argument should always be the independe variable
// -the second argument should always be the dependent variables
// -it may have more than two arguments
// -y is a vector 2x1: y(1) = theta, y(2) = theta'
// -z is a vector 2x1: z(1) = z , z(2) = z'
z(1) = y(2) //first equation: z = theta'
z(2) = 10*sin(y(1)) //second equation: z' = 10*sin(theta)
endfunction
Notice that even if t (the independent variable) does not explicitly appear in your system of ODEs, it still needs to be an argument of f(). Now you just use ode(), setting the flag 'rk' or 'rkf' to use either one of the available Runge-Kutta methods:
ts = linspace(0,3,200);
theta0 = %pi/4;
dtheta0 = 0;
y0 = [theta0; dtheta0];
t0 = 0;
thetas = ode('rk',y0, t0, ts, f); //the output have the same order
//as the argument `y` of f()
scf(1); clf();
plot2d(thetas(2,:),thetas(1,:),-5);
xtitle('Phase portrait', 'theta''(t)','theta(t)');
xgrid();
The output:

MATLAB return of vector function with IF statement

I am calling a self written function 'func' of a vector like this:
x_values=[0 1 2];
result=func(x_values);
The problem is that in this function i have an if statement to determine the ouput. If I apply this function to a scalar, I have no problem, but if I apply it to a vector of numbers, the if statement doesn't do his job. why? And how can i repair it?
function [y]=func(x)
if(x==0)
y=0
else
y=1./sin(x);
end
end
You need to treat the zero and non-zero entries separately. This is easily achieved via indexing:
function [y]=func(x)
xIsZero = x==0;
%# preassign y
y = x;
%# fill in values for y
y(xIsZero) = 0
y(~xIsZero) = 1./sin(x(~xIsZero))
The answer is explained in the help document of IF:
An evaluated expression is true when the result is nonempty and
contains all nonzero elements (logical or real numeric). Otherwise,
the expression is false.
Conclusion: either add a for loop, or find a better way to vectorize your expression
You want to assign only a subset of the vector. For example:
function [y]=func(x)
y=zeros(size(x));
mask = x ~= 0;
y(mask) = 1 ./ sin(x(mask));
end

How to write arbitrary datatypes into Matlab cell array

This is a general question, not related to a particular operation. I would like to be able to write the results of an arbitrary function into elements of a cell array without regard for the data type the function returns. Consider this pseudocode:
zout = cell(n,m);
myfunc = str2func('inputname'); %assume myfunc puts out m values to match zout dimensions
zout(1,:) = myfunc(x,y);
That will work for "inputname" == "strcat" , for example, given that x and y are strings or cells of strings with appropriate dimension. But if "inputname" == "strcmp" then the output is a logical array, and Matlab throws an error. I'd need to do
zout(1,:) = num2cell(strcmp(x,y));
So my question is: is there a way to fill the cell array zout without having to test for the type of variable generated by myfunc(x,y ? Should I be using a struct in the first place (and if so, what's the best way to populate it)?
(I'm usually an R user, where I could just use a list variable without any pain)
Edit: To simplify the overall scope, add the following "requirement" :
Let's assume for now that, for a function which returns multiple outputs, only the first one need be captured in zout . But when this output is a vector of N values or a vector of cells (i.e. Nx1 cell array), these N values get mapped to zout(1,1:N) .
So my question is: is there a way to fill the cell array zout without having to test for the type of variable generated by myfunc(x,y) ? Should I be using a struct in the first place (and if so, what's the best way to populate it)?
The answer provided by #NotBoStyf is almost there, but not quite. Cell arrays are the right way to go. However, the answer very much depends on the number of outputs from the function.
Functions with only one output
The function strcmp has only one output, which is an array. The reason that
zout{1,:} = strcmp(x,y)
gives you an error message, when zout is dimensioned N x 2, is that the left-hand side (zout{1,:}) expects two outputs from the right-hand side. You can fix this with:
[zout{1,:}] = num2cell(strcmp(x,y)); % notice the square brackets on the LHS
However, there's really no reason to do this. You can simply define zout as an N x 1 cell array and capture the results:
zout = cell(1,1);
x = 'a';
y = { 'a', 'b' };
zout{1} = strcmp(x,y);
% Referring to the results:
x_is_y_1 = zout{1}(1);
x_is_y_2 = zout{1}(2);
There's one more case to consider...
Functions with multiple outputs
If your function produces multiple outputs (as opposed to a single output that is an array), then this will only capture the first output. Functions that produce multiple outputs are defined like this:
function [outA,outB] = do_something( a, b )
outA = a + 1;
outB = b + 2;
end
Here, you need to explicitly capture both output arguments. Otherwise, you just get a. For example:
outA = do_something( [1,2,3], [4,5,6] ); % outA is [2,3,4]
[outA,outB] = do_something( [1,2,3], [4,5,6] ); % outA is [2,3,4], outB is [6,7,8]
Z1 = cell(1,1);
Z1{1,1} = do_something( [1,2,3], [4,5,6] ); % Z1{1,1} is [2,3,4]
Z2 = cell(1,2);
Z2{1,1:2} = do_something( [1,2,3], [4,5,6] ); % Same error as above.
% NB: You really never want to have a cell expansion that is not surrounded
% by square brackets.
% Do this instead:
[Z2{1,1:2}] = do_something( [1,2,3], [4,5,6] ); % Z2{1,1} is [2,3,4], Z2{1,2} is [6,7,8]
This can also be done programmatically, with some limits. Let's say we're given function
func that takes one input and returns a constant (but unknown) number of outputs. We
have cell array inp that contains the inputs we want to process, and we want to collect the results in cell around outp:
N = numel(inp);
M = nargout(#func); % number of outputs produced by func
outp = cell(N,M);
for i=1:N
[ outp{i,:} ] = func( inp{i} );
end
This approach has a few caveats:
It captures all of the outputs. This is not always what you want.
Capturing all of the outputs can often change the behavior of the function. For example, the find function returns linear indices if only one output is used, row/column indices if two outputs are used, and row/column/value if three outputs are used.
It won't work for functions that have a variable number of outputs. These functions are defined as function [a,b,...,varargout] = func( ... ). nargout will return a negative number if the function has varargout declared in its output list, because there's no way for Matlab to know how many outputs will be produced.
Unpacking array and cell outputs into a cell
All true so far, but: what I am hoping for is a generic solution. I can't use num2cell if the function produces cell outputs. So what worked for strcmp will fail for strcat and vice versa. Let's assume for now that, for a function which returns multiple outputs, only the first one need be captured in zout – Carl Witthoft
To provide a uniform output syntax for all functions that return either a cell or an array, use an adapter function. Here is an example that handles numeric arrays and cells:
function [cellOut] = cellify(input)
if iscell(input)
cellOut = input;
elseif isnumeric(input)
cellOut = num2cell(input);
else
error('cellify currently does not support structs or objects');
end
end
To unpack the output into a 2-D cell array, the size of each output must be constant. Assuming M outputs:
N = numel(inp);
% M is known and constant
outp = cell(N,M);
for i=1:N
outp(i,:) = cellify( func( inp{i} ) ); % NB: parentheses instead of curlies on LHS
end
The output can then be addressed as outp{i,j}. An alternate approach allows the size of the output to vary:
N = numel(inp);
% M is not necessary here
outp = cell(N,1);
for i=1:N
outp{i} = cellify( func( inp{i} ) ); % NB: back to curlies on LHS
end
The output can then be addressed as outp{i}{j}, and the size of the output can vary.
A few things to keep in mind:
Matlab cells are basically inefficient pointers. The JIT compiler does not always optimize them as well as numeric arrays.
Splitting numeric arrays into cells can cost quite a bit of memory. Each split value is actually a numeric array, which has size and type information associated with it. In numeric array form, this occurs once for each array. When the array is split, this incurs once for each element.
Use curly braces instead when asigning a value.
Using
zout{1,:} = strcmp(x,y);
instead should work.