I have developed the following code that simulates a process that decays over time and then returns to its initial state periodically.
When I pass a list of random integers in the interval $(1,0)$ as arguments, the function behaves as I expect it to.
However, when NMaximize calls the function, I get the following error:
NMaximize::nnum: The function value -1000 - 19 If[a[21] == 1,500, 1000] is not a number at {a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], a[16], a[17], a[18], a[19], a[20]} = {1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.}. >>
The interesting part of the error is the complaint about
a[21]; this variable doesn't exist unless the function is called by
NMaximize. The idea is that
NMaximize` will find integer, binary values for the parameters that will maximize the return value of the function.
My guess is that there is problem in how my function is being translated internally by NMaximize
, but I am not not sure what to do at this point.
(*Assign Initial Values*)
Clear[f, i, a, vars, realconstraints, integerconstraints]
PeriodCapacityLoss = 10;
InitialCapacity = 1000;
OOSCapacity = 500;
AssymtoticCapacity = 200;
Periods = 20;
CurrentCapacity[1] = InitialCapacity;
(*Generate random series of cleaning flags*)
For[j = 1, j < Periods + 1, j++,
RecoveryFlag[j] = RandomInteger[{0, 1}];
];
(*Function to simulate effect of capacity degredation and recovery*)
f[a_] := Module[{i},
(* Set initial condition as clean *)
CurrentCapacity[1] = InitialCapacity;
For[i = 2, i < Periods + 1, i++,
CurrentCapacity[i] =
If[a[i] == 0 && a[i - 1] == 0,
CurrentCapacity[i - 1] - PeriodCapacityLoss,
If[a[i] == 1, OOSCapacity, InitialCapacity]
];
];
Return[Total[Map[CurrentCapacity, Range[Periods]]]];
];
(*Pass random cleaning flags to degredation function and plot*)
Print[f[RecoveryFlag]];
ListLinePlot[Array[CurrentCapacity, Periods]]
(* Define the integer constraints *)
vars = Array[a, Periods];
realconstraints = And @@ Map[Greater[2, #, 0]&, vars];
integerconstraints = Append[realconstraints, Element[vars, Integers]];
(*
Find the value of the recovery flag that maximizes capacity across the
time window
*)
NMaximize[{f[a], integerconstraints}, vars, Method->{"DifferentialEvolution"}]
NMaximize
will be less inclined to sulk if the function is a "black box", that is, only evaluating for explicitly numeric arguments. That can be attained via e.g.f[a_?NumberQ] := ...
$\endgroup$a
is only aHead
… $\endgroup$