Skip to main content

ALAMO User Manual

Welcome, Anonymous

ALAMO user manual and installation guide v. 2026.9.10

September 10, 2026

Nick Sahinidis, The Optimization Firm, LLC, http://www.minlp.com.

1 Introduction

The purpose of ALAMO (Automatic Learning of Algebraic MOdels) is to generate algebraic surrogate models of black-box systems for which a simulator or experimental setup is available [5, 6, 32]. Consider a system for which the outputs z are an unknown function f of the system inputs x. The software identifies a function f, i.e., a relationship between the inputs and outputs of the system, that best matches data (pairs of x and corresponding z values) that are collected via simulation or experimentation. ALAMO can:

  • build an algebraic model of a simulation or experimental black-box system;

  • use previously collected data for model building;

  • call a user-specified function (simulator) to collect measurements;

  • enforce response variable bounds, physical limits, and boundary conditions;

  • use a preexisting data set for model testing;

  • output models in simple algebraic form.

The problems addressed by the software have long been studied in the fields of statistics, design of experiments, and machine learning. Whereas existing techniques from this literature can be used to fit data to models, the main challenges addressed by the ALAMO software are in determining where to run the simulations or experiments, what models to fit, and how to determine if the model is accurate and as simple as possible. A distinguishing feature of ALAMO is that it provides models that are accurate yet as simple as possible. Moreover, ALAMO is capable of utilizing theory-driven insights alongside data [6]. The ALAMO models can be used to facilitate subsequent system analysis, optimization, and decision making; applications range from correlation development for heat exchanger design [19] to the identification of chemical reaction networks [33].

1.1 When to use ALAMO

ALAMO is designed for situations in which a small, explicit algebraic expression is the desired end product. This is the case when the surrogate is to be embedded in a subsequent optimization model, when it is to be inspected or interpreted by a domain expert, or when it must be transcribed into a highly efficient control system or simulator. ALAMO is well suited to problems in which

  • data are expensive, so that the number of function evaluations must be kept small;

  • the number of input variables is modest, typically fewer than a few dozen;

  • the functional form is not known in advance but is expected to be sparse in a physically meaningful basis; and

  • known physics, such as bounds, limits, or boundary conditions, should be imposed on the surrogate.

ALAMO is not the right tool for every modeling task. If a well-established mechanistic model already exists, fitting its parameters may be preferable to learning a new functional form. If the goal is prediction accuracy alone and the model will never be optimized or read by a human, a neural network, a Gaussian process, or a gradient-boosted tree may fit the data more closely. If the goal is to optimize a black box directly, without building a model of it first, a derivative-free optimization solver such as BAM [20] is a more direct route; see https://minlp.com/bam-data-driven-optimizer.

1.2 Licensing and software requirements

The code is available for download at http://minlp.com/alamo. The same URL provides information about licensing the software. The software is free for academics, but a license is required to run it. ALAMO is stand-alone software, with no third party dependencies.

1.3 Installation

Install ALAMO and the ALAMO license file in any directory of your choice and add it to your path. On Windows, ALAMO’s installer will take care of these steps for you. On Linux and OSX systems, unzip the ALAMO download and place the files it contains in a directory in your path. Users should not open the license file in an editor as this may invalidate the license in certain operating systems. For all operating systems, make sure that ALAMO and the ALAMO license file are readable by all intended users on your machine.

For a silent (non-interactive) installation on Windows, download the installer and run it as follows from the command line:

    alamo-windows64.exe /SILENT

If an installation log file is additionally desired, it can be generated by the command:

    alamo-windows64.exe /SILENT /LOG=filename

where 𝚏𝚒𝚕𝚎𝚗𝚊𝚖𝚎 is the desired name for the log file. In both cases, Windows will still request permission to run the executable before the silent installer is launched.

2 Quickstart

This section shows a complete ALAMO run from start to finish. The file below is referred to as ‘e1.alm’ and pertains to learning the simple function z=x2. There is one input and one output in the model. The input is restricted between 5 and 5. An initial sampling data set is specified and is comprised of 11 preexisting data points. The user options do not call for adaptive sampling to be used, effectively requesting the best possible model that can be derived from the preexisting data set. Finally, the following functions are permitted in the model: linear, logarithmic, exponential, sine, cosine, and monomials with powers 2 and 3.

! Example 1 with data from z = x^2
ninputs 1
noutputs 1
xmin -5
xmax 5

ndata 11

linfcns 1
logfcns 1
expfcns 1
sinfcns 1
cosfcns 1
monomialpower 2 3

BEGIN_DATA
-5      25
-4      16
-3      9
-2      4
-1      1
0       0
1       1
2       4
3       9
4       16
5       25
END_DATA

To solve this problem, issue the command

    alamo e1.alm

ALAMO reports progress on the screen and writes the same information to the listing file ‘e1.lst’. For this problem, the model z=x2 is recovered exactly. The screen output of this run is reproduced and explained in Section 7.

Several additional examples of ALAMO input files accompany the distributed code. The remainder of this manual describes the algorithms behind these steps (Section 3), the ways in which ALAMO can be invoked (Section 4), the grammar of the input file (Section 5), and the full set of options (Section 6).

3 Algorithms implemented

ALAMO seeks to identify low-complexity surrogate models using a minimal amount of data for a system that is described by a simulator or an experiment. This section describes how it does so. Section 3.1 states the modeling problem and fixes notation. Section 3.2 gives the overall algorithm and maps each of its steps to the options of Section 6. The three components of that algorithm are then treated in turn: the candidate basis set in Section 3.3, model building by best subset selection in Section 3.4, and adaptive sampling in Section 3.5. Constrained regression, which allows theory-driven requirements to be imposed on the response surface, is described in Section 3.6. Section 3.7 summarizes the computational evidence behind these choices, and Section 3.8 points to the primary literature.

A reader who wants only to run the software can skip this section; a reader who wants to understand why a given model came out the way it did, or which option to change when it did not, will find the answer here.

3.1 The modeling problem

Consider a system whose outputs z are an unknown function of its inputs xn, where n is NINPUTS. ALAMO models each output variable separately, so it suffices to describe the treatment of a single output z; when NOUTPUTS exceeds one, the entire procedure of this section is repeated for each output that is not excluded by IGNORE. The data available at any point of the algorithm consist of N measurements

(xi,zi),i=1,,N,

where xi=(xi1,,xin) and zi. These measurements may be supplied by the user (NDATA), generated by sampling a simulator (NSAMPLE), or drawn from a data bank (NBANK), and their number grows as adaptive sampling proceeds.

ALAMO restricts its attention to models that are linear in a set of nonlinear transformations of the inputs. Given a collection of J=|| candidate basis functions Xj:n, the surrogate model has the form

z^(x)=jβjXj(x), (1)

where βj is the regression coefficient of the jth basis function. Writing Xij=Xj(xi) for the design matrix, the ordinary least squares (OLR) estimate of β solves

minβi=1N(zijβjXij)2. (2)

Two properties of (1) are worth emphasizing, because they are what distinguish ALAMO from most surrogate modeling software. First, the model is algebraic and explicit: it can be printed, read, differentiated, and handed to an algebraic optimization solver. Second, the model is a sparse linear combination. The point of the algorithm is not to estimate β over all of , which (2) already does, but to decide which of the βj should be nonzero at all. Denoting by 𝒮 the set of selected basis functions and by p=|𝒮| the model size, ALAMO solves a best subset selection problem

(BS)min𝒮,βΦ(𝒮,β), (3)

where Φ is a goodness-of-fit measure that rewards accuracy and penalizes model size. The choice of Φ is the MODELER option and is discussed in Section 3.4.1.

3.2 Algorithm overview

Surrogate models are constructed using the three-step process shown in Figure 1 [5].

Start Step 0. Initial sampling INITIALIZER, NSAMPLE, NDATA Step 1. Build surrogate model MODELER, SCREENER, SOLVEMIP Step 1b. Constrained regression ZMIN, ZMAX, CRNCUSTOM, NGROUPS Step 2. Adaptive sampling SAMPLER, MAXPOINTS, MINPOINTS Converged?Stop Black-box simulator or data bank SIMULATOR, NBANK YesNoupdate training set
Figure 1: The ALAMO algorithm, with the options that control each step. Step 1b is performed only when constrained regression is requested.

In the first step, an initial design of experiments is generated and the system is measured at these points. In the second step, an algebraic model is built from this initial training set. The model is built using integer optimization techniques to select the best subset from the collection of potential basis functions. In the third step, an adaptive sampling methodology based on derivative-free optimization techniques [25] is used to identify points where the model is inaccurate. Once these points are added to the training set, execution returns to the second step. The process continues until the third step confirms the accuracy of a previously built model, or until MAXITER, MAXTIME, the work-unit budget MAXWORK of Section 6.10, or the tolerances of Section 6.9 stop it.

Two features of this loop are worth stating explicitly. The model-building step and the sampling step are coupled: each new model determines where the next measurements are taken, and each new measurement changes which basis functions are selected. And the loop is designed for the regime in which measurements are expensive, so it spends optimization effort in order to save function evaluations rather than the reverse.

Compared with common techniques such as forward selection or backward elimination, which investigate model sensitivities with respect to one basis function at a time, ALAMO’s best subset selection accounts for the synergistic effects between different basis functions [32]. Before ALAMO, best subset selection was considered too time consuming for realistic data sets; exhaustive enumeration schemes such as leaps-and-bounds [10] scale poorly, and popular implementations are limited to a few dozen candidate regressors. While developing ALAMO, mixed-integer programming formulations were devised that rely on the BARON software [34, 2] to solve these models in realistic computing times for many industrially relevant systems. ALAMO is also unique in that it utilizes derivative-free optimization techniques in its adaptive sampling step, and in its constrained regression feature, which is capable of enforcing theory-driven requirements on the response variable [6].

3.3 The candidate basis set

Everything ALAMO can produce is a subset of what it is offered. The candidate set is therefore the single most consequential input to the algorithm, and the options of Section 6.6 exist to define it.

The simple basis functions are of the categories shown in Table 1. They are chosen from first-principles relationships, physical or engineering insight, or standard statistical fitting functions. The exponents α and the scaling constant γ are supplied by the user; values of α such as ±12,±1,±2,±3,±4 and of γ such as 0.1,1,10 produce either physically reasonable basis functions or common statistical fitting functions.

Category Xj(x) ALAMO option
I Polynomial (xd)α MONOMIALPOWER, LINFCNS
II Multinomial d𝒟𝒟(xd)αd MULTI2POWER, MULTI3POWER, RATIOPOWER
III Exponential and exp(xdγ)α,log(xdγ)α EXPFCNS, LOGFCNS
logarithmic
IV Trigonometric sin(xd),cos(xd) SINFCNS, COSFCNS
V Radial exp(λxxi2) GRBFCNS, RBFPARAM
VI Expected bases from experience or physics NCUSTOMBAS
Table 1: Categories of candidate basis functions and the options that generate them. Category VI functions are supplied verbatim by the user in a BEGIN_CUSTOMBAS section.

The virtue of a diverse candidate set is that it can represent a wide variety of unknown functional forms even when none of its members matches the truth exactly. For example, if z(x)=2x3/2+1 is modeled over x[0,1], a purely quadratic surrogate z^(x)=1.3x20.35x+2 already has an average error of about one percent [5]. Conversely, an over-generous candidate set is expensive: with five levels of α for polynomials and multinomials, pairwise multinomial terms with equal exponents, and γ=1, a two-, four-, and ten-dimensional problem generates 20, 59, and 246 candidate basis functions, respectively [5]. Since the difficulty of (3) grows combinatorially in J, the candidate set should be rich in the directions the physics suggests and thin elsewhere. The EXCLUDE option removes input variables from consideration, and NUMLIMITBASIS removes basis functions that are not numerically well defined over the box defined by XMIN and XMAX, which is what silently eliminates logarithms when an input may be nonpositive.

Custom basis functions deserve particular mention. Any expression the user can write in terms of the XLABELS may be added to , which is how Arrhenius, sigmoidal, and other structured relationships enter the model: the nonlinear parameter inside such a relationship is fixed and plays the role of a hyperparameter, while the coefficient multiplying it is estimated by regression. This is also the mechanism by which a known mechanistic term can be offered to the model alongside the generic bases, so that ALAMO can decide from the data whether it is needed.

3.4 Model building

3.4.1 Overfitting and the fitness metric

Solving (2) over the full candidate set is almost never what a user wants. As the number of active basis functions grows, the empirical error, that is, the discrepancy between the model and the training data, is nonincreasing. The true error, that is, the discrepancy between the model and the system, first falls and then rises as the model begins to describe the noise and the idiosyncrasies of the particular training set. This is the classical bias-variance trade-off sketched in Figure 2.

model size perrorempirical errortrue erroridealunderfittingoverfitting
Figure 2: Empirical and true model error as a function of model size. A fitness metric is a computable surrogate for the true error.

Since the true error cannot be computed without knowing the system, ALAMO optimizes an information criterion, which estimates it from the empirical error and the model size. Let p denote the number of nonzero regression coefficients, J the number of candidate basis functions, and

σ^2=SSROLRN1

an estimate of the residual variance obtained from the full J-term least squares model. The metrics selectable through MODELER are then

BIC =i=1N(ziXiβ)2σ^2+plogN, (4)
Cp =i=1N(ziXiβ)2σ^2+2pN, (5)
AICc =Nlog(1Ni=1N(ziXiβ)2)+2p+2p(p+1)Np1, (6)
HQC =Nlog(1Ni=1N(ziXiβ)2)+2plog(logN), (7)
MSE =i=1N(ziXiβ)2Np1, (8)
RIC =i=1N(ziXiβ)2σ^2+2plogJ, (9)

where Xi denotes the ith row of the design matrix. The two remaining choices are penalized error measures in which the user sets the penalty directly through CONVPEN, denoted here by c:

SSEp =i=1N(ziXiβ)2+cp, (10)
MADp =maxi=1,,N|ziXiβ|+cp. (11)

The metrics were derived from different principles and therefore identify different best subsets: AIC seeks to minimize the Kullback-Leibler divergence between the true distribution and the estimate produced by the candidate model [1], with AICc correcting it for small samples and large basis sets [14]; BIC maximizes the posterior model probability [27]; Cp minimizes the mean squared error of prediction [21]; HQC and RIC penalize size at rates that grow with loglogN and logJ, respectively [11, 9]. All of them account directly for the inclusion of a basis function when quantifying complexity, which is what makes them amenable to mixed-integer formulations.

The functional form of the metric determines how the resulting optimization problem is solved, and this has a pronounced effect on run time. Five of the eight are optimized directly, in a single integer program: (5), (10) and (9) because they are already integer convex quadratic functions of β and of the selection variables, (4) because it is replaced by the convex surrogate (15) of Section 3.4.2, and (11) because measuring the fit by maximum absolute deviation makes the program linear. The remaining three, (6) through (8), cannot be separated from the model size and require the parameterized scheme of Section 3.4.2. AICc carries the correction 2p(p+1)/(Np1) and MSE divides by Np1, so in both the size appears inside the term that depends on the residuals. Table 2 summarizes the correspondence.

MODELER Metric Equation Optimized by
1 BIC (4) direct MIQP
2 Mallow’s Cp (5) direct MIQP
3 AICc (6) cardinality-parameterized MIQP
4 HQC (7) cardinality-parameterized MIQP
5 MSE (8) cardinality-parameterized MIQP
6 SSEp (10) direct MIQP
7 RIC (9) direct MIQP
8 MADp (11) direct MILP
Table 2: Fitness metrics available through MODELER and the class of subproblem each one gives rise to.
3.4.2 Mixed-integer formulations

To turn (3) into a solvable problem, introduce a binary variable yj for each candidate basis function, with yj=1 if Xj is active in the model and yj=0 otherwise. The bilinear products yjβj that would otherwise appear are removed by the big-M constraints

βloyjβjβupyj,j, (12)

which force βj to zero when yj=0 and leave it free within its bounds when yj=1. Valid bounds are obtained by borrowing the logic of the lasso [31]: since the 1 norm of the coefficient vector of any subset model is no larger than that of the full least squares solution,

βup=βlo=j|βjOLR| (13)

is a valid choice. The model size is p=jyj.

Which of the two formulations below is used is decided by the metric, and the division is not the one a reader might guess from convexity alone. For BIC, Mallows’ Cp, SSEp, RIC and MADp, ALAMO poses the problem directly: the cardinality enters as an upper bound rather than an equality, one integer program is solved, and no sweep over the model size is performed. For AICc, HQC and MSE it uses the parameterized formulation, fixing the cardinality to p and sweeping p. Those three are exactly the metrics whose residual term cannot be separated from the model size. AICc carries the correction 2p(p+1)/(Np1) and MSE divides by Np1, so in both the size appears inside the term that depends on the residuals and cannot be moved outside the inner minimization.

The direct formulation is:

(M1)minβ,yFM(β,p)s.t.βloyjβjβupyj,jp=jyjyj{0,1},j, (14)

where FM is the chosen metric and pmax is the size limit of the paragraph below. Formulation (14) considers all 2J possible subsets at once, including the null model. When the cardinality bound is not binding, ALAMO omits the constraint ppmax altogether and hands the solver the unrestricted best subset problem.

Formulation (14) is always posed as a convex program. For Cp, SSEp and RIC the metric is already quadratic in β with a penalty linear in p, so it is written out as it stands. For BIC, whose usual form Nlog(SSE/N)+plogN is not, ALAMO does not hand the logarithm to the solver: the objective it writes is the convex surrogate

SSEσ^2+plogN, (15)

which orders models by the same trade-off without the nonlinearity. For MADp the fit is measured by maximum absolute deviation, so the objective is linear and (14) becomes a mixed-integer linear program. No metric gives rise to a mixed-integer nonlinear program in this step.

CVXBIC governs what happens afterwards, not what the solver is given. With CVXBIC set to 1, ALAMO also evaluates BIC through (15), so that the number it reports and compares across model sizes is the one the integer program minimized. With the default of 0 it evaluates the exact Nlog(SSE/N)+plogN instead, which is the quantity the literature calls BIC and the more meaningful one to report, at the cost of a mild inconsistency between the objective that was optimized and the metric that is displayed.

For AICc, HQC and MSE, ALAMO exploits the observation that the metric can be written as a term that depends on the residuals and a complexity penalty that depends only on p, once p is held fixed. Writing Φ(β,y)=Φβ,y(β,y|p)+Φp(p), the best subset problem becomes a nested minimization in which the outer problem chooses the model size and the inner problem chooses the basis functions and the coefficients for that size:

(M2)minp{1,,pmax}{Φp(p)+minβ,yi=1N(ziXiβ)2s.t.jyj=pβloyjβjβupyj,jyj{0,1},j}. (16)

The inner problem of (16) is a cardinality-constrained mixed-integer quadratic program. Because the outer minimization ranges over a finite and small set, ALAMO solves the inner problem for p=1,2, and stops as soon as the metric stops improving, so that only a handful of subproblems is ever solved. This parameterization is also what makes the intermediate models visible in the output: the model reported for each size is the optimal model of that size, not a by-product of a greedy pass. For the five metrics that use (14) instead, the intermediate models that appear in the output come from the enumeration and heuristic passes of Section 3.4.5 rather than from a sweep of integer programs.

The upper limit pmax is the smaller of N and J when DATALIMITTERMS is 1, further restricted by MAXTERMS. Limiting the number of terms to the number of measurements is not merely a safeguard: with pN the training residuals can be driven to zero and the metrics of Section 3.4.1 cease to be meaningful.

3.4.3 The linear-error formulation

Setting LINEARERROR to 1 replaces the squared error in the objective of the inner problem by the 1 error, which turns the subproblem into a mixed-integer linear program. Basis functions are then selected on linear error while the coefficients are still required to satisfy the stationarity conditions of the least squares problem, so that the reported coefficients remain least squares estimates on the selected subset. Specifically, the objective becomes i=1Nwi with

wizijβjXij,wijβjXijzi,i=1,,N,

and the stationarity condition of (2) with respect to the active coefficients,

βji=1N(zij𝒮βjXij)2i=1NXij(zij𝒮βjXij)= 0,j𝒮, (17)

is imposed through a second family of big-M constraints that activate only for the selected bases:

Uj(1yj)i=1NXij(zijβjXij)Uj(1yj),j, (18)

where Uj bounds the magnitude of the left-hand side over the bounds on β. The result is that active basis functions are chosen on the basis of linear error while the values of the regression parameters are those of a squared-error fit [5]. This formulation is useful on large candidate sets, where mixed-integer linear subproblems are considerably cheaper than quadratic ones; the price is that the subset selected need not be optimal for the squared-error metric.

3.4.4 Screening

When J is large relative to N, it is worth reducing the candidate set before any integer program is solved. SCREENER activates one of two screening methods.

Setting SCREENER to 1 applies the lasso [31], which solves

minβ12zXβ22+λβ1 (19)

and retains those basis functions whose coefficients are driven away from zero. The regularization parameter λ is chosen by NCVF-fold cross validation, with two folds used when fewer than ten measurements are available.

Setting SCREENER to 2 applies sure independence screening [7], which ranks candidate basis functions by the magnitude of their marginal correlation with the response and retains the top

SISmultNlnN

of them. Both methods are heuristics: a basis function that would have appeared in the optimal subset can be screened out, and neither should be used when the candidate set is small enough to be handled directly. What they buy is tractability, and their cost is best assessed by comparing the screened model with the unscreened one on a test set.

3.4.5 The model-building loop

The complete model-building step for one output variable proceeds as follows.

  1. 1.

    Evaluate every candidate basis function at every training point to form the design matrix Xij=Xj(xi), discarding basis functions that are not numerically acceptable over [XMIN,XMAX] when NUMLIMITBASIS is 1.

  2. 2.

    Solve (2) over the full candidate set to obtain βOLR and, from it, the big-M values (13) and the variance estimate σ^2.

  3. 3.

    If SCREENER is nonzero, reduce as described in Section 3.4.4.

  4. 4.

    If BUILDER is 1, run a greedy forward pass that adds one basis function at a time, and if BACKSTEPPER is 1, run a greedy backward pass that starts from the least squares model and removes one basis function at a time. These produce a starting point for the integer program.

  5. 5.

    Sweep the model size p=1,2,,pmax. At each size, if the number of subsets of that size does not exceed ENUM1, enumerate them all and fit each by least squares; otherwise turn the size over to the integer program. Stop and accept the model of size p1 as soon as the metric worsens, or accept the model of size p as soon as the improvement falls below TOLRELMETRIC or TOLABSMETRIC, the mean error falls below TOLMEANERROR, or the sum of squared errors comes within TOLSSE of that of the full least squares model.

  6. 6.

    The integer program is entered only for a size that enumeration declined. For AICc, HQC and MSE it is the inner problem of (16), posed at exactly that size, so the sweep of step 5 continues afterwards. For BIC, Cp, SSEp, RIC and MADp it is (14) with the cardinality bound set to pmax, and the sweep ends there: a single integer program returns the best model of any size up to the limit, so there is nothing left for the remaining sizes to discover. This is why a run using one of those five metrics reports at most one call to the optimizer per output variable, however many sizes the sweep visited before reaching it.

  7. 7.

    If constrained regression is active, refine the model as described in Section 3.6.

  8. 8.

    Report the model. Its coefficients are not re-estimated at this point: they are the ones produced by whichever step selected the model. Enumeration fits every candidate subset as it goes, so the coefficients it reports are already the least squares fit of the selected subset over the full current data set. That fit is the constrained least squares fit of Section 3.6 when constrained regression is active, and the minimum maximum-absolute-deviation fit when the metric is MADp. The integer program optimizes the coefficients jointly with the subset, so its coefficients are likewise already optimal for the subset it returns. A basis function whose coefficient comes back at exactly zero is dropped from the model, so that the reported model size and metric reflect the terms that actually appear.

Two remarks on step 5. First, increasing the number of allowed terms rarely amounts to appending one basis function to the previous model; the activity of several bases usually changes at once, which is exactly the synergistic effect that stepwise procedures cannot see. Second, the choice between enumerating and optimizing is made afresh at every model size, and it is made by counting subsets, not by timing anything: ALAMO enumerates the subsets of size p whenever there are at most ENUM1 of them. ENUM1 defaults to 214 when a greedy builder is enabled and to 218 otherwise. A small problem may therefore be solved to global optimality without the optimizer being called at all, which is what happens in the example of Section 7: with one input variable there are only six candidate basis functions, all six single-term models are enumerated and fitted, one of them reproduces the data exactly, and the sum of squared errors reaches the TOLSSE test before any integer program is posed. The run accordingly reports six ordinary linear regressions and zero optimization problems.

ENUMALL, which is off by default, is a separate and more aggressive control: it enumerates the entire search rather than one size at a time.

The integer programs of this section are solved by the BARON global optimization solver, which is embedded in ALAMO [34], and which relies on polyhedral branch-and-cut [29, 16] and branch-and-reduce [26, 28] techniques together with facilities for exploiting integrality [17]. With SOLVEMIP set to 0 these programs are not solved at all, and the model returned is the best that enumeration and the greedy heuristics of step 4 can find.

3.4.6 Example: a flash drum

The following example is drawn from [5]. Steam density ρ leaving a one-atmosphere flash drum is to be modeled as a function of the heat duty Q added to the drum, over Q[13 000W,40 000W], using an Aspen Plus simulation as the black box. With α{0,±13,±12,±1, ±2,±3} and γ=10 000 W, the candidate set contains thirteen basis functions and the model has the potential functional form

ρ^(Q)=β0+β1Q+β2Q+β3Q2+β4Q2+β5Q3+β6Q3+β7Q+β8Q+β9Q3+β10Q3+β11exp(Q10 000)+β12ln(Q10 000).

At the seventh and final iteration of the algorithm the training set holds nine points. The best one-term model is found by minimizing the squared error and its AICc is recorded. The best two-term model is then chosen from (132)=156 combinations by solving the inner problem of (16) with p=2; since AICc improves, a three-term model is tried, and so on. The criterion continues to improve through five terms and worsens at six, even though the training error still decreases from five to six terms, so the search stops and the five-term model is accepted. Its coefficients are then re-estimated on the full data set of twenty points, giving

ρ^(Q)=62.370.0001Q364.530.0001Q47.81ln(0.0001Q)+3.6591012Q3(6.5761015)Q3.

The whole run required twenty simulations of the flash drum.

3.5 Adaptive sampling

A model built from a fixed data set can be assessed only against that data set. Its empirical error is computable, but its true error is not, and no amount of cross validation on the existing points demonstrates that the problem space has been sampled adequately. ALAMO addresses this by interrogating the black box directly, using the current model to decide where to look. The technique is called error maximization sampling (EMS).

3.5.1 Error maximization sampling

Given the current surrogate z^, ALAMO searches the problem space for the point at which the model disagrees most strongly with the system:

maxxloxxup(z(x)z^(x))2, (20)

where xlo and xup are XMIN and XMAX.

The algebraic form of z^ is known, but that of z is not, so the objective of (20) must itself be treated as a black box and (20) must be solved by derivative-free optimization. ALAMO uses The Optimization Firm’s own implementation of SNOBFIT [15] for this purpose; the SAMPLER option selects it, with random sampling and Faure sequences [8] as the alternatives. Because derivative-free solvers lose effectiveness as dimension grows, sampling is most productive when the number of input variables is modest, which is one reason a large simulation is best disaggregated into blocks before it is modeled.

xzsystem z(x)current model z^(x)maximum errornew sample point
Figure 3: Error maximization sampling. The next measurement is taken where the current model and the system disagree most, rather than where the design space is emptiest.

The information returned by (20) is used twice, as Figure 3 suggests. The maximizer is a point at which a new measurement is likely to improve the next model, and the value at that maximizer is a conservative estimate of the true error of the current model. ALAMO therefore uses the same computation both to improve the model and to decide whether it is good enough to stop.

3.5.2 The sampling loop

One adaptive sampling iteration proceeds as follows.

  1. 1.

    Request MAXPOINTS candidate points from the sampler. Points are drawn from the data bank if NBANK is positive and are otherwise obtained by calling the SIMULATOR.

  2. 2.

    Evaluate the system at these points. If the simulator cannot compute an output at a point it returns PRESET for that output, and consecutive failures are counted against MAXSIM.

  3. 3.

    If fewer than MINPOINTS of the requested points could be evaluated, do not assess convergence; append what was obtained and repeat.

  4. 4.

    If the largest error observed exceeds TOLMAXERROR, append the new points to the training set and return to the model-building step of Section 3.4.

  5. 5.

    Otherwise, the newly sampled points fail to contradict the model. Fix the selected basis functions, re-estimate the coefficients by least squares on the enlarged data set, and terminate.

With the default MAXITER of 1 this loop is never entered and ALAMO builds a single model from the data it was given. This is the appropriate setting when the data are fixed and no simulator exists, and it is why activating adaptive sampling requires setting MAXITER as well as providing a SIMULATOR or a data bank.

It is normal, and not a sign of trouble, for the estimated and maximum errors to increase between the first and second iterations. Early models are built on so few points that EMS has little to work with; as the training set grows, the sampler becomes better at finding the regions in which the model fails, and the error estimate it reports becomes a tighter bound on the truth even as the model itself improves.

3.6 Constrained regression

Data are not the only information a modeler has. Concentrations and absolute pressures are nonnegative, mole fractions sum to one and lie in [0,1], a heat duty is bounded by the corresponding Carnot limit, an entropy is monotone, and a velocity profile vanishes at a wall. Information of this kind is usually available at no cost, and a surrogate that violates it is not merely inaccurate but unphysical, which matters a great deal when the surrogate is subsequently optimized: an optimizer will find and exploit the region in which the model is unphysical. ALAMO’s constrained regression facility enforces such requirements on the response surface over the entire input domain [6].

3.6.1 The semi-infinite problem

Let g(β) denote the loss function of the underlying regression problem, so that the unconstrained problem is minβ𝒜g(β) with 𝒜 the original set of regression constraints. A theory-driven requirement takes the form

Ω(𝒳):={βJ:f[x,z^(x;β)]0,x𝒳}, (21)

where f is a constraint written in the space of the predictors x and the modeled response z^, and 𝒳n is the domain over which it must hold. The constrained regression problem is

(C)minβ𝒜Ω(𝒳)g(β). (22)

Two things about (22) are worth noticing. First, the constraint is expressed in the space of the predictor and response variables rather than in the space of the regression parameters. This is the intuitive space: a modeler knows that a concentration is nonnegative, but rarely knows what that implies about β3. It is also the space in which the constraint is independent of the functional form, which matters here because ALAMO does not fix the functional form in advance. Second, (21) must hold for every x𝒳, that is, at infinitely many points. Problem (22) is therefore a semi-infinite program: finitely many variables, infinitely many constraints [13].

3.6.2 Solution by successive discretization

ALAMO solves (22) by a two-phase method for general semi-infinite programs [24]. In Phase I, it solves a relaxation in which the parametric constraint is enforced only on a finite subset 𝒳l𝒳:

(PI)minβ𝒜Ω(𝒳l)g(β). (23)

In Phase II, it takes the resulting βl and searches the full domain for violations:

(PII)maxx𝒳f(x,z^(x;βl)). (24)

If the maximum violation is nonpositive, βl is feasible and optimal for (22) and the method terminates. Otherwise, the violating points xl are appended, 𝒳l+1=𝒳lxl, and Phase I is repeated.

For linear regression, (23) preserves the structure of the original problem: each discretized constraint is linear in β, so Phase I remains a mixed-integer quadratic program of the kind already solved in Section 3.4.2. Problem (24), in contrast, is generally nonconvex, and a local solution of it proves nothing. ALAMO therefore solves (24) with BARON, which certifies global optimality. Rather than locating only the single worst violation, ALAMO asks BARON for up to CRNVIOL isolated feasible points of

(PIIfeas)maxx𝒳f(x,z^(x;βl))s.t.f(x,z^(x;βl))ϵviol0, (25)

where ϵviol is a small positive number, related to CRTOL, that excludes points which are merely feasible, and where the points returned are required to be isolated, xixiϵisol for every pair, so that near-duplicates are not added. Adding several violated points per round reduces the number of Phase I solutions, which is where most of the work lies. CRNINITIAL seeds 𝒳0 with random points, CRNTRIALS controls the random trial points used per round, and CRMAXITER caps the number of rounds.

3.6.3 A worked example

The mechanism is easiest to see on a fixed functional form. Suppose z=x5 is to be modeled over x[0,1] by z^(x)=β1x+β2x3 from four data points, with the a priori knowledge that the true function is nonnegative on this interval. The constrained regression problem is

minβ1,β2i=14(zi[β1xi+β2xi3])2s.t.β1x+β2x30,x[0,1].

The first Phase I problem has 𝒳0= and therefore reproduces the ordinary least squares model, z^(x)=0.308x+1.30x3. Phase II finds two isolated violating points, x=0.240 and x=0.281, at which the model predicts 0.0560 and 0.0578. Each violating point contributes one linear inequality in β, so the single parametric constraint has been replaced by

0.240β1+0.0138β20,0.281β1+0.0223β20,

and the second Phase I problem returns z^(x)=0.0588x+1.02x3. Phase II finds two further violations, at x=0.120 and x=0.138, adding

0.120β1+0.00173β20,0.138β1+0.00263β20,

after which Phase I returns z^(x)=0.954x3 and Phase II proves that no violation remains. The bound is now guaranteed over the whole interval, not merely at the sampled points.

Figure 4 shows what has happened in the space of the regression parameters. For this model form, the semi-infinite constraint is equivalent to the two conditions β10 and β1+β20, but neither of these is something a modeler would have thought to write down; they were inferred from a statement about the response. This is the general pattern. Intuitive restrictions among predictor and response variables are used to infer nonintuitive relationships between regression parameters.

β1β20feasible regionβ10,β1+β20β1 (least squares)β2βfinal
Figure 4: Constrained regression in the space of the regression parameters, for the example of Section 3.6.3. Successive Phase I solutions move toward the feasible region as violated points are added.
3.6.4 Classes of restriction

Table 3 lists the classes of restriction that arise in practice and the ALAMO mechanism for each.

Class Typical form ALAMO mechanism
Response bounds zloz^(x)zup ZMIN, ZMAX
Individual responses az^(x)+h(x)0 CRNCUSTOM, CUSTOMCON
Multiple responses d(z^1,,z^m)+h(x)0 CUSTOMCON on each response in turn
Response derivatives axz^+h(x)0,
ax2z^+h(x)0
CUSTOMCON
Alternative domains enforcement over 𝒳extrap𝒳 EXTRAPXMIN, EXTRAPXMAX
Boundary conditions enforcement over 𝒳{xi=xi} CUSTOMCON
Basis function groups combinatorial restrictions on y NGROUPS, GROUPS, GROUPCON
Table 3: Classes of theory-driven restriction and the options that implement them.

The simplest class is a bound on the response, which is what ZMIN and ZMAX impose. Nonconstant restrictions are handled identically, the only difference being that h(x) is no longer a constant; these arise from initial and boundary conditions, from mass and energy balances, and from limiting cases. When a simpler system is available that represents a theoretical limit rather than an approximation, that simpler system can be used to bound the surrogate: a Carnot engine bounds a heat duty, and a byproduct-free reaction model bounds a concentration.

Restrictions among several responses, such as a sum-to-one condition on compositions or the ordering z^kz^k of discretized state variables, are more delicate, because in general they require all response models to be regressed simultaneously, whereas ALAMO gains its efficiency by treating outputs independently. Currently, the implementation does not accomodate such constraints.

3.6.5 Safe extrapolation

The enforcement domain need not coincide with the sampled domain. Setting EXTRAPXMIN and EXTRAPXMAX enlarges 𝒳 so that the bounds are certified over a region wider than the one in which data were collected, as sketched in Figure 5. Regression models should not be used for extrapolation, but engineers extrapolate anyway, and a model that is certified to respect physical limits outside the training range is a safer alternative to blind extrapolation. The enforcement domain can equally be contracted, for instance to a face {xi=xi} of the box, which is how Dirichlet, Neumann, and Robin boundary conditions are imposed; equality conditions of this kind are enforced to within a tolerance rather than exactly, so as not to impede the convergence of the optimizer.

zxzloextrapolation zoneextrapolation zonetraining domainsystemconstrained modelunconstrained model
Figure 5: Safe extrapolation. Enforcing bounds over EXTRAPXMIN to EXTRAPXMAX certifies the model’s behavior in a region where no data were collected.
3.6.6 Example: a batch reactor

The following example is drawn from [6]. Two first-order reactions occur in series in a batch reactor,

AkaBkbC,(ka,kb)=(0.473,1.44),[A]0=1,[B]0=[C]0=0,

