Permalink
Cannot retrieve contributors at this time
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
387 lines (334 sloc)
17.1 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright 2010-2018 Google LLC | |
// Licensed under the Apache License, Version 2.0 (the "License"); | |
// you may not use this file except in compliance with the License. | |
// You may obtain a copy of the License at | |
// | |
// http://www.apache.org/licenses/LICENSE-2.0 | |
// | |
// Unless required by applicable law or agreed to in writing, software | |
// distributed under the License is distributed on an "AS IS" BASIS, | |
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
// See the License for the specific language governing permissions and | |
// limitations under the License. | |
// Linear Programming Protocol Buffers. | |
// | |
// The protocol buffers below make it possible to store and transfer the | |
// representation of Linear and Mixed-Integer Programs. | |
// | |
// A Linear Program (LP) is a mathematical optimization model with a linear | |
// objective function, and linear equality and inequality constraints. | |
// The goal is to achieve the best outcome (such as maximum profit or lowest | |
// cost) by modeling the real-world problem at hand using linear functions. | |
// In a Mixed Integer Program (MIP), some variables may also be constrained to | |
// take integer values. | |
// | |
// Check ./linear_solver.h and Wikipedia for more detail: | |
// http://en.wikipedia.org/wiki/Linear_programming | |
// | |
syntax = "proto2"; | |
option java_package = "com.google.ortools.linearsolver"; | |
option java_multiple_files = true; | |
// import "google/protobuf/wrappers.proto"; | |
import "ortools/util/optional_boolean.proto"; | |
package operations_research; | |
// A variable is always constrained in the form: | |
// lower_bound <= x <= upper_bound | |
// where lower_bound and upper_bound: | |
// - Can form a singleton: x = constant = lower_bound = upper_bound. | |
// - Can form a finite interval: lower_bound <= x <= upper_bound. (x is boxed.) | |
// - Can form a semi-infinite interval. | |
// - lower_bound = -infinity: x <= upper_bound. | |
// - upper_bound = +infinity: x >= lower_bound. | |
// - Can form the infinite interval: lower_bound = -infinity and | |
// upper_bound = +infinity, x is free. | |
// MPVariableProto furthermore stores: | |
// - The coefficient of the variable in the objective. | |
// - Whether the variable is integer. | |
message MPVariableProto { | |
// lower_bound must be <= upper_bound. | |
optional double lower_bound = 1 [default = -inf]; | |
optional double upper_bound = 2 [default = inf]; | |
// The coefficient of the variable in the objective. Must be finite. | |
optional double objective_coefficient = 3 [default = 0.0]; | |
// True if the variable is constrained to be integer. | |
// Ignored if MPModelProto::solver_type is *LINEAR_PROGRAMMING*. | |
optional bool is_integer = 4 [default = false]; | |
// The name of the variable. | |
optional string name = 5 [default = ""]; | |
} | |
// A linear constraint is always of the form: | |
// lower_bound <= sum of linear term elements <= upper_bound, | |
// where lower_bound and upper_bound: | |
// - Can form a singleton: lower_bound == upper_bound. The constraint is an | |
// equation. | |
// - Can form a finite interval [lower_bound, upper_bound]. The constraint is | |
// both lower- and upper-bounded, i.e. "boxed". | |
// - Can form a semi-infinite interval. lower_bound = -infinity: the constraint | |
// is upper-bounded. upper_bound = +infinity: the constraint is lower-bounded. | |
// - Can form the infinite interval: lower_bound = -infinity and | |
// upper_bound = +infinity. The constraint is free. | |
message MPConstraintProto { | |
// var_index[i] is the variable index (w.r.t. to "variable" field of | |
// MPModelProto) of the i-th linear term involved in this constraint, and | |
// coefficient[i] is its coefficient. Only the terms with non-zero | |
// coefficients need to appear. var_index may not contain duplicates. | |
repeated int32 var_index = 6 [packed = true]; | |
repeated double coefficient = 7 [packed = true]; // Must be finite. | |
// lower_bound must be <= upper_bound. | |
optional double lower_bound = 2 [default = -inf]; | |
optional double upper_bound = 3 [default = inf]; | |
// The name of the constraint. | |
optional string name = 4 [default = ""]; | |
// [Advanced usage: do not use this if you don't know what you're doing.] | |
// A lazy constraint is handled differently by the core solving engine, but | |
// it does not change the result. It may or may not impact the performance. | |
// For more info see: http://tinyurl.com/lazy-constraints. | |
optional bool is_lazy = 5 [default = false]; | |
} | |
// This message encodes a partial (or full) assignment of the variables of a | |
// MPModelProto problem. The indices in var_index should be unique and valid | |
// variable indices of the associated problem. | |
message PartialVariableAssignment { | |
repeated int32 var_index = 1 [packed = true]; | |
repeated double var_value = 2 [packed = true]; | |
} | |
// MPModelProto contains all the information for a Linear Programming model. | |
message MPModelProto { | |
// True if the problem is a maximization problem. Minimize by default. | |
optional bool maximize = 1 [default = false]; | |
// Offset for the objective function. Must be finite. | |
optional double objective_offset = 2 [default = 0.0]; | |
// All the variables appearing in the model. | |
repeated MPVariableProto variable = 3; | |
// All the constraints appearing in the model. | |
repeated MPConstraintProto constraint = 4; | |
// Name of the model. | |
optional string name = 5 [default = ""]; | |
// Solution hint. | |
// | |
// If a feasible or almost-feasible solution to the problem is already known, | |
// it may be helpful to pass it to the solver so that it can be used. A solver | |
// that supports this feature will try to use this information to create its | |
// initial feasible solution. | |
// | |
// Note that it may not always be faster to give a hint like this to the | |
// solver. There is also no guarantee that the solver will use this hint or | |
// try to return a solution "close" to this assignment in case of multiple | |
// optimal solutions. | |
optional PartialVariableAssignment solution_hint = 6; | |
} | |
// To support 'unspecified' double value in proto3, the simplest is to wrap | |
// any double value in a nested message (has_XXX works for message fields). | |
// We don't use google/protobuf/wrappers.proto because depending on it makes | |
// the following android integration test fail: | |
// http://sponge/c4bce1fd-41bd-4d0b-b4ca-fc04d4d64621 | |
message OptionalDouble { | |
optional double value = 1; | |
} | |
// MPSolverCommonParameters holds advanced usage parameters that apply to any of | |
// the solvers we support. | |
// All of the fields in this proto can have a value of unspecified. In this | |
// case each inner solver will use their own safe defaults. | |
// Some values won't be supported by some solvers. The behavior in that case is | |
// not defined yet. | |
message MPSolverCommonParameters { | |
// Limit for relative MIP gap. | |
// If the relative MIP gap reaches this value or below, stop the solve before | |
// the time limit. | |
// The relative MIP gap is an upper bound of the relative distance to the | |
// optimal: | |
// for a maximization problem, it is defined as either | |
// (best_bound - objective) / abs(objective) (Gurobi) | |
// abs((best_bound - objective) / best_bound) (SCIP) | |
// where "objective" is the max objective of any solution found so far, and | |
// "best_bound" is the tightest (i.e. lowest) upper bound of the objective | |
// determined so far. | |
// The MIP Gap is sensitive to objective offset. | |
// If the denominator is 0 the MIP Gap is INFINITY for SCIP and Gurobi. | |
// Ask or-core-team@ for other solvers. | |
optional OptionalDouble relative_mip_gap = 1; | |
// Tolerance for primal feasibility of basic solutions: this is the maximum | |
// allowed error in constraint satisfiability. | |
// For SCIP this includes integrality constraints. For Gurobi it does not, you | |
// need to set the custom parameter IntFeasTol. | |
optional OptionalDouble primal_tolerance = 2; | |
// Tolerance for dual feasibility. | |
// For SCIP and Gurobi this is the feasibility tolerance for reduced costs in | |
// LP solution: reduced costs must all be smaller than this value in the | |
// improving direction in order for a model to be declared optimal. | |
// Not supported for other solvers. | |
optional OptionalDouble dual_tolerance = 3; | |
enum LPAlgorithmValues { | |
LP_ALGO_UNSPECIFIED = 0; | |
LP_ALGO_DUAL = 1; // Dual simplex. | |
LP_ALGO_PRIMAL = 2; // Primal simplex. | |
LP_ALGO_BARRIER = 3; // Barrier algorithm. | |
} | |
// Algorithm to solve linear programs. | |
// Ask or-core-team@ if you want to know what this does exactly. | |
optional LPAlgorithmValues lp_algorithm = 4 [default = LP_ALGO_UNSPECIFIED]; | |
// Gurobi and SCIP enable presolve by default. | |
// Ask or-core-team@ for other solvers. | |
optional OptionalBoolean presolve = 5 [default = BOOL_UNSPECIFIED]; | |
// Enable automatic scaling of matrix coefficients and objective. Available | |
// for Gurobi and GLOP. | |
// Ask or-core-team@ if you want more details. | |
optional OptionalBoolean scaling = 7 [default = BOOL_UNSPECIFIED]; | |
} | |
message MPModelRequest { | |
// The model to be optimized by the server. | |
optional MPModelProto model = 1; | |
// The solver type, which will select a specific implementation, and will also | |
// impact the interpretation of the model (i.e. are we solving the problem | |
// as a mixed integer program or are we relaxing it as a continuous linear | |
// program?). | |
// This must remain consistent with MPSolver::OptimizationProblemType. | |
enum SolverType { | |
GLOP_LINEAR_PROGRAMMING = 2; // Recommended default for LP models. | |
CLP_LINEAR_PROGRAMMING = 0; | |
GLPK_LINEAR_PROGRAMMING = 1; | |
GUROBI_LINEAR_PROGRAMMING = 6; // Commercial, needs a valid license. | |
CPLEX_LINEAR_PROGRAMMING = 10; // Commercial, needs a valid license. | |
SCIP_MIXED_INTEGER_PROGRAMMING = 3; // Recommended default for MIP models. | |
GLPK_MIXED_INTEGER_PROGRAMMING = 4; | |
CBC_MIXED_INTEGER_PROGRAMMING = 5; | |
GUROBI_MIXED_INTEGER_PROGRAMMING = 7; // Commercial, needs a valid license. | |
CPLEX_MIXED_INTEGER_PROGRAMMING = 11; // Commercial, needs a valid license. | |
BOP_INTEGER_PROGRAMMING = 12; | |
// WARNING: This solver will currently interpret all variables as integer, | |
// so any solution you get will be valid, but the optimal might be far away | |
// for the real one (when you authorise non-integer value for continuous | |
// variables). | |
SAT_INTEGER_PROGRAMMING = 14; | |
KNAPSACK_MIXED_INTEGER_PROGRAMMING = 13; | |
} | |
optional SolverType solver_type = 2; | |
// Maximum time to be spent by the solver to solve 'model'. If the server is | |
// busy and the RPC's deadline_left is less than this, it will immediately | |
// give up and return an error, without even trying to solve. | |
// | |
// The client can use this to have a guarantee on how much time the | |
// solver will spend on the problem (unless it finds and proves | |
// an optimal solution more quickly). | |
// | |
// If not specified, the time limit on the solver is the RPC's deadline_left. | |
optional double solver_time_limit_seconds = 3; | |
// If this is set, then EnableOutput() will be set on the internal MPSolver | |
// that solves the model. | |
// WARNING: if you set this on a request to prod servers, it will be rejected | |
// and yield the RPC Application Error code MPSOLVER_SOLVER_TYPE_UNAVAILABLE. | |
optional bool enable_internal_solver_output = 4 [default = false]; | |
// Advanced usage. Solver-specific parameters in the solver's own format, | |
// different for each solver. For example, if you use SCIP and you want to | |
// stop the solve earlier than the time limit if it reached a solution that is | |
// at most 1% away from the optimal, you can set this to "limits/gap=0.01". | |
// | |
// Note however that there is no "security" mechanism in place so it is up to | |
// the client to make sure that the given options don't make the solve | |
// non thread safe or use up too much memory for instance. | |
// | |
// If the option format is not understood by the solver, the request will be | |
// rejected and yield an RPC Application error with code | |
// MPSOLVER_MODEL_INVALID_SOLVER_PARAMETERS. | |
optional string solver_specific_parameters = 5; | |
} | |
// Status returned by the solver. They follow a hierarchical nomenclature, to | |
// allow us to add more enum values in the future. Clients should use | |
// InCategory() to match these enums, with the following C++ pseudo-code: | |
// | |
// bool InCategory(MPSolverResponseStatus status, MPSolverResponseStatus cat) { | |
// if (cat == MPSOLVER_OPTIMAL) return status == MPSOLVER_OPTIMAL; | |
// while (status > cat) status >>= 4; | |
// return status == cat; | |
// } | |
enum MPSolverResponseStatus { | |
// Normal responses -- the model was valid, and the solver ran. | |
// These statuses should be "somewhat" repeatable, modulo the fact that the | |
// solver's time limit makes it undeterministic, and could change a FEASIBLE | |
// model to an OPTIMAL and vice-versa (the others, except NOT_SOLVED, should | |
// normally be deterministic). Also, the solver libraries can be buggy. | |
// The solver found the proven optimal solution. This is what should be | |
// returned in most cases. | |
// | |
// WARNING: for historical reason, the value is zero, which means that this | |
// value can't have any subcategories. | |
MPSOLVER_OPTIMAL = 0x0; | |
// The solver had enough time to find some solution that satisfies all | |
// constraints, but it did not prove optimality (which means it may or may | |
// not have reached the optimal). | |
// | |
// This can happen for large LP models (Linear Programming), and is a frequent | |
// response for time-limited MIPs (Mixed Integer Programming). In the MIP | |
// case, the difference between the solution 'objective_value' and | |
// 'best_objective_bound' fields of the MPSolutionResponse will give an | |
// indication of how far this solution is from the optimal one. | |
MPSOLVER_FEASIBLE = 0x1; | |
// The model does not have any solution, according to the solver (which | |
// "proved" it, with the caveat that numerical proofs aren't actual proofs), | |
// or based on trivial considerations (eg. a variable whose lower bound is | |
// strictly greater than its upper bound). | |
MPSOLVER_INFEASIBLE = 0x2; | |
// There exist solutions that make the magnitude of the objective value | |
// as large as wanted (i.e. -infinity (resp. +infinity) for a minimization | |
// (resp. maximization) problem. | |
MPSOLVER_UNBOUNDED = 0x3; | |
// An error (most probably numerical) occurred. | |
// One likely cause for such errors is a large numerical range among variable | |
// coefficients (eg. 1e-16, 1e20), in which case one should try to shrink it. | |
MPSOLVER_ABNORMAL = 0x4; | |
// The solver did not have a chance to diagnose the model in one of the | |
// categories above. | |
MPSOLVER_NOT_SOLVED = 0x6; | |
// Like "NOT_SOLVED", but typically used by model validation functions | |
// returning a "model status", to enhance readability of the client code. | |
MPSOLVER_MODEL_IS_VALID = 0x61; | |
// Special value: the solver status could not be properly translated and is | |
// unknown. | |
MPSOLVER_UNKNOWN_STATUS = 0x63; | |
// Model errors. These are always deterministic and repeatable. | |
// They should be accompanied with a string description of the error. | |
MPSOLVER_MODEL_INVALID = 0x5; | |
// Something is wrong with the fields "solution_hint_var_index" and/or | |
// "solution_hint_var_value". | |
MPSOLVER_MODEL_INVALID_SOLUTION_HINT = 0x54; | |
// Something is wrong with the solver_specific_parameters request field. | |
MPSOLVER_MODEL_INVALID_SOLVER_PARAMETERS = 0x55; | |
// Implementation error: the requested solver implementation is not | |
// available (see MPModelRequest.solver_type). | |
// The linear solver binary was probably not linked with the required library, | |
// eg //ortools/linear_solver:linear_solver_scip for SCIP. | |
MPSOLVER_SOLVER_TYPE_UNAVAILABLE = 0x7; | |
}; | |
message MPSolutionResponse { | |
// Result of the optimization. | |
optional /*required*/ MPSolverResponseStatus status = 1 | |
[default = MPSOLVER_UNKNOWN_STATUS]; | |
// Objective value corresponding to the "variable_value" below, taking into | |
// account the source "objective_offset" and "objective_coefficient". | |
// This is set iff 'status' is OPTIMAL or FEASIBLE. | |
optional double objective_value = 2; | |
// This field is only filled for MIP problems. For a minimization problem, | |
// this is a lower bound on the optimal objective value. For a maximization | |
// problem, it is an upper bound. It is only filled if the status is OPTIMAL | |
// or FEASIBLE. In the former case, best_objective_bound should be equal to | |
// objective_value (modulo numerical errors). | |
optional double best_objective_bound = 5; | |
// Variable values in the same order as the MPModelProto::variable field. | |
// This is a dense representation. These are set iff 'status' is OPTIMAL or | |
// FEASIBLE. | |
repeated double variable_value = 3 [packed = true]; | |
// [Advanced usage.] | |
// Values of the dual variables values in the same order as the | |
// MPModelProto::constraint field. This is a dense representation. | |
// These are not set if the problem was solved with a MIP solver (even if | |
// it is actually a linear program). | |
// These are set iff 'status' is OPTIMAL or FEASIBLE. | |
repeated double dual_value = 4 [packed = true]; | |
// [Advanced usage.] | |
// Values of the reduced cost of the variables in the same order as the | |
// MPModelProto::variable. This is a dense representation. | |
// These are not set if the problem was solved with a MIP solver (even if it | |
// is actually a linear program). | |
// These are set iff 'status' is OPTIMAL or FEASIBLE. | |
repeated double reduced_cost = 6 [packed = true]; | |
} |