Iterating over different functions with different number of parameters in Julia - julia

I'm trying to run a loop over different functions with different number of arguments. The variables are created at runtime inside the loop, and I want to use eval at each iteration to instantiate a Struct using the variable :symbol. However, I can't do this since eval only works in the global scope. This is the MWE for the case that works:
function f1(x); return x; end
function f2(x1,x2); return x1+x2; end
handles = [f1,f2]
args =[:(x1),:(x1,x2)]
x1 = 1; x2 = 1;
for (i,f) in enumerate(handles)
params = eval(args[i])
#show f(params...)
end
f(params...) = 1
f(params...) = 2
However, if I move the variable definitions inside the loop, which is what I actually want, it doesn't work after restarting Julia to clear the workspace.
function f1(x); return x; end
function f2(x1,x2); return x1+x2; end
handles = [f1,f2]
args =[:(x1),:(x1,x2)]
for (i,f) in enumerate(handles)
x1 = 1; x2 = 1;
params = eval(args[i])
#show f(params...)
end
ERROR: UndefVarError: x1 not defined
I've tried several of the answers, such as this one, but I can't seem to make it work. I could write a custom dispatch function that takes[x1,x2] and calls f1 or f2 with the correct arguments. But still, is there any way to do this with eval or with an alternative elegant solution?
EDIT: here are more details as to what I'm trying to do in my code. I have a config struct for each algorithm, and in this I want to define beforehand the arguments it takes
KMF_config = AlgConfig(
name = "KMF",
constructor = KMC.KMF,
parameters = :(mu,N,L,p),
fit = KMC.fit!)
MF_config = AlgConfig(
name = "MF",
constructor = KMC.MF,
parameters = :(mu,N,L),
fit = KMC.fit!)
alg_config_list = [KMF_config, MF_config]
for (i,alg_config) in enumerate(alg_config_list)
mu,N,L,p,A,B,C,D,data = gen_vars() #this returns a bunch of variables that are used in different algorithms
method = alg_config.constructor(eval(method.parameters)...)
method.fit(data)
end
One possible solution is to have a function take all the variables and method, and return a tuple with a subset of variables according to method.name. But I'm not sure if it's the best way to do it.

Here's an approach using multiple dispatch rather than eval:
run_a(x, y) = x + 10*y
run_b(x, y, z) = x + 10*y + 100*z
extract(p, ::typeof(run_a)) = (p.x, p.y)
extract(p, ::typeof(run_b)) = (p.x, p.y, p.z)
genvars() = (x=1, y=2, z=3)
function doall()
todo = [
run_a,
run_b,
]
for runalg in todo
v = genvars()
p = extract(v, runalg)
#show runalg(p...)
end
end
In your example you would replace run_a and run_b with KMC.KMF and KMC.MF.
Edit: Cleaned up example to avoid structs that don't exist in your example.

Related

scilab, passing parameters to the function and changing variable type

