Skip to content
BEST·BOOKS
+ MENU
← Back to AMPL: A Modeling Language for Mathematical Programming

AI Study Notebook AI-generated

Study Guide: AMPL: A Modeling Language for Mathematical Programming

Robert Fourer, David M. Gay and Brian Kernighan

By Best Books

This AI-generated study guide is a reading aid. The source-backed recommendation record and evidence for this book live on the book page.

Key points Not available Flashcards Not available
On this page

AMPL: A Modeling Language for Mathematical Programming — Chapter-by-Chapter Outline

Author: Robert Fourer, David M. Gay, Brian W. Kernighan First published: 1993 (first edition); second edition 2003 Edition covered: Second edition (Thomson Brooks/Cole, 2003; ISBN 0-534-38809-4; 517 + xxi pp.). The second edition added Chapter 10 (Database Access), Chapter 19 (Complementarity Problems), and expanded coverage of solver interactions and scripting relative to the first edition.


Central thesis

Mathematical programming practitioners face a persistent translation problem: optimization problems are naturally conceived in the algebraic notation of textbooks and papers, but solvers require them as dense coefficient matrices with indexed variables and bounds — a representation that is tedious to construct, hard to audit, and fragile when the model changes. This gap has historically made large-scale optimization accessible only to specialists who could write and maintain matrix generators in Fortran or C.

AMPL closes the gap by providing an algebraic modeling language that mirrors the mathematical notation modelers already use. A model written in AMPL looks almost identical to its mathematical statement: sets index variables and parameters; constraints are written as inequalities; objectives are explicit minimize or maximize expressions. The language then handles the mechanical transformation to solver input automatically, and returns results in the same notation.

The book's argument is both practical and principled: AMPL is not merely a convenient interface but a contribution to the design of notation for computational mathematics. By separating model (the algebraic structure) from data (the numerical instance), AMPL enables a single model file to solve problems of any size without modification. By supporting a wide variety of problem classes — linear, network, piecewise-linear, nonlinear, integer, and complementarity — within a single consistent language, AMPL gives modelers a unified environment for the full range of mathematical programming.

How can the precision and economy of algebraic mathematical notation be brought directly to bear on large-scale computational optimization, without passing through an error-prone manual translation step?


Chapter 1 — Production Models: Maximizing Profits

Central question

How can a manufacturer decide how much of each product to make in order to maximize profit subject to limited resources, and how does that question get formulated in AMPL?

Main argument

The two-variable linear program. The chapter opens with the simplest possible production scenario: a steel plant producing two products, bands and coils, at rates of 200 and 140 tons per hour respectively, earning $25 and $30 per ton. With 40 hours of rolling-mill time available, the profit-maximizing decision is not obvious because the more profitable product (coils, at $30/ton) is slower to produce. The authors write down the linear program explicitly: maximize 25XB + 30XC subject to XB/200 + XC/140 ≤ 40 and nonnegativity. The optimal solution — 6,000 tons of bands and 1,400 tons of coils for $192,000 profit — is counterintuitive: it favors the less profitable product because the rolling mill is the binding constraint.

Translating to AMPL. The same problem appears in AMPL. The model file declares a set PROD, a parameter rate indexed over products, a parameter profit indexed over products, a scalar parameter avail, and a variable Make indexed over products. The objective is maximize Total_Profit: sum {p in PROD} profit[p] * Make[p] and the capacity constraint is subject to Time: sum {p in PROD} (1/rate[p]) * Make[p] <= avail. Data is supplied separately. This separation of structure from numbers is introduced here as the governing design principle.

Scaling up: three products and multiple resource constraints. When plate is added as a third product (at 160 tons/hour and $29/ton), the optimal solution shifts to 6,000 bands, 0 coils, and 1,600 plate for $196,400. With additional constraints — market commitments (minimum 500 tons coils), production-stage bottlenecks (reheat furnace at 35 hours/week) — the model grows but the AMPL code changes only in the data file and through adding indexed constraint blocks. The authors demonstrate that adding lower bounds on variables and additional resource constraints requires minor model edits, not rewrites.

Interfaces. The chapter closes with a brief tour of AMPL's interactive session, the solve command, and solver output including reduced costs and dual prices (shadow prices), which quantify how much the objective would improve if a binding constraint were relaxed.

Key ideas

  • The optimal solution to a linear program is often counterintuitive; it lies at a vertex of the feasible polyhedron determined by which constraints are tight, not by which products are most profitable in isolation.
  • The model-data separation principle: AMPL model files encode structure; data files supply numbers. The same model solves instances of any size.
  • Decision variables (var Make {PROD} >= 0) represent unknowns; parameters (param profit {PROD}) represent known data.
  • Reduced costs tell the modeler how much a non-produced product's profitability would need to increase before it enters the optimal solution.
  • Dual prices (marginal values) tell the modeler the per-unit value of relaxing each binding constraint — actionable information for capacity investment.
  • The AMPL sum notation over indexed sets replaces explicit enumeration; the same expression works for two products or two thousand.

Key takeaway

The production problem is a template for the entire book: formulate a real problem algebraically, encode it in AMPL with data separated from structure, solve it, and read economic insights from the dual solution.


Chapter 2 — Diet and Other Input Models: Minimizing Costs

Central question

How can a least-cost combination of inputs be selected to meet a set of minimum requirements, and how does this "input selection" structure generalize across industries?

Main argument

The diet problem. The chapter's running example is the classic diet problem: select amounts of eight foods (beef, chicken, fish, ham, macaroni and cheese, meatloaf, spaghetti, turkey, with unit costs between $1.89 and $3.19) to minimize weekly cost while meeting minimum requirements for four nutrients (vitamins A, B1, B2, C). The LP solution — 46⅔ packages of macaroni and cheese at $88.20 — is nutritionally valid but practically absurd, illustrating the gap between LP feasibility and real-world acceptability.

AMPL formulation. The diet model introduces the cost-minimization template: a set FOOD, a set NUTR, parameters cost, f_min, f_max indexed over foods, parameters n_min, n_max indexed over nutrients, a matrix amt indexed over {NUTR,FOOD}, and variables Buy indexed over foods. The objective minimizes total cost; dietary constraints are n_min[i] <= sum {j in FOOD} amt[i,j]*Buy[j] <= n_max[i]. This double-inequality constraint form is introduced here.

Refinements. Adding upper and lower bounds on each food item and further nutrients (sodium, calories) produces a six-nutrient model with per-food limits. The integer version — requiring whole packages — gives $119.30 from a varied selection. Sensitivity analysis reveals which constraints bind and which foods are close to entering the solution.