and the concentration of B is to be modeled as a function of batch time t[0.6,10] from ten training points, with exponentials, logarithms, and powers ±12,±1,±2,±3,±4 available as candidate bases. Physics supplies two bounds: [B] is nonnegative and cannot exceed the initial loading of A. Table 4 compares three runs: unconstrained, constrained over the training domain t[0.6,10], and constrained over the extended domain t[0.1,11].

Method Five-term model [B]^(t) Test error
Unconstrained 0.339logt+2.31/t0.911/t2+0.318/t41.494 0.0856
Constrained 0.175logt+0.885/t0.711/t+0.00395t20.000197t3 0.0118
Extended domain 3.30106expt+0.458t0.280t+0.0180t25.16105t4 0.00155
Table 4: Five-term models for the concentration of B, and their errors on 1000 test points drawn from the training domain. All three models have the same size.

Three points are worth drawing out. The constrained models are no larger than the unconstrained one, so the improvement is not bought with complexity. The constrained models have worse training error, necessarily so, since constraining the feasible region cannot improve the objective, and yet their test error is better by a factor of seven, and by a factor of fifty-five when the enforcement domain is extended. Finally, the restriction changes which basis functions are selected: as the constraint tightens, inverse powers that diverge at small t are deactivated in favor of terms that remain bounded. ALAMO was not told to avoid inverse powers; it inferred that they cannot satisfy the bound.

The same pattern holds outside the training domain, which is where safe extrapolation earns its keep. Over the extrapolation regions t[0.1,0.6] and t[10,11], the test errors of the three models are 0.951, 0.0788, and 0.00717, respectively.

3.7 Computational evidence

The design choices described above have been tested extensively, and the results are worth summarizing, both because they justify the defaults and because they indicate what to expect.

Best subset selection versus alternatives. On a test set of 45 functions built from bases available to every method, the deviation of the surrogate model size from the true model size, TsurrogateTtrue, averaged 0.86 with a standard deviation of 1.69 for ALAMO’s best subset modeler, against 4.62 (5.01) for the lasso and 10.18 (8.26) for ordinary least squares regression [5]. The best subset models are not only smaller; across both of the test sets used in that study they were also the most accurate on independent validation data.

Error maximization sampling versus space-filling designs. On a set of 150 reaction modeling problems, EMS produced a better model than a Latin hypercube design [22] of the same size in 120 of the 150 cases [32]. The number of points EMS required to reach a tolerance of 104 ranged from 14 to 46, with a mean of 21.7 and a median of 21, and 97 percent of the problems converged in fewer than 30 samples. Averaging 21 points, EMS attained a mean R2 on validation data of 0.994, against 0.965 for a fixed Latin hypercube design of 20 points.

Constrained regression. On the same 150 problems, extending the enforcement domain beyond the training range produced the most accurate model on the lower extrapolation region in 117 cases, against 29 for constraints enforced only over the training domain and 9 for the unconstrained models [32]. Within the training domain the ordering reverses, as it must, since the unconstrained problem is a relaxation of the constrained one.

Choice of metric. On benchmarks drawn from the UC Irvine repository, the NIST standard regression database, and the Virtual Library of Simulated Experiments, BIC solved the resulting subproblems more than two orders of magnitude faster than AIC, MSE, and HQC, and produced smaller and more accurate models, on account of its heavier penalty on model size and of the direct mixed-integer quadratic formulation (14) it admits. This is the reason BIC is the default value of MODELER.

3.8 Further reading

The bibliography at the end of this document offers more details of the methodology implemented in ALAMO and demonstrates the advantages of this methodology in comparison to currently utilized approaches, including classical regression and the lasso. The methodology of Sections 3.4 and 3.5 is developed in [5] and reviewed and compared against the machine learning literature in [32]; constrained regression is developed in [6]; a comprehensive treatment, including material that has not appeared elsewhere, is given in [4]; and the transfer of information criteria between related modeling problems is treated in [3]. Parts of the algorithm have been implemented commercially in the gPROMS simulator [23].

4 Running ALAMO

4.1 Running the interactive GUI

The ALAMO GUI allows for a convenient spreadsheet-style input of problem data and algorithmic options, and offers facilities for visualizing the data and results, and saving your work. On all operating systems, Java is required in order to use the ALAMO GUI. Additionally, the user must have write privileges in the directory where the GUI is invoked.

On Windows systems, the installer will create an ALAMO icon on your desktop. Double click at this icon in order to launch ALAMO’s interactive GUI.

On Linux and OSX, the interactive GUI is available in the download directory and named alamogui.jar. To run this, open a terminal and type the following command at the prompt

    java -jar alamogui.jar

On all systems, the GUI allows you to save the model input data in the form of an ALAMO file that can be read later by the GUI. After running ALAMO, the results can be saved in an ALAMO listing file that can also be read later by the GUI to reconstruct the problem inputs and results.

Even if you are not planning to use ALAMO from the command line, you should still plan to quickly read the next subsection and following section as they explain how ALAMO works and what is expected to make it run correctly. Additionally, these sections describe material related to algorithmic options that are available in a very similar format through the GUI.

4.2 Running ALAMO from the command line

As an alternative to using the GUI, users can utilize ALAMO from the command line. ALAMO reads model data and algorithmic options from a text file in a simple format. Even though it is not required, it is strongly recommended that all ALAMO input files have the extension ‘.alm.’ If the input file is named ‘test.alm’ and the ALAMO executable is named ‘alamo,’ issuing the command

    alamo test

or

    alamo test.alm

results in ALAMO parsing test.alm and solving the problem. In addition to screen displays, ALAMO can also provide results in the listing file ‘test.lst’ that is generated during the run. The .lst file is always stored in the execute directory, even when the .alm file is in a different path. During execution, ALAMO creates and utilizes a directory for storing various work files. When calling ALAMO, the user may optionally include a second command line argument in order to specify ALAMO’s working directory:

    alamo test.alm myscratchdir

where ‘myscratchdir’ denotes the name of ALAMO’s scratch directory. If this argument is not specified, ALAMO will create and utilize a directory named ‘almscr’ in the execute directory. If the scratch exists, it is erased in the beginning of the run. At the end of the run, ALAMO will delete its scratch directory.

4.3 Calling ALAMO from a program

In addition to the GUI and the command line, ALAMO can be driven directly from a calling program through a callable library. The library exposes the same functionality as the input file: the caller initializes ALAMO, sets options and data through a collection of set routines, requests a solve, and retrieves the resulting model and statistics through a collection of get routines. No .alm file is involved.

This interface is documented in full, with complete worked examples in C, fixed-form Fortran and Fortran 90, in Section 8.

4.4 Using ALAMO from Python

ALAMO is available to Python users through ALAMOPY (Automatic Learning of Algebraic MOdels PYthon wrapper), which is distributed as part of the IDAES Integrated Platform [18, 30]. ALAMOPY is a wrapper around the ALAMO executable: it writes an input file, invokes ALAMO, and parses the results back into Python objects. A licensed installation of ALAMO is therefore required; ALAMOPY does not include the solver.

The two objects a user interacts with are AlamoTrainer, which trains a surrogate from data, and AlamoSurrogate, which wraps the resulting model so that it can be embedded in a Pyomo [12] flowsheet. A minimal session has the following shape:

from idaes.core.surrogate.alamopy import AlamoTrainer, AlamoSurrogate

trainer = AlamoTrainer(input_labels=[’x1’, ’x2’],
                       output_labels=[’z1’],
                       training_dataframe=data_training)
trainer.config.linfcns = 1
trainer.config.monomialpower = [2, 3]
trainer.config.modeler = 1
success, alm_surr, msg = trainer.train_surrogate()

Options are set as attributes of trainer.config and carry the same names and meanings as the corresponding ALAMO keywords documented in Section 6; 0-1 keywords are given as 0/1 or as True/False, and vector keywords are given as Python lists. Custom basis functions are supplied through trainer.config.custom_basis_functions, which is the ALAMOPY equivalent of the BEGIN_CUSTOMBAS section. The path to the ALAMO executable, the working directory, and the name of the generated .alm file can all be set through trainer.config as well, which is useful when the executable is not on the user’s path. A trained surrogate can be serialized to JSON and reloaded in a different script or notebook.

Because ALAMOPY is maintained by the IDAES project rather than by The Optimization Firm, its option names and calling conventions have changed between IDAES releases and may change again. Users should consult the current IDAES documentation [30] for the authoritative list of supported options and for the mapping between ALAMOPY results and ALAMO output. A Python interface built directly on ALAMO’s callable library (Section 4.3), and therefore free of the overhead of writing and parsing files, is planned for a future release.

5 Input file grammar

The following rules should be followed when preparing an ALAMO input file:

  • The name of the input file should include its exact path location if the file is not present in the execute directory.

  • The name of the input file should not exceed 1000 characters in length.

  • The input is not case sensitive.

  • Most options are entered one per line, in the form of ‘keyword’ followed by ‘value’. Certain vector options are entered in multiple lines, starting with ‘BEGIN_<keyword>’, followed by the vector input, followed by ‘END_<keyword>’.

  • Certain options must appear first in the input file. This requirement is discussed explicitly in option descriptions provided below.

  • With the exception of arguments involving paths, character-valued options should not contain spaces.

  • Blank lines, white space, and lines beginning with *, #, % or ! are skipped. Inline comments that are preceded by #, % or ! are permitted in any line that contains alphanumeric options. Blocks of comment lines are allowed using ‘BEGIN_COMMENT’, followed by the block of comment lines, followed by ‘END_COMMENT’; these comment blocks are entirely ignored by ALAMO.

6 ALAMO data and options specification statements

6.1 Required scalar parameters

The following parameters must be specified in the input file before any vector parameters described below.

Parameter Description
NINPUTS Number of model input variables. NINPUTS must be a positive integer and defines the dimension of the vector x.
NOUTPUTS Number of model output variables. NOUTPUTS must be a positive integer and defines the dimension of the vector z.

6.2 Required vector parameters

The following parameters must be specified in the input file only after the scalar required parameters have already been specified.

Parameter Description
XMIN Row vector specifying minimum values for each of the input variables. This should contain exactly NINPUTS entries that are space delimited.
XMAX Row vector specifying maximum values for each of the input variables. This should contain exactly NINPUTS entries that are space delimited.

XMIN and XMAX do not necessarily correspond to the minimum and maximum values of the data provided by the user to ALAMO. Instead, they should reflect the physically meaningful lower and upper bounds for the input variables. These values are used by ALAMO for scaling purposes as well as for generating samples when no preexisting data set is provided or, in general, when adaptive sampling is done.

6.3 Options you are most likely to change

ALAMO has many options, but a first model rarely requires more than a handful of them. The options that most often determine whether a run succeeds are the following.

  • The basis function flags (LINFCNS, MONOMIALPOWER, MULTI2POWER, LOGFCNS, EXPFCNS, and the rest of Section 6.6). ALAMO can only select from the basis functions it is given. The default set is a constant and linear terms, which is almost never enough.

  • MODELER (Section 6.7), which decides how model error is traded against model size.

  • SOLVEMIP (Section 6.7). With the default value of 0, ALAMO relies on enumeration and heuristics rather than on the embedded optimizer. Set it to 1 to obtain the best subset for the chosen fitness metric on problems that are too large to enumerate; expect higher CPU time.

  • SIMULATOR and MAXITER (Section 6.8), which together activate adaptive sampling. With the default MAXITER of 1, ALAMO builds one model from the data it is given and stops.

  • ZMIN, ZMAX, and the constrained regression options of Section 6.12, if the response is known to obey physical limits.

  • MAXTIME (Section 6.9), whose default of 1000 seconds is often the binding constraint on larger problems.

The remaining options are grouped by function in the subsections that follow. Any option not specified takes the default value listed in the tables. The parser is not case sensitive. For example, output variable labels Z1 and z1 are equivalent. For vector inputs, any items provided in excess of those required will be ignored. For example, if more than NINPUTS XLABELS are provided, the extra labels are ignored.

6.4 Data sets

The options in this section describe the data available to ALAMO: preexisting measurements, points to be sampled before model building begins, points at which predictions are requested, and points reserved for testing.

Option Description Default
NDATA Number of data points in a preexisting data set specified by the user. NDATA must be a nonnegative integer. 0
NBANK If positive, the last NBANK of the NDATA measurements provided by the user will be placed in a data bank from which ALAMO will sample and utilize measurements at will. NDATANBANK measurements will be used first to build an initial model before adaptive sampling explores the NBANK measurements for model building. NBANK must be an integer from 1 to NDATA. Setting NBANK equal to 1 is equivalent to setting it equal to NDATA. 0
NPREDATA Number of data points for which ALAMO will provide predictions to the user. At the end of the run, ALAMO will calculate predictions using its best model at each of the NPREDATA data points. NPREDATA must be a nonnegative integer. 0
NSAMPLE Number of data points to be generated by sampling before any model is built. ALAMO will first sample from any available NBANK points before it calls a simulator for additional samples. NSAMPLE must be a nonnegative integer. If NSAMPLE and NDATANBANK are zero, ALAMO will set NSAMPLE equal to the larger of NINPUTS and MINPOINTS to populate data for building an initial model. 0
NTESTSETS Number of data sets to be used for testing after model generation. Testing of the model will be performed on each data set separately. NTESTSETS must be a nonnegative integer. 0
NTESTDATA Number of preexisting data points in each of the NTESTSETS data sets. These data points are not used to develop the model but only to compute model errors at the test data points. NTESTDATA must be an array of NTESTSETS nonnegative integers. If NTESTDATA is provided and NTESTSETS has not already been specified in the input file, ALAMO will assume that NTESTSETS equals 1. 0 0 0 …
NTESTSAMPLE Number of data points to be sampled and added to each of the NTESTSETS data sets for testing. These data points are not used to develop the model but only to compute model errors at the test data points. NTESTSAMPLE points are sampled randomly and added to the test data sets. The sampling facility requires that the user provides a SIMULATOR. Testing can rely exclusively on preexisting data (through the NTESTDATA option), exclusively on sampled data (through the NTESTSAMPLE option), or on any combination desired by the user. NTESTSAMPLE must be an array of NTESTSETS nonnegative integers. If NTESTSAMPLE is provided and NTESTSETS has not already been specified in the input file, ALAMO will assume that NTESTSETS equals 1. 0 0 0 …

If the parameter NDATA is set, then a data section must follow subsequently in the input file with precisely NDATA rows, one for each data point (pair of x and z values) specified in the following form:

BEGIN_DATA



END_DATA

If the parameter NPREDATA is set, then a data section must follow subsequently in the input file with precisely NPREDATA rows, each containing precisely NINPUTS values, thus corresponding to a point in the x-space, specified in the following form:

BEGIN_XPREDATA



END_XPREDATA

If the parameter NTESTDATA is set, a similar data section must be provided using a similar construct:

BEGIN_TESTDATA



END_TESTDATA

6.5 Variables, labels, and scaling

The options in this section control how input and output variables are named, scaled, and treated during model building.

Option Description Default
XLABELS Row vector of labels to denote the input variables. One per input variable, space separated. Each label can be no more than 128 characters long. All labels must begin with an alphabetical character (A-Z or a-z) and contain only alphanumerical characters (A-Z, a-z, 0-9) or underscores. No label should start with the string ‘alm_’. X1 X2 X3 …
ZLABELS Row vector of labels to denote the output variables. One per output variable, space separated. Each label can be no more than 128 characters long. All labels must begin with an alphabetical character (A-Z or a-z) and contain only alphanumerical characters (A-Z, a-z, 0-9) or underscores. No label should start with the string ‘alm_’. Z1 Z2 Z3 …
XFACTOR Row vector of scaling factors used to scale the input variables. One per input variable, space separated. 1 1 1 …
XSCALING A 0-1 indicator. If 1 and XFACTORS are not provided in the input file, ALAMO sets XFACTORS equal to the range of each input variable. 0
SCALEZ A 0-1 indicator. If 1, outputs are scaled when solving mixed-integer optimization problems; otherwise, they are not scaled. 0
EXCLUDE Row vector of 0/1 flags that specify which input variables, if any, ALAMO should exclude during the model building process. All input variables must be present in the data but ALAMO will not include basis functions that involve input variables for which EXCLUDE equals 1. This feature does not apply to custom basis functions or RBFs. 0 0 0 …
IGNORE Row vector of 0/1 flags that specify which output variables, if any, ALAMO should ignore. All output variables must be present in the data but ALAMO does not model output variables for which IGNORE equals 1. 0 0 0 …
XISINT Row vector of 0/1 flags that specify which input variables, if any, ALAMO should treat as integers. For integer inputs, ALAMO’s sampling will be restricted to integer values. 0 0 0 …
ZISINT Row vector of 0/1 flags that specify which output variables, if any, ALAMO should treat as integers. For integer variables, ALAMO’s model will include the rounding of a function to the nearest integer (equivalent to the nint function in Fortran.) 0 0 0 …
NTRANS A nonnegative integer showing how many of the output variables are to be obtained through transformations of input/output variables. The last NTRANS of the output variables are obtained through algebraic transformations of the input variables and/or the first NOUTPUTSNTRANS output variables; their values should not be provided in any DATA section or calculated by the simulator. 0

Scaling matters more than it may appear. ALAMO’s fitness metrics and its mixed-integer subproblems are formulated in the units of the data, so input variables that differ by many orders of magnitude can distort basis function selection and degrade the numerics of the subproblems. Setting XSCALING to 1 is a safe default when the input ranges are dissimilar; XFACTOR gives explicit control when the ranges alone are not the right scaling.

If the parameter NTRANS is set to a positive entry, NTRANS functions must be provided using the construct:

BEGIN_TRANSFORMS



END_TRANSFORMS

where transformation functions are provided one per line. Line k of a TRANSFORMS section provides an algebraic transformation that determines transformed output k which, in turn, corresponds to output variable NOUTPUTS-NTRANS+k. The parser is not case sensitive and allows for Fortran functional expression in terms of the XLABELS and ZLABELS. For the types of functions supported, see the discussion under BEGIN_CUSTOMBAS above.

6.6 Basis functions

ALAMO builds its model as a linear combination of a subset of a user-specified collection of basis functions, as described in Section 3.3. The options in this section define that collection. A collection that is too small cannot represent the system; a collection that is far larger than the number of available measurements makes the subset selection problem harder and increases the risk of overfitting. A common starting point is linear terms plus a few monomial powers, enriched with pairwise products or logarithms only if the resulting model is not accurate enough.

