Calling a function in matlab. Is it wrong like this? - function

I have the following class in matlab:
classdef floating_search
properties
S,M;
end
methods
function s = support(x,y)
for i=1:length(x)
if(y(i)~=1)
s = x(i);
end
end
end
end
end
Now, in the command winows, I did the following:
>> x=1:10;
>> floating_search.S = x;
>> y=trapmf(x,[1 3 5 9])
y =
Columns 1 through 7
0 0.5000 1.0000 1.0000 1.0000 0.7500 0.5000
Columns 8 through 10
0.2500 0 0
>> floating_search.M = y;
>> floating_search.support(floating_search.S, floating_search.M)
??? Reference to non-existent field 'support'.
For the last command, why did I get this error? Am I calling the function wrong? How can I pass th values floating_search.S and floating_search.M to the function and retrieve the values of S for which Y~=1?
Thanks.

You never initialize your object.
Furthermore, I think you should reconcider using your code as a non-static method:
classdef floating_search
properties
S
M
end
methods
function s = support(obj)
for i=1:length(obj.S)
if(obj.M(i)~=1)
s = obj.S(i);
end
end
end
end
end
Then execute:
x = 1:10;
y = trapmf(x,[1 3 5 9])
myInstance = floating_search()
myInstance.S = x;
myInstance.M = y;
myInstance.support()

your class is missing a constructor.
furthermore you never initialize any object.
your floating_search.S = x; statement generates a struct called floating_search:
>> whos floating_search
Name Size Bytes Class Attributes
floating_search 1x1 256 struct
Try this instead (save file as floating_search.m):
classdef floating_search
properties
S;
M;
end
methods
% constructor - place to initialize things
function obj = floating_search()
end
% you need the first input argument 'obj', since this is a value class
% see http://www.mathworks.de/de/help/matlab/matlab_oop/comparing-handle-and-value-classes.html
function s = support(obj, x, y)
for i=1:length(x)
if(y(i)~=1)
s = x(i);
end
end
end
end
end
and then run the code:
% generate your data
x = 1:10;
y = trapmf(x,[1 3 5 9]);
# initialize object
a = floating_search()
a.S = x;
a.M = y;
a.support(a.S, a.M)

Related

Please explain this Octave Error Code: op1 is 1x12, op2 is 1x3

Code:
function result = assess_polynomial_n(y,n)
[coeff, t, pred_accum] = fit_data(y, n);
[avg, std_dev] = compute_error(coeff,y);
[coeff1, t, pred_accum1] = fit_data(y, n+1);
[avg1, std_dev1] = compute_error(coeff1,y);
if avg1>avg
result = n;
elseif avg<0.1 && std_dev<0.1
result = n;
elseif pred_accum1.*(1)<0.0001
result = n;
else
result = 0;
end
end
***Error***
error: compute_error: operator -: nonconformant arguments (op1 is 1x12, op2 is 1x3)
error: called from
compute_error at line 11 column 17
assess_polynomial_n at line 19 column 18
__tester__.octave at line 38 column 1
Does anyone know why I could be getting this error? We're supposed to be working in MATLAB but pasting our code into Moodle which uses Octave if that clears anything up.
I also will post the functions I'm calling for reference since the error is occurring in Compute_Error. This is a part of an overall project where I was to define the functions I'm calling before creating assess_polynomial_n.
function [coeff, t, pred_accum] = fit_data(y, n)
len = length(y);
t = 10*[0:len-1];
coeff = polyfit(t, y, n);
pred_accum = polyval(coeff, t);
end
function [avg std_dev] = compute_error(x,y)
s=[];
for i=1:length(x)
error=abs(x(i)-y(i));
s=[s,error];
end
avg = mean(s);
std_dev = std(s);
end
The problem lies in this line of code:
[avg1, std_dev1] = compute_error(coeff1,y);
You are trying to compute the error between the original data and the coefficients of the fitted polynomial. It doesn't make sense, right?
Instead, you should compute the error between the original data and the fitted data, which is the polynomial's output at each t value. The correct code would be:
[avg1, std_dev1] = compute_error(pred_accum1,y);

Vectorizing groups of function calls