Generalizations. The structural pattern — minimize cost of inputs to meet output requirements — applies beyond nutrition: animal feed blending (ingredients must meet protein, fat, fiber specifications), gasoline refining (crude fractions blended to octane and vapor pressure specs), economic input-output models (industries using each other's outputs as inputs), and work scheduling (staff assigned across days to cover daily demand). All share the same constraint matrix structure; only the data changes.

Key ideas

  • The cost-minimization LP has the same algebraic structure as the profit-maximization LP; the two are mathematical duals of each other.
  • Double-inequality constraints (n_min[i] <= expr <= n_max[i]) model requirements that must be met within a range.
  • Continuity and linearity are the assumptions that make LP tractable; where these fail (whole packages, nonlinear yield curves), extensions are required.
  • Sensitivity analysis — reduced costs and dual prices — reveals which nutrient requirements are expensive to meet and which foods are almost competitive.
  • The same AMPL model file solves diet, blending, scheduling, and input-output problems; the model structure is the insight, the data is the application.

Key takeaway

The diet problem is the canonical input-selection LP; its AMPL formulation is a reusable template for any least-cost blending problem across manufacturing, agriculture, and scheduling.


Chapter 3 — Transportation and Assignment Models

Central question

How should goods be shipped from multiple origins to multiple destinations to minimize total cost, and how does this structure generalize to assignment and allocation problems?

Main argument

The transportation LP. The running example ships steel coils from three mills (Gary: 1,400 tons, Cleveland: 2,600 tons, Pittsburgh: 2,900 tons) to seven factories demanding between 900 and 1,700 tons each, totaling 6,900 tons. The objective minimizes total shipping cost; supply constraints bound outflow from each mill; demand constraints require each factory to receive its requirement. The LP has 21 decision variables and 10 constraints (3 supply + 7 demand).

AMPL formulation. The transportation model uses sets ORIG and DEST, parameters supply and demand, a matrix cost indexed over {ORIG,DEST}, and variables Trans indexed over the same. The key AMPL feature introduced is the double-indexed sum in constraints: subject to Supply {i in ORIG}: sum {j in DEST} Trans[i,j] <= supply[i]. This pattern — summing over one index while the other is fixed — appears throughout transportation and assignment problems.

Properties of transportation solutions. The authors explain why transportation problems always yield integer optimal solutions when all supply and demand parameters are integers: the constraint matrix is totally unimodular (each column has exactly one +1, one -1, and zeros elsewhere). This structural property eliminates the need for integer programming in the basic case.

Alternative interpretations. The transportation model extends naturally to: (1) assignment problems, where "flow" represents personnel assignments to offices rather than physical shipments; (2) allocation problems, where the "supply" at each origin and "demand" at each destination represent capacities and requirements of different kinds. The authors show that these reinterpretations require only data changes, not model modifications.

Key ideas

  • Transportation models describe flow from origins to destinations subject to supply and demand balance; the structure is fully captured by a set of origin-destination pairs.
  • Total unimodularity guarantees integer solutions automatically; no integer programming is needed for the basic transportation problem.
  • Multiple optimal solutions often exist in transportation problems because many shipment patterns achieve the same minimum cost.
  • AMPL's double-indexed constraint declaration scales the model automatically: 3 origins and 7 destinations, or 300 and 700, use the same code.
  • The assignment interpretation (people to tasks, machines to jobs) uses the same matrix but with unit supplies and demands.

Key takeaway

Transportation and assignment problems form the second great LP template after production/diet; their totally unimodular structure guarantees integral solutions, making them unusually well-behaved and broadly applicable.


Chapter 4 — Building Larger Models

Central question

How can multiple LP building blocks — production, transportation, multiperiod planning — be combined into integrated large-scale models, and when should such integration be done versus solving problems separately?

Main argument

Multicommodity transportation. The first extension adds a product dimension to transportation: now three products (bands, coils, plate) move from three mills to seven factories, with separate supply and demand for each product and separate per-route-per-product shipping costs. The model indexes the Trans variable over {ORIG,DEST,PROD}, multiplying the number of decision variables to 63. The constraint structure is identical to Chapter 3 but with an additional product index. The authors note that "5 origins, 20 destinations and 10 products give 250 constraints in 1,000 variables" — sizes typical of real distribution planning.

Multiperiod production. The second extension adds time: a four-week planning horizon with weekly availability, per-period revenues, and inventory balance constraints linking periods. The key new constraint type is the inventory balance: Inv[p,t] = Inv[p,t-1] + Make[p,t] - Sell[p,t], where Inv[p,t-1] requires the ordered set feature introduced later in Chapter 5. This constraint links decisions across periods, making the problem genuinely dynamic rather than a sequence of independent weekly LPs.

Integrated production-transportation. The third extension merges production at multiple mills with transportation to multiple factories: each mill produces each product, and each unit produced at a mill can be shipped to any factory at a per-route cost. The full model achieves an objective of 1,392,175, with specific trade-offs between production cost advantages at different mills and transportation cost differences. The authors emphasize that integration is correct only when constraints genuinely link the sub-problems; if no constraint couples production at one mill to shipments from another, the problems should be solved separately.

When not to integrate. The chapter makes an important negative point: merging independent problems into a single LP adds variables and constraints without improving solutions. Only constraints that create actual coupling — shared resources, inventory linking periods, capacity limits on combined flows — justify integration.

Key ideas

  • Multicommodity transportation adds a product index to the basic transportation model; the constraint structure is identical but scaled.
  • Inventory balance constraints Inv[p,t] = Inv[p,t-1] + Make[p,t] - Sell[p,t] link periods in multiperiod models and require ordered set indexing.
  • Dual prices on shared capacity constraints quantify the value of additional capacity for managerial investment decisions.
  • Model integration is justified by coupling constraints, not by organizational convenience; independent sub-problems should remain separate.
  • Nonzero shipment patterns in the solution reveal the cost trade-offs between producing close to demand versus at low-cost production sites.

Key takeaway

Large models are built by indexing existing constraint patterns over additional sets (products, time periods, locations); the decision to integrate sub-models should be driven by whether constraints genuinely couple them.


Chapter 5 — Simple Sets and Indexing

Central question

What are the types of sets AMPL supports, how are they declared and manipulated, and how does indexing over sets make models general-purpose?

Main argument

Set membership types. AMPL sets can contain strings (quoted literals like "bands", "New_York"), numbers (integers or floating-point), or mixtures. String members that contain only alphanumeric characters and periods do not need quotes; numbers that should be treated as strings (like "+1") do. The authors recommend using strings for semantic clarity (product names, city names) and integers for sequence positions (weeks, periods).

Set declaration syntax. The basic declaration set PROD; declares an unordered set whose membership is provided in data. Membership can also be fixed in the model: set PROD = {"bands", "coils", "plate"};, though the authors recommend data-file assignment for reusability. The ordered keyword (set WEEKS ordered;) enables sequence operations.

Set operations. AMPL supports the standard set-theoretic operations: union, inter (intersection), diff (difference), and symdiff (symmetric difference). Numeric sets support interval notation: set YEARS = 1990 .. 2020 by 5 creates a set of every fifth year. These operations enable derived sets to be computed from existing data rather than entered redundantly.

Indexing expressions. The pattern {i in SET: condition} is central to AMPL modeling. It appears in constraints (subject to Diet {i in NUTR}: ...), objectives (sum {j in FOOD} cost[j] * Buy[j]), and display commands. The condition after the colon filters set members, enabling partial summations and conditional constraints without separate set declarations.

Ordered sets. When sets are declared ordered, the functions first(S), last(S), member(k,S), prev(t), next(t), and ord(t) become available. These are essential for multiperiod models where inventory at period t depends on the previous period: if t = first(WEEKS) then inv0[p] else Inv[p,prev(t)].

Key ideas

  • Sets are the structural backbone of AMPL models; indexed variables, parameters, and constraints take their shape from set declarations.
  • Set membership belongs in data files for reusability; the model file should declare only the set's name and type.
  • Set operations (union, inter, diff) derive new sets from existing ones, reducing data entry and keeping sources consistent.
  • The {i in S: condition} pattern combines iteration with filtering in a single expression.
  • Ordered sets enable temporal and sequential reasoning through prev(t) and next(t) without explicit loop counters.
  • Floating-point sets should be avoided because rounding errors accumulate; integer ranges are safer for sequences.

Key takeaway

Sets are the primary abstraction mechanism in AMPL; their operations and indexing patterns determine the generality and compactness of every model.


Chapter 6 — Compound Sets and Indexing

Central question

How does AMPL handle multi-dimensional indexing — pairs, triples, and longer tuples — and how can modelers express sparse relationships efficiently?

Main argument

Ordered pairs and cross products. When a variable or parameter is indexed over two sets simultaneously, the indexing set is a set of ordered pairs. The cross product {ORIG,DEST} contains all origin-destination combinations. But in practice, not all pairs may be valid routes; the set LINKS within {ORIG,DEST} declares a subset of pairs. The within keyword asserts that every element of LINKS is a valid origin-destination pair, which AMPL can check for data consistency.

Slicing. Once a compound set is declared, slices extract one-dimensional subsets. The expression {(i,j) in LINKS} iterates over all pairs; {j in DEST: (i,j) in LINKS} gives all destinations reachable from a fixed origin i. Slicing is how transportation constraints are written: sum {j in DEST: (i,j) in LINKS} Trans[i,j] <= supply[i].

Longer tuples. Multicommodity transportation uses triples {ORIG,DEST,PROD} or compound subsets ROUTES within {ORIG,DEST,PROD}. The indexing logic extends naturally: {(i,j,p) in ROUTES} iterates over valid route-product combinations. Operations (union, intersection, difference) extend to tuple sets with appropriate arity matching.

Indexed collections of sets. Sometimes the natural structure is hierarchical rather than relational: each product has its own set of market areas, leading to set AREA {PROD}. This declares a family of sets, one per product. Indexed set collections suit hierarchical relationships (each node has its own neighbors); compound tuple sets suit symmetric many-to-many relationships (all valid origin-destination pairs).

Key ideas

  • Compound sets of ordered pairs, triples, and longer tuples are the natural data structure for multi-indexed variables and parameters.
  • The within keyword restricts compound sets to valid subsets and enables consistency checking.
  • Slicing extracts one-dimensional subsets from compound sets for use in summations and constraint generation.
  • Left-to-right evaluation of indexing expressions allows earlier indices to constrain later ones in a single pass.
  • Indexed collections of sets (set AREA {PROD}) model hierarchical structures; tuple sets model symmetric many-to-many relationships.
  • Operations on sets of tuples (union, inter, diff, cross product) extend naturally from operations on simple sets.

Key takeaway

Compound sets and tuple indexing are how AMPL captures the multi-dimensional structure of real problems — routing, scheduling, multicommodity flow — without enumerating all combinations explicitly.


Chapter 7 — Parameters and Expressions

Central question

How does AMPL handle the full range of data types and computations needed to define model coefficients, including arithmetic, logic, conditions, and validation?

Main argument

Parameter declarations. A parameter is declared with param name {index} attributes;. Attributes specify type (integer, binary), bounds (>= 0, <= 1), and optionally a default value or computed formula. The index may be any set expression, including compound sets. Parameters serve as the model's connection to external data; they are fixed once data is loaded.

Arithmetic expressions. AMPL supports the standard arithmetic operators (+, -, *, /, ^) with standard precedence. Division by a constant is recognized as linear (multiplying by the inverse); division by a variable makes the expression nonlinear. The sum, prod, min, max iterated operators apply over indexed sets: sum {i in ORIG} supply[i] sums all supplies.

Logical and conditional expressions. Logical operators (and, or, not) and comparisons (<, <=, =, >=, >, <>) produce 0/1 values. The conditional expression if condition then value1 else value2 handles special cases like boundary periods: if t = first(WEEKS) then inv0[p] else Inv[p,prev(t)] selects initial inventory for the first period and the previous period's inventory variable thereafter.

Data validation with check. The check statement asserts conditions that must hold in any valid data instance: check {p in PROD}: sum {i in ORIG} supply[i,p] = sum {j in DEST} demand[j,p] verifies supply-demand balance. Violations are reported as errors before optimization begins, catching common data entry mistakes early.

Computed parameters. A parameter with an = phrase is computed from other parameters rather than read from data: param demand {j in DEST, p in PROD} = share[j] * tot_dem[p] / tot_sh. Computed parameters centralize formulas, improve readability, and reduce the risk of inconsistencies across constraint definitions.

Symbolic and logical parameters. Symbolic parameters store string values (param name symbolic;) for use in conditional expressions and display. Logical parameters store 0/1 values and are useful for flagging whether options are enabled.

Key ideas

  • Parameters encapsulate model data; their declarations specify type, bounds, and optionally computed values, enforcing consistency.
  • The conditional if-then-else expression handles boundary conditions in multiperiod models without special-case code.
  • check statements validate data before solving; failing checks identify data errors that would produce meaningless solutions.
  • Computed parameters centralize derived quantities, avoiding duplicated formulas across multiple constraint definitions.
  • Iterated operators (sum, prod, min, max) over indexed sets are the core of constraint and objective expressions.
  • Symbolic parameters enable semantic rather than numeric indexing (using names rather than codes) for clarity.

Key takeaway

Parameters and expressions are the language's data layer; their validation features (check) and derivation capabilities (computed parameters) reduce modeling errors before any solver is invoked.


Chapter 8 — Linear Programs: Variables, Objectives and Constraints

Central question

What is the complete AMPL syntax for declaring variables, objectives, and constraints in linear programs, and what constitutes a valid linear expression?

Main argument

Variables vs. parameters. Variables are declared with var name {index} attributes; where attributes may include bounds (>= 0, <= market[p]), integer, or binary. Unlike parameters (fixed before solving), variables are the unknowns determined by the optimization algorithm. The bounds in a variable declaration are recognized automatically by solvers as simple bounds, which they handle more efficiently than general constraints.

What makes an expression linear. The chapter gives a precise definition: a linear expression is a sum of terms where each term is either a numeric constant or the product of a numeric constant and a single variable reference. Division of a variable by a constant is linear (it is multiplication by the reciprocal); division by another variable is not. AMPL automatically recognizes whether expressions are linear and reports nonlinear constructs that appear in LP models.

Objectives. An objective is declared as minimize name: expression or maximize name: expression. Only one objective can be active at a time; the objective command selects among multiple declared objectives. The authors explain that objectives can only reference variables and parameters — not set membership — in linear form.

Constraints. Constraints use subject to name {indexing}: expression relation expression, where relation is <=, >=, or =. Double-inequality constraints (lb <= expr <= ub) constrain an expression between bounds. AMPL automatically moves variable terms to the left and constant terms to the right internally; modelers can write constraints in any algebraically equivalent form.

Defined variables. A variable declared with var X = expression is substituted directly rather than sent to the solver as an extra variable, reducing problem size. This is useful for computed quantities needed in multiple places.

Key ideas

  • Variable bounds in declarations are handled as simple bounds by solvers, more efficiently than equivalent general constraints.
  • AMPL's linearity checker identifies nonlinear terms in LP formulations, catching errors before the solver is invoked.
  • Double-inequality constraints model range requirements compactly without splitting into two separate constraints.
  • Multiple objectives can coexist in a model; the objective command activates one for each solve.
  • Defined variables (var X = expr) are substituted away before solving, keeping the problem smaller.
  • AMPL handles algebraic rearrangement internally; modelers can write constraints in the form most natural to read.

Key takeaway

This chapter is the reference for correct LP formulation in AMPL: it establishes what counts as linear, how bounds are most efficiently specified, and how objectives and constraints are formally declared.


Chapter 9 — Specifying Data

Central question

What are the syntactic forms for supplying set membership and parameter values in AMPL data files, and how can large datasets be organized legibly?

Main argument

Data mode and lists. AMPL distinguishes model mode (declarations) from data mode (assignments). The data command initiates data mode. In list format, a set is assigned by listing its members: set PROD := bands coils plate ;. A parameter is assigned by listing member-value pairs: param rate := bands 200 coils 140 plate 160 ;. Combined list format assigns both a set and its associated parameter in one statement.

Table format. For two-dimensional parameters, table format is more readable: columns are destination names, rows are origin names, and entries are the parameter values. A dot (.) marks absent entries in sparse tables. The authors show that the choice between list and table format is purely presentational; both produce the same internal representation.

Templates and wildcards. For compound sets, templates reduce redundancy. The expression (GARY,*) DET LAN STL LAF specifies all GARY-destination pairs at once; [*,*] in a parameter table assigns all index combinations. Templates are particularly valuable for large sparse transportation networks where most origin-destination pairs do not exist.

Default values. The default keyword in a parameter declaration (param cost default 9999) provides a fallback value for unspecified entries, useful when most entries share a value (e.g., very high cost for infeasible routes).

Initial variable values. The let statement and default in variable declarations set starting values for solvers, particularly important for nonlinear programs (Chapter 18) where starting points affect which local optimum is found.

The read command. For data organized as free-form streams (one record per line), the read command provides a loop that reads values sequentially: read T, {t in 1..T} avail[t] <week_data.txt. This accommodates data formats from external systems that do not match AMPL's standard formats.

Key ideas

  • List format suits one-dimensional sets and parameters; table format suits two-dimensional parameters indexed over pairs.
  • Dots in sparse tables mark absent entries; default values cover all unspecified positions.
  • Templates ((ORIG,*), [*,*]) reduce data entry for sets of pairs and multi-dimensional parameters.
  • Multiple data commands can read from different files; AMPL reports errors on duplicate assignments.
  • The read command interfaces AMPL with free-format external data streams.
  • Data format is a presentation choice; all valid formats produce the same internal parameter values.

Key takeaway

AMPL's data syntax offers list, table, and template formats for flexibility and readability; the key discipline is complete, consistent, and non-redundant specification of set membership and parameter values.


Chapter 10 — Database Access

Central question

How can AMPL read from and write to relational databases and spreadsheets, enabling integration with the data management systems where operational data typically resides?

Main argument

The table concept. A relational table in AMPL's sense has columns and rows (records). One or more columns form a key whose values uniquely identify each row — analogous to a database primary key. Non-key columns hold the data values. The table declaration in AMPL maps between this relational structure and AMPL sets and parameters.

Reading from external tables. The read table command populates AMPL sets and parameters from a named external source. The declaration specifies the connection string, the key columns (which populate a set), and the data columns (which populate indexed parameters). For example, a diet data table with columns FOOD, cost, f_min, f_max populates the set FOOD and parameters cost, f_min, f_max in one read operation.

Writing solution results. The write table command exports variable values and computed expressions to external tables after solving. This enables AMPL to feed results directly into downstream reporting or planning systems without manual data transfer.

Database and spreadsheet handlers. AMPL ships with handlers for ODBC-compliant databases (including Microsoft Access, SQL Server, Oracle), Excel spreadsheets, and text/CSV files. The choice of handler is specified in the connection string; the model code is identical regardless of data source.

Data management workflow. The chapter shows a complete workflow: data is entered and maintained in a relational database (with forms for ease of entry), read into AMPL for model building and solving, and results written back to the database for further analysis. This two-way integration makes AMPL suitable for production environments where data changes frequently.

Key ideas

  • The table declaration maps relational keys to AMPL sets and relational columns to indexed parameters.
  • read table and write table handle data transfer; the AMPL model code is independent of the data source.
  • Multiple handlers support ODBC databases, Excel, and CSV; connection strings specify the target.
  • Two-way data flow (read before solving, write after) enables AMPL integration in production data pipelines.
  • Database key constraints correspond to AMPL set membership — each row's key must be a member of the appropriate set.

Key takeaway

Database access transforms AMPL from an interactive modeling tool into an embeddable component of production optimization systems that draw data from enterprise databases and return results to them.


Chapter 11 — Modeling Commands

Central question

What commands does AMPL provide for interactively setting up, solving, modifying, and interrogating optimization problems, and how can the system be driven through a session?

Main argument

The interactive session. AMPL operates at a command prompt, executing each command as it is entered and terminating at semicolons. The workflow is: model diet.mod loads the model file; data diet.dat loads data; solve invokes the solver; display commands examine results. Subsequent model and data commands add to the current problem incrementally.

Options. The option command gets and sets named options that control AMPL's behavior: option solver cplex selects a solver; option display_width 60 sets output formatting; option presolve 0 disables preprocessing. Options accept both numeric and string values and persist for the session.

Modifying data. The let command updates individual parameter values or variable bounds without reloading data: let f_max["CHK"] := 11. The reset data command discards a parameter's current value so it can be reassigned. These commands support sensitivity analysis by allowing rapid re-solution with modified data.

Modifying models. The drop command removes a constraint from the active problem without deleting its declaration: drop Diet_Max["CAL"]. The restore command re-activates it. The fix command forces a variable to a specific value; unfix releases it. The relax_integrality option temporarily removes integrality requirements, solving the LP relaxation.

Presolve awareness. AMPL automatically simplifies problems before sending them to solvers: it deduces tighter variable bounds from constraints, eliminates redundant constraints, and can determine variable values without solving. The presolve option controls aggressiveness (0–10). The chapter warns that integrality relaxation (relax_integrality 1) acts on the pre-presolved problem differently from solver-level integrality relaxation.

Key ideas

  • Interactive AMPL sessions are incremental: model files, data files, and commands accumulate in sequence.
  • The let command modifies individual data values for sensitivity experiments without reloading entire datasets.
  • drop/restore and fix/unfix selectively deactivate constraints or fix variables for scenario analysis.
  • Presolve reduces problem size automatically; its behavior and aggressiveness are configurable via option.
  • The solve_result string reports whether the solver found an optimal solution, infeasibility, unboundedness, or a resource limit.

Key takeaway

AMPL's command layer enables a rapid experimentation workflow: set up a base model, solve it, then iterate by modifying data, dropping constraints, or fixing variables to explore the solution space interactively.


Chapter 12 — Display Commands

Central question

How does AMPL present optimization results, and what commands and options control the format, precision, and selection of displayed information?

Main argument

The display command. The primary output command formats sets, parameters, variables, and expressions in readable tables or lists depending on dimensionality. display Make shows all production variables; display {p in PROD, t in 1..T} revenue[p,t]*Sell[p,t] computes and displays revenue by product and week. AMPL automatically selects between table (many items) and list (few items) formats, and between row-oriented and column-oriented layouts.

Formatting options. display_1col sets the threshold above which output switches from one-column to multi-column format. display_transpose flips table orientation. display_width controls line length. These options allow output to fit within different terminal widths and match downstream reporting formats.

Numeric precision. Two distinct precision concerns arise: display precision (how many digits appear) and solution precision (whether solver rounding artifacts are suppressed). display_precision and display_round control appearance; solution_precision and solution_round round the stored solution values. The display_eps option suppresses very small values (like 6.86647e-18) that arise from floating-point arithmetic.

Qualified names and suffixes. Variable and constraint solution components are accessed through dot-notation suffixes. Variable suffixes: .val (current value), .lb (lower bound), .ub (upper bound), .rc (reduced cost), .slack (distance from bound). Constraint suffixes: .body (current value of the constraint expression), .lb, .ub, .dual (shadow price/dual variable), .slack. These suffixes are available in any AMPL expression.

print and printf. The print command outputs a list of values one per line. The printf command formats output using C-style format strings: printf "Total revenue is $%6.2f.\n", sum {p in PROD, t in 1..T} revenue[p,t]*Sell[p,t] produces a formatted dollar amount. Output can be redirected to files with > filename or appended with >> filename.

Key ideas

  • display automatically adapts format based on data dimensionality; explicit formatting options override defaults.
  • Solver artifacts (tiny nonzero values near zero) require either display_eps suppression or solution_round for clean output.
  • Suffixes (.dual, .rc, .slack) access the full economic interpretation of the solution beyond just optimal variable values.
  • printf with C-format strings enables professional reporting output redirected to files.
  • Ordered sets preserve original data sequence in displays; other sets sort alphanumerically.

Key takeaway

AMPL's display commands expose the full solution — optimal values, reduced costs, dual prices, slacks — in configurable formats that can be redirected to files for downstream reporting.


Chapter 13 — Command Scripts

Central question

How can AMPL commands be organized into scripts that automate sensitivity analyses, loop over parameter values, and generate structured reports?

Main argument

Script execution. The include command reads a file of commands in the current mode. The commands command (which requires a semicolon) is the statement form for use within other structures. model and data are specialized include variants that also switch mode. Scripts can call other scripts, enabling modular organization.

Iteration with for. The for loop iterates commands over a set: for {t in 1..T} { printf "Week %d: ", t; solve; } solves the model for each week and displays results. Nested for loops build two-dimensional reports. Set membership, including computed sets, can drive the iteration.

Conditional looping with repeat. The repeat while condition { ... } and repeat until condition { ... } structures continue looping until a termination condition is met. This is used for iterative methods, parametric analysis, and re-solving with tightened bounds until convergence.

Conditional execution with if-then-else. The if condition then { ... } else { ... } statement executes different command blocks based on solution status, parameter values, or other conditions. This enables error handling (stop if infeasible) and branching (display different tables based on problem type).

String operations. AMPL provides string manipulation for dynamic command generation: the & operator concatenates strings and numbers ("diet" & j & ".dat" produces filenames like diet1.dat); sprintf formats a string; length, substr, match inspect strings; sub and gsub perform pattern substitution. These operations make scripts adaptive to variable numbers of data files or solver configurations.

Debugging. The option single_step 1 setting causes AMPL to pause before each statement, showing what it is about to execute. This single-step mode is the primary debugging mechanism for scripts that produce unexpected results.

Key ideas

  • Scripts automate repetitive tasks: sensitivity analyses over parameter ranges, multi-scenario comparisons, formatted reports.
  • for loops iterate solve-and-display sequences over set members for parametric studies.
  • repeat loops enable iterative re-solving until convergence criteria are met.
  • String concatenation with & builds dynamic filenames and option settings.
  • Single-stepping (option single_step 1) provides interactive debugging without external debuggers.
  • break and continue provide fine-grained loop control within for and repeat structures.

Key takeaway

Command scripts transform AMPL from an interactive query tool into an automated modeling pipeline capable of systematic sensitivity analysis, parametric sweeps, and formatted report generation.


Chapter 14 — Interactions with Solvers

Central question

What happens between issuing solve and receiving results, how does AMPL preprocess problems before passing them to solvers, and how are solver statuses and solution information communicated back?

Main argument

Presolve. Before invoking the solver, AMPL's presolve phase simplifies the problem by: deducing tighter variable bounds from constraints (e.g., if a constraint forces a variable to zero, the variable is fixed and removed); eliminating constraints that are satisfied for all feasible variable values; detecting infeasibility (if deduced bounds become contradictory). The presolve option (0–10) controls aggressiveness; setting it to 0 disables presolve entirely. Presolve can dramatically reduce problem size — particularly for models with many redundant or trivially satisfied constraints.

Solver communication protocol. AMPL writes the presolved problem to a temporary file in a standard format (the .nl format), invokes the solver as a subprocess, and reads back the solution file. This architecture means any solver that reads .nl files and writes standard solution files can be used with AMPL without modification to either.

Retrieving results. After solving, solve_result reports the outcome as a string: "solved" (optimal found), "infeasible" (no feasible solution exists), "unbounded" (objective can be made arbitrarily good), "limit" (time or iteration limit reached), or "failure" (solver error). The solve_result_num parameter provides a numeric code. The current objective value is accessible as _objval.

Basis statuses and warm starts. Linear program solvers maintain basis statuses for variables and constraints. AMPL preserves these statuses across successive solves in a script. When parameters change slightly, the warm start from the previous basis reduces iterations dramatically — from 18–19 cold-start iterations to 0–1 warm-start iterations in the authors' steel production example. The .sstatus suffix accesses the solver basis status; .astatus tracks AMPL's own status (whether a component is active, dropped, or fixed).

Suffixes for solver communication. Solvers can define their own suffixes to pass additional information to AMPL (e.g., infeasibility diagnostics, Lagrange multipliers) or receive information from it (initial values, hints). This extensible suffix mechanism allows solver-specific features without changing AMPL's core syntax.

Key ideas

  • Presolve reduces problem size before solving; its output is what the solver actually receives.
  • The .nl file format is the standard interface between AMPL and all compatible solvers; any solver supporting it works with AMPL.
  • solve_result must be checked in scripts before using solution values; using values from an infeasible or failed solve produces nonsensical results.
  • Basis warm starts reduce re-solve time dramatically in parametric analyses or iterative scripts.
  • Solver-defined suffixes extend AMPL's interface for solver-specific capabilities (branching hints, infeasibility certificates).

Key takeaway

The presolve-transmit-retrieve cycle is AMPL's solver interface: presolve reduces the problem, the .nl format communicates it to any compatible solver, and status codes and suffixes bring results back for inspection and scripting.


Chapter 15 — Network Linear Programs

Central question

When does a linear program have network structure, and what are the advantages — in modeling clarity and solver speed — of declaring that structure explicitly in AMPL?

Main argument

Minimum-cost transshipment. The most general network flow model is the minimum-cost transshipment problem: a graph of nodes and arcs, each arc with a capacity and cost, each node with a supply or demand. The objective minimizes total flow cost; the constraints enforce flow balance at every node (inflow + supply = outflow + demand). Transportation, assignment, and shortest-path problems are all special cases.

Flow balance constraints. At each node, the conservation law holds: sum {(i,j) in LINKS} Flow[i,j] - sum {(j,k) in LINKS} Flow[j,k] = net_supply[j]. For transshipment nodes, net_supply = 0; for supply nodes, it is positive; for demand nodes, negative. This single constraint family, when written in AMPL's algebraic notation, captures all network flow problems.

Specialized network syntax. Alternatively, AMPL allows declaring the network structure directly with node and arc keywords. Each node declaration specifies the net supply; each arc declaration specifies its originating node, destination node, capacity bounds, and cost coefficient. AMPL then generates flow balance constraints automatically. This formulation makes the network structure explicit and enables specialized network simplex solvers.

Solver performance. Network LP solvers exploit the totally unimodular structure of flow balance constraints to solve far faster than general LP solvers. The chapter shows that explicitly declaring network structure allows AMPL to route the problem to such specialized solvers when available.

Other network models. Maximum flow (find the maximum flow from a source to a sink subject to arc capacities), shortest path (find the minimum cost path from source to destination), and bipartite assignment (match elements of two sets at minimum cost) are formulated as special cases by setting supply/demand values and objective coefficients appropriately.

Key ideas

  • All network flow problems share the flow balance constraint structure; their diversity lies only in objective and supply/demand configuration.
  • The totally unimodular constraint matrix guarantees integer optimal solutions when all data is integer.
  • AMPL's node and arc declarations express network structure at a higher level than constraint matrices, improving readability.
  • Specialized network simplex solvers are orders of magnitude faster than general LP solvers on pure network problems.
  • Maximum flow, shortest path, assignment, and transportation are all special transshipment cases.

Key takeaway

Recognizing network structure and using AMPL's explicit node-arc declarations unlocks specialized solvers that are dramatically faster than general LP algorithms on the large-scale flow problems common in logistics and telecommunications.


Chapter 16 — Columnwise Formulations

Central question

When is it more natural and less error-prone to organize a model around variables (columns) rather than constraints (rows), and how does AMPL support this columnwise style?

Main argument

The row-wise default. AMPL's standard style writes constraints first, with each constraint's expression referencing variables. This row-wise organization is natural when constraints have simple structure and many variables — as in production models. But in some problems, each variable (column) affects a fixed small set of constraints, while each constraint spans a large number of variables. For these, columnwise formulation is clearer.

The obj and coeff phrases. AMPL extends variable declarations with obj and coeff phrases that specify contributions to objectives and constraints directly in the variable's declaration. A variable var Shift {s in SCHEDS} >= 0: obj Obj profit[s], coeff {d in DAYS: s in covers[d]} Coverage[d] 1 declares both its profit contribution (to the objective Obj) and its coverage contribution (coefficient 1 in each Coverage[d] constraint it participates in). The constraint declarations use to_come as a placeholder: subject to Coverage {d in DAYS}: to_come >= required[d].

Input-output models. The first example is an industrial input-output model where the output of one activity becomes input to another. The columnwise formulation captures each activity's contributions to multiple balance constraints in one variable declaration, making the input-output coefficients explicit without a separate parameter matrix.

Scheduling models. The second example is a shift-scheduling problem: minimize payroll by assigning workers to feasible weekly schedules, where each schedule covers a subset of days. The set covers[d] for each day d lists which schedules include that day. Columnwise formulation assigns each schedule variable its coverage contributions directly, making it easy to add new schedules.

When to use columnwise style. The authors give guidance: use columnwise when (1) the number of constraints is much smaller than the number of variables, (2) each variable contributes to few constraints, and (3) the contribution pattern is the primary modeling insight. Avoid it when constraints are more natural focal points.

Key ideas

  • Columnwise formulation organizes models around variables rather than constraints, useful when each variable contributes to a small number of constraints.
  • The obj and coeff phrases in variable declarations specify objective and constraint contributions co-located with the variable.
  • to_come marks constraint expressions that accumulate column contributions; AMPL fills them in from variable declarations.
  • Columnwise style simplifies adding new activities or schedules: only a new variable declaration is needed, not constraint edits.
  • The choice between row-wise and columnwise is organizational, not computational; both produce identical LP problems.

Key takeaway

Columnwise formulations are the natural fit for scheduling and input-output models where each new activity (shift, product) has a well-defined contribution pattern across a fixed set of constraints.


Chapter 17 — Piecewise-Linear Programs

Central question

How can costs that vary nonlinearly but in a piecewise-linear manner — such as tiered shipping rates, penalty functions, and inventory costs — be modeled and solved efficiently in AMPL?

Main argument

Piecewise-linear functions. A piecewise-linear (PL) function is defined by a sequence of breakpoints and slopes. Between consecutive breakpoints the function is linear with a given slope; at each breakpoint the slope changes. AMPL's << >> notation expresses these directly in objective or constraint expressions: <<limit1[i,j], limit2[i,j]; rate1[i,j], rate2[i,j], rate3[i,j]>> Trans[i,j] defines a three-piece cost function for each route.

Convexity and LP equivalence. A PL function with nondecreasing slopes (convex) can be minimized exactly using LP, because the optimal solution will naturally "fill" cheaper pieces before using more expensive ones. A PL function with nonincreasing slopes (concave) can be maximized via LP. For these cases, AMPL automatically generates the LP reformulation — auxiliary variables and constraints representing the pieces — without modeler intervention.

Non-convex cases and integer programming. When slopes are not monotone (e.g., a fixed-charge cost that is zero for zero flow and then jumps to a positive intercept before continuing with a per-unit rate), LP is insufficient. AMPL automatically generates a mixed-integer program to handle these cases, with binary variables selecting which piece is active.

Common two- and three-piece terms. The chapter catalogs frequently needed PL forms: two-piece functions for soft constraints (zero cost up to a limit, then a penalty slope); three-piece functions for inventory (holding cost in one direction, shortage cost in the other, with zero cost at zero); absolute value; and threshold activation.

Guidelines. Explicitly declaring PL functions with << >> is always preferable to reformulating them manually with max(), abs(), or conditional expressions, because AMPL generates the most efficient solver representation from the explicit declaration. PL approximation of smooth nonlinear functions works well with 5–12 pieces; beyond that, direct nonlinear methods may be more efficient.

Key ideas

  • Piecewise-linear functions with monotone slopes (convex or concave) are reformulated as LP by AMPL automatically.
  • Non-monotone PL functions require integer programming; AMPL generates the MIP reformulation automatically.
  • The << breakpoints; slopes >> syntax is more efficient than manual reformulations using max() or abs().
  • Common forms (penalty, absolute value, inventory cost) have standard two- or three-piece representations.
  • Indexed breakpoints and slopes (<<limit1[i,j], limit2[i,j]; rate1[i,j], rate2[i,j], rate3[i,j]>>) vary piece thresholds across model instances.

Key takeaway

AMPL's piecewise-linear syntax handles tiered costs and penalties naturally, automatically selecting LP or MIP reformulation based on convexity — provided the modeler uses << >> notation rather than manual conditional expressions.


Chapter 18 — Nonlinear Programs

Central question

How does AMPL handle optimization problems with nonlinear objectives or constraints, what additional considerations arise, and why can't nonlinear solving be as automated as linear solving?

Main argument

Sources of nonlinearity. The authors identify three origins: (1) relaxing linear assumptions that were only approximations (e.g., shipping cost as a nonlinear congestion function rather than a fixed rate); (2) constructing nonlinear functions to capture desired behavior (e.g., a cost function that approaches infinity as capacity is exhausted); (3) modeling inherently nonlinear physical processes (e.g., gas pipeline pressure-flow relationships following Flow² = c² × (Press_i² - Press_j²)).

Variable declarations for nonlinear models. Initial values matter far more in nonlinear than in linear programming. The var X := value form sets a starting point; the solver begins searching from there. Different starting points may reach different local optima, and no general-purpose algorithm can guarantee finding the global optimum. The = expr form defines a variable as a computed expression (substituting it away before solving); the := expr form sets an initial value.

Nonlinear expressions. Any AMPL expression involving variables in a nonlinear combination — product of two variables, division of a variable by another, exponentiation, trigonometric functions — is valid syntax, and AMPL passes it to nonlinear solvers. The authors warn against using discontinuous functions like abs(), min(), and max() applied to variables in constraints; these create non-smooth problems that most nonlinear solvers handle poorly.

Pitfalls. Four major pitfalls are identified: (1) function range violations (division by zero if a denominator variable approaches zero; taking the log of a negative value); (2) multiple local optima with different starting points yielding different solutions; (3) smoothness violations from discontinuous constructs; (4) solver limitations — unlike LP solvers, nonlinear solvers cannot certify global optimality or always find feasibility.

Key ideas

  • Nonlinear programs arise from three sources: linearization failure, deliberate design, and physical reality.
  • Initial variable values (:= value) significantly affect which local optimum a nonlinear solver finds.
  • Smooth nonlinear functions (products, powers, exp, log applied to variables within their valid domains) work reliably; discontinuous functions (piecewise-linear with max, abs) should use the PL syntax from Chapter 17.
  • Nonlinear solvers cannot guarantee global optimality; multiple starting points should be tried for non-convex problems.
  • Range constraints on variables (var X >= 0.01) prevent evaluation errors at singularities.

Key takeaway

Nonlinear programming in AMPL requires modeler judgment that LP does not: initial values, smoothness, and domain constraints must be considered explicitly because no algorithm can fully automate the search for global optima in non-convex problems.


Chapter 19 — Complementarity Problems

Central question

What are complementarity constraints, where do they arise in economics and engineering, and how does AMPL express and solve them?

Main argument

The complementarity condition. A complementarity constraint between two expressions f and g requires: f ≥ 0, g ≥ 0, and f × g = 0. In plain language, at least one of the two expressions must equal zero (they cannot both be strictly positive). This condition naturally models equilibrium: if supply exceeds demand (g > 0), the price must be zero (f = 0); if the price is positive (f > 0), supply must equal demand (g = 0).

AMPL syntax. The complements keyword joins the two sides: subject to Opt_Price {p in PROD}: revenue[p] - cost[p] complements Make[p] >= 0 means either the profit margin is zero or no production occurs (or both). The double-inequality form lb <= expr <= ub complements var covers the case where a variable is bounded and its complementary expression is a constraint.

Economic equilibrium models. The primary application is competitive equilibrium in production economics: prices, quantities, and profits must simultaneously satisfy optimality conditions for producers and market-clearing conditions for consumers. These conditions take the form of complementarity systems — a generalization of LP optimality conditions (KKT conditions) that extends to nonlinear demand functions.

Square problems. A complementarity problem is "square" when the number of variables equals the number of complementarity constraints; square problems are what specialized solvers like PATH handle. AMPL ensures the problem is square by construction when the model is properly formulated.

Nash equilibrium. The chapter notes that Nash equilibrium in game theory is another complementarity application: each player's strategy must be a best response (complementarity between the player's deviation benefit and their current strategy).