Option Description Default
LINFCNS A 0-1 indicator. Linear functions are considered as basis functions if 1; otherwise, they are not considered. 1
EXPFCNS A 0-1 indicator. Exponential functions are considered as basis functions if 1; otherwise, they are not considered. 0
LOGFCNS A 0-1 indicator. Logarithmic functions are considered as basis functions if 1; otherwise, they are not considered. Natural logarithms are used. 0
SINFCNS A 0-1 indicator. Sine functions are considered as basis functions if 1; otherwise, they are not considered. The arguments of these functions are assumed in radians. 0
COSFCNS A 0-1 indicator. Cosine functions are considered as basis functions if 1; otherwise, they are not considered. The arguments of these functions are assumed in radians. 0
CONSTANT A 0-1 indicator. A constant will be considered as a basis function if 1; otherwise, it will not be considered. 1
MONO Number of monomial powers to be considered as basis functions. MONO must be a nonnegative integer. 0
MULTI2 Number of powers to be considered for pairwise combinations of basis functions. MULTI2 must be a nonnegative integer. 0
MULTI3 Number of powers to be considered for three variable combinations of basis functions. MULTI3 must be a nonnegative integer. 0
RATIOS Number of ratio combinations of powers to be considered as basis functions. RATIOS must be a nonnegative integer. 0
NCUSTOMBAS Number of user-specified basis functions. NCUSTOMBAS must be a nonnegative integer. If this option is utilized, then a BEGIN_CUSTOMBAS … END_CUSTOMBAS section must be supplied to provide the algebraic expressions of the user-specified basis functions. 0
GRBFCNS A 0-1 indicator. Gaussian radial basis functions centered around the set of the user-specified NDATA points are considered as basis functions if 1; otherwise, they are not considered. These functions are deactivated if constrained regression (Section 6.12) is requested by the user or if their textual representation requires more than 128 characters (in the case of too many input variables and/or data points). 0
RBFPARAM Multiplicative constant used in the Gaussian radial basis functions. 1.0
LINKERNEL A 0-1 indicator. If 1, linear kernel functions centered at the data points are considered as basis functions, the linear counterpart of the Gaussian functions selected by GRBFCNS. 0
MONOLIM Upper limit on the number of monomial basis functions retained. A value of 0, the default, applies no limit. MONOLIM must be a nonnegative integer. 0
MULTI2LIM Upper limit on the number of two-variable multinomial basis functions retained. A value of 0 applies no limit. MULTI2LIM must be a nonnegative integer. 0
MULTI3LIM Upper limit on the number of three-variable multinomial basis functions retained. A value of 0 applies no limit. MULTI3LIM must be a nonnegative integer. 0
RATIOSLIM Upper limit on the number of ratio basis functions retained. A value of 0 applies no limit. RATIOSLIM must be a nonnegative integer. 0
PRBFPOWER Row vector of positive integer powers for polyharmonic spline radial basis functions, centered like the Gaussian ones at the NDATA data points. An odd power q generates rq and an even power generates rqlogr, where r is the distance to the center. The number of powers supplied determines how many such families are generated, so no separate count option is needed. Like the Gaussian functions, these are deactivated when constrained regression is requested. none

The four limit options above cap families whose size grows quickly with the number of input variables. They are applied after the family has been generated, so they bound the size of the candidate set rather than the combinations considered when forming it.

If the parameters MONO, MULTI2, MULTI3, or RATIOS are set, the corresponding powers must also be specified as row vectors of corresponding length in the following way:

Parameter Description
MONOMIALPOWER Row vector of monomial powers considered in basis functions; powers of 0 or 1 are not allowed. If MONO is provided, MONOMIALPOWER must be of length MONO.
MULTI2POWER Row vector of powers to be considered for pairwise combinations in basis functions. If MULTI2 is provided, MULTI2POWER must be of length MULTI2.
MULTI3POWER Row vector of powers to be considered for triplet combinations in basis functions. If MULTI3 is provided, MULTI3POWER must be of length MULTI3.
RATIOPOWER Row vector of powers to be considered for ratios in basis functions. If RATIOS is provided, RATIOPOWER must be of length RATIOS.

The entries of the above vectors must be space separated. As stated above, the user is not obligated to specify the parameters MONO, MULTI2, MULTI3, or RATIOS. If any of the corresponding power options are provided, ALAMO will count them and infer the total number of powers specified by the user.

If the parameter NCUSTOMBAS is set, user-specified basis functions must be provided using the construct:

BEGIN_CUSTOMBAS



END_CUSTOMBAS

where basis functions are provided one per line. The parser is not case sensitive and allows for Fortran functional expression in terms of the XLABELS. The following functions are currently accepted by the parser: addition, subtraction, multiplication, division, power ( and ^), abs, exp, log, log10, sqrt, sinh, cosh, tanh, sin, cos, tan, asin, acos, and atan. Other functions may be expressed in terms of the preceding operators and functions, e.g., min(a,b)=(a+b)/2|ab|/2.

6.7 Model building and selection

The options in this section control how ALAMO chooses a subset of the available basis functions, as described in Section 3.4.

Option Description Default
MODELER Fitness metric to be used for model building [32, 3]; see the discussion following this table. Possible values are 1 through 8, with the following meaning: 1. BIC: Bayesian information criterion [27], 2. Cp: Mallow’s Cp [21], 3. AICc: the corrected Akaike’s information criterion [14], 4. HQC: the Hannan-Quinn information criterion [11], 5. MSE: mean square error, 6. SSEp: the sum of square errors plus a penalty proportional to model size, 7. RIC: the risk inflation criterion [9], and 8. MADp: the maximum absolute deviation plus a penalty proportional to model size. The deviation is expressed as absolute percent deviation from measurements that exceed 103 in magnitude and as an absolute difference for small measurements. 1
CONVPEN When MODELER is set to 6 or 8, a penalty consisting of the sum of square errors (MODELER=6) or the maximum absolute error (MODELER=8) and a term penalizing model size is used for model building. The size of the model is weighted by CONVPEN. If CONVPEN=0, this metric reduces to the classical sum of square errors (MODELER=6) or the maximum absolute deviation (MODELER=8). 0.0
BUILDER A 0-1 indicator. If set to 1, a greedy heuristic builds up a model by adding one variable at a time. This model is used as a starting point for solving an integer programming formulation according to the choice of MODELER. If an optimizer is not available, the heuristic model will be the final model to be returned. 1
BACKSTEPPER A 0-1 indicator. If set to 1, a greedy heuristic builds down a model by starting from the least squares model and removing one variable at a time. 0
SCREENER Screening method used to reduce the number of potential basis functions before optimization of the selected fitness metric. Possible values are 0, 1, and 2, corresponding to no screening, screening with the lasso [31], and sure independence screening [7], respectively. See the discussion following this table. 0
NCVF Number of folds to be used for cross validation by the lasso screener. ALAMO will use a two-fold validation if fewer than 10 data points are available. NCVF must be a nonnegative integer. 5
SISmult This parameter must be non-negative and is used to determine the number of basis functions retained by the SIS screener. The number of basis functions retained equals the floor of SISmultnln(n), where n is the number of measurements available at the current ALAMO iteration. 1
DATALIMITTERMS A 0-1 indicator. If 1, ALAMO will limit the number of terms in the model to be no more than the number of data measurements; otherwise, no limit based on the number of data measurements will be placed. The user may provide an additional limit on the number of terms in the model through the MAXTERMS option. 1
MAXTERMS Row vector of maximum terms allowed in the modeling of output variables. One per output variable, space separated. A 1 signals that no limit is imposed. -1 -1 -1 …
NUMLIMITBASIS A 0-1 indicator. If 1, ALAMO will eliminate basis functions that are not numerically acceptable over the box defined by XMIN and XMAX; for example, log(x) is eliminated if x may be nonpositive. If 0, no such elimination is performed. The user may provide additional limits on the type and number of selected basis functions through the options EXCLUDE and GROUPCON. 1
SOLVEMIP A 0-1 indicator. The BARON optimization solver [34, 2], which is embedded in ALAMO, will be used to solve ALAMO’s MIPs/MIQPs if this option is set to 1; if set to 0, no MIP/MIQP optimizer will be used. 0
LINEARERROR A 0-1 indicator. If 1, a linear objective is used when solving mixed-integer optimization problems; otherwise, a squared error will be employed. 0
MIPOPTCA Absolute convergence tolerance for mixed-integer optimization problems. This must be a nonnegative scalar. 0.05
MIPOPTCR Relative convergence tolerance for mixed-integer optimization problems. This must be a nonnegative scalar. 0.0001

A few remarks on the choices in this table.

Choosing a fitness metric. MODELER determines the trade-off between accuracy and model size; the metrics are defined in Section 3.4.1. BIC (the default) and RIC penalize model size aggressively and are the appropriate choices when the intent is to recover a compact, interpretable expression from limited data; BIC is the more conservative of the two when the number of candidate basis functions is comparable to the number of measurements. AICc and Mallow’s Cp penalize size less heavily and tend to return larger models that fit the training data more closely. HQC sits between BIC and AICc. MSE applies no size penalty at all and will select as many terms as the data permit; it is useful mainly as a reference point. SSEp and MADp with a nonzero CONVPEN allow the penalty to be set directly, and MADp is the right metric when the requirement is a uniform error bound rather than a small average error. When in doubt, build with two or three metrics and compare the resulting expressions on a test set. Note also that BIC, Mallow’s Cp, RIC, and SSEp give rise to subproblems that ALAMO optimizes directly, whereas AICc, HQC, and MSE require the model size to be parameterized and a separate subproblem to be solved for each size; on the benchmarks of Section 3.7 this made BIC more than two orders of magnitude faster than the latter group.

Screening. SCREENER reduces the number of candidate basis functions before the fitness metric is optimized. Screening is worth activating when the candidate set is large relative to the number of measurements, since the cost of the subset selection problem grows quickly with the number of candidates. Screening is a heuristic: it can discard a basis function that would have appeared in the optimal subset, so it should not be used when the candidate set is small enough to handle directly. The two methods are described in Section 3.4.4.

Heuristics and the optimizer. BUILDER and BACKSTEPPER are greedy heuristics that add and remove one basis function at a time. They are inexpensive and provide a starting point for the integer program. SOLVEMIP determines whether that integer program is actually solved. With SOLVEMIP set to 0, ALAMO returns the best model it can find by enumeration and heuristics, which is optimal when the candidate set is small enough to enumerate completely but not otherwise. Setting SOLVEMIP to 1 invokes the embedded BARON solver and is what makes the best subset selection guarantee described in Section 3.4.2 available in practice.

Limiting model size directly. DATALIMITTERMS and MAXTERMS impose hard caps on the number of terms. These are blunter instruments than the fitness metric but are useful when the surrogate must satisfy an external size requirement, for example because it will be embedded in a larger optimization model.

6.8 Adaptive sampling and the simulator

The options in this section govern the third step of the algorithm of Section 3.5, in which ALAMO decides where to collect additional measurements. Adaptive sampling is inactive unless MAXITER differs from 1 and either a SIMULATOR or a data bank (NBANK) is available.

Option Description Default
INITIALIZER Technique to be used for sampling of the NSAMPLE points (or INITIALPOINTS minus (NDATANBANK)) at the beginning of the algorithm. A nonzero value of NSAMPLE directs ALAMO to use sampling according to the value of INITIALIZER and requires the presence of a user-provided SIMULATOR or data set to sample from. Possible INITIALIZER values are: 1 (random); 3 (Faure). INITIALPOINTS is described in Section 11. 1
SAMPLER Technique to be used for adaptive sampling. A value of MAXITER different than 1 directs ALAMO to use adaptive sampling according to the value of SAMPLER and requires the presence of a user-provided SIMULATOR or preexisting data bank to sample from. Possible SAMPLER values are: 1 (random), 2 (SNOBFIT), 3 (Faure). 2
MINPOINTS At any stage of the adaptive sampling process, convergence is assessed only if the sampler or simulator is able to compute the output variables for at least MINPOINTS out of the data points requested by ALAMO. MINPOINTS must be a positive integer. NINPUTS
MAXPOINTS The number of data points requested by ALAMO during an adaptive sampling iteration. MAXPOINTS must be a positive integer at least as large as MINPOINTS. NINPUTS+6
MAXITER Maximum number of ALAMO iterations. Each iteration begins with a model-building step. An adaptive sampling step follows if MAXITER does not equal 1. If MAXITER is set to a number less than or equal to 0, ALAMO will enforce no limit on the number of iterations. 1
SIMULATOR Name of the executable ALAMO calls in order to obtain function evaluations of the black box. If left unspecified, no simulator is called. The executable must be capable of reading the file named by SIMIN and writing the file named by SIMOUT; the format of both files and the conventions ALAMO expects of the simulator are given in Section 6.8.1. The simulator must be in the directory where ALAMO is launched or in the user’s path; alternatively, its complete path must be specified through this option. ‘’ (empty string)
SIMIN Name of input file for the simulator. ALAMO generates this file. input.txt
SIMOUT Name of output file for the simulator. ALAMO expects the simulator to provide this file after each call. output.txt
PRESET A value indicating that the simulator was not able to compute a specific output variable at a specific point. This value must be carefully chosen to be an otherwise not realizable value for the output variables. -111111.
MAXSIM Maximum number of successive simulator failures allowed before we quit. MAXSIM must be a non-negative integer. If MAXSIM equals 0, ALAMO will continue calling the simulator even in the case of repeated failures. 0

The interaction between these options is worth stating explicitly. ALAMO first obtains NSAMPLE initial points using the design specified by INITIALIZER. It then builds a model, and, if MAXITER permits, calls the technique specified by SAMPLER to propose MAXPOINTS new points where the current model is suspected to be inaccurate. These points are drawn from the data bank if one exists and are otherwise requested from the SIMULATOR. If fewer than MINPOINTS of them can be evaluated, convergence is not assessed and the iteration is repeated. The cycle terminates when the model passes the tolerance tests of Section 6.9, when MAXITER iterations have been performed, or when MAXTIME is exhausted.

6.8.1 The simulator protocol

ALAMO communicates with the simulator through two files, named by SIMIN and SIMOUT, in a scratch directory that ALAMO creates for the run.

SIMIN.

ALAMO writes this file before each call. Its first line holds the number of requested data points, k, followed by pid, the process id of the ALAMO process that generated the file. The next k lines each hold one requested point as NINPUTS space-separated reals. A final line holds NOUTPUTS space-separated T/F (true/false) flags indicating which output variables ALAMO is requesting; the simulator may ignore this information or use it to avoid computing outputs whose flag is F.

SIMOUT.

The simulator writes one line per evaluated point: the point itself as NINPUTS space-separated reals, followed by the corresponding NOUTPUTS output values. The number of points returned need not equal k, and the points returned need not be the points requested, which allows a simulator to report measurements taken where the experiment could actually be run. If more than k points are provided, only the first k are used.

Failures.

If the simulation fails or is impossible for particular output variables, the simulator returns partial results and sets the unavailable outputs equal to PRESET. Consecutive failures are counted against MAXSIM. The simulator must not return NaN; codes 42 and 43 of Section 10 result.

Working directory.

ALAMO executes the simulator in the scratch directory it generates during the run, so the simulator must not rely on relative paths to reach other programs or files.

Suspending a run.

The simulator may use pid to halt and resume ALAMO. Under Linux this is done with ‘kill -TSTP pid’ and ‘kill -CONT pid’. Checkpointing can be used to preserve program state if the machine is rebooted while ALAMO waits for the simulator.

6.9 Convergence tolerances and resource limits

Option Description Default
TOLRELMETRIC Relative convergence tolerance for the chosen fitness metric for the modeling of output variables. One per output variable, space separated. Incremental model building will stop if two consecutive iterations do not improve the chosen metric by at least this amount. 1e-6 1e-6 1e-6 …
TOLABSMETRIC Absolute convergence tolerance for the chosen fitness metric for the modeling of output variables. One per output variable, space separated. Incremental model building will stop if two consecutive iterations do not improve the chosen metric by at least this amount. 1e-6 1e-6 1e-6 …
TOLMEANERROR Row vector of convergence tolerances for mean errors in the modeling of output variables. One per output variable, space separated. Incremental model building will stop if TOLMEANERROR, TOLRELMETRIC, or TOLABSMETRIC is satisfied. 0 0 0 …
TOLMAXERROR Absolute tolerance for the adaptive sampling procedure to terminate during the modeling of output variables. One per output variable, space separated. Adaptive sampling will stop if the current model predictions and measurements do not differ in magnitude by more than this amount. 0.05 0.05 0.05 …
TOLSSE Absolute tolerance on sum of square errors (SSE). ALAMO will terminate if it finds a solution whose SSE is within TOLSSE from the SSE of the full least squares problem. 0
MAXTIME Maximum total execution time allowed in seconds. This time includes all steps of the algorithm, including time to read problem, preprocess data, solve optimization subproblems, and print results. A negative value disables the time limit. 1000
MAXWORK Budget on the amount of work ALAMO is allowed to perform, expressed in work units and described in Section 6.10. Fractional values are accepted. A negative value, the default, imposes no limit. Unlike MAXTIME, this budget is machine independent: the same run stopped by the same MAXWORK budget stops at the same place and returns the same model on any machine. Exhausting the budget terminates the run with condition 154. -1

6.10 Work units and reproducibility

MAXTIME bounds a run in seconds, and seconds are not a property of the problem. The same input file stopped by the same MAXTIME on two machines, or on the same machine under different load, will in general stop at different places in the search and return different models. That is a nuisance when a run must be reproduced, and it is unacceptable when results are to be compared across machines or regression-tested.

ALAMO therefore also meters itself in work units, a machine independent measure of how much work has been done. One work unit is 105 OLR-datapoints, and the counter is advanced by the three operations that dominate the cost of model building:

  • an ordinary linear regression over m rows costs m OLR-datapoints;

  • a constrained linear regression over m rows of data and mc rows of discretized constraints costs m+mc;

  • one call to the integer programming solver costs a fixed number of OLR-datapoints, so that the metering does not depend on how long the solver happens to run.

The count depends only on the sequence of operations ALAMO performs, not on how fast the machine performs them. Setting MAXWORK to a nonnegative value therefore makes termination deterministic: the run stops after the same amount of work, at the same point in the search, with the same incumbent model, on any machine and under any load. This is the reproducible counterpart of MAXTIME, and the two may be used together, in which case whichever limit is reached first ends the run.

Every run reports the work units it consumed, whether or not a budget was set, on the line

 Work units consumed   0.66E-03

of the termination summary described in Section 7. A convenient way to choose a budget is to run the problem once without one, read the figure off that line, and set MAXWORK to a fraction or a multiple of it. Fractional budgets are accepted, which matters because the individual figures are often small: the example above consumed less than a thousandth of a work unit.

