1
$\begingroup$

The following code runs in Mathematica 12. But, I have two problems that I would like to solve: (1) How to pass a list as an argument to the function g in such a way that it can be used seamlessly in NMinimize or FindMinimum? (2) How to stop Mathematica from evaluating symbolically in the 'right' way? The code is written for 13 variables x1--x13, which are put in by hand. Surely there is a way to simply specify a variable name x so that in effect x={x1,x2,etc}. How is this done? Fixing this would also avoid using the list called data that is created by hand instead of using Table for example. Of course, using thirteen variables has no significance. The question is how to write g so its argument has n variables in such a way that it can be passed seamlessly to NMinimize or FindMinimum. A workaround for stopping the symbolic evaluation of NDSolve in the definition of g is to use If and a logical check that the interpolating function produces a numerical value. This works, but what is the right way of doing this?

g[x1_?NumericQ, x2_?NumericQ, x3_?NumericQ, x4_?NumericQ, 
  x5_?NumericQ, x6_?NumericQ, x7_?NumericQ, x8_?NumericQ, 
  x9_?NumericQ, x10_?NumericQ, x11_?NumericQ, x12_?NumericQ, 
  x13_?NumericQ] := 
 Block[{\[Alpha]0 = 1.0, w0 = 3.0, P = 2.0, tend = 12.0}, 
  stop = tend;
  data = {{0.0, x1}, {1.0, x2}, {2.0, x3}, {3.0, x4}, {4.0, x5}, {5.0,
      x6}, {6.0, x7}, {7.0, x8}, {8.0, x9}, {9.0, x10}, {10.0, 
     x11}, {11.0, x12}, {12.0, x13}}; \[Zeta] = Interpolation[data];
  If[NumericQ[\[Zeta][0]], 
   NDSolveValue[{\[Alpha]'[t] == -(P - \[Zeta][t]^2)/w[t] \[Alpha][t],
      w'[t] == (P - \[Zeta][t]^2)/
        w[t] (1.0 - w[t]^2 + \[Alpha][t]), \[Alpha][0.0] == \[Alpha]0,
      w[0.0] == w0, 
     WhenEvent[{\[Alpha][t] == 0.1}, {stop = t, 
       "StopIntegration"}]}, {\[Alpha], w}, {t, 0.0, tend}]];
  stop]

(* \Test Function g*)
g[0.`, 0.`, 0.`, 0.`, 0.`, 0.0, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`, 0.`]
(* Run NMimimize *)
ans = NMinimize[{g[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, 
    x13], 
   0 <= x1 <= 1.0 && 0 <= x2 <= 1.0 && 0 <= x3 <= 1.0 && 
    0 <= x4 <= 1.0 && 0 <= x5 <= 1.0 && 0 <= x6 <= 1.0 && 
    0 <= x7 <= 1.0 && 0 <= x8 <= 1.0 && 0 <= x9 <= 1.0 && 
    0 <= x10 <= 1.0 && 0 <= x11 <= 1.0 && 0 <= x12 <= 1.0 && 
    0 <= x13 <= 1.0}, {x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, 
   x12, x13}]
```
$\endgroup$
  • $\begingroup$ Maybe xList = Table[ToExpression["x" <> ToString[i]], {i, 1, 13}], then g[Sequence @@ xList]. The other lists can be generated in a similar way. $\endgroup$ – Rohit Namjoshi May 18 at 22:48
  • $\begingroup$ Here is another potential way to create the left hand side g[PatternSequence[ StringTemplate["x``_"] /@ Range[13] // ToExpression]?NumericQ]. $\endgroup$ – Tim Laska May 18 at 22:49
  • $\begingroup$ A=Array[a,13] creates an array of 13 variables labelled a[1], a[2], ... a[13]. You can refer to them collectively as A. $\endgroup$ – bill s Jun 30 at 3:31
1
$\begingroup$

Placing constraints on the arguments of the function g, seems to achieve the goal (1) How to pass a list as an argument to the function g in such a way that it can be used seamlessly in NMinimize or FindMinimum.

The constaint is implemented with /; AllTrue[xVals_, NumericQ]. AllTrue applies the test NumericQ to each element in the list xVals.

Note that in the function g, the variable data was modified from the original code. So that it could be assigned to using a list, rather than explicit parameters for each x.

g[xVals_List /; AllTrue[xVals, NumericQ] ] := 
 Block[{\[Alpha]0 = 1.0, w0 = 3.0, P = 2.0, tend = 12.0, qList}, 
  stop = tend;
  qList = Range[0, Length@xVals - 1];
  data = Transpose[{qList, xVals}];
  \[Zeta] = Interpolation[data];
  If[NumericQ[\[Zeta][0]], 
   NDSolveValue[{\[Alpha]'[t] == -(P - \[Zeta][t]^2)/w[t] \[Alpha][t],
      w'[t] == (P - \[Zeta][t]^2)/
        w[t] (1.0 - w[t]^2 + \[Alpha][t]), \[Alpha][0.0] == \[Alpha]0,
      w[0.0] == w0, 
     WhenEvent[{\[Alpha][t] == 0.1}, {stop = t, 
       "StopIntegration"}]}, {\[Alpha], w}, {t, 0.0, tend}]];
  stop]

(* \prepare symbols for x values*)
nX = 13;
xSymbols = ToExpression["x" <> ToString[#] ] & /@ Range[nX];

(* \prepare constraints for x values*)
xConstraintsList = 0 <= # <= 1.0 & /@ xSymbols;
xConstraints = Apply[And, xConstraintsList];

(* \Test Function g*)
xTest = ConstantArray[0, nX];
g[xTest]

(*Run NMimimize*)
ansAlt = NMinimize[{g[xSymbols], xConstraints}, xSymbols]

ans == ansAlt
(*True*)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.