Key ideas

  • Complementarity constraints capture equilibrium conditions: either a slack is zero or its complementary variable is zero.
  • Economic equilibrium (prices and quantities) and KKT optimality conditions are naturally expressed as complementarity systems.
  • AMPL's complements keyword replaces the manual encoding of complementarity as products or min-max conditions.
  • Square complementarity problems (equal numbers of variables and constraints) are solved by specialized solvers such as PATH.
  • Nonlinear demand functions create complementarity problems with no equivalent LP form.
  • Suffixes .Lslack and .Rslack access the slack values on each side of a complementarity constraint.

Key takeaway

Complementarity constraints generalize LP optimality conditions to equilibrium modeling; AMPL's complements keyword makes economic and engineering equilibrium models expressible directly without manual KKT reformulation.


Chapter 20 — Integer Linear Programs

Central question

How does requiring variables to take integer values extend the power of LP to handle discrete decisions, and what are the computational costs and formulation strategies that result?

Main argument

Integer and binary variables. Adding the integer keyword to a variable declaration restricts it to whole-number values; binary restricts it to 0 or 1. The diet problem with integer food quantities yields $119.30 (versus $118.06 for the continuous LP), requiring whole packages — a small cost increase for a much more practical solution. The integer keyword requires only one word added to an existing variable declaration.