A run that ends because the budget is exhausted terminates with condition 154, “Work-unit budget (MAXWORK) exhausted”, and reports the best model found up to that point; it is not an error.

6.11 Output control

Option Description Default
PRINT_TO_SCREEN A 0-1 indicator. Output is directed to the screen if this option is set to 1; if set to 0, no output is sent to the screen. 1
PRINT_TO_FILE A 0-1 indicator. Output is directed to the listing file if this option is set to 1; if set to 0, no output is sent to the listing file. 1
FUNFORM A positive integer to specify the format for printing basis functions and models found by ALAMO. Fortran intrinsics used in custom basis functions are retained in Fortran format; all other functions are translated based on the value of FUNFORM. Possible values are 1 through 6, with the following meaning: 1. FORTRAN format 2. GAMS format 3. BARON format 4. C format 5. Excel format 6. Python format Note that a large number of digits may be printed in all of these formats. In order to avoid problems reading these strings into GAMS, the GAMS $offdigit option can be used in the user’s GAMS file. 5
TRACE A 0-1 indicator. If set to 1, a trace file is generated at the end of the run, including a succinct summary of the results. First, a header line beginning with a # is printed describing the contents of each line of the trace file. Then, for each output, results are printed in one line for each data set. Data sets are marked by the numbers 0 (observed data set), -1 (user-provided test data set), and 1, …, NTESTSETS (ALAMO-generated test sets). 0
TRACEFNAME Name of trace file. Summaries are appended to an existing trace file; see Section 7.3. trace.trc

In deciding whether to deactivate printing to the screen or file, users should consider that model coefficients are printed with two significant digits to the screen and with 23 digits to the listing file.

The contents of the listing file and of the trace file are described in Sections 7.2 and 7.3, respectively.

6.12 Constrained regression

This section describes ALAMO’s constrained regression capabilities [6]; the underlying algorithm is described in Section 3.6. There are two distinct constrained regression capabilities implemented currently in ALAMO:

  • The ability to enforce constraints, such as bounds, on the response function.

  • The ability to enforce combinatorial constraints on the types of basis functions utilized, including constraints on groups of basis functions.

The primary options that control application of constrained regression to ALAMO’s response function are:

Parameter Description
ZMIN Minimum values for output variables. One per output variable, space separated. If this vector is specified, the corresponding lower bounds on output variables are enforced.
ZMAX Maximum values for output variables. One per output variable, space separated. If this vector is specified, the corresponding upper bounds on output variables are enforced.
EXTRAPXMIN Minimum values for safe extrapolation region. One per input variable, space separated. If this vector is specified, ZMIN and ZMAX are enforced over EXTRAPXMIN to (EXTRAP)XMAX; otherwise, they are enforced over XMIN to (EXTRAP)XMAX.
EXTRAPXMAX Maximum values for safe extrapolation region. One per input variable, space separated. If this vector is specified, ZMIN and ZMAX are enforced over (EXTRAP)XMIN to EXTRAPXMAX; otherwise, they are enforced over (EXTRAP)XMIN to XMAX.
PRINTEXTRAP A 0/1 flag to signal printing of ALAMO’s predictions in the extrapolation region. By default, PRINTEXTRAP is set to 0. If set to 1, ALAMO will report predicted values at points within the region between EXTRAPXMIN to EXTRAPXMAX. The reported points will be generated randomly with approximately the same density as that of input points within XMIN to XMAX that were used by ALAMO for model determination (these points include points in the user-specified preexisting data set and ALAMO-selected simulation set).

Custom constrained regression, i.e., constrained regression for enforcing conditions other than simple bounds, can be done by setting the option CRNCUSTOM:

Option Description Default
CRNCUSTOM Number of custom constraints (other than bounds). CRNCUSTOM must be a nonnegative integer. 0

If CRNCUSTOM is specified, the custom constraints themselves are described through a related section:

BEGIN_CUSTOMCON



END_CUSTOMCON

where, in each of CRNCUSTOM lines of this section, one would need to specify the output variable index j associated with a custom constraint, followed by white space, followed by a function g(x,z) expressed in terms of a Fortran expression of input and output variable labels. ALAMO will then enforce the constraint g0 when building a model for output variable j. This feature supports nonlinear expressions in g that include multiplication, division, powers, and exponentials.

The following are algorithmic options that control implementation aspects of the above constrained regression features. These options may be optionally set as follows:

Option Description Default
CRTOL Tolerance within which custom constraints must be satisfied. CRTOL must be a real that is no smaller than 1e-5. Bound and custom constraints will be satisfied within an absolute tolerance equal to CRTOL. 1e-3
CRNINITIAL Number of random bounding points at which constraints are sampled initially. CRNINITIAL must be a nonnegative integer. 0
CRMAXITER Maximum allowed constrained regression iterations. Constraints are enforced on additional points during each iteration. CRMAXITER must be a nonnegative integer; 0 enforces the constraints only on the initial point set. 10
CRNVIOL Number of bounding points added per round per constraint (bound or custom) in each iteration. CRNVIOL must be a positive integer. 2*NINPUTS
CRNTRIALS Number of random trial bounding points per round of constrained regression. CRNTRIALS must be a nonnegative integer. 100
CRISOLTOL Isolation tolerance for the bounding points added in each round. Two points are considered distinct only if they differ by at least CRISOLTOL in the infinity norm, which prevents a round from adding several near-duplicates of the same violation. This is the ϵisol of Section 3.6.2. CRISOLTOL must be a real no smaller than 1e-6. 0.1
CRCORNER If 1, the corners of the box [XMIN, XMAX] are included in the initial set of bounding points, so that constraints are enforced at the extremes of the domain from the first round. 1
CRROBUST If 1, the search for constraint violations is carried out by the global optimizer, which certifies that a model reported as feasible has no violation anywhere in the domain. If 0, the search is limited to the sampled trial points and no such certificate is obtained. 1

In addition to imposing constraints on the response surface it produces, ALAMO has the ability to enforce constraints on groups of selected basis functions. This can be accomplished through ALAMO’s NGROUPS option:

Option Description Default
NGROUPS Number of groups that must be constrained. NGROUPS must be a nonnegative integer. 0

If a positive NGROUPS is specified, the groups themselves must be specified through a related section:

BEGIN_GROUPS



END_GROUPS

where, in each line of this section, one would need to specify information of the form

Group-id Member-type Member-indices <Powers>

In this construct, each group is uniquely associated with a Group-id ranging from 1 to NGROUPS. Each line must contain three required parameters (Group-id, Member-type, Member-indices); the fourth parameter (Powers) is required only in the context of basis functions that involve powers. The syntax of this section must obey the following rules:

  • Each line pertains to a single group.

  • A group may be described over several lines, with each line restricted to describing a single type of component of the group.

  • Group-id is a nonnegative integer between 1 and NGROUPS that denotes the numerical id (index) of a group described (at least partly) in a line.

  • Member-type is an attribute for the member(s) of the group described in the specific line and can take any one of the values LIN, LOG, EXP, SIN, COS, MONO, MULTI2, MULTI3, RATIO, RBF, CUST, and CONST corresponding to different types of basis functions. In addition, Member-type may be set equal to GRP if it is desired to specify a group of groups.

  • Member-indices is used to specify the composition of a group in terms of indices of input variables and groups. The keyword CONST should not be followed by any Member-indices (as there is only one constant in the model). The keywords MONO, EXP, LOG, SIN and COS must be followed by exactly one index that has a value between 1 and NINPUTS corresponding to the input variable involved in the basis function; alternatively, a value of 1 may be used to denote that all input variables should be considered (with a specific power in the case of MONO). The keywords MULTI2, MULTI3 and RATIO must be followed by two, three, and two indices, respectively, indicating the input variables involved in the corresponding basis function; alternatively, an index of 1 may be used to denote that all possible input variable combinations in any of these basis functions should be considered. The keyword LIN may be followed by as many as NINPUTS Member-indices and specifies which linear terms of the model are included in the group; alternatively, an index of 1 may be used to denote that all possible linear terms are included in the group. Similarly, the keywords CUST and RBF may be followed by as many as NCUSTOMBAS and NDATA Member-indices and an index of 1 may be used to denote all possible custom basis functions and RBFs in a group. As many as NGROUPS1 indices may follow the keyword GRP in order to specify which groups form a group.

  • When Member-type is one of MONO, MULTI2, MULTI3, or RATIO, in addition to Member-indices, the input line must specify the power(s) involved in the group; if power equals 1111, all powers are considered.

  • Membership in a group is non-exclusive; a basis function or group may belong to multiple groups.

Once the number of groups has been specified and each group has been described through the GROUPS construct, group constraints can be specified through the GROUPCON section:

BEGIN_GROUPCON



END_GROUPCON

ALAMO permits different group constraints to be imposed on different output variables. Each line of the GROUPCON section is dedicated to a group-output variable combination and has the following information:

Group-id Output-id Constraint-type Integer-parameter

The rules for completing this section are as follows:

  • Each line describes a single group constraint.

  • Group-id is a nonnegative integer between 1 and NGROUPS that denotes the numerical id (index) of the primary (and sometimes only) group involved in the constraint.

  • Output-id is a nonnegative integer between 1 and NOUTPUTS for which the constraint will be imposed; a value of 1 can be used in this entry to denote that the constraint should be enforced for all output variables.

  • Constraint-type is a string descriptor that can take any one of the following values:

    • NMT: to denote a no-more-than constraint, i.e., require that no more than Integer-parameter members of this group should be selected in the model.

    • ATL: to denote an at-least constraint, i.e., require that at least Integer-parameter members of this group should be selected in the model.

    • REQ: to require that, if the primary group is selected, then the group with id equal to Integer-parameter should also be selected.

    • XCL: to require that, if the primary group is selected, then the group with id equal to Integer-parameter should not be selected.

  • A group may appear in more than one constraint. This flexibility coupled with the fact that input variables and groups may belong to multiple groups allows us to enforce sparsity constraints on model attributes within groups, between groups, and groups organized in clusters, trees, or any other structure.

7 ALAMO output

7.1 ALAMO screen output

The screen output below is obtained for problem e1.alm.

 ***************************************************************************
 ALAMO version 2026.9.10. Built: WIN-64 2026-09-10 18:09:46

 ALAMO is a product of The Optimization Firm. For more information and
 related optimization and data analytics products visit https://minlp.com.

 If you use this software, please cite:
 Cozad, A., N. V. Sahinidis and D. C. Miller,
 Automatic Learning of Algebraic Models for Optimization,
 AIChE Journal, 60, 2211-2227, 2014.

 ALAMO is powered by the BARON software from http://www.minlp.com/.
 ***************************************************************************
 Reading input data
 Licensee: Nick Sahinidis at The Optimization Firm, LLC, niksah@minlp.com.
 ***************************************************************************
 Checking input consistency and initializing data structures
 Warning: eliminating basis log(X1)

 Step 0: Initializing data set
 User provided an initial data set of 11 data points
 We will sample no more data points at this stage
 ***************************************************************************
 Iteration 1 (Approx. elapsed time 0.31E-01 s)

 Step 1: Model building using BIC

 Model building for variable Z
 ----
 BIC = -0.100E+31 with Z = X1^2

 Calculating quality metrics

 Quality metrics for output Z
 ----------------------------
 SSE OLR:           0.00
 SSE:               0.00
 RMSE:              0.00
 R2:                1.00
 R2 adjusted:       1.00
 Model size:        1
 BIC:               -0.100E+31
 Cp:                -9.00
 AICc:              -0.100E+31
 HQC:               -0.100E+31
 MSE:               0.00
 SSEp:              0.00
 RIC:               3.89
 MAD:               0.00

 Work units consumed   0.66E-03
 Total execution time 0.31E-01 s
 Times breakdown
     OLR time:        0.0 s in 6 ordinary linear regression problems
     MINLP time:      0.0 s in 0 optimization problems
     Simulation time: 0.0 s to simulate 0 points
     All other time:  0.31E-01 s in 1 iterations

 Normal termination
 ***************************************************************************

The software first reports the version, platform, and compilation date of the executable, followed by credits. Then, after reading the input data, a consistency check is run on the problem data and, if passed, the data structures are initialized. In this specific example, a warning is issued that logarithmic basis functions are not considered since the input variable is allowed to take negative values. Subsequently, information is provided for all algorithmic steps. During initialization (Step 0), it is reported that 11 data points are used for sampling and that no sampling is done in addition to using the preexisting data set. In Step 1, the model is built in stages. Earlier in the search, the perfect model z=x2 is identified. Since there is no simulator provided and NBANK is zero, there is no adaptive sampling and execution terminates here after reporting the ALAMO work units consumed and a detailed breakdown of CPU times for the different algorithmic steps, including the number of calls to the optimizer (0 in this example) and the simulator (0 in this example). There are no calls to an optimizer in this example because the problem is small enough to be solved faster by complete enumeration.

7.2 ALAMO listing file

Unless PRINT_TO_FILE is set to 0, ALAMO writes a listing file whose name is that of the input file with the extension replaced by ‘.lst.’ The listing file is always placed in the execute directory, even when the input file resides elsewhere.

The listing file contains the same sequence of sections as the screen output. The two differ in one respect that matters when the model is to be used elsewhere: model coefficients are printed with two significant digits to the screen and with 23 digits to the listing file. The screen output is therefore suitable for reading, and the listing file is the copy to use when transcribing a model into another tool. The listing file can also be read back by the GUI in order to reconstruct the problem inputs and results.

7.3 ALAMO trace file

Setting TRACE to 1 directs ALAMO to append a compact, machine-readable summary of the run to the file named by TRACEFNAME. This is the output to use when ALAMO is run over many problems and the results are to be collected and compared automatically.

The file begins with a header line marked by a # that names the fields of each subsequent line. After the header, ALAMO writes one line per output variable per data set. Data sets are identified by the numbers 0 for the observed data set, 1 for a user-provided test data set, and 1,, NTESTSETS for the test sets generated by ALAMO. Because summaries are appended rather than overwritten, a trace file accumulates the results of successive runs; delete or rename it between experiments if that is not the intent.

8 ALAMO Application Programming Interface (API)

8.1 Introduction

ALAMO ships as a shared library (libalamo.so on Linux, libalamo.dylib on macOS, libalamo.dll on Windows) that can be linked into a calling program. Everything the input file can express can be expressed through this interface, and nothing needs to be written to disk: the caller sets the options and the data in memory, asks for a solve, and reads the model back as a string.

Every entry point exists in two flavors:

  • a C-callable routine alm_xxx, declared in the header file alminterface.h reproduced in Appendix A; and

  • a native Fortran routine alm_xxx_f, taking ordinary Fortran character, integer and real arguments, which Fortran callers may call directly with no iso_c_binding declarations.

The C routine is a thin shim: it marshals C types to Fortran types and calls the _f routine of the same base name. The two are therefore always in step, and a Fortran program may use whichever it prefers. ALAMO holds one problem at a time; alm_init resets all of it, so a program that builds several models in succession calls alm_init before each. The library is not reentrant and a single problem must not be driven from more than one thread at a time.

Every function that returns an int returns 0 on success and an ALAMO status code otherwise. The codes are those of Section 10; codes 142 through 159 are raised only by this interface, and alm_get_status_message turns any of them into the text printed there.

8.2 Available routines

Lifecycle
  • alm_init()
    Reset ALAMO so that a fresh problem can be specified. Must be called before the first option is set, and again before each subsequent problem. Any simulator callback registered earlier is forgotten.

  • alm_alamo()
    Build the surrogate model or models for the problem just specified, returning the ALAMO status code. This is the same computation the executable performs; the screen output described in Section 7 appears as usual.

Setting options and data
  • alm_set_int(name, value)

  • alm_set_real(name, value)

  • alm_set_string(name, value)

  • alm_set_int_vector(name, values, n)

  • alm_set_real_vector(name, values, n)

  • alm_set_string_vector(name, values, n)

The name argument is an option keyword from Section 6, in lower case and without the BEGIN_ prefix that the input file uses for block options: the BEGIN_DATA block is set with alm_set_real_vector under the name data, BEGIN_CUSTOMBAS with alm_set_string_vector under the name custombas, and so on. The alternative spellings the input file accepts are accepted here too, so nvars may be used for ninputs and xlabel for xlabels.

An option must be set through the routine that matches its type. A keyword that names a vector, such as xmin or groups, returns status 158 if it is offered to a scalar setter, and an unknown keyword returns status 143.

The order of the calls matters only where the input file would also require an order: a dimension must be set before anything sized by it. In practice this means ninputs and noutputs first, then the counts (ndata, ngroups, ncustombas, ntrans, …), then the vectors and blocks that depend on them. A call made too early returns the same status the input file would produce, for instance 12 when xlabels precedes ninputs.

Data blocks are passed row by row, as a single flat vector. A data set of NDATA points on NINPUTS inputs and NOUTPUTS outputs is NDATA×(NINPUTS+NOUTPUTS) reals, the first row first: this is similar to the layout an .alm file has, read left to right and top to bottom. When output transformations are in use, a row carries only the NOUTPUTS NTRANS untransformed outputs, since the rest are derived. A vector of the wrong length returns status 146.

Registering an in-process simulator
  • alm_set_simulator(fproc, user_data)
    Register a C-interoperable simulator callback.

  • alm_set_simulator_f(fproc, user_data)
    Register a native Fortran simulator callback.

Adaptive sampling normally obtains new values by writing a point file, running the program named by SIMULATOR, and reading the results back (Section 6.8.1). A caller that already has the simulator in its own address space can avoid that round trip by registering a callback instead. Registering one supersedes the SIMULATOR option.

The callback is batched: ALAMO passes every point it currently wants in a single call, exactly as it writes every point into the point file and runs the external program once. This permits users to compute several evaluated points in parallel. The C callback has the signature

void simfun(int n, int *k, double *x, double *z,
            int *stopit, void *user_data);

and the Fortran callback

subroutine simfun(n, k, x, z, stopit, user_data)
    use iso_c_binding
    use iso_fortran_env, only: int32, real64
    integer(int32)     :: n, k, stopit
    real(real64)       :: x(*), z(*)
    type(c_ptr), value :: user_data
end subroutine

Here, n is NINPUTS and k the number of points. The array x holds n*k reals, point j occupying x((j-1)*n+1:j*n), and it is writable: a callback may move a point, for instance to project it onto its bounds, and ALAMO reads back what it leaves, exactly as it reads the point back from the simulator’s output file. The callback writes one value per point into z. The callback path carries a single output variable. stopit is 0 on entry; leaving it at 0 asks ALAMO to continue, and setting it to a nonzero value asks for a clean stop, which alm_alamo reports as condition 151. user_data is the opaque pointer supplied at registration and is passed through untouched.