I'm trying to build a GUI to output plots for control system design when input parameters of transfer function.I got some problems on passing parameters to the function and changing variable type.
I've got a stucture with examples of simulation parameters:
param = [];
param.parameter = "s";
param.dom = "c"; //domain(c for continuous, d for discrete)
param.num = 1; //numerator of transfer function
param.den = "(s+1)^3"; //denominator
param.fmin = 0.01; //min freq of the plot
param.fmax = 100; //max freq
and a function to plot the graphs:
// display function
function displayProblem(param)
parameter = param.parameter;
dom = param.dom;
num = param.num;
den = param.den;
fmin = param.fmin;
fmax = param.fmax;
s = poly(0,parameter.string);
h = syslin(dom.string,num,den);
// Plotting of model data
delete(gca());
//bode(h,fmin1,fmax1);
gain_axes = newaxes();
gain_axes.title.font_size = 3;
gainplot(h,fmin,fmax);
gain_axes.axes_bounds = [1/3,0,1/3,1/2];
gain_axes.title.text = "Gain Plot";
phase_axes = newaxes();
gain_axes.title.font_size = 3;
phaseplot(h,fmin,fmax);
phase_axes.axes_bounds = [1/3,1/2,1/3,1/2];
phase_axes.title.text = "Phase Plot";
phase_axes = newaxes();
gain_axes.title.font_size = 3;
nyquist(h);
phase_axes.axes_bounds = [2/3,0,1/3,1/2];
phase_axes.title.text = "Nyquist Plot";
endfunction
There's something wrong when passing numerator and denominator to the function. The variable type doesn't match what syslin required. If I replace 'num' and 'den' with '1' and '(s+1)^3', everything worked quite well. Also if I try this line-by-line in control panel, it works, but not in SciNotes. What's the proper way to deal with this? Any suggestion will be greatly appreaciated.
There are 3 errors in your code: Replace
param.den = "(s+1)^3"; //denominator
with
param.den = (%s+1)^3;
Indeed, Scilab has a built-in polynomial type. Polynomials are not defined as a string nor as a vector of coefficients. The predefined constant %s is the monomial s.
In addition,
s = poly(0,parameter.string);
is useless (and incorrect: parameter would work, while parameter.string won't since parameter has no string field: It IS the string). Just remove the line.
As well, replace
h = syslin(dom.string,num,den);
with simply
h = syslin(dom, num,den);
Finally, although the figure's layout is not simple, you can use bode() in the function in the following way:
// delete(gca());
subplot(1,3,2)
bode(h, fmin, fmax)
subplot(2,3,3)
nyquist(h)
gcf().children.title.text=["Nyquist Plot" "Phase Plot" "Gain Plot"]
All in one, the code of your function may resume to
function displayProblem(param)
[dom, num, den] = (param.dom, param.num, param.den);
[fmin, fmax] = (param.fmin, param.fmax);
h = syslin(dom, num,den);
// Plotting of model data
subplot(1,3,2)
bode(h,fmin,fmax);
subplot(2,3,3)
nyquist(h);
gcf().children.title.text=["Nyquist Plot" "Phase Plot" "Gain Plot"];
endfunction
Best regards

How to use the "6" char code in overloading insertion function on Scilab?

In the Help Documentation of Scilab 6.0.2, I can read the following instruction on the Overloading entry, regarding the last operation code "iext" showed in this entry's table:
"The 6 char code may be used for some complex insertion algorithm like x.b(2) = 33 where b field is not defined in the structure x. The insertion is automatically decomposed into temp = x.b; temp(2) = 33; x.b = temp. The 6 char code is used for the first step of this algorithm. The 6 overloading function is very similar to the e's one."
But I can't find a complete example on how to use this "char 6 code" to overload a function. I'm trying to use it, without success. Does anyone have an example on how to do this?
The code bellow creates a normal "mlist" as a example. Which needs overloading functions
A = rand(5,3)
names = ["colA" "colB" "colC"]
units = ["ft" "in" "lb"]
M = mlist(["Mlog" "names" "units" names],names,units,A(:,1),A(:,2),A(:,3))
Following are the overload functions:
//define display
function %Mlog_p(M)
n = size(M.names,"*")
formatStr = strcat(repmat("%10s ",1,n)) + "\n"
formatNum = strcat(repmat("%0.10f ",1,n)) + "\n"
mprintf(formatStr,M.names)
mprintf(formatStr,M.units)
disp([M(M.names(1)),M(M.names(2)),M(M.names(3))])
end
//define extraction operation
function [Mat]=%Mlog_e(varargin)
M = varargin($)
cols = [1:size(M.names,"*")] // This will also work
cols = cols(varargin($-1)) // when varargin($-1) = 1:1:$
Mat = []
if length(varargin)==3 then
for i = M.names(cols)
Mat = [Mat M(i)(varargin(1))]
end
else
for i=1:size(M.names(cols),"*")
Mat(i).name = M.names(cols(i))
Mat(i).unit = M.units(cols(i))
Mat(i).data = M(:,cols(i))
end
end
endfunction
//define insertion operations (a regular matrix into a Mlog matrix)
function ML=%s_i_Mlog(i,j,V,M)
names = M.names
units = M.units
A = M(:,:) // uses function above
A(i,j) = V
ML = mlist(["Mlog" "names" "units" names],names,units,A(:,1),A(:,2),A(:,3))
endfunction
//insertion operation with structures (the subject of the question)
function temp = %Mlog_6(j,M)
temp = M(j) // uses function %Mlog_e
endfunction
function M = %st_i_Mlog(j,st,M)
A = M(:,:) // uses function %Mlog_e
M.names(j) = st.name // uses function above
M.units(j) = st.unit // uses function above
A(:,j) = st.data // uses function above
names = M.names
units = M.units
M = mlist(["Mlog" "names" "units" names],names,units,A(:,1),A(:,2),A(:,3))
endfunction
The first overload (displays mlist) will show the matrix in the form of the following table:
--> M
M =
colA colB colC
ft in lb
0.4720517 0.6719395 0.5628382
0.0623731 0.1360619 0.5531093
0.0854401 0.2119744 0.0768984
0.0134564 0.4015942 0.5360758
0.3543002 0.4036219 0.0900212
The next overloads (extraction and insertion) Will allow the table to be access as a simple matrix M(i,j).
The extraction function Will also allow M to be access by column, which returns a structure, for instance:
--> M(2)
ans =
name: "colB"
unit: "in"
data: [5x1 constant]
The last two functions are the overloads mentioned in the question. They allow the column metadata to be changed in a structure form.
--> M(2).name = "length"
M =
colA length colC
ft in lb
0.4720517 0.6719395 0.5628382
0.0623731 0.1360619 0.5531093
0.0854401 0.2119744 0.0768984
0.0134564 0.4015942 0.5360758
0.3543002 0.4036219 0.0900212

How do I evaluate the function in only one of its variables in Scilab

How do I evaluate the function in only one of its variables, that is, I hope to obtain another function after evaluating the function. I have the following piece of code.
deff ('[F] = fun (x, y)', 'F = x ^ 2-3 * y ^ 2 + x * y ^ 3');
fun (4, y)
I hope to get 16-3y ^ 2 + 4y ^ 3
If what you want to do is to write x = f(4,y), and later just do x(2) to get -36, that is called partial application:
Intuitively, partial function application says "if you fix the first arguments of the function, you get a function of the remaining arguments".
This is a very useful feature, and very common Functional Programming Languages, such as Haskell, but even JS and Python now are able to do it. It is also possible to do this in MATLAB and GNU/Octave using anonymous functions (see this answer). In Scilab, however, this feature is not available.
Workround
Nonetheless, Scilab itself uses a workarounds to carry a function with its arguments without fully evaluating. You see this being used in ode(), fsolve(), optim(), and others:
Create a list containing the function and the arguments to partial evaluation: list(f,arg1,arg2,...,argn)
Use another function to evaluate such list and the last argument: evalPartList(list(...),last_arg)
The implementation of evalPartList() can be something like this:
function y = evalPartList(fList,last_arg)
//fList: list in which the first element is a function
//last_arg: last argument to be applied to the function
func = fList(1); //extract function from the list
y = func(fList(2:$),last_arg); //each element of the list, from second
//to last, becomes an argument
endfunction
You can test it on Scilab's console:
--> deff ('[F] = fun (x, y)', 'F = x ^ 2-3 * y ^ 2 + x * y ^ 3');
--> x = list(fun,4)
x =
x(1)
[F]= x(1)(x,y)
x(2)
4.
--> evalPartList(x,2)
ans =
36.
This is a very simple implementation for evalPartList(), and you have to be careful not to exceed or be short on the number of arguments.
In the way you're asking, you can't.
What you're looking is called symbolic (or formal) computational mathematics, because you don't pass actual numerical values to functions.
Scilab is numerical software so it can't do such thing. But there is a toolbox scimax (installation guide) that rely on a the free formal software wxmaxima.
BUT
An ugly, stupid but still sort of working solution is to takes advantages of strings :
function F = fun (x, y) // Here we define a function that may return a constant or string depending on the input
fmt = '%10.3E'
if (type(x)==type('')) & (type(y)==type(0)) // x is string is
ys = msprintf(fmt,y)
F = x+'^2 - 3*'+ys+'^2 + '+x+'*'+ys+'^3'
end
if (type(y)==type('')) & (type(x)==type(0)) // y is string so is F
xs = msprintf(fmt,x)
F = xs+'^2 - 3*'+y+'^2 + '+xs+'*'+y+'^3'
end
if (type(y)==type('')) & (type(x)==type('')) // x&y are strings so is F
F = x+'^2 - 3*'+y+'^2 + '+x+'*'+y+'^3'
end
if (type(y)==type(0)) & (type(x)==type(0)) // x&y are constant so is F
F = x^2 - 3*y^2 + x*y^3
end
endfunction
// Then we can use this 'symbolic' function
deff('F2 = fun2(y)',' F2 = '+fun(4,'y'))
F2=fun2(2) // does compute fun(4,2)
disp(F2)

Variable/List Component scope in R?

I come from OOP background (C#/Java to be specific) and I really do not understand how R treat the variable from outside the function.
I made this example:
result = list();
result$total = 0;
result$count = 0;
result$something = "abc";
a = 1:10;
b = 10:20;
mapply(function(x, y) {
print(result$something);
# Does not work with either = or <--
result$total <-- result$total + x + y;
result$count <-- result$count + 1;
print(result$count);
}, x = a, y = b);
result$average = result$total / result$count;
print(result$total);
print(result$count);
print(result$average);
Here, clearly result is available to the anonymous function because the program did print "abc" 10 times.
However, the change to its component total and count does not survive. 10 times it prints 1 for the result$count, and the final 3 lines are 0, 0 and NaN.
Why is this happening? What should I do in this case, if I want the function to be able to change the variable value?
Note: in my real case, result is NOT a global variable, but is inside another function, and I will use return (result) from the function.

Function call in R with named parameters - the name is in a variable instead of writing it directly in the function call

Suppose I have this function:
f <- function(a = 0, b = 1) {
...
}
I want to call this function and specify only parameter b:
f(b = 2);
However, instead of writing b directly above, I would like, if possible, to have the parameter name in a variable:
temp = "b";
f(temp = 2);
The above attempt obviously does not work in R. Any way to do this? Thanks!

Resources