Binary variables for logical conditions. The real power of integer programming lies in using binary variables to encode logical conditions. A binary variable Use[i,j] indicates whether route (i,j) is active; the constraint sum {p in PROD} Trans[i,j,p] <= limit[i,j] * Use[i,j] links the shipment variables to the activation variable, enabling a fixed charge to apply only when the route is used. Similarly, minimum load requirements (sum {p} Trans[i,j,p] >= minload * Use[i,j]) ensure routes either carry nothing or meet a threshold — the "zero or minimum" structure that LP alone cannot handle.

Cardinality and set-covering constraints. Binary variables encode set covering: sum {j in DEST} Use[i,j] <= maxserve limits the number of destinations each origin serves. These cardinality constraints, combined with activation logic, produce facility location, set covering, and set packing formulations.

Computational hardness. Integer programming is fundamentally harder than LP. The authors report that a transportation problem requiring 41 iterations as an LP may require 280–400+ iterations as an IP. Problem scaling with IP is much worse than with LP; small changes in problem size can multiply solution time dramatically. The book demonstrates this empirically with the multicommodity transportation example.

Formulation criticality. Unlike LP, where alternative formulations of the same problem typically perform similarly, in IP the choice of formulation can change solution time by orders of magnitude. Strategies include: minimizing the number of integer variables, tightening LP relaxation bounds (adding constraints that are implied but tighten the LP), and exploiting special structure (e.g., the totally unimodular property of network constraints).

