You can define any number of objective functions in an AMPL model. However, solvers only minimize or maximize one objective at a time. If your model has, say, three minimize
statements that define objectives A, B, and C, then you can minimize each one of them separately (subject to the same constraints) by including their names in solve
commands:
solve A;
solve B;
solve C;
But usually, a solution that is optimal for one objective will not be optimal for other objectives. There might be multiple solutions that minimize A, for instance, but you should not expect any of them to also be minimal for B or C. It happens only rarely that some combination of model and data allow a solution to be optimal for more than one objective at the same time.
There do exist strategies for balancing the goals of different objectives, to produce solutions that, if not optimal, are at least very good for every objective function of interest. AMPL supports a generic collection of solver options for multi-objective optimization, which work with any solver that uses the MP interface library. Additionally, some solvers offer their own implementations of related options, which work somewhat differently but which may be more efficient. Availability of these features is summarized in our MP Solver Support table.
To use MP’s generic multi-objective feature, add obj:multi=2
to your solver’s option string. Then to provide priority and/or weighting information, you will need to use AMPL suffix
command to define multiobjective properties, which may include the following:
suffix objweight IN;
suffix objpriority IN;
suffix objreltol IN;
suffix objabstol IN;
Use the objweight
suffix to specify a weighted sum of your model’s objectives. For instance, if you want the solver to minimize a weighted combination 80*A
+
20*B
+
10*C
, you can use AMPL let
statements* to assign corresponding objweight
values to the objectives:
let A.objweight := 80;
let B.objweight := 20;
let C.objweight := 10;
Use the objpriority
suffix to specify a series of optimizations, in order of importance. For example, if you want the solver to first minimize A, then fix A at its minimum value and minimize B, then also fix B at the resulting minimum value and minimize C, you can assign corresponding objpriority
values to the objectives:
let A.objpriority := 5;
let B.objpriority := 2;
let C.objpriority := 1;
You can use any integers as objpriority
values; the objective with the highest priority is minimized first, then the objective with the next highest priority, and so forth.
Weighting and priority may be used together. If several objectives have the same priority, then their weighted sum is minimized with the priority given by objpriority
, using weights given by objweight
. So for example if you set
let A.objpriority := 5;
let B.objpriority := 1;
let C.objpriority := 1;
let A.objweight := 1;
let B.objweight := 9;
let C.objweight := 6;
then after A is minimized, the solver fixes A at its minimum value and minimizes 9*B
+
6*C
. (A.objweight
must be assigned a positive value, even if it is 1, as otherwise it would default to 0.)
If you are willing to accept a value for a higher-priority objective that is a bit greater than its minimum, you might be able to find a solution that has a substantially better value for lower-priority objectives. To explore such a possibility, you can assign a “tolerance” to an objective, which specifies how much its optimal value may be degraded when lower-priority objectives are optimized. There are two possibilities;
-
objreltol
specifies a fraction by which an objective value may become worse when lower-priority objectives are optimized. -
objabstol
specifies an amount by which an objective value may become worse when lower-priority objectives are optimized.
For instance, continuing with the previous example, if you set A.objreltol
to 0.05, then instead of fixing A at its minimum value, the solver adds a constraint that A’s value must be \leq its minimum value times 1.05. If you set A.objabstol
to 100, then instead of fixing A at its minimum value, the solver adds a constraint that A’s value must be \leq its minimum value plus 100.
It is possible for more than one objreltol
and/or objabstol
setting to apply at the same priority level, in which case the one specifying the greatest tolerance is used. Consider the situation where the settings in our example are instead
let A.objpriority := 1;
let B.objpriority := 5;
let C.objpriority := 5;
let A.objweight := 1;
let B.objweight := 9;
let C.objweight := 6;
let B.objreltol := 0.025;
let C.objreltol := 0.05;
let B objabstol := 30;
B and C share the highest priority, so 9*B
+
6*C
is first minimized; suppose its optimal value is 800. Then since tolerance values have been set for B and C, the solver adds a constraint that the value of 9*B
+
6*C
must be \leq 800 + max (0.025*800, 0.05*800, 30) = 840, after which it computes the minimum of the lower-priority objective A. (Since C.objabstol
is not set, it defaults to 0, which does not make any difference to the chosen tolerance.)
All of these features apply equally well to maximization objectives, with any tolerances being enforced by \geq constraints. Also minimization and maximization can be combined, though this should be done with care:
-
Objectives that are combined using
objweight
typically have the same sense (minimize or maximize). Weighted combinations that involve objectives of both senses are allowed, but in that case one sense will be chosen for the combined objective, and objectives of the other sense will be negated in the combination. -
objpriority
,objweight
,objreltol
, andobjabstol
values are typically >= 0. Negativeobjweight
settings are accepted, but they may change the objective sense; see your solver’sobj:multi:weight
option for details. -
Multi-objective features tend to work best with linear objectives and constraints. More general model expressions are accepted but may may encounter numerical issues that make them difficult to solve accurately.
To use the multi-objective features that are native (built in) to certain solvers, add obj:multi=1
to your solver’s option string, and consult the appropriate solver documentation:
You will use the objpriority
, objweight
, objreltol
, and objabstol
suffixes as before, but the concepts of “priority”, “weight”, and “tolerance” may be defined somewhat differently, and as a result the suffix values may be subject to different interpretations and rules. Additional obj:
options may also be available; check the solver’s option listing for details. (For MP-based solvers not listed above, obj:multi=1
and obj:multi=2
both select the generic multi-objective feature described previously.)
Whereas the generic multi-objective feature calls the solver separately for each priority level, native multi-objective optimization is performed in a single solver call. As a consequence, native alternatives can be substantially faster, especially where priorities are specified, or where the solver spends a significant amount of time in preprocessing phases. Native alternatives may be more limited in the problem types they accept, however, and their results are sometimes harder to interpret.
* As an alternative to let
statements, you can specify suffix values at the end of an objective’sminimize
or maximize
statement in the model; for example,
minimize A:
sum {j in PROD} cost[j] * Make[j],
suffix objweight 8, suffix objpriority 5;