Date: 2025-03-29T05:58:47+00:00

Actual source code: matlab_ls_test.c

      1: static char help[] = "TAO/Pounders MATLAB Testing on the More'-Wild Benchmark Problems\n\
      2: The interface calls:\n\
      3:     TestingInitialize.m to initialize the problem set\n\
      4:     ProblemInitialize.m to initialize each instance\n\
      5:     ProblemFinalize.m to store the performance data for the instance solved\n\
      6:     TestingFinalize.m to store the entire set of performance data\n\
      7: \n\
      8: TestingPlot.m is called outside of TAO/Pounders to produce a performance profile\n\
      9: of the results compared to the MATLAB fminsearch algorithm.\n";

     11: #include <petsctao.h>
     12: #include <petscmatlab.h>

     14: typedef struct {
     15:   PetscMatlabEngine mengine;

     17:   double delta; /* Initial trust region radius */

     19:   int n;     /* Number of inputs */
     20:   int m;     /* Number of outputs */
     21:   int nfmax; /* Maximum function evaluations */
     22:   int npmax; /* Maximum interpolation points */
     23: } AppCtx;

     25: static PetscErrorCode EvaluateResidual(Tao tao, Vec X, Vec F, void *ptr)
     26: {
     27:   AppCtx *user = (AppCtx *)ptr;

     29:   PetscFunctionBegin;
     30:   PetscCall(PetscObjectSetName((PetscObject)X, "X"));
     31:   PetscCall(PetscMatlabEnginePut(user->mengine, (PetscObject)X));
     32:   PetscCall(PetscMatlabEngineEvaluate(user->mengine, "F = func(X);"));
     33:   PetscCall(PetscObjectSetName((PetscObject)F, "F"));
     34:   PetscCall(PetscMatlabEngineGet(user->mengine, (PetscObject)F));
     35:   PetscFunctionReturn(PETSC_SUCCESS);
     36: }

     38: static PetscErrorCode EvaluateJacobian(Tao tao, Vec X, Mat J, Mat JPre, void *ptr)
     39: {
     40:   AppCtx *user = (AppCtx *)ptr;

     42:   PetscFunctionBegin;
     43:   PetscCall(PetscObjectSetName((PetscObject)X, "X"));
     44:   PetscCall(PetscMatlabEnginePut(user->mengine, (PetscObject)X));
     45:   PetscCall(PetscMatlabEngineEvaluate(user->mengine, "J = jac(X);"));
     46:   PetscCall(PetscObjectSetName((PetscObject)J, "J"));
     47:   PetscCall(PetscMatlabEngineGet(user->mengine, (PetscObject)J));
     48:   PetscFunctionReturn(PETSC_SUCCESS);
     49: }

     51: static PetscErrorCode TaoPounders(AppCtx *user)
     52: {
     53:   Tao  tao;
     54:   Vec  X, F;
     55:   Mat  J;
     56:   char buf[1024];

     58:   PetscFunctionBegin;
     59:   /* Set the values for the algorithm options we want to use */
     60:   PetscCall(PetscSNPrintf(buf, PETSC_STATIC_ARRAY_LENGTH(buf), "%d", user->npmax));
     61:   PetscCall(PetscOptionsSetValue(NULL, "-tao_pounders_npmax", buf));
     62:   PetscCall(PetscSNPrintf(buf, PETSC_STATIC_ARRAY_LENGTH(buf), "%5.4e", user->delta));
     63:   PetscCall(PetscOptionsSetValue(NULL, "-tao_pounders_delta", buf));

     65:   /* Create the TAO objects and set the type */
     66:   PetscCall(TaoCreate(PETSC_COMM_SELF, &tao));

     68:   /* Create starting point and initialize */
     69:   PetscCall(VecCreateSeq(PETSC_COMM_SELF, user->n, &X));
     70:   PetscCall(PetscObjectSetName((PetscObject)X, "X0"));
     71:   PetscCall(PetscMatlabEngineGet(user->mengine, (PetscObject)X));
     72:   PetscCall(TaoSetSolution(tao, X));

     74:   /* Create residuals vector and set residual function */
     75:   PetscCall(VecCreateSeq(PETSC_COMM_SELF, user->m, &F));
     76:   PetscCall(PetscObjectSetName((PetscObject)F, "F"));
     77:   PetscCall(TaoSetResidualRoutine(tao, F, EvaluateResidual, (void *)user));

     79:   /* Create Jacobian matrix and set residual Jacobian routine */
     80:   PetscCall(MatCreateSeqAIJ(PETSC_COMM_WORLD, user->m, user->n, user->n, NULL, &J));
     81:   PetscCall(PetscObjectSetName((PetscObject)J, "J"));
     82:   PetscCall(TaoSetJacobianResidualRoutine(tao, J, J, EvaluateJacobian, (void *)user));

     84:   /* Solve the problem */
     85:   PetscCall(TaoSetType(tao, TAOPOUNDERS));
     86:   PetscCall(TaoSetMaximumFunctionEvaluations(tao, user->nfmax));
     87:   PetscCall(TaoSetFromOptions(tao));
     88:   PetscCall(TaoSolve(tao));

     90:   /* Finish the problem */
     91:   PetscCall(MatDestroy(&J));
     92:   PetscCall(VecDestroy(&X));
     93:   PetscCall(VecDestroy(&F));
     94:   PetscCall(TaoDestroy(&tao));
     95:   PetscFunctionReturn(PETSC_SUCCESS);
     96: }

     98: int main(int argc, char **argv)
     99: {
    100:   AppCtx      user;
    101:   PetscScalar tmp;
    102:   PetscInt    prob_id = 0;
    103:   PetscBool   flg, testall = PETSC_FALSE;
    104:   int         i, i0, imax;

    106:   PetscFunctionBeginUser;
    107:   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
    108:   PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_all", &testall, NULL));
    109:   PetscCall(PetscOptionsGetInt(NULL, NULL, "-prob_id", &prob_id, &flg));
    110:   if (!testall) {
    111:     if (!flg) {
    112:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Problem number must be specified with -prob_id");
    113:     } else if ((prob_id < 1) || (prob_id > 53)) {
    114:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Problem number must be between 1 and 53!");
    115:     } else {
    116:       PetscCall(PetscPrintf(PETSC_COMM_SELF, "Running problem %d\n", prob_id));
    117:     }
    118:   } else {
    119:     PetscCall(PetscPrintf(PETSC_COMM_SELF, "Running all problems\n"));
    120:   }

    122:   PetscCall(PetscMatlabEngineCreate(PETSC_COMM_SELF, NULL, &user.mengine));
    123:   PetscCall(PetscMatlabEngineEvaluate(user.mengine, "TestingInitialize"));

    125:   if (testall) {
    126:     i0   = 1;
    127:     imax = 53;
    128:   } else {
    129:     i0   = (int)prob_id;
    130:     imax = (int)prob_id;
    131:   }

    133:   for (i = i0; i <= imax; ++i) {
    134:     PetscCall(PetscPrintf(PETSC_COMM_SELF, "%d\n", i));
    135:     PetscCall(PetscMatlabEngineEvaluate(user.mengine, "np = %d; ProblemInitialize", i));
    136:     PetscCall(PetscMatlabEngineGetArray(user.mengine, 1, 1, &tmp, "n"));
    137:     user.n = (int)tmp;
    138:     PetscCall(PetscMatlabEngineGetArray(user.mengine, 1, 1, &tmp, "m"));
    139:     user.m = (int)tmp;
    140:     PetscCall(PetscMatlabEngineGetArray(user.mengine, 1, 1, &tmp, "nfmax"));
    141:     user.nfmax = (int)tmp;
    142:     PetscCall(PetscMatlabEngineGetArray(user.mengine, 1, 1, &tmp, "npmax"));
    143:     user.npmax = (int)tmp;
    144:     PetscCall(PetscMatlabEngineGetArray(user.mengine, 1, 1, &tmp, "delta"));
    145:     user.delta = (double)tmp;

    147:     /* Ignore return code for now -- do not stop testing on inf or nan errors */
    148:     PetscCall(TaoPounders(&user));

    150:     PetscCall(PetscMatlabEngineEvaluate(user.mengine, "ProblemFinalize"));
    151:   }

    153:   PetscCall(PetscMatlabEngineEvaluate(user.mengine, "TestingFinalize"));
    154:   PetscCall(PetscMatlabEngineDestroy(&user.mengine));
    155:   PetscCall(PetscFinalize());
    156:   return 0;
    157: }

    159: /*TEST

    161:    build:
    162:       requires: matlab

    164:    test:
    165:       localrunfiles: more_wild_probs TestingInitialize.m TestingFinalize.m ProblemInitialize.m ProblemFinalize.m
    166:       args: -tao_monitor_short -prob_id 5

    168: TEST*/