Key ideas

  • integer and binary keywords transform continuous variables into integer or 0/1 variables; the LP structure is otherwise unchanged.
  • Binary variables encode logical conditions (if-then, either-or, minimum load) that LP cannot represent without them.
  • Fixed-charge formulations link continuous flow variables to binary activation variables through big-M constraints.
  • Integer programming is NP-hard in general; problem size growth quickly renders exact solution impractical.
  • Formulation quality — tightness of LP relaxation — determines whether branch-and-bound finds the optimal solution in reasonable time.
  • Practical guidance: minimize integer variables, tighten bounds, add implied constraints, and verify scalability on small instances before committing to an integer model.

Key takeaway

Integer programming extends LP to handle discrete decisions — fixed charges, logical conditions, cardinality constraints — but at dramatically higher computational cost that requires careful formulation and realistic scalability testing.


The book's overall argument

  1. Chapter 1 (Production Models: Maximizing Profits) — Introduces LP through a concrete steel production example, establishing the model-data separation principle that governs the entire language.
  2. Chapter 2 (Diet and Other Input Models: Minimizing Costs) — Presents the cost-minimization template (the LP dual counterpart to Chapter 1) and shows how a single algebraic structure covers diet, blending, and scheduling.
  3. Chapter 3 (Transportation and Assignment Models) — Introduces the network flow template, explains total unimodularity and guaranteed integer solutions, and shows assignment as a special case.
  4. Chapter 4 (Building Larger Models) — Demonstrates model composition by indexing existing patterns over additional dimensions (products, time, locations), and establishes when sub-models should be integrated.
  5. Chapter 5 (Simple Sets and Indexing) — Provides the formal foundations of AMPL's set system: types, operations, ordered sets, and the {i in S: condition} indexing expression.
  6. Chapter 6 (Compound Sets and Indexing) — Extends set theory to ordered pairs, triples, and tuples for multi-dimensional data, introducing slicing and indexed collections for sparse structures.
  7. Chapter 7 (Parameters and Expressions) — Completes the data layer: parameter declarations, arithmetic and conditional expressions, data validation with check, and computed parameters.
  8. Chapter 8 (Linear Programs: Variables, Objectives and Constraints) — Provides the formal reference for LP formulation in AMPL: what constitutes a linear expression, how bounds are declared, and how multiple objectives are managed.
  9. Chapter 9 (Specifying Data) — Explains all data input formats (list, table, template, default, read) for supplying parameter values to model instances.
  10. Chapter 10 (Database Access) — Shows how table declarations connect AMPL to relational databases and spreadsheets for two-way data exchange in production environments.
  11. Chapter 11 (Modeling Commands) — Covers the interactive command environment: options, incremental model building, data modification (let, reset), and model modification (drop, fix, relax_integrality).
  12. Chapter 12 (Display Commands) — Details result presentation: display, formatting options, precision control, suffixes (.dual, .rc, .slack), and formatted output with printf.
  13. Chapter 13 (Command Scripts) — Enables automation through for, repeat, if-then-else, string operations, and debugging via single-stepping.
  14. Chapter 14 (Interactions with Solvers) — Explains the presolve-transmit-retrieve cycle, the .nl file interface, solve_result status codes, and basis warm starts.
  15. Chapter 15 (Network Linear Programs) — Formalizes network LP as minimum-cost transshipment, introduces node-arc syntax, and explains how specialized network simplex solvers exploit structure.
  16. Chapter 16 (Columnwise Formulations) — Presents the column-organized alternative to row-organized models, suited to scheduling and input-output problems where each variable has a small fixed contribution pattern.
  17. Chapter 17 (Piecewise-Linear Programs) — Covers piecewise-linear cost functions with AMPL's << >> notation, automatic LP/MIP reformulation based on convexity, and guidelines for PL approximation.
  18. Chapter 18 (Nonlinear Programs) — Addresses nonlinear optimization: sources of nonlinearity, initial value sensitivity, smoothness requirements, and the fundamental limits of nonlinear solvers.
  19. Chapter 19 (Complementarity Problems) — Introduces complementarity constraints and their economic equilibrium applications, with AMPL's complements keyword enabling direct formulation.
  20. Chapter 20 (Integer Linear Programs) — Extends LP to discrete decisions using integer and binary variables, explains the computational hardness of IP, and provides formulation strategies for tractability.

