Skip to content

Commit

Permalink
improve writing of ampl starting point
Browse files Browse the repository at this point in the history
- allow to write d segment
- allow to specify which initial values to pass on to AMPL
  • Loading branch information
svigerske committed Feb 7, 2023
1 parent 300a435 commit 277de62
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 12 deletions.
17 changes: 17 additions & 0 deletions src/amplsolver/amplsolver.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ typedef struct
int stublen;
char solver[GMS_SSSIZE];
int nlbinary;
char initprimal[GMS_SSSIZE];
char initdual[GMS_SSSIZE];

} amplsolver;

Expand Down Expand Up @@ -166,6 +168,9 @@ int processOptions(

as->nlbinary = optGetIntStr(opt, "nlbinary");

optGetStrStr(opt, "initprimal", as->initprimal);
optGetStrStr(opt, "initdual", as->initdual);

rc = 0;

TERMINATE:
Expand Down Expand Up @@ -194,6 +199,18 @@ void writeNL(
writeopts.filename = as->filename;
writeopts.binary = as->nlbinary;

writeopts.primalstart = convert_initall;
if( strcmp(as->initprimal, "none") == 0 )
writeopts.primalstart = convert_initnone;
else if( strcmp(as->initprimal, "nondefault") == 0 )
writeopts.primalstart = convert_initnondefault;

writeopts.dualstart = convert_initall;
if( strcmp(as->initdual, "none") == 0 )
writeopts.dualstart = convert_initnone;
else if( strcmp(as->initdual, "nondefault") == 0 )
writeopts.dualstart = convert_initnondefault;

if( convertWriteNL(as->gmo, writeopts) == RETURN_ERROR )
{
gmoSolveStatSet(as->gmo, gmoSolveStat_Capability);
Expand Down
102 changes: 90 additions & 12 deletions src/amplsolver/convert_nl.c
Original file line number Diff line number Diff line change
Expand Up @@ -738,32 +738,110 @@ RETURN writeNLVarBounds(
return RETURN_OK;
}

/** write the x segment */
/** write the x and d segments */
static
RETURN writeNLInitialPoint(
struct gmoRec* gmo,
convertWriteNLopts writeopts
)
{
int nnz = 0;
int nnz;
int i;

assert(gmo != NULL);

/* count nonzeros */
for( i = 0; i < gmoN(gmo); ++i )
if( gmoGetVarLOne(gmo, i) != 0.0 )
++nnz;
if( writeopts.dualstart != convert_initnone )
{
/* count marginal values to be printed */
if( writeopts.dualstart == convert_initall )
{
nnz = gmoM(gmo);
}
else
{
nnz = 0;
for( i = 0; i < gmoM(gmo); ++i )
if( gmoGetEquMOne(gmo, i) != 0.0 )
++nnz;
}

if( nnz == 0 )
return RETURN_OK;
CHECK( writeNLPrintf(writeopts, "d%d\n", nnz) );

/* write marginal values */
for( i = 0; i < gmoM(gmo); ++i )
if( writeopts.dualstart == convert_initall || gmoGetEquMOne(gmo, i) != 0.0 )
{
CHECK( writeNLPrintf(writeopts, "%d %g\n", i, gmoGetEquMOne(gmo, i)) );
}
}

CHECK( writeNLPrintf(writeopts, "x%d\n", nnz) );
if( writeopts.primalstart != convert_initnone )
{
/* count level values to be printed */
if( writeopts.primalstart == convert_initall )
{
nnz = gmoN(gmo);
}
else
{
nnz = 0;
for( i = 0; i < gmoN(gmo); ++i )
{
double val = gmoGetVarLOne(gmo, i);

/* check whether variable level is at default (0 projected onto bounds) */
double lb = gmoGetVarLowerOne(gmo, i);
double ub = gmoGetVarUpperOne(gmo, i);
if( gmoGetVarTypeOne(gmo, i) == gmovar_SC || gmoGetVarTypeOne(gmo, i) == gmovar_SI )
{
/* correct to actual bounds if semi-cont/integral */
if( lb != gmoMinf(gmo) && lb > 0.0 )
lb = 0.0;
if( ub != gmoPinf(gmo) && ub < 0.0 )
ub = 0.0;
}
if( lb > 0.0 && val == lb )
continue;
if( ub < 0.0 && val == ub )
continue;
if( val == 0.0 )
continue;

++nnz;
}
}

CHECK( writeNLPrintf(writeopts, "x%d\n", nnz) );

/* write level values */
for( i = 0; i < gmoN(gmo); ++i )
{
double val = gmoGetVarLOne(gmo, i);

if( writeopts.primalstart == convert_initnondefault )
{
/* check whether variable level is at default (0 projected onto bounds) */
double lb = gmoGetVarLowerOne(gmo, i);
double ub = gmoGetVarUpperOne(gmo, i);
if( gmoGetVarTypeOne(gmo, i) == gmovar_SC || gmoGetVarTypeOne(gmo, i) == gmovar_SI )
{
/* correct to actual bounds if semi-cont/integral */
if( lb != gmoMinf(gmo) && lb > 0.0 )
lb = 0.0;
if( ub != gmoPinf(gmo) && ub < 0.0 )
ub = 0.0;
}
if( lb > 0.0 && val == lb )
continue;
if( ub < 0.0 && val == ub )
continue;
if( val == 0.0 )
continue;
}

/* write nonzero level values */
for( i = 0; i < gmoN(gmo); ++i )
if( gmoGetVarLOne(gmo, i) != 0.0 )
CHECK( writeNLPrintf(writeopts, "%d %g\n", i, gmoGetVarLOne(gmo, i)) );
}
}

return RETURN_OK;
}
Expand Down
9 changes: 9 additions & 0 deletions src/amplsolver/convert_nl.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,22 @@

#include "def.h"

/** which initial values to write to .nl file */
typedef enum {
convert_initnone = 0, /**< don't write any initial values */
convert_initnondefault = 1, /**< write only values that are not at default */
convert_initall = 2 /**< write all values */
} convert_initvalues;

typedef struct
{
/* parameters */
const char* filename; /**< name of nl file to write */
int binary; /**< whether to print binary .nl */
int comments; /**< whether to print many comments to .nl (text only) */
int shortfloat; /**< whether to print float as short as possible or like AMPL (text only) */
convert_initvalues primalstart; /**< which of the variable level values to write into x-section */
convert_initvalues dualstart; /**< which of the equation marginal values to write into d-section */

/* private */
FILE* f; /**< nl file stream */
Expand Down
17 changes: 17 additions & 0 deletions src/amplsolver/optamplsolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,23 @@ int main(int argc, char** argv)

gmsopt.collect("nlbinary", "Whether .nl file should be written in binary form", "", true);

GamsOption::EnumVals initvals;
initvals.append("none", "pass no values");
initvals.append("nondefault", "pass only values that are not at GAMS default");
initvals.append("all", "pass on all values");

gmsopt.collect("initprimal", "Which initial variable level values to pass to AMPL solver", "",
"all", initvals);

// reusing initvals would give a double-free at the end; should fix that someday...
GamsOption::EnumVals initvals2;
initvals2.append("none", "pass no values");
initvals2.append("nondefault", "pass only values that are not at GAMS default");
initvals2.append("all", "pass on all values");

gmsopt.collect("initdual", "Which initial equation marginal values to pass to AMPL solver", "",
"all", initvals2);

gmsopt.finalize();

gmsopt.writeDef();
Expand Down

0 comments on commit 277de62

Please sign in to comment.