Function name defined by a variable in VBA - function

New VBA user here, engineer-not a programmer. Your patience is appreciated. Did spend hours in help and online trying to find this answer. Found some answers to this, but they were for php. Working with MS Office Home and Student 2007.
I have a list of 8 equations. I have the user input the number of the equation they want to evaluate, I call that number index. Is there a way to put the index into a function name when it's defined?
such as:
Function PlotFun[index]= some f(x)
Or is it possible to redefine the function using an index within a subroutine?
such as:
If index=1 then PlotFun=PlotFun[index] 'so PlotFun would equal PlotFun1
I think I read in the help that a function has to be defined in a function routine, so this one probably isn't feasible.
Or is it possible to read the function from a cell in excel? I tried using
Function PlotFun=Worksheets(1).Range("BC6")
where BC6 contains "24 - 50 * x + 35 * x ^ 2 - 10 * x ^ 3 + x * 4" which is correct syntax for a function of x, as it was copied from my PlotFun1 routine. But I don't have the syntax down right. I get Compile Error: Expected: End of statement, right at the equals sign.
I've also been referred to the lamda function, but again, I get the Expected: End of Statement error.
Sub Bisection()
Dim index
Call FuncIndex 'sets the index number for which equation to use for analysis
If index = 1 Then
Dim PlotFun=Function(x) x ^ 3 - 6 * x ^ 2 + 11 * x - 6
If index = 2 Then
Dim PlotFun=Function(x) 24 - 50 * x + 35 * x ^ 2 - 10 * x ^ 3 + x * 4
Do 'my calculations using PlotFun
Loop 'for specified error or iterations
End Sub
I need to use PlotFun or PlotFun1 in a few places within many subroutines. I don't want to have to write/copy code for each f(x). Perhaps there is a better way to do this than what I've thought of? I cannot use an array, as the equations are not all polynomials.
Thank you!

Is there a way to put the index into a function name when it's
defined? such as:
Not in-line really. You can use a select case switch, or a series of if/else statements. I ordinarily prefer the select case method.
NOTE This code does not specify any value for x, so it will be interpreted as an Empty or zero-value, unless you change the code or provide a means for user to input the variable x value.
Sub WhichFunction()
Dim i as Long
Dim functionResult as Double
i = Application.InputBox "Please enter the function's index #"
Select Case i
Case 1
functionResult = x ^ 3 - 6 * x ^ 2 + 11 * x - 6
Case 2
functionResult = - 50 * x + 35 * x ^ 2 - 10 * x ^ 3 + x * 4
Case 3
'etc.
Case 4
Case 5
Case 6
Case 7
Case 8
Case else
MsgBox "invalid function index!"
End Select
MsgBox functionResult
End Sub
About your code:
I get the Expected: End of Statement error
Probably because your Dim statements don't end where they should. In VBA, you generally can't declare and simultaneously assign a variable. There are exceptions, and visual shortcuts, but that's not necessary to discuss here.
Or is it possible to read the function from a cell in excel? I tried
using Function PlotFun=Worksheets(1).Range("BC6")
Yes, it is possible for a function to read from a specific cell, but not the way you're implementing it. YOu need to go back to basics and learn how to create a function, e.g,:
Function MyFunctionName(arg1 as integer, arg2 as integer)
'Code the evaluates some methods on the arguments provided
Dim myVal as Double
myVal = arg1 ^ arg2
MyFunction = myVal 'Return the calculated value
End Function
Likewise you could do:
Function GetValueFromSheet(byVal cl as Range)
'This function will ALWAYS return the value in B6
GetValueFromSheet = Range("B6").Value
End Function

It sounds like you want to vary what algorithm is used, or in your case what equation is called based on a parameter that you would pass to a single function. This problem can be solved by the use a of a well know software pattern known as the "strategy pattern". This pattern allows you to vary an algorithm while keeping its implementation the same.
You can combine the strategy pattern with a factory pattern to achieve the desired architecture you are seeking.
Here is a fairly clear vba implementation of a strategy pattern.
Hope this helps.