Retrieving the model
  • alm_get_model_length(k, length)
    Report, in length, the number of characters needed to hold the model for output variable k, counting from 1.

  • alm_get_model(buffer, k)
    Write the model for output variable k into buffer. The buffer must be at least as long as alm_get_model_length reported, or the call returns status 150 rather than overrunning it. A value of k outside 1NOUTPUTS returns status 147.

The two are meant to be used in that order: ask for the length, allocate, then fetch. The model is returned in the form controlled by FUNFORM.

Retrieving statistics
  • alm_get_real(name, value)

  • alm_get_int(name, value)

These fetch, by name, the quantities the termination summary prints. The real names are totaltime, olrtime, clrtime, minlptime (also miptime), bartime, lassotime, samtime (also samplingtime), simtime (also simulationtime), othertime, wuused, the work units consumed in the sense of Section 6.10, and maxwork, the budget in force. The integer names are numolrs, numclrs, nummiqps, numnlps, numiters, simdata, nbank, nbankleft, nbanksampled, and status, several of which have the alternative spellings listed in Appendix A. An empty name returns status 152 and an unrecognized one status 153.

Utility routines
  • alm_get_status()
    The status code of the last operation.

  • alm_get_status_count()
    The number of termination conditions, that is, the largest value alm_get_status_message accepts.

  • alm_get_status_message(status, buffer, buflen)
    Write the message for status into buffer. The result is always terminated and never overruns the buffer; an out-of-range code yields a sentinel string rather than an error.

  • alm_get_time()
    Total execution time of the last solve, in seconds.

  • alm_get_version(yr, mo, da)
    The version date of the library.

  • alm_dump_input(filename)
    Write the problem currently held in memory to filename as a .alm input file. Called after the alm_set_ calls and before alm_alamo, it makes a run set up through this interface reproducible with the executable, which is the easiest way to communicate a problematica ALAMO instance with the developing team.

8.3 Calling the API from C

The program below builds the Quickstart problem of Section 2, the same eleven points and the same basis set, without reading e1.alm.

/* e1api.c -- the Quickstart problem e1.alm, built through the ALAMO
   callable library instead of being read from a file.                  */

#include <stdio.h>
#include <stdlib.h>
#include "alminterface.h"

int main(void)
{
    /* the 11 data points, one row per point: x followed by z */
    static const double data[22] = {
        -5.0, 25.0,   -4.0, 16.0,   -3.0,  9.0,   -2.0,  4.0,
        -1.0,  1.0,    0.0,  0.0,    1.0,  1.0,    2.0,  4.0,
         3.0,  9.0,    4.0, 16.0,    5.0, 25.0
    };
    static const double xmin[1]  = { -5.0 };
    static const double xmax[1]  = {  5.0 };
    static const double mono[2]  = {  2.0, 3.0 };

    int status, len;
    double wu;
    char msg[256], *model;

    alm_init();

    if ((status = alm_set_int("ninputs",  1)))              goto failed;
    if ((status = alm_set_int("noutputs", 1)))              goto failed;
    if ((status = alm_set_real_vector("xmin", xmin, 1)))    goto failed;
    if ((status = alm_set_real_vector("xmax", xmax, 1)))    goto failed;

    if ((status = alm_set_int("ndata", 11)))                goto failed;
    if ((status = alm_set_real_vector("data", data, 22)))   goto failed;

    if ((status = alm_set_int("linfcns", 1)))               goto failed;
    if ((status = alm_set_int("logfcns", 1)))               goto failed;
    if ((status = alm_set_int("expfcns", 1)))               goto failed;
    if ((status = alm_set_int("sinfcns", 1)))               goto failed;
    if ((status = alm_set_int("cosfcns", 1)))               goto failed;
    if ((status = alm_set_int("mono", 2)))                  goto failed;
    if ((status = alm_set_real_vector("monomialpower", mono, 2)))
                                                            goto failed;

    if ((status = alm_alamo()) != 0) goto failed;

    if (alm_get_model_length(1, &len) == 0) {
        model = malloc((size_t) len + 1);
        if (model && alm_get_model(model, 1) == 0)
            printf("model: %s\n", model);
        free(model);
    }
    if (alm_get_real("wuused", &wu) == 0)
        printf("work units consumed: %g\n", wu);
    return 0;

 failed:
    alm_get_status_message(status, msg, (int) sizeof msg);
    printf("ALAMO failed with status %d: %s\n", status, msg);
    return 1;
}

Besides the usual ALAMO output, this program prints

model: X1^2
work units consumed: 0.00066

recovering z=x2 exactly, and consuming the same 0.66E-03 work units that the run of Section 7 reports. It must, the two runs being the same computation.

8.4 Calling the native Fortran API

Fortran callers can use the _f entry points directly. No module and no include file is needed: the routines take ordinary Fortran types, and the program below declares them as externals.

      program e1api

      use iso_fortran_env, only: real64, int32
      implicit none

      integer(int32) :: alm_set_int_f, alm_set_real_vector_f
      integer(int32) :: alm_alamo_f, alm_get_model_length_f
      integer(int32) :: alm_get_model_f, alm_get_real_f
      external :: alm_set_int_f, alm_set_real_vector_f
      external :: alm_alamo_f, alm_get_model_length_f
      external :: alm_get_model_f, alm_get_real_f
      external :: alm_dummy_simulator

      real(real64) :: data(22), xmin(1), xmax(1), mono(2), wu
      integer(int32) :: st, ml
      character(len=:), allocatable :: model
      character*256 :: msg

*     the 11 data points, one row per point: x followed by z
      data data / -5.d0, 25.d0,  -4.d0, 16.d0,  -3.d0,  9.d0,
     $            -2.d0,  4.d0,  -1.d0,  1.d0,   0.d0,  0.d0,
     $             1.d0,  1.d0,   2.d0,  4.d0,   3.d0,  9.d0,
     $             4.d0, 16.d0,   5.d0, 25.d0 /
      data xmin / -5.d0 /
      data xmax /  5.d0 /
      data mono /  2.d0, 3.d0 /

      call alm_init_f()

      st = alm_set_int_f(’ninputs’, 1)
      if (st /= 0) goto 900
      st = alm_set_int_f(’noutputs’, 1)
      if (st /= 0) goto 900
      st = alm_set_real_vector_f(’xmin’, xmin, 1)
      if (st /= 0) goto 900
      st = alm_set_real_vector_f(’xmax’, xmax, 1)
      if (st /= 0) goto 900

      st = alm_set_int_f(’ndata’, 11)
      if (st /= 0) goto 900
      st = alm_set_real_vector_f(’data’, data, 22)
      if (st /= 0) goto 900

      st = alm_set_int_f(’linfcns’, 1)
      if (st /= 0) goto 900
      st = alm_set_int_f(’logfcns’, 1)
      if (st /= 0) goto 900
      st = alm_set_int_f(’expfcns’, 1)
      if (st /= 0) goto 900
      st = alm_set_int_f(’sinfcns’, 1)
      if (st /= 0) goto 900
      st = alm_set_int_f(’cosfcns’, 1)
      if (st /= 0) goto 900
      st = alm_set_int_f(’mono’, 2)
      if (st /= 0) goto 900
      st = alm_set_real_vector_f(’monomialpower’, mono, 2)
      if (st /= 0) goto 900

      st = alm_alamo_f(alm_dummy_simulator)
      if (st /= 0) goto 900

      if (alm_get_model_length_f(1, ml) == 0) then
         allocate(character(len=ml) :: model)
         if (alm_get_model_f(model, 1) == 0) then
            print *, ’model: ’ // trim(model)
         endif
      endif
      if (alm_get_real_f(’wuused’, wu) == 0) then
         print *, ’work units consumed: ’, wu
      endif
      stop

 900  call alm_get_status_message_f(st, msg)
      print *, ’ALAMO failed with status ’, st, ’: ’ // trim(msg)

      end program e1api

The native alm_alamo_f takes one argument, the simulator procedure. A program that has registered a callback with alm_set_simulator_f, or that needs no simulator at all as here, passes alm_dummy_simulator, a do-nothing procedure the library exports for the purpose.

8.5 Calling the C API from Fortran 90

A Fortran 90 program may also call the C entry points, which is what a program does when it wants to exercise exactly the ABI a C caller sees. The interfaces do not have to be written out: the file alminterface.inc, shipped in the include directory and reproduced in Appendix B, declares all of them. Include it in the declaration part of the program, after use iso_c_binding, whose kind parameters it refers to.

!-----------------------------------------------------------------------
!  e1api.f90 -- the Quickstart problem e1.alm, built through the ALAMO
!  callable library using the C-bound entry points.  The interfaces come
!  from alminterface.inc, which is shipped in the include directory, so
!  nothing has to be declared by hand.
!-----------------------------------------------------------------------
program e1api
  use iso_c_binding
  implicit none

  include ’alminterface.inc’

  ! the 11 data points, one row per point: x followed by z
  real(c_double), parameter :: dat(22) = [ &
       -5.0d0, 25.0d0,  -4.0d0, 16.0d0,  -3.0d0,  9.0d0, &
       -2.0d0,  4.0d0,  -1.0d0,  1.0d0,   0.0d0,  0.0d0, &
        1.0d0,  1.0d0,   2.0d0,  4.0d0,   3.0d0,  9.0d0, &
        4.0d0, 16.0d0,   5.0d0, 25.0d0 ]
  real(c_double), parameter :: xmin(1) = [ -5.0d0 ]
  real(c_double), parameter :: xmax(1) = [  5.0d0 ]
  real(c_double), parameter :: mono(2) = [  2.0d0, 3.0d0 ]

  character(len=256) :: buf
  real(c_double) :: wu
  integer(c_int) :: st, ml
  integer :: i

  call alm_init()

  st = alm_set_int(cstr(’ninputs’), 1);            if (st /= 0) goto 900
  st = alm_set_int(cstr(’noutputs’), 1);           if (st /= 0) goto 900
  st = alm_set_real_vector(cstr(’xmin’), xmin, 1); if (st /= 0) goto 900
  st = alm_set_real_vector(cstr(’xmax’), xmax, 1); if (st /= 0) goto 900

  st = alm_set_int(cstr(’ndata’), 11);             if (st /= 0) goto 900
  st = alm_set_real_vector(cstr(’data’), dat, 22); if (st /= 0) goto 900

  st = alm_set_int(cstr(’linfcns’), 1);            if (st /= 0) goto 900
  st = alm_set_int(cstr(’logfcns’), 1);            if (st /= 0) goto 900
  st = alm_set_int(cstr(’expfcns’), 1);            if (st /= 0) goto 900
  st = alm_set_int(cstr(’sinfcns’), 1);            if (st /= 0) goto 900
  st = alm_set_int(cstr(’cosfcns’), 1);            if (st /= 0) goto 900
  st = alm_set_int(cstr(’mono’), 2);               if (st /= 0) goto 900
  st = alm_set_real_vector(cstr(’monomialpower’), mono, 2)
  if (st /= 0) goto 900

  st = alm_alamo();                                if (st /= 0) goto 900

  if (alm_get_model_length(1, ml) == 0 .and. ml < len(buf)) then
     buf = ’’
     if (alm_get_model(buf, 1) == 0) then
        i = index(buf, char(0))
        if (i > 0) buf(i:) = ’’
        print *, ’model: ’ // trim(buf)
     endif
  endif
  if (alm_get_real(cstr(’wuused’), wu) == 0) then
     print *, ’work units consumed: ’, wu
  endif
  stop

900 print *, ’ALAMO failed with status ’, st

contains

  ! append the NUL that the C entry points expect
  function cstr(s) result(c)
    character(len=*), intent(in) :: s
    character(len=len(s)+1, kind=c_char) :: c
    c = s // char(0)
  end function cstr

end program e1api

Two points of technique are worth noting. The C entry points expect NUL-terminated strings, which the small cstr helper supplies, and the model comes back NUL-terminated as well, so the trailing NUL is located and removed before the string is printed.

Fortran callers who would rather work in native Fortran types need none of this. The alm_xxx_f entry points of Section 8.4 take ordinary Fortran arguments and may be declared as plain externals, with no include file and no iso_c_binding.

8.6 Compilation and linking

Three ingredients are needed: the driver, the shared library, and, for C and for Fortran 90 drivers that include the interfaces, the file from the include directory. The commands below assume ALAMO is installed under /usr/local/alamo and that the driver is one of e1api.c, e1api.f or e1api.f90 of the preceding sections. Adjust the installation path and nothing else.

Linux with the GNU compilers
gcc -O2 e1api.c \
    -I/usr/local/alamo/include \
    -L/usr/local/alamo/lib -lalamo \
    -Wl,-rpath,/usr/local/alamo/lib \
    -lm -o e1api

gfortran -O2 -ffixed-line-length-none e1api.f \
    -L/usr/local/alamo/lib -lalamo \
    -Wl,-rpath,/usr/local/alamo/lib \
    -o e1api

gfortran -O2 -ffree-line-length-none e1api.f90 \
    -I/usr/local/alamo/include \
    -L/usr/local/alamo/lib -lalamo \
    -Wl,-rpath,/usr/local/alamo/lib \
    -o e1api
Linux with the Intel oneAPI compilers
icx -O2 e1api.c \
    -I/usr/local/alamo/include \
    -L/usr/local/alamo/lib -lalamo \
    -Wl,-rpath,/usr/local/alamo/lib \
    -lm -o e1api

ifx -O2 -extend-source e1api.f \
    -L/usr/local/alamo/lib -lalamo \
    -Wl,-rpath,/usr/local/alamo/lib \
    -o e1api

ifx -O2 e1api.f90 \
    -I/usr/local/alamo/include \
    -L/usr/local/alamo/lib -lalamo \
    -Wl,-rpath,/usr/local/alamo/lib \
    -o e1api

ifort may be used in place of ifx and icc in place of icx with the same arguments.

macOS with the GNU compilers

The library is libalamo.dylib and the run-time path is expressed relative to the executable:

gcc -O2 e1api.c \
    -I/usr/local/alamo/include \
    -L/usr/local/alamo/lib -lalamo \
    -Wl,-rpath,@executable_path \
    -Wl,-rpath,/usr/local/alamo/lib \
    -lm -o e1api

gfortran -O2 -ffixed-line-length-none e1api.f \
    -L/usr/local/alamo/lib -lalamo \
    -Wl,-rpath,@executable_path \
    -Wl,-rpath,/usr/local/alamo/lib \
    -o e1api

gfortran -O2 -ffree-line-length-none e1api.f90 \
    -I/usr/local/alamo/include \
    -L/usr/local/alamo/lib -lalamo \
    -Wl,-rpath,@executable_path \
    -Wl,-rpath,/usr/local/alamo/lib \
    -o e1api

Should the loader still fail to find the library, put its directory on DYLD_LIBRARY_PATH:

export DYLD_LIBRARY_PATH=/usr/local/alamo/lib:$DYLD_LIBRARY_PATH
Windows with MinGW-w64 (GNU)

Link against the import library libalamo.dll.a. Windows has no run-time path, so libalamo.dll must sit beside the executable or on PATH:

gcc -O2 e1api.c ^
    -IC:\alamo\include ^
    -LC:\alamo\lib -lalamo ^
    -o e1api.exe

gfortran -O2 -ffixed-line-length-none e1api.f ^
    -LC:\alamo\lib -lalamo ^
    -o e1api.exe

gfortran -O2 -ffree-line-length-none e1api.f90 ^
    -IC:\alamo\include ^
    -LC:\alamo\lib -lalamo ^
    -o e1api.exe

copy C:\alamo\lib\libalamo.dll .
Windows with the Intel compilers

Link against libalamo.lib and, as above, keep libalamo.dll beside the executable or on PATH:

icx /O2 e1api.c ^
    /IC:\alamo\include ^
    C:\alamo\lib\libalamo.lib ^
    /Fee1api.exe

ifx /O2 /extend-source e1api.f ^
    C:\alamo\lib\libalamo.lib ^
    /exe:e1api.exe

ifx /O2 e1api.f90 ^
    /IC:\alamo\include ^
    C:\alamo\lib\libalamo.lib ^
    /exe:e1api.exe

copy C:\alamo\lib\libalamo.dll .
Locating the MI(N)LP solver at run time

ALAMO looks for almbaron, the solver it uses for the integer programs of Section 3.4.2, next to the shared library, so a driver placed anywhere finds it. If the library has been moved away from the rest of the distribution, put the ALAMO bin directory on PATH:

export PATH=/usr/local/alamo/bin:$PATH

Without it, a problem that needs an integer program terminates with condition 132.

9 Troubleshooting

This section collects the situations that most often puzzle new users. The termination codes referenced below are listed in Section 10.

9.1 The model is too large or fits the noise

A model with many terms and an excellent training fit is a symptom of a fitness metric that is too permissive, of a candidate basis set that is too rich for the amount of data available, or of both. Move MODELER toward a criterion that penalizes size more heavily, such as BIC or RIC; reduce the basis set; impose an explicit cap through MAXTERMS; or supply a test set through NTESTDATA or NTESTSAMPLE so that the discrepancy between training and test error becomes visible. Note also that with SOLVEMIP set to 0 the model returned is the output of enumeration and greedy heuristics, which on a large candidate set may be neither small nor accurate.

9.2 The model is too crude

The complementary failure is a model that is small and inaccurate. In many cases, the cause is a candidate basis set that cannot represent the system. ALAMO selects only from the functions it is offered, and the default set consists of a constant and linear terms. Add monomial powers, pairwise or three-way products, or logarithmic and exponential terms as the physics suggests, and consider supplying problem-specific functions through the BEGIN_CUSTOMBAS section. If the basis set is adequate and the error remains large, the training data are likely too sparse; activate adaptive sampling as described below.

9.3 Adaptive sampling does not terminate

Adaptive sampling stops when the tolerances of Section 6.9 are met, when MAXITER iterations have elapsed, or when MAXTIME is exhausted. A run that ends on time or on iteration count rather than on tolerance usually means that TOLMAXERROR is tighter than the model class can achieve, or that the simulator is returning values that the model cannot reconcile, for example because the response is discontinuous or noisy. Loosen TOLMAXERROR, enrich the basis set, or accept the model produced at the iteration limit after inspecting its test error.

9.4 The simulator fails

