User guide · 2.0 development
Running the SHOT Console Application¶
This describes how to run the SHOT executable and its command-line
switches. ./SHOT --help lists the switches and problem formats that your
build supports.
For the debug-output mechanism specifically (--debug, intermediate
problem/solution files), see
docs/DebuggingSHOT.md.
For an annotated solve, iteration-column definitions, row types, and final statuses, see Understanding SHOT output. For settings precedence and common configurations, see Configuring SHOT.
Basic usage¶
./SHOT PROBLEMFILE [ARGUMENTS] [OPTIONS]
PROBLEMFILE is the only required positional argument. Everything else is
optional. Run ./SHOT --help for the built-in usage summary.
The SHOTpy pip package (pip install SHOTpy, or pipx install SHOTpy /
uv tool install SHOTpy for only the command) contains the executable, built
with Cbc, Ipopt and HiGHS, and installs it as the command SHOT, which takes
the same arguments. In Python, SHOTpy_bin.executable() gives the path of the
executable itself.
Without Python, download the archive for your platform (Linux x86_64 or ARM64,
macOS ARM64, or Windows x64) and its .sha256 checksum from the
GitHub releases. It contains the same executable and
solvers as the pip package. Extract it, keep the directory together, and run
./SHOT on Linux and macOS or SHOT.exe on Windows.
Supported problem file formats¶
SHOT always supports:
OSiL (
.osilor.xml)
Support for the following is only present if enabled at compile time
(CMake options HAS_AMPL and HAS_GAMS, both ON by default, but a given
build/package may have either disabled):
AMPL (
.nl) — requiresHAS_AMPLGAMS (
.gms) — requiresHAS_GAMS
./SHOT --help prints exactly which formats the binary you’re running
supports (a “SHOT has been compiled with support for the following problem
formats” line). If a .nl or .gms file is rejected, check that first —
it usually means the build lacks that interface, not that the file is
malformed. OSiL is the safe fallback that’s always available.
When using .nl files through the AMPL Solver Library calling convention,
pass --AMPL (or -AMPL) in addition to the problem file (only valid for
.nl files; requires HAS_AMPL). In this mode SHOT also reads options from
the environment variable shot_options, which AMPL sets with
option shot_options '...';. The options are given as KEY=VALUE
separated by whitespace, and a value with spaces can be put in quotes, e.g.
option shot_options 'Termination.TimeLimit=60 Output.Debug.Path="my dir"';.
Options on the command line take precedence over those in shot_options.
Shorthand flags¶
Flag |
Effect |
|---|---|
|
Assumes the problem is convex (sets |
|
Enables debug-output mode; see DebuggingSHOT.md |
|
Selects the MIP (dual) solver — only the ones the build was compiled with are available |
|
Selects the primal NLP solver |
|
Selects single-tree (branch-and-cut) vs. multi-tree dual strategy — single-tree requires solver callback support, currently only available with CPLEX or Gurobi; Cbc and HiGHS are always forced to multi-tree |
|
Maximum number of threads ( |
|
Absolute objective gap termination tolerance ( |
|
Relative objective gap termination tolerance ( |
|
Time limit in seconds ( |
There is no shorthand flag for the iteration limit — set it directly as
Termination.IterationLimit=<n> (see “Setting any option directly”). It’s often more useful
than --timelimit when you want a reproducible, machine-speed-independent
stopping point (e.g. while debugging).
Setting any option directly¶
Beyond the shorthand flags above, any SHOT setting can be set directly
as a positional KEY=VALUE argument (case-sensitive, no spaces around the
=):
./SHOT problemfile Termination.TimeLimit=100.0 Termination.ObjectiveGap.Absolute=0.1
SHOT matches KEY against its known setting identifiers (checked in order:
string, boolean, integer, enum, then double settings) and parses VALUE
accordingly — booleans are true/false in any case, or 1/0 (the
same holds in options files), enums accept their integer value. Unrecognized keys are ignored: they are listed under
“Unrecognized options” in the log, but do not produce an error — double
check the name (e.g. via --docs, “Full/current options reference”) if a
KEY=VALUE argument doesn’t seem to take effect.
Options can also be read from a file instead of (or in addition to) inline arguments:
--opt [FILE]— read options fromFILEin SHOT’s own (GAMS-like) format; ifFILEis omitted, an existingSHOT.optin the current directory is used, or a new template one is generated.--osol [FILE]— same idea but in OSoL (XML) format; defaults toSHOT.osol.
Output/result files¶
--log FILE— sets the log file name (default:SHOT.login the current directory). See DebuggingSHOT.md for theOutput.Console.LogLevel/Output.File.LogLevelsettings that control verbosity.The solution result is always written in OSrL format, to
--osrl FILEif given, otherwise to<Output.ResultPath>/<problem name>.osrl.--trc [FILE]— additionally writes a trace file (default:<Output.ResultPath>/<problem name>.trc).--sol [FILE]— additionally writes an AMPL.solfile (default:<problemfile with .sol extension>); written automatically when running in--AMPLmode.
Exit codes¶
The exit code tells whether the run itself succeeded. It does not give the model status: an infeasible or unbounded problem, or a run stopped by a limit, still exits with 0, and the status is written to the result files.
Code |
Meaning |
|---|---|
0 |
The problem was solved (whatever the model status), or |
1 |
Invalid command line, e.g. no problem file given, or |
2 |
The problem file or the options file given by |
3 |
An error occurred while solving the problem, e.g. a callback failed |
4 |
A result file (OSrL, trace, |
Using SHOT from Pyomo¶
Pyomo calls SHOT through the AMPL Solver Library
interface: it writes the model to an .nl file, runs the SHOT executable
in -AMPL mode and reads the solution back from the .sol file. This needs
a SHOT executable built with HAS_AMPL (see “Supported problem file
formats”). The SHOTpy pip package contains such an executable (see “Basic
usage”); otherwise build SHOT from source as described in the
compilation instructions.
Pyomo has no built-in shot solver, so use its generic asl: interface and
give the path to the executable, unless SHOT is on your PATH. With the
pip package, executable=SHOTpy_bin.executable() works in any environment:
import pyomo.environ as pyo
from pyomo.opt import TerminationCondition
m = pyo.ConcreteModel()
m.x = pyo.Var(domain=pyo.Integers, bounds=(0, 5))
m.y = pyo.Var(bounds=(0, 5))
m.obj = pyo.Objective(expr=(m.x - 2.3)**2 + (m.y - 1.7)**2)
m.c = pyo.Constraint(expr=m.x**2 + m.y**2 <= 9)
opt = pyo.SolverFactory('asl:shot', executable='/path/to/SHOT')
opt.options['Termination.TimeLimit'] = 60
opt.options['Dual.MIP.NumberOfThreads'] = 1
opt.options['Primal.FixedInteger.Use'] = True
results = opt.solve(m, tee=True)
if results.solver.termination_condition == TerminationCondition.optimal:
print(pyo.value(m.obj), m.x.value, m.y.value)
Options. Each entry in opt.options is passed to SHOT both as a
KEY=VALUE argument and in the environment variable shot_options, so the
rules in “Setting any option directly” apply. Use the full, case-sensitive
setting names. Booleans can be given as Python’s True/False, and enum
settings take their integer value. With tee=True, SHOT’s log lists the
options it received under “Non-default options”, marked [user], and any
names it does not recognize under “Unrecognized options”.
Results. The solution values are loaded into the model, and
results.solver.message holds SHOT’s solve message. Its first part is the
status, e.g. SHOT 2.0.0: Solved to global optimality. The rest names the
problem types and the MIP and NLP solvers used. Pyomo writes : in the
message as \x3a.
Pyomo turns SHOT’s AMPL status code into a termination condition by code
range, so different outcomes can map to the same condition. The exact code is
available in results.solver.id:
Code |
SHOT status |
Pyomo termination condition / solver status |
|---|---|---|
0 |
Solved to global optimality |
|
100 |
Solved to local optimality |
|
101 |
Iteration limit reached, feasible solution found |
|
102 |
User abort, feasible solution found |
|
103 |
Error occurred, feasible solution found |
|
104 |
Feasible solution found, optimality not guaranteed (e.g. nonconvex problems) |
|
200 |
No solution found since dual problem is infeasible |
|
300 |
No solution found since dual problem is unbounded |
|
400 |
Time limit, feasible solution found; or a limit was reached with no solution |
|
500 |
No solution found since an error occurred |
|
600 |
No solution found due to user abort |
|
So optimal only means a global optimum when the solver status is ok
(code 0). A time limit is reported as maxIterations. When SHOT has no
solution it returns no variable values, so the variables in the model keep
the values they had before the solve. Check the termination condition before
using the variable values.
Full/current options reference¶
./SHOT --docs
Writes options.md to the current directory, generated live from the
solver’s actual registered settings (name, type, default, description,
allowed enum values). This is the authoritative settings reference —
prefer it over guessing a setting name, since settings can be added,
renamed, or have their defaults changed between versions.
Quick reference¶
./SHOT --help
prints a build-specific summary of everything above (supported formats for
this build, all shorthand flags available given how it was compiled, and
the general KEY=VALUE mechanism).