I am trying to write a functionality, (using macro, generated function or something), that effectively vectorizes Julia function calls to functions that I've written. Basically, I'm trying to write my own version of the #. macro, but instead, I'd like it to accept functions instead of a for loop--- if I understand this correctly. Here are some documents that I've read on the subject:
https://docs.julialang.org/en/v1/manual/functions/#man-vectorized-1
https://github.com/JuliaLang/julia/blob/master/base/broadcast.jl
https://julialang.org/blog/2017/01/moredots
https://docs.julialang.org/en/v1/manual/metaprogramming/index.html#Code-Generation-1
Here is my preliminary toy example that I'm working with to achieve such a functionality:
function add!(v_add::Vector{Float64}, a_add::Float64, j::Int64)
v_add[j] = v_add[j]+a_add
end
function add!(v_add::Vector{Float64}, a_add::Float64)
for j in 1:length(v_add)
v_add[j] = v_add[j]+a_add
end
end
macro vectorize(args)
print("\n****************** args\n")
print(args)
print("\n******************\n")
e = :(:call,
$args[1],
$args[2],
$args[3])
print("\n****************** expression\n")
show(e)
print(e)
print("\n******************\n")
return e
end
function test!(v_test, a_test)
# # Traverse vector twice
# add!(v_test, a_test)
# add!(v_test, a_test)
# Traverse vector once
args = [
add!, v_test, a_test,
add!, v_test, a_test
]
e = #vectorize(args)
# eval(e) # Next step
end
v_main = Vector([Float64(i) for i in 1:3])
a_main = Float64(2.0)
print("\n",v_main, "\n")
Main.test!(v_main, a_main)
print("\n",v_main, "\n")
The problem I'm having so far is that I can't even get the de-vectorized version running using macros. This example results in the LoadError: UndefVarError: args not defined. I would definitely appreciate any help in getting this script working as expected (input is [1, 2, 3], and output should be [5, 6, 7]).
Any help/suggestions are greatly appreciated.
Update
More concretely, given the following defined functions:
function add!(v::Vector{Float64}, a::Float64)
for j in 1:length(v)
v[j]+= a
end
end
function add!(v::Vector{Float64}, a::Float64, j::Int64)
v[j]+= a
end
I would like to be able to use a macro to convert the following lines of code:
v = [Float64(j) for j in 1:10]
a = 1
b = 2
#vectorize_I_would_like_to_define(
# I don't know the exact form that the args to this macro should take.
add!(v, a),
add!(v, b)
)
To generate code that is compiled like this:
v = [Float64(j) for j in 1:10]
a = 1
b = 2
for j in 1:length(v)
add!(v, a, j)
add!(v, b, j)
end
My goal is to write code that requires a single memory traversal.
Even better, if I could generate code that looks like this at compile time:
v = [Float64(j) for j in 1:10]
a = 1
b = 2
for j in 1:length(v)
v[j]+= a # taken from add!(v::Vector{Float64}, a::Float64, j::Int64)
v[j]+= b # taken from add!(v::Vector{Float64}, a::Float64, j::Int64)
end
But I'm not sure if this is as feasable for more complex cases that I'm considering compared to this toy example.
** Update 2**
Here is a MWE of #Bogumił Kamiński's solution---except that I've moved the macro call into a function, so now it doesn't work because it complains that v_test is not defined.
macro vectorize(args...)
expr = :()
for arg in args
a = deepcopy(arg) # for safety in case arg is also used somewhere else
push!(a.args, :j)
expr = :($expr; $a)
end
quote
for j in 1:length(v)
$expr
end
end
end
function add!(v::Vector{Float64}, a::Float64)
for j in 1:length(v)
v[j]+= a
end
end
function add!(v::Vector{Float64}, a::Float64, j::Int64)
v[j]+= a
end
v = [Float64(j) for j in 1:10]
a = 1.0
b = 2.0
function test!(v_test, a_test, b_test)
#vectorize(
add!(v_test, a_test),
add!(v_test, b_test)
)
end
test!(v, a, b)
Is this what you want?
macro vectorize(args...)
expr = :()
for arg in args
a = deepcopy(arg) # for safety in case arg is also used somewhere else
push!(a.args, :j)
expr = :($expr; $a)
end
quote
for j in 1:length(v)
$expr
end
end
end
and now
function add!(v::Vector{Float64}, a::Float64)
for j in 1:length(v)
v[j]+= a
end
end
function add!(v::Vector{Float64}, a::Float64, j::Int64)
v[j]+= a
end
v = [Float64(j) for j in 1:10]
a = 1.0
b = 2.0
#vectorize(add!(v, a), add!(v, b))
Note that I have changed a and b definitions as your add! required Float64 as a second argument.
EDIT: If you want to use this macro inside a function the simplest thing to do is to esc its whole return value:
macro vectorize(args...)
expr = :()
for arg in args
a = deepcopy(arg) # for safety in case arg is also used somewhere else
push!(a.args, :j)
expr = :($expr; $a)
end
esc(quote
for j in 1:length(v)
$expr
end
end)
end
Then you can define e.g.:
function f()
v = [Float64(j) for j in 1:10]
a = 1.0
b = 2.0
#vectorize(add!(v, a), add!(v, b))
v
end
and run f() to get the same result as above in global scope.
EDIT 2: I just realized that actually I have to sanitize j as otherwise the following code will fail:
test!(v_test, j, b_test) =
#vectorize(add!(v_test, j), add!(v_test, b_test))
Here is how you should do it:
macro vectorize(args...)
expr = :()
j = gensym()
for arg in args
a = deepcopy(arg) # for safety in case arg is also used somewhere else
push!(a.args, j)
expr = :($expr; $a)
end
esc(quote
for $j in 1:length(v)
$expr
end
end)
end
As you can see developing macros is a non-obvious task (hopefully the final recipe is bug-free :)).
EDIT 3: Here is the code that correctly handles length. Also now in each expression actually you can pass a different value as a first argument (so you can independently process different vectors). If you do want to process the same vector check is a.args[2] is always the same symbol:
macro vectorize(args...)
expr = :()
j = gensym()
for arg in args
a = deepcopy(arg) # for safety in case arg is also used somewhere else
var = a.args[2]
push!(a.args, j)
q = quote
for $j in 1:length($var)
$a
end
end
expr = :($expr; $q)
end
esc(expr)
end