VBA is the worst language to try to do this in. (Actually, it's the worst language to try to do most things in.)
VBA functions are unfortunately not values or objects, and they cannot be stored in variables whatsoever. Therefore, none of this is remotely legal:
Function PlotFun[index]= some f(x)
Function PlotFun=Worksheets(1).Range("BC6")
Dim PlotFun=Function(x) x ^ 3 - 6 * x ^ 2 + 11 * x - 6
Since you don't need too many functions, the easiest solution is this:
Function PlotFun(index, x)
Select Case index
Case 1
PlotFun = x ^ 3 - 6 * x ^ 2 + 11 * x - 6
Case 2
PlotFun = 24 - 50 * x + 35 * x ^ 2 - 10 * x ^ 3 + x * 4
Case 3
' ... and so on
End Select
End Function
I.e., declare PlotFun as an ordinary function, and use your index variable to tell it what internal expression to evaluate. The disadvantage is that you will have to include the function index variable everywhere you want to call PlotFun.
Note that the PlotFun = ... syntax here does not assign the function itself, but rather is VBA's way of setting the return value from a particular invocation of the function. Within the function, PlotFun is just the name of a variable to assign to.

Related

Schwefel function trying to find global minimum with three variables, but I am receiving a error from function

I am writing a Schwefel function with three variables x1, x2 and x3 with x (-400,400), I am trying to find the global minimum of a Schwefel function. Can anybody tell me what's wrong with the function code.
function output = objective_function(in)
x1 = in(1);
x2 = in(2);
x3 = in(3);
output=(-x1.*sin(sqrt(mod(x1)))+(-x2.*sin(sqrt(mod(x2)))+(-x3.*sin(sqrt(mod(x3)));
ouput=[F1 F2];
Current Problems:
1: Mismatched delimiters in line:
output=(-x1.*sin(sqrt(mod(x1)))+(-x2.*sin(sqrt(mod(x2)))+(-x3.*sin(sqrt(mod(x3)));
2: Modulus requires a second argument. The second argument inputted into the mod() function needs to be the divisor. The modulus can only return the remainder if it knows the number being divided (dividend) and the number that is dividing (divisor). Calling the mod() function can follow the form:
mod(dividend,divisor);
Aside:
mod() is often used accidentally in replace of abs()
Modulus → mod() : Returns the remainder after division.
Example: mod(10,3) = 1 → 10/3 = 3 with remainder 1
Absolute → abs(): Returns the absolute/magnitude of the number.
Example: abs(-10) = 10 or abs(1 + 1i) = 1.4142
3: Variables F1 and F2 are not defined or initialized before being used. The variable called ouput may be a typo.
ouput=[F1 F2];
Playground Script:
Not sure what the function is supposed to exactly do but here is a script that you can modify to meet your needs. This gets rid of the errors but might need to be reconfigured to suit your exact functionality and output equation.
in = [1 2 3];
[output] = objective_function(in);
function [output] = objective_function(in)
x1 = in(1);
x2 = in(2);
x3 = in(3);
%Splitting into terms will help with debugging bracket balancing issues%
Divisor = 2;
Term_1 = (-x1.*sin(sqrt(mod(x1,Divisor))));
Term_2 = (-x2.*sin(sqrt(mod(x2,Divisor))));
Term_3 = (-x3.*sin(sqrt(mod(x3,Divisor))));
output = Term_1 + Term_2 + Term_3;
end
Ran using MATLAB R2019b

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

Piecewise functions in the Octave symbolic package?

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

Trying to find a way to construct Julia `generator`

I'm new to Julia.
I mainly program in python.
In python,
if you want to iterate over a large set of values,
it is typical to construct a so-called generator to save memory usage.
Here is one example code:
def generator(N):
for i in range(N):
yield i
I wonder if there is anything alike in Julia.
After reading julia manual,
#task macro seems to have the same (or similar) functionality as generator in python.
However,
after some experiments,
the memory usage seems to be larger than usual array in julia.
I use #time in IJulia to see the memory usage.
Here is my sample code:
[Update]: Add the code for generator method
(The generator method)
function generator(N::Int)
for i in 1:N
produce(i)
end
end
(generator version)
function fun_gener()
sum = 0
g = #task generator(100000)
for i in g
sum += i
end
sum
end
#time fun_gener()
elapsed time: 0.420731828 seconds (6507600 bytes allocated)
(array version)
function fun_arry()
sum = 0
c = [1:100000]
for i in c
sum += i
end
sum
end
#time fun_arry()
elapsed time: 0.000629629 seconds (800144 bytes allocated)
Could anyone tell me why #task will require more space in this case?
And if I want to save memory usage as dealing with a large set of values,
what can I do?
I recommend the "tricked out iterators" blogpost by Carl Vogel, which discusses julia's iterator protocol, tasks and co-routines in some detail.
See also task-aka-coroutines in the julia docs.
In this case you should use the Range type (which defines an iterator protocol):
julia> function fun_arry()
sum = 0
c = 1:100000 # remove the brackets, makes this a Range
for i in c
sum += i
end
sum
end
fun_arry (generic function with 1 method)
julia> fun_arry() # warm up
5000050000
julia> #time fun_arry()
elapsed time: 8.965e-6 seconds (192 bytes allocated)
5000050000
Faster and less memory allocated (just like xrange in python 2).
A snippet from the blogpost:
From https://github.com/JuliaLang/julia/blob/master/base/range.jl, here’s how a Range’s iterator protocol is defined:
start(r::Ranges) = 0
next{T}(r::Range{T}, i) = (oftype(T, r.start + i*step(r)), i+1)
next{T}(r::Range1{T}, i) = (oftype(T, r.start + i), i+1)
done(r::Ranges, i) = (length(r) <= i)
Notice that the next method calculates the value of the iterator in state i. This is different from an Array iterator, which just reads the element a[i] from memory.
Iterators that exploit delayed evaluation like this can have important performance benefits. If we want to iterate over the integers 1 to 10,000, iterating over an Array means we have to allocate about 80MB to hold it. A Range only requires 16 bytes; the same size as the range 1 to 100,000 or 1 to 100,000,000.
You can write a generator method (using Tasks):
julia> function generator(n)
for i in 1:n # Note: we're using a Range here!
produce(i)
end
end
generator (generic function with 2 methods)
julia> for x in Task(() -> generator(3))
println(x)
end
1
2
3
Note: if you replace the Range with this, the performance is much poorer (and allocates way more memory):
julia> #time fun_arry()
elapsed time: 0.699122659 seconds (9 MB allocated)
5000050000
This question was asked (and answered) quite a while ago. Since this question is ranked high on google searches, I'd like to mention that both the question and answer are outdated.
Nowadays, I'd suggest checking out https://github.com/BenLauwens/ResumableFunctions.jl for a Julia library with a macro that implements Python-like yield generators.
using ResumableFunctions
#resumable function fibonnaci(n::Int) :: Int
a = 0
b = 1
for i in 1:n-1
#yield a
a, b = b, a+b
end
a
end
for fib in fibonnaci(10)
println(fib)
end
Since its scope is much more limited than full coroutines, it is also an order of magnitude more efficient than pushing values into a channel since it can compile the generator into a FSM. (Channels have replaced the old produce() function mentioned in the question and previous answers).
With that said, I'd still suggest pushing into a channel as your first approach if performance isn't an issue, because resumablefunctions can sometimes be finicky when compiling your function and can occasionally hit some worst-case behaviour. In particular, because it is a macro that compiles to an FSM rather than a function, you currently need to annotate the types of all variables in the Resumablefunction to get good performance, unlike vanilla Julia functions where this is handled by JIT when the function is first called.
I think that Task has been superseded by Channel(). The usage in terms of Ben Lauwens's Fibonacci generator is:
fibonacci(n) = Channel(ctype=Int) do c
a = 1
b = 1
for i in 1:n
push!(c, a)
a, b = b, a + b
end
end
it can be used using
for a in fibonacci(10)
println(a)
end
1
1
2
3
5
8
13
21
34
55

Why is this Mathematica function definition returning an error?

I am trying to put in a rather large function into mathematica:
(http://i.imgur.com/BqBYxfp.png)
I want to get it in so I can compute the global maxima, but I keep getting an error when I try and define the function. Does anyone know why this is happening?
Also, U(C) is U(C) not U(N) because it is a Kuhn Tucker reduction of an earlier equation, but the function should be a function of n in mathematica as that is all that will be allowed to vary.
All other variables are fixed values.
In[1]:= f(n) :=
((A*n^a)^(1/s) +
c*(B*(a*c*(B/A)^(1/s)*n^(1 - (a/s)))^(-(a*s)/(a - s)))^(1/s))^s +
b*log (1 - n - ((a*c*(B/A)^(1/s)*n^(1 - (a/s)))^(-(a*s)/(a - s))))
SetDelayed::write: Tag Times in f n is Protected. >>
Out[1]= $Failed
Use f[n_]:= (n with an underscore _) when declaring the function, and not f(n):=