Skip to content
Development
Skill

/cuopt-multi-objective-exploration

Trace, complete, and interpret the Pareto frontier across competing objectives using repeated single-objective cuOpt solves (weighted-sum and ε-constraint).

From plugin
nvidia-skills
2.8k200 skills3 agents
Install
$ npx -y skills add NVIDIA/skills --skill cuopt-multi-objective-exploration --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/cuopt-multi-objective-exploration

Context preview

The summary Claude sees to decide when to auto-load this skill.

Trace, complete, and interpret the Pareto frontier across competing objectives using repeated single-objective cuOpt solves (weighted-sum and ε-constraint).

SKILL.md

cuopt-multi-objective-exploration.SKILL.md
name: cuopt-multi-objective-exploration
version: "26.10.00"
description: Trace, complete, and interpret the Pareto frontier across competing objectives using repeated single-objective cuOpt solves (weighted-sum and ε-constraint).
license: Apache-2.0
origin: cuopt-skill-evolution
metadata:
  author: NVIDIA cuOpt Team
  tags:
    - multi-objective
    - pareto
    - epsilon-constraint
    - tradeoff
    - workflow

Multi-Objective Exploration

cuOpt optimizes **one** objective per solve. Many real problems have several objectives that pull against each other — cost vs. service level, return vs. risk, makespan vs. overtime, distance vs. vehicle count. A single solve answers "what's optimal *for one particular weighting*," but it hides the tradeoff the user actually needs to see.

This skill turns a sequence of single-objective cuOpt solves into a **Pareto frontier** — the set of solutions where you can't improve one objective without giving up another — and gives the discipline to read it. It adds no solver features; it orchestrates the LP / MILP / QP solves already covered by the formulation and API skills.

When this applies

Reach for this workflow when the problem has **two or more objectives with no agreed-upon weighting**, signalled by language like:

  • "balance X and Y", "trade off", "as cheap as possible *without* hurting service"
  • "minimize cost *and* maximize coverage", "I want options, not one answer"
  • any objective the user is willing to relax in exchange for another

If there is a single clear objective (everything else is a hard constraint), this skill does not apply — formulate and solve once.

Core idea — one solve is one point on a curve

A single optimum encodes **one implicit weighting** of the objectives. Change the weighting and the optimum moves. The frontier is the curve traced by all the non-dominated optima.

A solution **A dominates** B when A is at least as good on every objective and strictly better on one. Dominated solutions are never worth choosing. The **Pareto frontier** is exactly the non-dominated set; the user's job is to pick a point on it, and yours is to show them the whole curve plus where the tradeoff is sharpest.

Do not collapse a multi-objective problem to a single weighted number and report its optimum as "the answer" — that silently makes the tradeoff decision *for* the user. Trace the frontier and let them choose.

Objectives and constraints are interchangeable. A requirement currently treated as fixed — a coverage floor, a fairness cap, a budget — is often a latent objective: its level was assumed, not given. Promoting such a constraint to a parametric ε-constraint and sweeping it reveals a tradeoff you'd otherwise hide, so read a single-objective model's hard constraints as candidate objectives, not just limits — but only when the level was an assumption. A genuinely fixed, non-negotiable limit (a hard budget cap, a regulatory minimum) stays a constraint; don't manufacture a tradeoff that isn't there. Express any promoted quantity linearly so it can serve as an ε-constraint (see `cuopt-numerical-optimization-formulation`).

Step 1 — define the objectives

An informative frontier needs objectives that genuinely conflict: if they don't pull against each other, it collapses to a single point with nothing to trade off. And each objective has to be formulated correctly, since a wrong form, sense, or scale distorts the tradeoff and shifts where the knee falls. Formulate each one with `cuopt-numerical-optimization-formulation` before sweeping.

Step 2 — build a payoff table (anchor each objective)

Solve each objective **on its own** first. For *k* objectives this is *k* solves. Record, for each, the value of every objective at that optimum:

              f1        f2        f3
min f1   →   f1*       f2(at f1*) f3(at f1*)
min f2   →   ...       f2*        ...
min f3   →   ...       ...        f3*

The diagonal (`f1*`, `f2*`, …) is each objective's best achievable value; the off-diagonals give the **range** each objective spans across the others' optima. This table does double duty:

  • It sets the **sweep bounds** for the ε-constraint method (the feasible range of each constrained objective).
  • It supplies the **scales** for normalization — objectives in dollars, percent, and hours can't be weighted meaningfully until divided by their ranges.

If any single-objective solve is already infeasible, stop and fix the model before sweeping — the frontier doesn't exist yet.

Step 3 — choose a scalarization

Weighted sum

Combine the objectives into one and sweep the weights:

minimize  w1·f1(x) + w2·f2(x) + ... ,   for a grid of weight vectors w

Cheap and trivial with any solver. Two limitations to respect:

  • **It only finds points on the convex hull of the frontier.** Concave (non-convex) regions of the frontier are unreachable no matter how you choose weights, and for MILP the reachable points can be sparse with large gaps. A frontier that looks suspiciously linear or has only a few clustered points is the symptom.
  • **Weights are not priorities until the objectives are normalized.** Divide each `f_k` by its payoff-table range first; otherwise the largest-magnitude objective dominates regardless of intent.

ε-constraint (preferred for a complete frontier)

Keep one objective; move the rest to constraints and sweep their right-hand sides:

minimize  f1(x)
subject to  f2(x) ≤ ε2
            f3(x) ≤ ε3
            (original constraints)

Sweep each `ε_k` across the range from the payoff table. Each `(ε2, ε3, …)` combination is a single standard cuOpt solve. This recovers the **full** frontier, including the concave regions weighted-sum cannot reach, which is why it's the default when completeness matters. The cost is more solves (a grid over the constrained objectives) and bookkeeping of the ε values.

ε-constrain *linear* objectives directly. A quadratic objective (e.g. risk `xᵀΣx`)

Read more
Ships withnvidia-skills

Official, NVIDIA-verified Agent Skills for Claude Code, Codex, and other coding agents.

Get the whole plugin