How to pass variadic arguments in Octave

I would like to implement a function duration = timer(n, f, arguments_of_f) that would measure how much time does a method f with arguments arguments_of_f need to run n times. My attempt was the following:
function duration = timer(n, f, arguments_of_f)
duration = 0;
for i=1:n
t0 = cputime;
f(arguments_of_f);
t1 = cputime;
duration += t1 - t0;
end
In another file, I have
function y = f(x)
y = x + 1;
end
The call d1 = timer(100, #f, 3); works as expected.
In another file, I have
function y = g(x1, x2)
y = x1 + x2;
end
but the call d2 = timer(100, #g, 1, 2); gives an error about undefined
argument x2, which is, when I look back, somehow expected, since I pass only
1 to g and 2 is never used.
So, how to implement the function timer in Octave, so that the call like
timer(4, #g, x1, ... , xK) would work? How can one pack the xs together?
So, I am looking for the analogue of Pythons *args trick:
def use_f(f, *args):
f(*args)
works if we define def f(x, y): return x + y and call use_f(f, 3, 4).
You don't need to pack all the arguments together, you just need to tell Octave that there is more than one argument coming and that they are all necessary. This is very easy to do using variadic arguments.
Your original implementation is nearly spot on: the necessary change is minimal. You need to change the variable arguments_to_f to the special name varargin, which is a magical cell array containing all your arbitrary undeclared arguments, and pass it with expansion instead of directly:
function duration = timer(n, f, varargin)
duration = 0;
for i=1:n
t0 = cputime;
f(varargin{:});
t1 = cputime;
duration += t1 - t0;
end
That's it. None of the other functions need to change.

Matlab second order derivative

I have followed the tutorial on http://www.mit.edu/people/abbe/matlab/ode.html and prepared a function as follows:
function dxy = diffxy(xy)
%
%split xy into variables in our equations
%
x = xy(1);
xdot = xy(2);
y = xy(3);
%
% define the derivatives of these variables from equations
%
xdot = xdot;
ydot = 3*x + 2*y + 5;
xdoubledot = 3 - ydot + 2*xdot;
%
%return the derivatives in dxy in the right order
%
dxy = [xdot; xdoubledot; ydot]
end
When I call it using
[T, XY] = ode45('diffxy',0,10,[0 1 0])
I get an error
??? Error using ==> diffxy
Too many input arguments.
I also tried
XY= ode45(#diffxy,[0 10],[0;1;0])
Anybody have any idea?
haven't read the whole tutorial but aren't you supposed to define your function as
function dxy = diffxy(t, xy)
where t is time vector

Passing a function as a parameter in a MATLAB function [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Passing a function as argument to another function
Below is a simple code for the bisection method. I would like to know how to be able to pass in any function I choose as a parameter instead of hard coding functions.
% This is an implementation of the bisection method
% for a solution to f(x) = 0 over an interval [a,b] where f(a) and f(b)
% Input: endpoints (a,b),Tolerance(TOL), Max # of iterations (No).
% Output: Value p or error message.
function bjsect(a,b,TOL,No)
% Step 0
if f(a)*f(b)>0
disp('Function fails condition of f(a),f(b) w/opposite sign'\n);
return
end
% Step 1
i = 1;
FA = f(a);
% Step 2
while i <= No
% Step 3
p = a +(b - a)/2;
FP = f(p);
% Step 4
if FP == 0 || (b - a)/2 < TOL
disp(p);
return
end
% Step 5
i = i + 1;
% Step 6
if FA*FP > 0
a = p;
else
b = p;
end
% Step 7
if i > No
disp('Method failed after No iterations\n');
return
end
end
end
% Hard coded test function
function y = f(x)
y = x - 2*sin(x);
end
I know this is an important concept so any help is greatly appreciated.
The simplest method is using anonymous functions. In your example, you would define your anonymous function outside bjsect using:
MyAnonFunc = #(x) (x - 2 * sin(x));
You can now pass MyAnonFunc into bjsect as an argument. It has the object type of function handle, which can be validated using isa. Inside bjsect simply use MyAnonFunc as if it is a function, ie: MyAnonFunc(SomeInputValue).
Note, you can of course wrap any function you've written in an anonymous function, ie:
MyAnonFunc2 = #(x) (SomeOtherCustomFunction(x, OtherInputArgs));
is perfectly valid.
EDIT: Oops, just realized this is almost certainly a duplicate of another question - thanks H. Muster, I'll flag it.