LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Toggle main menu visibility
Loading...
Searching...
No Matches
bisection_solver.h
Go to the documentation of this file.
1
#ifndef LINE_OPT_BISECTION_SOLVER_H
2
#define LINE_OPT_BISECTION_SOLVER_H
3
4
/**
5
* @file
6
* @ingroup line_opt
7
* Binary search for the smallest, or largest, feasible value of ONE variable.
8
*
9
* Where the feasible set is an interval in a single integer variable -- "how few
10
* servers meet this response-time target" -- a population search is the wrong
11
* tool: feasibility is monotone in the variable, so bisection finds the boundary
12
* in log(range) solves. `direction` is `min_feasible` or `max_feasible`.
13
*
14
* It REFUSES anything else: the problem must have exactly one dimension-1
15
* variable whose bounds are integral, and it throws rather than falling back to a
16
* general search, because a silent fallback would hide that the monotonicity
17
* assumption does not hold. Probes are cached by value, so a repeated midpoint
18
* costs nothing.
19
*
20
* Formatting note: written compactly, one member per line, unlike the rest of
21
* the tree.
22
*/
23
#include <chrono>
24
#include <cmath>
25
#include <map>
26
#include <string>
27
#include <utility>
28
#include <vector>
29
#include "
line/opt/problem.h
"
30
#include "
line/util/error.h
"
31
namespace
line
{
namespace
opt
{
32
class
BisectionSolver
{
33
struct
Probe{
bool
feasible;
EvaluationResult
base;std::map<std::string,double>violations;};
34
public
:
BisectionSolver
(
const
OptimizationProblem
&p,std::string direction=
"min_feasible"
,
LineEvaluator::SolveFunction
solve
={}):problem_(p),direction_(std::move(direction)),solve_(std::move(
solve
)){
35
if
(!problem_.
validate
().empty())
throw
InputError
(
"BisectionSolver: invalid optimization problem"
);
if
(problem_.
variables
().size()!=1||problem_.
variables
()[0]->dimension()!=1)
throw
InputError
(
"BisectionSolver requires exactly one dimension-1 decision variable"
);var_=problem_.
variables
()[0];
36
const
double
lo=
scalar_value
(var_->decode({0})),hi=
scalar_value
(var_->decode({1}));
if
(!std::isfinite(lo)||!std::isfinite(hi)||std::fmod(lo,1.0)!=0.0||std::fmod(hi,1.0)!=0.0)
throw
InputError
(
"BisectionSolver requires an integer-valued variable"
);lo_=long(std::llround(lo));hi_=long(std::llround(hi));
37
evaluators_.emplace_back(problem_.
model_variant
(),problem_.
variables
(),problem_.
fixed_variables
(),solve_);
for
(
const
auto
&s:problem_.
scenarios
())evaluators_.emplace_back(s.model,problem_.
variables
(),problem_.
fixed_variables
(),solve_);
38
}
39
OptimizationResult
solve
(){
auto
start=std::chrono::steady_clock::now();
long
lo=lo_,hi=hi_;std::size_t it=0;
if
(direction_==
"min_feasible"
)
while
(lo<hi){
long
m=(lo+hi)/2;
if
(probe(m).feasible)hi=m;
else
lo=m+1;++it;}
else
if
(direction_==
"max_feasible"
)
while
(lo<hi){
long
m=(lo+hi+1)/2;
if
(probe(m).feasible)lo=m;
else
hi=m-1;++it;}
else
throw
InputError
(
"BisectionSolver: unknown direction '"
+direction_+
"'"
);
auto
&p=probe(lo);
OptimizationResult
out;out.
variable_values
[var_->name()]={double(lo)};out.
feasible
=p.feasible;out.
constraint_violations
=p.violations;out.
iterations
=it;
for
(
const
auto
&e:evaluators_)out.
model_evaluations
+=e.evaluation_count();out.
terminated_by
=
"bisection"
;
VariableValues
all=fixed_values();all[var_->name()]={double(lo)};out.
objective_value
=problem_.objective()->evaluate(p.base,all);out.
solve_time
=std::chrono::duration<double>(std::chrono::steady_clock::now()-start).count();
return
out;}
40
private
:std::vector<ConstraintPtr>all_constraints()
const
{
auto
c=problem_.
objective
()->constraints;c.insert(c.end(),problem_.
constraints
().begin(),problem_.
constraints
().end());
return
c;}
VariableValues
fixed_values()
const
{
VariableValues
v;
for
(
const
auto
&f:problem_.
fixed_variables
())v[f.first->name()]=f.second;
return
v;}
41
Probe&probe(
long
value){
auto
found=cache_.find(value);
if
(found!=cache_.end())
return
found->second;
VariableValues
v;v[var_->name()]={double(value)};
VariableValues
all=fixed_values();all.insert(v.begin(),v.end());Probe p{
true
,EvaluationResult(),{}};
bool
first=
true
;
for
(
auto
&e:evaluators_){
auto
r=e.evaluate(v);
if
(first){p.base=r;first=
false
;}
if
(!r.feasible){p.feasible=
false
;
continue
;}
for
(
const
auto
&c:all_constraints()){
double
x=c->evaluate(r,all);
if
(x>0){p.feasible=
false
;p.violations[c->name()]=std::max(p.violations[c->name()],x);}}}
return
cache_.emplace(value,std::move(p)).first->second;}
42
const
OptimizationProblem&problem_;std::string direction_;
LineEvaluator::SolveFunction
solve_;
VariablePtr
var_;
long
lo_=0,hi_=0;std::vector<LineEvaluator>evaluators_;std::map<long,Probe>cache_;
43
};
44
} }
45
#endif
line::InputError
Malformed or inconsistent input (dimensions, negative populations, ...).
Definition
error.h:37
line::InputError::InputError
InputError(const std::string &what)
Definition
error.h:39
line::opt::BisectionSolver::solve
OptimizationResult solve()
Definition
bisection_solver.h:39
line::opt::BisectionSolver::BisectionSolver
BisectionSolver(const OptimizationProblem &p, std::string direction="min_feasible", LineEvaluator::SolveFunction solve={})
Definition
bisection_solver.h:34
line::opt::LineEvaluator::SolveFunction
std::function< mva::AvgResult< double >( const qn::NetworkStruct< double > &)> SolveFunction
Definition
evaluator.h:49
line::opt::OptimizationProblem
Definition
problem.h:40
line::opt::OptimizationProblem::constraints
const std::vector< ConstraintPtr > & constraints() const
Definition
problem.h:111
line::opt::OptimizationProblem::validate
std::vector< std::string > validate() const
Definition
problem.h:79
line::opt::OptimizationProblem::objective
const ObjectivePtr & objective() const
Definition
problem.h:110
line::opt::OptimizationProblem::variables
const std::vector< VariablePtr > & variables() const
Definition
problem.h:109
line::opt::OptimizationProblem::scenarios
const std::vector< Scenario > & scenarios() const
Definition
problem.h:113
line::opt::OptimizationProblem::model_variant
const OptimizationModel & model_variant() const
Definition
problem.h:108
line::opt::OptimizationProblem::fixed_variables
const std::vector< std::pair< VariablePtr, Value > > & fixed_variables() const
Definition
problem.h:112
error.h
The exception types the port throws.
line::opt
Definition
bisection_solver.h:31
line::opt::scalar_value
double scalar_value(const Value &v)
Definition
results.h:35
line::opt::VariablePtr
std::shared_ptr< DecisionVariable > VariablePtr
Definition
variables.h:160
line::opt::VariableValues
std::map< std::string, Value > VariableValues
Definition
results.h:33
line
Definition
aoi_dist2ph.h:52
line::solve
std::vector< T > solve(const Matrix< T > &A, const std::vector< T > &b)
Convenience: solve Ax = b, leaving A and b untouched.
Definition
lu.h:158
problem.h
The optimization problem: a model, the decision variables to search over, an objective,...
line::opt::EvaluationResult
Definition
results.h:68
line::opt::OptimizationResult
Definition
results.h:98
line::opt::OptimizationResult::objective_value
double objective_value
Definition
results.h:99
line::opt::OptimizationResult::terminated_by
std::string terminated_by
Definition
results.h:103
line::opt::OptimizationResult::model_evaluations
std::size_t model_evaluations
Definition
results.h:102
line::opt::OptimizationResult::variable_values
VariableValues variable_values
Definition
results.h:100
line::opt::OptimizationResult::solve_time
double solve_time
Definition
results.h:102
line::opt::OptimizationResult::feasible
bool feasible
Definition
results.h:102
line::opt::OptimizationResult::iterations
std::size_t iterations
Definition
results.h:102
line::opt::OptimizationResult::constraint_violations
std::map< std::string, double > constraint_violations
Definition
results.h:101
include
line
opt
bisection_solver.h
Generated by
1.18.0