Common misunderstandings

Misunderstanding: AMPL is a solver.

AMPL is a modeling language, not an optimizer. It translates human-readable model specifications into the coefficient matrices that solvers require, invokes an external solver, and returns results in the original notation. Solvers (CPLEX, Gurobi, MINOS, PATH, and others) do the mathematical computation; AMPL handles the interface.

Misunderstanding: changing data requires rewriting the model.

The model-data separation principle means data can change completely without touching the model file. A single AMPL model file for a transportation problem solves instances with 3 origins and 7 destinations or 300 origins and 700 destinations — the data file alone changes.

Misunderstanding: LP optimal solutions are always "obvious" or proportional to profits.

The production model in Chapter 1 immediately demonstrates the opposite: the optimal solution favors bands ($25/ton) over coils ($30/ton) because bands are faster to produce. LP optima depend on the entire constraint structure; intuition about unit profitability is frequently wrong.

Misunderstanding: integer programming is just LP with rounding.

Rounding LP solutions to integers often yields infeasible or severely suboptimal integer solutions. Integer programming requires branch-and-bound or similar combinatorial algorithms; the computational cost can be orders of magnitude higher than LP, and good formulation is critical.

Misunderstanding: nonlinear programs are just harder linear programs with the same guarantees.

LP solvers guarantee global optimality; nonlinear solvers in general do not. Different initial values can yield different local optima. The "Pitfalls" section of Chapter 18 documents this explicitly: nonlinear programming requires modeler judgment that LP does not.

