Nonlinear Modeler
Overview
The Knitro Nonlinear Modeler allows describing expressions symbolically as expression trees. Once the expression is described, Knitro evaluates it and computes all required derivatives automatically using automatic differentiation (AD).
Note
The Nonlinear Modeler is currently available through the C and Python APIs only.
Introduction
Consider the following nonlinear program:

Both the objective and the constraint body are general nonlinear expressions. The Nonlinear Modeler represents each one as a directed acyclic graph (DAG), commonly referred to as an expression tree, in which every node is a mathematical operation and every leaf is either a variable or a numeric constant. Each intermediate node takes the values of its children as inputs; the root node’s value is the final result of the expression.
The expression trees for the objective
and the constraint body
are illustrated in the diagrams below:
Expression trees are built bottom-up: starting from the leaves (variables and constants), combining them with operations to form sub-expressions, and continuing until the root is reached. The root is then passed to Knitro as an objective term or a constraint body term.
Available operations
The following operations are available to build expression trees.
Operator |
Math notation |
Type |
Domain |
|---|---|---|---|
Negation |
|
Unary |
|
Sign |
|
Unary |
|
Absolute value |
|
Unary |
|
Square root |
|
Unary |
|
Exponential |
|
Unary |
|
Exponential minus one |
|
Unary |
|
Natural logarithm |
|
Unary |
|
Natural logarithm of |
|
Unary |
|
Base-10 logarithm |
|
Unary |
|
Sine |
|
Unary |
|
Cosine |
|
Unary |
|
Tangent |
|
Unary |
|
Arcsine |
|
Unary |
|
Arccosine |
|
Unary |
|
Arctangent |
|
Unary |
|
Hyperbolic sine |
|
Unary |
|
Hyperbolic cosine |
|
Unary |
|
Hyperbolic tangent |
|
Unary |
|
Inverse hyperbolic sine |
|
Unary |
|
Inverse hyperbolic cosine |
|
Unary |
|
Inverse hyperbolic tangent |
|
Unary |
|
Error function |
|
Unary |
|
Complementary error function |
|
Unary |
|
Addition |
|
Binary |
|
Subtraction |
|
Binary |
|
Multiplication |
|
Binary |
|
Division |
|
Binary |
|
Power |
|
Binary |
|
Two-argument arctangent |
|
Binary |
|
Logarithm to an arbitrary base |
|
Binary |
|
Sum of |
|
N-ary |
|
Product of |
|
N-ary |
|
C interface
Types
-
type KNVarId
An integer index that identifies a decision variable in the Knitro context. Variable indices are filled in by
KN_add_varswhen variables are added to the model.
-
type KNExprId
An integer handle that identifies a single expression node in the context. Every expression-builder function returns a
KNExprIdfor the node it just created. The handle is then passed to other builder functions to compose larger expressions, or toKN_add_obj_expr/KN_add_con_exprto attach the finished tree to the model.
-
type KNConId
An integer index that identifies a constraint in the Knitro context. Constraint indices are filled in by
KN_add_conswhen constraints are added to the model, and are passed toKN_add_con_exprto associate an expression tree with a specific constraint.
Leaf expressions
Leaf nodes are the starting points of any expression tree. A leaf is either a variable or a numeric constant.
KN_var_expr
int KN_var_expr(KN_context *kc, KNVarId var, KNExprId *expr);
int KN_var_exprs(KN_context *kc, size_t n, const KNVarId *vars, KNExprId *exprs);
Return the expression handle(s) for the given variable(s). Most builder functions accept a KNVarId directly via the _v suffix (see below), which is usually more convenient than calling this function explicitly.
KN_constant_expr
int KN_constant_expr(KN_context *kc, double constant, KNExprId *expr);
int KN_constant_exprs(KN_context *kc, size_t n, const double *constants, KNExprId *exprs);
Return the expression handle(s) for the given numeric constant(s). Similarly, builder functions accept a double directly via the _c suffix.
Operand-type suffix convention
Rather than always converting variables and constants to expression handles first, builder functions accept operands of several types directly. The operand type is encoded in a suffix appended to the function name:
Suffix |
Operand type(s) |
|---|---|
(none) |
|
|
|
|
|
|
Two operands: variable/variable, variable/constant, constant/variable, or constant/constant |
|
An expression paired with a variable or a constant |
|
A heterogeneous mix of expressions, variables, and constants (n-ary only) |
For example, KN_pow_expr_vc(kc, x0, 2.0, &result) computes
where x0 is a KNVarId and 2.0 is a constant — no intermediate leaf-expression calls are needed.
Unary expressions
Each function below creates a new node applying a unary operation to a single operand. Three variants exist for every operator: the base name (operand is a KNExprId), the _v variant (operand is a KNVarId), and the _c variant (operand is a double).
All share the same signature pattern:
int KN_<op>_expr (KN_context *kc, KNExprId operand, KNExprId *expr);
int KN_<op>_expr_v (KN_context *kc, KNVarId operand, KNExprId *expr);
int KN_<op>_expr_c (KN_context *kc, double operand, KNExprId *expr);
Operator |
C function |
Math notation |
|---|---|---|
Negation |
|
|
Sign |
|
|
Absolute value |
|
|
Square root |
|
|
Exponential |
|
|
Exponential minus one |
|
|
Natural logarithm |
|
|
Natural logarithm of |
|
|
Base-10 logarithm |
|
|
Sine |
|
|
Cosine |
|
|
Tangent |
|
|
Arcsine |
|
|
Arccosine |
|
|
Arctangent |
|
|
Hyperbolic sine |
|
|
Hyperbolic cosine |
|
|
Hyperbolic tangent |
|
|
Inverse hyperbolic sine |
|
|
Inverse hyperbolic cosine |
|
|
Inverse hyperbolic tangent |
|
|
Error function |
|
|
Complementary error function |
|
|
Binary expressions
Each function below creates a node applying a binary operation to two operands. All operand-type suffixes are supported: _vv, _vc, _cv, _cc, _xv, _vx, _xc, _cx, and no suffix (both operands are KNExprId).
Example signatures:
/* both operands are KNExprId */
int KN_add_expr (KN_context *kc, KNExprId left, KNExprId right, KNExprId *expr);
/* variable base, constant exponent */
int KN_pow_expr_vc (KN_context *kc, KNVarId base, double exp, KNExprId *expr);
/* expression numerator, constant denominator */
int KN_div_expr_xc (KN_context *kc, KNExprId numer, double denom, KNExprId *expr);
Operator |
C function |
Math notation |
|---|---|---|
Addition |
|
|
Subtraction |
|
|
Multiplication |
|
|
Division |
|
|
Power |
|
|
Two-argument arctangent |
|
|
Logarithm to an arbitrary base |
|
|
N-ary expressions
When an operation involves more than two operands of the same kind, n-ary builders accept all operands at once, avoiding the need to chain binary operations.
The standard variants share this signature pattern:
int KN_<op>_expr (KN_context *kc, size_t n, const KNExprId *operands, KNExprId *expr);
int KN_<op>_expr_v (KN_context *kc, size_t n, const KNVarId *operands, KNExprId *expr);
int KN_<op>_expr_c (KN_context *kc, size_t n, const double *operands, KNExprId *expr);
The _xvc variant accepts a heterogeneous mix of operand types in a single call:
int KN_<op>_expr_xvc(KN_context *kc,
size_t n_exprs, const KNExprId *exprs,
size_t n_vars, const KNVarId *vars,
size_t n_constants, const double *constants,
KNExprId *expr);
Operator |
C function |
Math notation |
|---|---|---|
Sum of |
|
|
Product of |
|
|
Registering expressions with the model
Once the root of an expression tree has been built, it must be attached to the model before calling KN_solve.
KN_add_obj_expr
int KN_add_obj_expr(KN_context *kc, KNExprId expr);
int KN_add_obj_exprs(KN_context *kc, size_t n, const KNExprId *exprs);
Add one or more expression trees to the objective function. Multiple calls accumulate: every registered expression is summed to form the complete objective.
KN_add_con_expr
int KN_add_con_expr(KN_context *kc, KNConId con, KNExprId expr);
int KN_add_con_exprs(KN_context *kc, KNConId con, size_t n, const KNExprId *exprs);
Add one or more expression trees to the body of constraint con. The expression is summed with any linear or quadratic structure already loaded for that constraint.
Evaluating expressions
KN_evaluate_expr
int KN_evaluate_expr(KN_context *kc, KNExprId expr, const double *x, double *y);
int KN_evaluate_exprs(KN_context *kc, size_t n, const KNExprId *exprs, const double *x, double *y);
int KN_evaluate_exprs_all(KN_context *kc, const double *x, double *y);
Evaluate one, several, or all registered expression trees at the point x (an array of variable values of length equal to the number of variables in the model). If x is NULL, the current variable values stored in the context are used. Results are written to y. Knitro calls these functions internally during the solve; they are primarily useful for debugging or post-processing.
C examples
The following code builds the expression tree for the HS15 objective
. The full example is available as examples/C/exampleNLP1AD.c.
/* Add two variables; KN_add_vars fills xIndex with their KNVarId values */
KNVarId xIndex[2];
KN_add_vars(kc, 2, xIndex);
/* x0^2 */
KNExprId x0sq;
KN_pow_expr_vc(kc, xIndex[0], 2.0, &x0sq);
/* x1 - x0^2 */
KNExprId x1_minus_x0sq;
KN_sub_expr_vx(kc, xIndex[1], x0sq, &x1_minus_x0sq);
/* (x1 - x0^2)^2 */
KNExprId x1_minus_x0sq_sq;
KN_pow_expr_xc(kc, x1_minus_x0sq, 2.0, &x1_minus_x0sq_sq);
/* 1 - x0 */
KNExprId one_minus_x0;
KN_sub_expr_cv(kc, 1.0, xIndex[0], &one_minus_x0);
/* (1 - x0)^2 */
KNExprId one_minus_x0_sq;
KN_pow_expr_xc(kc, one_minus_x0, 2.0, &one_minus_x0_sq);
/* 100*(x1 - x0^2)^2 */
KNExprId obj_expr;
KN_mul_expr_cx(kc, 100.0, x1_minus_x0sq_sq, &obj_expr);
/* 100*(x1 - x0^2)^2 + (1 - x0)^2 — root node */
KN_add_expr(kc, obj_expr, one_minus_x0_sq, &obj_expr);
/* Attach the root to the objective */
KN_add_obj_expr(kc, obj_expr);
A second example, examples/C/exampleNLP2AD.c, models problem HS40 where the objective is a product of four variables — a natural fit for the n-ary KN_nmul_expr_v:

/* Add four variables; KN_add_vars fills xIndex with their KNVarId values */
KNVarId xIndex[4];
KN_add_vars(kc, 4, xIndex);
/* Add three constraints; KN_add_cons fills cIndex with their KNConId values */
KNConId cIndex[3];
KN_add_cons(kc, 3, cIndex);
/* Objective: x0*x1*x2*x3 via n-ary product */
KNExprId obj_expr;
KN_nmul_expr_v(kc, 4, xIndex, &obj_expr);
KN_add_obj_expr(kc, obj_expr);
/* Constraint c0: x0^3 + x1^2 */
KNExprId x0_cubed, x1_sq, c0_expr;
KN_pow_expr_vc(kc, xIndex[0], 3.0, &x0_cubed);
KN_pow_expr_vc(kc, xIndex[1], 2.0, &x1_sq);
KN_add_expr(kc, x0_cubed, x1_sq, &c0_expr);
KN_add_con_expr(kc, cIndex[0], c0_expr);
examples/C/exampleMINLP1AD.c shows the same approach applied to a MINLP with binary variables and logarithmic expressions (KN_log1p_expr).
Python interface
The Problem class exposes the Nonlinear Modeler through Python operator overloading and a set of mathematical methods, so that expression trees can be written in natural mathematical notation without any API boilerplate.
Types and Problem methods
The full reference for the Python Nonlinear Modeler API — including types (Variable, Expression, Constraint, Relation, ComplementarityConstraint) and Problem methods — is available in the Knitro/Python reference.
Unary expressions
Unary operators are available either as Python operators applied directly to
Variable and Expression objects, or as methods on the
Problem instance. All methods accept an ExpressionLike and
return an Expression.
Operator |
Python expression |
Math notation |
|---|---|---|
Negation |
|
|
Absolute value |
|
|
Sign |
|
|
Square root |
|
|
Exponential |
|
|
Exponential minus one |
|
|
Natural logarithm |
|
|
Natural logarithm of |
|
|
Base-10 logarithm |
|
|
Sine |
|
|
Cosine |
|
|
Tangent |
|
|
Arcsine |
|
|
Arccosine |
|
|
Arctangent |
|
|
Hyperbolic sine |
|
|
Hyperbolic cosine |
|
|
Hyperbolic tangent |
|
|
Inverse hyperbolic sine |
|
|
Inverse hyperbolic cosine |
|
|
Inverse hyperbolic tangent |
|
|
Error function |
|
|
Complementary error function |
|
|
Binary expressions
Binary operators are available either as Python operators on Variable
and Expression objects, or as methods on the Problem instance.
Operator |
Python expression |
Math notation |
|---|---|---|
Addition |
|
|
Subtraction |
|
|
Multiplication |
|
|
Division |
|
|
Power |
|
|
Two-argument arctangent |
|
|
Logarithm to an arbitrary base |
|
|
N-ary expressions
N-ary operators are methods on the Problem instance. Each accepts
either a single iterable or a variable number of ExpressionLike
arguments.
Operator |
Python expression |
Math notation |
|---|---|---|
Sum of |
|
|
Product of |
|
|
Python example
The same HS15 problem expressed with the Python interface:
import knitro
with knitro.Problem() as prob:
x0 = prob.add_variable(ub=0.5, x0=-2.0)
x1 = prob.add_variable(x0=1.0)
prob.add_constraint(x0 * x1 >= 1.0)
prob.add_constraint(x0 + x1**2 >= 0.0)
prob.add_objective(100.0 * (x1 - x0**2)**2 + (1.0 - x0)**2)
status = prob.solve()
print("x0 =", x0.value, "x1 =", x1.value)
The arithmetic operators on Variable and Expression build the same tree shown in the Introduction section — the only difference is that the tree is described in Python syntax rather than with explicit API calls.
The following snippet shows add_complementarity_constraint for a simple complementarity pair
,
:
import knitro
with knitro.Problem() as prob:
x = prob.add_variable(lb=0.0)
y = prob.add_variable(lb=0.0)
prob.add_complementarity_constraint(x, y)
prob.add_objective(x + y)
prob.solve()
Interaction with callbacks
For most models, the Nonlinear Modeler suffices: expression trees are built, KN_solve (or prob.solve()) is called, and Knitro handles evaluation and differentiation automatically.
For advanced use cases, Knitro also provides a lower-level callback interface in which user-defined functions evaluate the objective and constraints. The two approaches can be mixed in the same model: some parts can be described as expression trees while others are handled by user callbacks. A new-point callback — a function Knitro calls every time it computes a new iterate — can always be registered alongside expression trees regardless of which approach is used for the model structure.
See also
Evaluation callbacks for a description of the callback-based derivative interface.
Callable library API reference for the complete callable library reference.



















![x \in [-1,\, 1]](../_images/math/ad90b177b14bc76c184731802d9cc2d1fa02c7b8.png)
























operands