Termination code 123 indicates that the simulator could not be found; check that the executable named by SIMULATOR is on the path or that the full path was supplied, and recall that ALAMO runs the simulator in a scratch directory it creates, so the simulator must not depend on relative paths. Code 124 indicates that the simulator failed MAXSIM times in succession. Codes 37 and 38 point at the SIMIN and SIMOUT files themselves. Code 37 means that ALAMO was unable to write on disk, perhaps due to a full disk or permission issues. Code 38 means that the simulator did not write the expected number of values, because of similar I/O issues or bugs in the simulator itself. Codes 42 and 43 indicate that the simulator returned NaN; for an output variable that cannot be computed at a given point, the simulator must return PRESET rather than NaN.

9.5 Basis functions disappear without being asked to

With NUMLIMITBASIS set to 1, ALAMO discards basis functions that are not numerically well defined over the box between XMIN and XMAX. Logarithmic and, on some data, ratio basis functions are the usual casualties, and a warning to that effect appears in the screen and listing output. If those functions are needed, restrict XMIN and XMAX to a region on which they are defined rather than turning NUMLIMITBASIS off. Note that XMIN and XMAX describe the physically meaningful range of each input and are not required to coincide with the range of the supplied data.

9.6 Constrained regression cannot satisfy a bound

Constrained regression enforces ZMIN, ZMAX, and any custom constraints at a growing finite set of points, adding CRNVIOL violated points per constraint per iteration for at most CRMAXITER iterations. A run that exits with a model still violating a bound usually needs a larger CRMAXITER or CRNVIOL, or a basis set rich enough to satisfy the constraint at all. Note that satisfaction is enforced only to within CRTOL, and that constrained regression is not supported together with trigonometric basis functions (code 134) and requires an optimizer (code 73).

9.7 An optimizer is required but not available

Termination code 132 means that the current combination of options requires the embedded mixed-integer solver but that it is not available. This is most commonly encountered with SOLVEMIP set to 1 or with constrained regression active. Verify that the BARON executable that came with the ALAMO distribution is in the same location as your ALAMO executable or callable library. In general, ensure that all executables and libraries that come with your ALAMO install remain together in the same location on your computer.

10 Termination conditions and error messages

Errors in the input file are reported on the screen and/or the listing file in the form of “warnings” and “severe errors.” ALAMO attempts to continue execution despite warnings. If the errors are severe, the program execution is stopped and the line where the fatal error occurred is displayed. Section 9 discusses the most commonly encountered of these conditions in context. The input file should be checked even if the warnings are not severe, as the problem might have been parsed in a way other than it was intended to be. Detailed error messages are provided in that case.

If execution terminates normally, ALAMO prints ‘Normal termination.’ If there is a severe error, the message on the screen or file is ‘ALAMO terminated with termination code,’ followed by one of the following error codes, all of which are self-explanatory:

  1. 1.

    ALAMO must be called with one or two command line arguments.

  2. 2.

    ALAMO input file name must be no longer than 1000 characters.

  3. 3.

    ALAMO input file not found.

  4. 4.

    ALAMO input file cannot be opened.

  5. 5.

    Keyword not recognized in input file.

  6. 6.

    Keyword too long in input file.

  7. 7.

    Incomplete input file.

  8. 8.

    Input value in error in input file.

  9. 9.

    Number of input variables (NINPUTS) must be specified before specifying XMIN values.

  10. 10.

    Number of input variables (NINPUTS) must be specified before specifying XMAX values.

  11. 11.

    Number of input variables (NINPUTS) must be specified before specifying XFACTOR values.

  12. 12.

    Number of input variables (NINPUTS) must be specified before specifying XLABELS.

  13. 13.

    Number of output variables (NOUTPUTS) must be specified before specifying ZLABELS.

  14. 14.

    MONOMIALPOWER values have been set already. Multiple declarations are not allowed.

  15. 15.

    Number of input variables (NINPUTS) must be specified before the DATA section of the input file.

  16. 16.

    Number of output variables (NOUTPUTS) must be specified before the DATA section of the input file.

  17. 17.

    Number of data points (NDATA) must be specified before the DATA section of the input file.

  18. 18.

    Number of input variables (NINPUTS) must be specified before the XDATA section of the input file.

  19. 19.

    Number of data points (NDATA) must be specified before the XDATA section of the input file.

  20. 20.

    Number of output variables (NOUTPUTS) must be specified before the ZDATA section of the input file.

  21. 21.

    Number of data points (NDATA) must be specified before the ZDATA section of the input file.

  22. 22.

    Input data file missing required keyword(s).

  23. 23.

    END_DATA missing or incomplete DATA section.

  24. 24.

    END_XDATA missing or incomplete XDATA section.

  25. 25.

    END_ZDATA missing or incomplete ZDATA section.

  26. 26.

    Only one of XDATA and DATA sections is allowed.

  27. 27.

    Only one of ZDATA and DATA sections is allowed.

  28. 28.

    MULTI2POWER values have been set already. Multiple declarations are not allowed.

  29. 29.

    MULTI3POWER values have been set already. Multiple declarations are not allowed.

  30. 30.

    Unable to open output file.

  31. 31.

    Maximum number of iterations reached.

  32. 32.

    RATIOPOWER values have been set already. Multiple declarations are not allowed.

  33. 33.

    Error while trying to use the optimizer to solve the MIP for best subset.

  34. 34.

    Error while attempting to access the ALAMO execution directory.

  35. 35.

    Error while attempting to access the ALAMO scratch directory.

  36. 36.

    Error while attempting to access the external simulator.

  37. 37.

    Error while attempting to write the external simulator input file.

  38. 38.

    Error while attempting to read the external simulator output file.

  39. 39.

    Scaling by zero is not allowed.

  40. 40.

    XMAX cannot be smaller than XMIN for an input variable.

  41. 41.

    XDATA must be in the range [XMIN, XMAX].

  42. 42.

    Simulator should not return NaN for input variable values.

  43. 43.

    Simulator should not return NaN for output variable values. For any variable that the simulator cannot compute, return the value of PRESET.

  44. 44.

    Input file is missing XMIN values.

  45. 45.

    Input file is missing XMAX values.

  46. 46.

    MONOMIALPOWERS must be specified if MONO is used.

  47. 47.

    MULTI2POWER must be specified if MULTI2 is used.

  48. 48.

    MULTI3POWER must be specified if MULTI3 is used.

  49. 49.

    RATIOPOWER must be specified if RATIOS is used.

  50. 50.

    DATA section must be specified when NDATA is nonzero.

  51. 51.

    Insufficient memory to allocate data structures.

  52. 52.

    Number of test data points (NTESTDATA) must be specified before the TESTDATA section of the input file.

  53. 53.

    TESTDATA section must be specified when NTESTDATA is nonzero.

  54. 54.

    TESTDATA section must be specified when NTESTSECTIONS is nonzero.

  55. 55.

    Premature end of input file.

  56. 56.

    Number of custom constraints (CRNCUSTOM) must be specified before specifying CUSTOMCON section.

  57. 57.

    END_ZMIN missing or incomplete ZMIN section.

  58. 58.

    END_ZMAX missing or incomplete ZMAX section.

  59. 59.

    Number of input variables (NINPUTS) must be specified before specifying EXTRAPXMIN values.

  60. 60.

    Number of input variables (NINPUTS) must be specified before specifying EXTRAPXMAX values.

  61. 61.

    END_CUSTOMCON missing or incomplete CUSTOMCON section.

  62. 62.

    Number of output variables (NOUTPUTS) must be specified before specifying ZMIN values.

  63. 63.

    Unable to open trace file.

  64. 64.

    No keyword (parameter) may be specified more than once.

  65. 65.

    Variable index is out of range.

  66. 66.

    Error while trying to run SNOBFIT.

  67. 67.

    Error while trying to solve ordinary least squares regression subproblem with the optimizer.

  68. 68.

    Maximum CPU time (MAXTIME) exceeded.

  69. 69.

    Error while trying to write in the ALAMO scratch directory.

  70. 70.

    Number of output variables (NOUTPUTS) must be specified before specifying TOLMEANERROR values.

  71. 71.

    A least squares subproblem failed during enumeration and no optimizer is available.

  72. 72.

    Licensing error. A valid license is required in order to run this software.

  73. 73.

    Error while trying to use the optimizer to solve the constrained regression model.

  74. 74.

    Error while trying to copy file to disk.

  75. 75.

    CUSTOMCON section must be specified when CRNCUSTOM is nonzero.

  76. 76.

    All output variables ignored by user. No point in calling ALAMO.

  77. 77.

    END_CUSTOMBAS missing or incomplete CUSTOMBAS section.

  78. 78.

    Number of custom basis functions (NCUSTOMBAS) must be specified before the CUSTOMBAS section of the input file.

  79. 79.

    Syntax error in custom basis function.

  80. 80.

    All variable labels must begin with an alphabetical character (A-Z or a-z).

  81. 81.

    Variable labels may only contain alphanumerical characters (A-Z, a-z, 0-9) or underscores.

  82. 82.

    All variable labels must be distinct.

  83. 83.

    All CRCUSTOMIND values must range from 1 to NOUTPUTS.

  84. 84.

    Each custom constraint must be expressed in terms of the labels of input variables and a single output variable.

  85. 85.

    Each line of the input file must contain no more than 10000 characters. Longer data records may be split into multiple lines using & at the end of a line to signify continuation of the record in the next line.

  86. 86.

    Syntax error in input file.

  87. 87.

    Inline comments must be preceded by ! or #.

  88. 88.

    Inconsistent use of NDATA, NBANK and INITIALPOINTS.

  89. 89.

    A least squares subproblem failed during model buildup and no optimizer is available.

  90. 90.

    Number of output variables (NOUTPUTS) must be specified before specifying MAXTERMS values.

  91. 91.

    Number of output variables (NOUTPUTS) must be specified before specifying TOLRELMETRIC values.

  92. 92.

    Number of output variables (NOUTPUTS) must be specified before specifying TOLABSMETRIC values.

  93. 93.

    END_TRANSFORMS missing or incomplete TRANSFORMS section.

  94. 94.

    Number of transformed output variables (NTRANS) must be specified before the TRANSFORMS section of the input file.

  95. 95.

    Syntax error in output transformation function.

  96. 96.

    Number of transformed output variables (NTRANS) cannot exceed total number of outputs (NOUTPUTS).

  97. 97.

    Number of transformed output variables (NTRANS) must be specified after specifying total number of outputs (NOUTPUTS).

  98. 98.

    Number of transformed output variables (NTRANS) must be specified before providing output data section (DATA or ZDATA).

  99. 99.

    Number of output variables (NOUTPUTS) must be specified before specifying ZISINT values.

  100. 100.

    Number of prediction points (NPREDATA) must be specified before the PREDATA section of the input file.

  101. 101.

    END_XPREDATA missing or incomplete XPREDATA section.

  102. 102.

    Number of input variables (NINPUTS) must be specified before the XPREDATA section of the input file.

  103. 103.

    XPREDATA section must be specified when NPREDATA is nonzero.

  104. 104.

    A GROUPS section is allowed only if NGROUPS is positive.

  105. 105.

    A GROUPS section is allowed only after NINPUTS has been defined.

  106. 106.

    A GROUPS section is allowed only after NOUTPUTS has been defined.

  107. 107.

    A GROUPS section is allowed only after NDATA has been defined.

  108. 108.

    Group-ids must be integers between 1 and NGROUPS.

  109. 109.

    Member-type must be one of LIN, LOG, EXP, SIN, COS, MONO, MULTI2, MULTI3, RATIO, RBF, CUST, and CONST.

  110. 110.

    All powers in group definitions must appear in user-specified basis functions.

  111. 111.

    NGROUPS has been specified but a smaller number of groups has been described in the GROUPS section or the GROUPS section is entirely missing.

  112. 112.

    A GROUPCON section is allowed only if NGROUPS is positive.

  113. 113.

    A GROUPCON section is allowed only after NOUTPUTS has been defined.

  114. 114.

    Member-indices for input variables must be equal to 1 or integers between 1 and NINPUTS.

  115. 115.

    Member-indices for radial basis functions must be integers between 1 and number of data points (NDATA).

  116. 116.

    Member-indices for custom basis functions must be integers between 1 and NCUSTOMBAS.

  117. 117.

    Member-indices for groups must be equal to 1 or integers between 1 and NGROUPS.

  118. 118.

    Output variable indices must be equal to 1 or integers between 1 and NOUTPUTS.

  119. 119.

    Constraint-type must be one of NMT, ATL, REQ, and XCL.

  120. 120.

    Integer-parameters for REQ and XCL group constraints must be integers between 1 and NGROUPS.

  121. 121.

    Number of input variables (NINPUTS) must be specified before specifying EXCLUDE values.

  122. 122.

    Number of output variables (NOUTPUTS) must be specified before specifying IGNORE values.

  123. 123.

    Unable to find the external simulator.

  124. 124.

    Simulator failed MAXSIM times.

  125. 125.

    TRANSFORMS section must be specified when NTRANS is nonzero.

  126. 126.

    Evaluation error with transformation function. Try a different transformation.

  127. 127.

    Error while trying to write file to disk.

  128. 128.

    Number of output variables (NOUTPUTS) must be specified before specifying ZMAX values.

  129. 129.

    Powers for polynomial basis functions have been set already. Multiple declarations are not allowed.

  130. 130.

    Number of input variables (NINPUTS) must be specified before specifying XISINT values.

  131. 131.

    Number of output variables (NOUTPUTS) must be specified before specifying TOLMAXERROR values.

  132. 132.

    A MI(N)LP solver is required to proceed with the current set of options but one is not available or found.

  133. 133.

    Variable labels may not start with the string ‘alm_’.

  134. 134.

    Constrained regression is currently not supported with trigonometric basis functions.

  135. 135.

    Number of data points (NDATA) must be specified before specifying NBANK.

  136. 136.

    MAXITER should be set to 1 if no simulator is provided.

  137. 137.

    If used, NBANK must be specified before DATA section.

  138. 138.

    NBANK cannot exceed number of data points (NDATA).

  139. 139.

    Only one DATA section is allowed.

  140. 140.

    Only one XDATA section is allowed.

  141. 141.

    Only one ZDATA section is allowed.

  142. 142.

    Set function called with an empty parameter string.

  143. 143.

    Set function called with an unknown parameter string.

  144. 144.

    ZDATA section provided but XDATA section is missing.

  145. 145.

    XDATA section provided but ZDATA section is missing.

  146. 146.

    Inconsistent length in call to set vector function.

  147. 147.

    Specified output variable does not exist.

  148. 148.

    ALAMO must be initialized through a call to alminit.

  149. 149.

    Option names must have length between 1 and 1000.

  150. 150.

    Longer string is needed to store the model.

  151. 151.

    Simulator requested termination.

  152. 152.

    Get function called with an empty parameter string.

  153. 153.

    Get function called with an unknown parameter string.

  154. 154.

    Work-unit budget (MAXWORK) exhausted.

  155. 155.

    The callable library cannot run from a .alm input file.

  156. 156.

    Set the count (NCUSTOMBAS/CRNCUSTOM/NTRANS) before the list.

  157. 157.

    Expression-list option; use alm_set_string_vector instead.

  158. 158.

    Custom constraint must start with its output index.

11 Compatibility with previous versions of ALAMO

Starting with ALAMO v. 2013.10.0, the input format was changed. Input requirements of earlier versions were maintained with two exceptions:

  • Previous versions required that ALAMO options be specified in a separate file than preexisting data. All ALAMO input must now be entered in a single file.

  • Preexisting data can now be entered in a format that combines input and output measurements in a column wise fashion.

For compatibility with early versions of ALAMO, the following keywords are also acceptable in ALAMO v. 2013.10.0 and beyond:

Parameter Description
NCVL This is equivalent to NCVF.
NVALDATA This is equivalent to NTESTDATA.
NVALSAMPLE This is equivalent to NTESTSAMPLE.
NVALSETS This is equivalent to NTESTSETS.
NVALSECTIONS This is equivalent to NTESTSECTIONS.
BEGIN_VALDATA This is equivalent to BEGIN_TESTDATA.
INITIALPOINTS Number of data points in the initial sample set. This parameter represents the sum of NDATA and NSAMPLE. INITIALPOINTS must be a nonnegative integer. If declared, INITIALPOINTS must be greater than or equal to NDATANBANK. If INITIALPOINTS is declared, NSAMPLE will be ignored and set equal to the difference of INITIALPOINTS and NDATA; otherwise, INITIALPOINTS will be set equal to the sum of NDATANBANK and NSAMPLE.
NVARS This is equivalent to NINPUTS.
BEGIN_XDATA Can be used in conjunction with BEGIN_ZDATA to pass x-values separately from z-values. Only one of BEGIN_XDATA and BEGIN_DATA is permitted.
BEGIN_ZDATA Can be used in conjunction with BEGIN_XDATA to pass x-values separately from z-values. Only one of BEGIN_ZDATA and BEGIN_DATA is permitted.
CONREG It used to serve as an indication that constrained regression will be invoked. This is now ignored and the need for constrained regression is inferred from other options.

Starting with ALAMO v. 2019.7.30, the keyword REGULARIZER was replaced by the more appropriate SCREENER. The keyword REGULARIZER is still acceptable and the possible values of SCREENER are backwards compatible with those of REGULARIZER.

Starting with ALAMO v. 2026.8.12, the keyword WORKUNITS was replaced by MAXWORK for compatibility with MAXTIME and other ALAMO keywords. The keyword WORKUNITS is still an acceptable alternative.

Appendix A: Header file alminterface.h

The header file alminterface.h, which C users must include and which Fortran 90 users may consult when writing the interface block of Section 8.5, is the only include file the callable library requires. It is distributed in the include directory of the ALAMO installation and has the following contents:

#ifndef ALMINTERFACE_H
#define ALMINTERFACE_H