Misunderstanding: AMPL's check statements are optional extras.

Data validation with check is a fundamental modeling discipline. Without it, supply-demand imbalances, negative rates, and other data errors silently produce wrong solutions; with it, errors are caught before optimization begins.


Central paradox / key insight

The central paradox of mathematical programming is that the formulations most natural for human understanding — algebraic inequalities written in the notation of mathematics — are the least natural for computation, which requires dense coefficient matrices with indexed rows and columns. For decades this forced a split between modelers (who formulated problems in algebra) and programmers (who translated those formulations into matrix generators). The two communities developed different vocabularies, and errors in translation were common and hard to detect.

AMPL's resolution is to make the algebraic notation itself the computational specification. A model that looks like:

minimize TotalCost: sum {j in FOOD} cost[j] * Buy[j]; subject to Diet {i in NUTR}: nmin[i] <= sum {j in FOOD} amt[i,j] * Buy[j] <= n_max[i];

is simultaneously the human specification and the machine-readable program. The translator — which generates the coefficient matrix — is inside the language, not in a separate program written by a different person. This collapses the modeler-programmer split and eliminates an entire class of translation errors.

The deeper insight is that this approach scales: the same notation that works for a 4-food, 2-nutrient diet problem works for a 10,000-food, 500-nutrient problem because the language's indexed sets and summations generate the coefficient matrix at any size. The modeler's work scales at the rate of conceptual complexity (how many types of constraints), not at the rate of data size (how many rows and columns).


Important concepts

Algebraic modeling language (AML)

A language that expresses optimization models in notation close to standard mathematical algebra, handling the translation to solver-readable coefficient matrices automatically. AMPL is one of several AMLs; GAMS and LINGO are others.

Model-data separation

The design principle that AMPL model files encode only mathematical structure (which sets, parameters, variables, constraints, and objectives exist and how they relate) while data files supply numerical values. A model file is reusable across any instance; a data file is instance-specific.

Set

An unordered collection of elements (strings or numbers) over which variables, parameters, and constraints are indexed. AMPL sets support union, intersection, difference, cross product, and filtering with conditions.

Indexed expression

An expression of the form {i in SET: condition} that iterates over a (possibly filtered) set. Indexed expressions appear in sums, products, constraint declarations, and loop statements.

Parameter

A named, fixed data value indexed over a set. Parameters connect model structure to instance data; they are set in data files and cannot be changed by the solver.

Variable

A named unknown indexed over a set, determined by the optimization algorithm. Variables can have bounds (>= 0, <= market[p]), integrality requirements (integer, binary), or defined values (= expr).

Dual price (shadow price)

The marginal value of relaxing a binding constraint by one unit; it reports how much the objective would improve if the right-hand side were increased by one. Accessed via the .dual suffix on constraints.

Reduced cost

The amount by which a non-basic variable's objective coefficient would need to change before that variable enters the optimal solution. Accessed via the .rc suffix on variables.

Presolve

AMPL's preprocessing phase that simplifies a problem before passing it to a solver, by deducing tighter bounds, eliminating redundant constraints, and detecting infeasibility early.

Totally unimodular matrix

A constraint matrix where every square submatrix has determinant 0, 1, or -1. Transportation and network flow constraint matrices are totally unimodular, guaranteeing integer optimal solutions for integer data without integer programming.

Piecewise-linear function

A function composed of linear segments with different slopes meeting at breakpoints. In AMPL, expressed with << breakpoints; slopes >> variable. Convex PL functions are reformulated as LP; non-convex ones generate MIP formulations.

Complementarity constraint

A constraint of the form f ≥ 0, g ≥ 0, f × g = 0 — at least one expression must equal zero. Models equilibrium conditions in economics (price equals zero if supply exceeds demand) and KKT optimality conditions.

.nl file format

The standard binary/text format AMPL uses to communicate presolved problems to external solvers. Any solver that reads .nl files is compatible with AMPL without modification.

Branch-and-bound

The algorithmic strategy used by integer programming solvers: solve the LP relaxation (removing integrality), branch on a fractional variable by adding constraints forcing it to floor or ceiling, and recursively bound and prune the search tree.


Primary book and edition information

Background and overview

Individual chapter PDFs (official)

Background on algebraic modeling languages

Additional study resources

These are secondary resources and should be used alongside, rather than instead of, the original book.

Send feedback

Optional. We'll only use this if you want a reply.