/*
 * C-callable interface to ALAMO.
 *
 * Every entry point below is a thin bind(C) shim implemented in
 * module ALMAPI (src/almapi.f); each one marshals C<->Fortran types
 * and forwards to a native Fortran routine of the same base name with
 * an "_f" suffix (alm_set_int -> alm_set_int_f, ...), which Fortran
 * code may call directly.  Functions returning "int" return 0 on
 * success and a nonzero ALAMO status code otherwise.
 *
 * Naming follows the same convention as BAM’s bamapi: routines that
 * take/return C "double" arguments use "real" in their name
 * (alm_set_real, alm_set_real_vector, alm_get_real).
 *
 * (almc2f / almf2c remain internal Fortran helpers; they are not part
 *  of this public interface.)
 */

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

  /* ---- lifecycle ------------------------------------------------- */

  /* reset internal state so a fresh problem can be set up */
  void alm_init(void);

  /* build the surrogate model(s) for the problem just specified.
   * Uses the in-process simulator registered with alm_set_simulator if
   * there is one, otherwise ALAMO’s file-based SIMULATOR handling;
   * returns the ALAMO status code (0 on success), also obtainable via
   * alm_get_status. */
  int  alm_alamo(void);

  /* ---- in-process simulator -------------------------------------- */

  /*
     Register a C simulator callback:

         void simfun(int n, int *k, double *x, double *z,
                     int *stopit, void *user_data);

     ALAMO calls this whenever it needs the output at sampled points,
     instead of writing SIMIN, running the SIMULATOR program and reading
     SIMOUT.  Registering one works whatever cmdcount is.

     The call is BATCHED, as bam_set_obj_fun’s is: ALAMO hands over every
     point it currently wants, the way it writes every point into SIMIN
     and runs the SIMULATOR program once.  That matters for any simulator
     whose answer for a point depends on how many points share the
     invocation -- one drawing pseudorandom noise from a seed that resets
     per call, say.  Such a simulator gives the same values through this
     interface as it does through the file-based one.

         n  number of input variables (NINPUTS), by value.
         k  number of points to evaluate, by reference.  ALAMO sets *k on
            entry; the callback should not change it.
         x  the *k points, laid out as *k contiguous blocks of n doubles:
            point j (0-based) is x[j*n + 0 .. j*n + (n-1)].  x is
            writable -- the callback may overwrite a point (e.g. to
            project it onto its bounds) and ALAMO reads back what it
            leaves, just as it reads x back out of SIMOUT.
         z  output objective values, one per point: z[0 .. *k-1].  The
            callback writes z[j] = simulated output for point j.  The
            callback path carries a single output variable.
         stopit  0 on entry.  Leave it 0 to continue; set it nonzero to
            ask ALAMO to stop the run cleanly, which it reports as
            status 151.
         user_data  the opaque pointer passed to alm_set_simulator.

     Returns 0 on success, 12 if NINPUTS has not been set yet, 143 for a
     null function pointer, 148 if alm_init is due.  The registration is
     cleared by alm_init.  The Fortran entry is alm_set_simulator_f. */
  int alm_set_simulator(
                        void (*fproc)(int     n,
                                      int    *k,
                                      double *x,
                                      double *z,
                                      int    *stopit,
                                      void   *user_data),
                        void *user_data);

  /* ---- option and data input ------------------------------------- */

  int  alm_set_int   (const char *name, int    inval);
  int  alm_set_real  (const char *name, double inval);
  int  alm_set_string(const char *name, const char *value);

  int  alm_set_int_vector (const char *name, const int    *value,
                           int inlength);
  int  alm_set_real_vector(const char *name, const double *value,
                           int inlength);
  /* value[] is an array of n NUL-terminated strings (e.g. xlabels,
   * zlabels); n must match the dimension implied by name. */
  int  alm_set_string_vector(const char *name, const char *const *value,
                             int n);

  /* ---- results and introspection --------------------------------- */

  void   alm_get_version(int *yr, int *mo, int *da);
  double alm_get_time(void);
  int    alm_get_status(void);

  /* number of termination/error codes; valid status arguments to
   * alm_get_status_message run from 1 to this value */
  int    alm_get_status_count(void);
  /* write the message for ‘status‘ into ‘buffer‘ (capacity ‘buflen‘
   * bytes including the trailing NUL); always NUL-terminated, never
   * overflows, no-op for buflen <= 0; out-of-range status yields the
   * "Unknown status code." sentinel */
  void   alm_get_status_message(int status, char *buffer, int buflen);

  /* model text for output variable ‘inval‘ (1-based): first ask for
   * the required buffer length, then fetch the NUL-terminated text. */
  int    alm_get_model_length(int inval, int *outval);
  int    alm_get_model(char *name, int inval);

  /* fetch, by name, a quantity reported by almtermination.
   *   alm_get_real names: totaltime, olrtime, clrtime, minlptime
   *                       (= miptime), bartime, lassotime,
   *                       samtime (= samplingtime),
   *                       simtime (= simulationtime), othertime
   *                       wuused (work units consumed by the run) and
   *                       maxwork (the budget in force, -1 if none)
   *   alm_get_int  names: numolrs (= numolr), numclrs (= numclr),
   *                       nummiqps (= nummip, numminlp),
   *                       numnlps (= numnlp, numlasso),
   *                       numiters (= numiter), simdata (= numsim),
   *                       nbank, nbankleft, nbanksampled,
   *                       status (= almstatus), statusloc
   * returns 0 on success, 152 for an empty name, 153 for an unknown
   * one. */
  int    alm_get_real(const char *name, double *value);
  int    alm_get_int (const char *name, int    *value);

  /* ---- diagnostics ------------------------------------------------ */

  /* Write the problem currently held in memory to ‘filename‘ as a .alm
   * input file, so that a run set up through this interface can be
   * reproduced with the alamo executable and compared against it.  Call
   * it after the alm_set_* calls and before alm_alamo.  Returns 0, or 30
   * if the file cannot be opened. */
  int    alm_dump_input(const char *filename);

#ifdef __cplusplus
}
#endif

#endif /* ALMINTERFACE_H */

Appendix B: Include file alminterface.inc

The include file alminterface.inc carries the C API interfaces that Fortran users include in their programs when they wish to call the C entry points rather than the native Fortran ones. It is distributed in the include directory alongside alminterface.h and is used as shown in Section 8.5: place it in the declaration part of the program, after use iso_c_binding. Its contents are:

  !--------------------------------------------------------------
  ! alminterface.inc
  !
  ! C API interfaces for the ALAMO callable library, for Fortran
  ! users to INCLUDE in the declaration part of a driver program:
  !
  !     program mydriver
  !       use iso_c_binding
  !       implicit none
  !       include ’alminterface.inc’
  !       ...
  !
  ! It is the Fortran counterpart of alminterface.h and the ALAMO
  ! analogue of BAM’s bam.inc.  Including it saves writing out the
  ! interface block by hand and keeps every driver in step with the
  ! library.  The file must be included AFTER ‘use iso_c_binding‘,
  ! whose kind parameters it refers to.
  !
  ! Fortran callers who would rather use native Fortran types have
  ! no need of this file: the alm_xxx_f entry points take ordinary
  ! Fortran character, integer and real arguments and may be
  ! declared as plain externals.
  !--------------------------------------------------------------
  interface

  !--------------------------------------------------------------
  ! alm_init: reset ALAMO for a fresh problem
  !--------------------------------------------------------------
  subroutine alm_init() bind(C, name="alm_init")
  end subroutine alm_init

  !--------------------------------------------------------------
  ! alm_alamo: build the surrogate model(s)
  !--------------------------------------------------------------
  integer(c_int) function alm_alamo() bind(C, name="alm_alamo")
    import :: c_int
  end function alm_alamo

  !--------------------------------------------------------------
  ! alm_set_int
  !--------------------------------------------------------------
  integer(c_int) function alm_set_int(name, value) &
                 bind(C, name="alm_set_int")
    import :: c_int, c_char
    character(kind=c_char), dimension(*), intent(in) :: name
    integer(c_int), value :: value
  end function alm_set_int

  !--------------------------------------------------------------
  ! alm_set_real
  !--------------------------------------------------------------
  integer(c_int) function alm_set_real(name, value) &
                 bind(C, name="alm_set_real")
    import :: c_int, c_char, c_double
    character(kind=c_char), dimension(*), intent(in) :: name
    real(c_double), value :: value
  end function alm_set_real

  !--------------------------------------------------------------
  ! alm_set_string
  !--------------------------------------------------------------
  integer(c_int) function alm_set_string(name, value) &
                 bind(C, name="alm_set_string")
    import :: c_int, c_char
    character(kind=c_char), dimension(*), intent(in) :: name
    character(kind=c_char), dimension(*), intent(in) :: value
  end function alm_set_string

  !--------------------------------------------------------------
  ! alm_set_int_vector
  !--------------------------------------------------------------
  integer(c_int) function alm_set_int_vector(name, value, n) &
                 bind(C, name="alm_set_int_vector")
    import :: c_int, c_char
    character(kind=c_char), dimension(*), intent(in) :: name
    integer(c_int), dimension(*), intent(in) :: value
    integer(c_int), value :: n
  end function alm_set_int_vector

  !--------------------------------------------------------------
  ! alm_set_real_vector
  !--------------------------------------------------------------
  integer(c_int) function alm_set_real_vector(name, value, n) &
                 bind(C, name="alm_set_real_vector")
    import :: c_int, c_char, c_double
    character(kind=c_char), dimension(*), intent(in) :: name
    real(c_double), dimension(*), intent(in) :: value
    integer(c_int), value :: n
  end function alm_set_real_vector

  !--------------------------------------------------------------
  ! alm_set_string_vector
  !
  ! value is an array of n C pointers, each to a NUL-terminated
  ! string; build it with c_loc on NUL-terminated targets.
  !--------------------------------------------------------------
  integer(c_int) function alm_set_string_vector(name, value, n) &
                 bind(C, name="alm_set_string_vector")
    import :: c_int, c_char, c_ptr
    character(kind=c_char), dimension(*), intent(in) :: name
    type(c_ptr), dimension(*), intent(in) :: value
    integer(c_int), value :: n
  end function alm_set_string_vector

  !--------------------------------------------------------------
  ! alm_set_simulator: register an in-process simulator callback
  !
  ! The callback is batched; see alminterface.h for the contract.
  !--------------------------------------------------------------
  integer(c_int) function alm_set_simulator(fproc, user_data) &
                 bind(C, name="alm_set_simulator")
    import :: c_int, c_funptr, c_ptr
    type(c_funptr), value :: fproc
    type(c_ptr), value :: user_data
  end function alm_set_simulator

  !--------------------------------------------------------------
  ! alm_get_model_length / alm_get_model
  !--------------------------------------------------------------
  integer(c_int) function alm_get_model_length(inval, outval) &
                 bind(C, name="alm_get_model_length")
    import :: c_int
    integer(c_int), value :: inval
    integer(c_int) :: outval
  end function alm_get_model_length

  integer(c_int) function alm_get_model(name, inval) &
                 bind(C, name="alm_get_model")
    import :: c_int, c_char
    character(kind=c_char), dimension(*) :: name
    integer(c_int), value :: inval
  end function alm_get_model

  !--------------------------------------------------------------
  ! alm_get_real / alm_get_int
  !--------------------------------------------------------------
  integer(c_int) function alm_get_real(name, value) &
                 bind(C, name="alm_get_real")
    import :: c_int, c_char, c_double
    character(kind=c_char), dimension(*), intent(in) :: name
    real(c_double) :: value
  end function alm_get_real

  integer(c_int) function alm_get_int(name, value) &
                 bind(C, name="alm_get_int")
    import :: c_int, c_char
    character(kind=c_char), dimension(*), intent(in) :: name
    integer(c_int) :: value
  end function alm_get_int

  !--------------------------------------------------------------
  ! Status and version
  !--------------------------------------------------------------
  integer(c_int) function alm_get_status() &
                 bind(C, name="alm_get_status")
    import :: c_int
  end function alm_get_status

  integer(c_int) function alm_get_status_count() &
                 bind(C, name="alm_get_status_count")
    import :: c_int
  end function alm_get_status_count

  subroutine alm_get_status_message(status, buffer, buflen) &
             bind(C, name="alm_get_status_message")
    import :: c_int, c_char
    integer(c_int), value :: status
    character(kind=c_char), dimension(*) :: buffer
    integer(c_int), value :: buflen
  end subroutine alm_get_status_message

  subroutine alm_get_version(yr, mo, da) &
             bind(C, name="alm_get_version")
    import :: c_int
    integer(c_int) :: yr, mo, da
  end subroutine alm_get_version

  real(c_double) function alm_get_time() &
                 bind(C, name="alm_get_time")
    import :: c_double
  end function alm_get_time

  !--------------------------------------------------------------
  ! alm_dump_input: write the in-memory problem out as a .alm file
  !--------------------------------------------------------------
  integer(c_int) function alm_dump_input(name) &
                 bind(C, name="alm_dump_input")
    import :: c_int, c_char
    character(kind=c_char), dimension(*), intent(in) :: name
  end function alm_dump_input

  end interface

Bibliography

  • [1] H. Akaike. A new look at the statistical model identification. IEEE Transactions on Automatic Control, 19:716–723, 1974.
  • [2] BARON. http://minlp.com/baron-solver.
  • [3] S. Chen, N. V. Sahinidis, and C. Gao. Transfer learning in information criteria-based feature selection. Journal of Machine Learning Research, 23:1–105, 2022.
  • [4] A. Cozad. Data- and theory-driven techniques for surrogate-based optimization. PhD thesis, Department of Chemical Engineering, Carnegie Mellon University, Pittsburgh, PA, May 2014.
  • [5] A. Cozad, N. V. Sahinidis, and D. C. Miller. Learning surrogate models for simulation-based optimization. AIChE Journal, 60:2211–2227, 2014.
  • [6] A. Cozad, N. V. Sahinidis, and D. C. Miller. A combined first-principles and data-driven approach to model building. Computers & Chemical Engineering, 73:116–127, 2015.
  • [7] J. Fan and J. Lv. Sure independence screening for ultrahigh dimensional feature space. Journal of the Royal Statistical Society, Series B, 70:849–911, 2008.
  • [8] H. Faure. Discrépance de suites associées à un système de numération (en dimension s). Acta Arithmetica, 41:337–351, 1982.
  • [9] D. P. Foster and E. I. George. The risk inflation criterion for multiple regression. The Annals of Statistics, 22:1947–1975, 1994.
  • [10] G. M. Furnival and R. W. Wilson. Regressions by leaps and bounds. Technometrics, 16:499–511, 1974.
  • [11] E. J. Hannan and B. G. Quinn. The determination of the order of an autoregression. Journal of the Royal Statistical Society, Series B, 41:190–195, 1979.
  • [12] W. E. Hart, C. D. Laird, J.-P. Watson, D. L. Woodruff, G. A. Hackebeil, B. L. Nicholson, and J. D. Siirola, editors. Pyomo—Optimization Modeling in Python. Springer-Verlag, New York, 2nd edition, 2017.
  • [13] R. Hettich and K. O. Kortanek. Semi-infinite programming: Theory, methods, and applications. SIAM Review, 35:380–429, 1993.
  • [14] C. M. Hurvich and C.-L. Tsai. Regression and time series model selection in small samples. Biometrika, 76:297–307, 1989.
  • [15] W. Huyer and A. Neumaier. SNOBFIT–Stable noisy optimization by branch and fit. ACM Transactions on Mathematical Software, 35:1–25, 2008.
  • [16] A. Khajavirad and N. V. Sahinidis. A hybrid LP/NLP paradigm for global optimization relaxations. Mathematical Programming Computation, 10:383–421, 2018.
  • [17] M. Kılınç and N. V. Sahinidis. Exploiting integrality in the global optimization of mixed-integer nonlinear programming problems in BARON. Optimization Methods and Software, 33:540–562, 2019.
  • [18] A. Lee, J. H. Ghouse, J. C. Eslick, C. D. Laird, J. D. Siirola, M. A. Zamarripa, D. Gunter, J. H. Shinn, A. W. Dowling, D. Bhattacharyya, L. T. Biegler, A. P. Burgard, and D. C. Miller. The IDAES process modeling framework and model library—Flexibility for process simulation and optimization. Journal of Advanced Manufacturing and Processing, 3:e10095, 2021.
  • [19] K. Lindqvist, Z. T. Wilson, E. Næss, and N. V. Sahinidis. A machine learning approach to correlation development applied to fin-tube bundle heat exchangers. Energies, 11:3450, 2018.
  • [20] K. Ma, L. M. Rios, A. Bhosekar, N. V. Sahinidis, and S. Rajagopalan. Branch-and-Model: A derivative-free global optimization algorithm. Computational Optimization and Applications, 85:337–367, 2023.
  • [21] C. L. Mallows. Some comments on Cp. Technometrics, 15:661–675, 1973.
  • [22] M. D. McKay, R. J. Beckman, and W. J. Conover. A comparison of three methods for selecting values of input variables in the analysis of output from a computer code. Technometrics, 21:239–245, 1979.
  • [23] K. M. Nauta, A. Silva, and C C. Pantelides. Developing a new tool for hybrid process modelling, accessed February 19, 2026. https://www.aspire2050.eu/sites/default/files/users/user533/JointWorkshop_poster_PSE.pdf.
  • [24] R. Reemtsen and S. Görner. Numerical methods for semi-infinite programming: A survey. In Semi-Infinite Programming, Reemtsen R. and Rückmann, J.-J. (eds.), Kluwer Academic Publishers, Boston, MA, pages 195–275, 1998.
  • [25] L. M. Rios and N. V. Sahinidis. Derivative-free optimization: A review of algorithms and comparison of software implementations. Journal of Global Optimization, 56:1247–1293, 2013.
  • [26] H. S. Ryoo and N. V. Sahinidis. A branch-and-reduce approach to global optimization. Journal of Global Optimization, 8:107–139, 1996.
  • [27] G. Schwarz. Estimating the dimension of a model. The Annals of Statistics, 6:461–464, 1978.
  • [28] M. Tawarmalani and N. V. Sahinidis. Global optimization of mixed-integer nonlinear programs: A theoretical and computational study. Mathematical Programming, 99:563–591, 2004.
  • [29] M. Tawarmalani and N. V. Sahinidis. A polyhedral branch-and-cut approach to global optimization. Mathematical Programming, 103:225–249, 2005.
  • [30] The IDAES Project. ALAMOPY: ALAMO Python, Current as of 5 August, 2026.
    https://idaes-pse.readthedocs.io/en/stable/explanations/modeling_extensions/surrogate/api/alamopy/index.html.
  • [31] R. Tibshirani. Regression shrinkage and selection via the lasso. Journal of the Royal Statistical Society, Series B, 58:267–288, 1996.
  • [32] Z. T. Wilson and N. V. Sahinidis. The ALAMO approach to machine learning. Computers & Chemical Engineering, 106:785–795, 2017.
  • [33] Z. T. Wilson and N. V. Sahinidis. Automated learning of chemical reaction networks. Computers & Chemical Engineering, 127:88–98, 2019.
  • [34] Y. Zhang and N. V. Sahinidis. Solving continuous and discrete nonlinear programs with BARON. Computational Optimization and Applications, 92:1123–1161, 2025.