1#ifndef LINE_OPT_VARIABLES_H
2#define LINE_OPT_VARIABLES_H
41 throw InputError(
"line-opt: variable '" +
name_ +
"' cannot be applied to a flat Network");
44 throw InputError(
"line-opt: variable '" +
name_ +
"' cannot be applied to a LayeredNetwork");
46 virtual std::string
type()
const=0;
64public:
ServerAllocation(std::string station,
int lo,
int hi,std::string n=
""):
DecisionVariable(n.empty()?station+
"_servers":n),station_(std::move(station)),lo_(lo),hi_(hi){
if(lo>hi)
throw InputError(
"ServerAllocation: invalid bounds");}
65 Value decode(
const std::vector<double>&x)
const override{
return {double(std::clamp<int>(
int(std::llround(lo_+x.at(0)*(hi_-lo_))),lo_,hi_))};}
67 std::string
type()
const override{
return "server_allocation";}
private:std::string station_;
int lo_,hi_;
70public:
StationReplicas(std::string station,
int lo,
int hi,std::string n=
""):
DecisionVariable(n.empty()?station+
"_replicas":n),station_(std::move(station)),lo_(lo),hi_(hi){}
71 Value decode(
const std::vector<double>&x)
const override{
return {double(std::clamp<int>(
int(std::llround(lo_+x.at(0)*(hi_-lo_))),lo_,hi_))};}
73 std::string
type()
const override{
return "station_replicas";}
private:std::string station_;
int lo_,hi_;
76public:
ServiceRate(std::string station,std::string jobclass,
double lo,
double hi,std::string n=
""):
DecisionVariable(n.empty()?station+
"_"+jobclass+
"_rate":n),station_(std::move(station)),class_(std::move(jobclass)),lo_(lo),hi_(hi){}
77 Value decode(
const std::vector<double>&x)
const override{
return {lo_+x.at(0)*(hi_-lo_)};}
79 std::string
type()
const override{
return "service_rate";}
private:std::string station_,class_;
double lo_,hi_;
83 Value decode(
const std::vector<double>&x)
const override{
return {double(std::clamp<int>(
int(std::llround(lo_+x.at(0)*(hi_-lo_))),lo_,hi_))};}
85 std::string
type()
const override{
return "job_population";}
private:std::string class_;
int lo_,hi_;
88public:
RoutingProbabilities(std::string c,std::string source,std::vector<std::string>targets,std::string n=
""):
DecisionVariable(n.empty()?c+
"_routing_from_"+source:n,std::max<std::size_t>(1,targets.size()-1)),class_(std::move(c)),source_(std::move(source)),targets_(std::move(targets)){
if(targets_.empty())
throw InputError(
"RoutingProbabilities: no targets");}
89 Value decode(
const std::vector<double>&x)
const override{
Value p(targets_.size());
if(p.size()==1){p[0]=1;
return p;}
double rem=1;
for(std::size_t i=0;i+1<p.size();++i){p[i]=rem*x.at(i);rem-=p[i];}p.back()=rem;
return p;}
91 std::string
type()
const override{
return "routing";}
private:std::string class_,source_;std::vector<std::string>targets_;
94public:
ClassPriority(std::vector<std::string>c,std::string mode=
"levels",
int lo=1,
int hi=10,std::string n=
"class_priorities"):
DecisionVariable(std::move(n),mode==
"levels"?c.size():std::max<std::size_t>(1,c.size()-1)),classes_(std::move(c)),mode_(std::move(mode)),lo_(lo),hi_(hi){}
95 Value decode(
const std::vector<double>&x)
const override{
Value v;
if(mode_==
"levels"){
for(
double z:x)v.push_back(std::round(lo_+z*(hi_-lo_)));
return v;}std::vector<std::pair<double,std::size_t>>k;
for(std::size_t i=0;i<classes_.size();++i)k.push_back({-(i<x.size()?x[i]:0),i});std::stable_sort(k.begin(),k.end());
for(
auto&p:k)v.push_back(
double(p.second));
return v;}
96 void apply(
qn::Network<double>&m,
const Value&v)
const override{
auto&s=m.
raw_struct();
if(mode_==
"levels")
for(std::size_t i=0;i<classes_.size();++i)s.classes.at(
cls(s,classes_[i])-1).prio=int(v.at(i));
else for(std::size_t rank=0;rank<v.size();++rank)s.classes.at(
cls(s,classes_.at(std::size_t(v[rank])))-1).prio=int(v.size()-rank);}
97 std::string
type()
const override{
return "class_priority";}
private:std::vector<std::string>classes_;std::string mode_;
int lo_,hi_;
103 std::string
name =
"")
105 class_(std::move(jobclass)), stations_(std::move(stations)) {}
108 if (stations_.empty())
return {-1.0};
109 const std::size_t index = std::min(
110 static_cast<std::size_t
>(std::floor(std::clamp(x.at(0), 0.0, 1.0) * stations_.size())),
111 stations_.size() - 1);
112 return {
static_cast<double>(index)};
116 if (stations_.empty())
return;
118 const std::size_t mapped_class =
cls(
sn, class_);
119 const std::size_t selected = std::min(
120 static_cast<std::size_t
>(std::max(0.0, std::floor(
scalar_value(value)))),
121 stations_.size() - 1);
122 std::vector<bool> blocked(
sn.nodes.size() + 1,
false);
123 for (std::size_t k = 0; k < stations_.size(); ++k) {
124 const std::size_t station =
node(
sn, stations_[k]);
125 if (k != selected) blocked[station] =
true;
128 std::vector<std::vector<bool>> connected(
129 sn.nodes.size() + 1, std::vector<bool>(
sn.nodes.size() + 1,
false));
130 for (
const auto& block :
sn.P)
131 for (std::size_t i = 1; i <=
sn.nodes.size(); ++i)
132 for (std::size_t j = 1; j <=
sn.nodes.size(); ++j)
133 if (block.second(i - 1, j - 1) > 0.0) connected[i][j] =
true;
136 for (std::size_t r = 1; r <=
sn.classes.size(); ++r) {
137 for (std::size_t i = 1; i <=
sn.nodes.size(); ++i) {
138 std::size_t degree = 0;
139 for (std::size_t j = 1; j <=
sn.nodes.size(); ++j)
140 if (connected[i][j] && (r != mapped_class || !blocked[j])) ++degree;
141 if (degree == 0)
continue;
142 const double probability = 1.0 /
static_cast<double>(degree);
143 for (std::size_t j = 1; j <=
sn.nodes.size(); ++j)
144 if (connected[i][j] && (r != mapped_class || !blocked[j]))
145 routing.set(r, r, i, j, probability);
153 std::string
type()
const override {
return "class_mapping"; }
157 std::vector<std::string> stations_;
void apply(qn::Network< double > &m, const Value &v) const override
Value decode(const std::vector< double > &x) const override
ClassPriority(std::vector< std::string >c, std::string mode="levels", int lo=1, int hi=10, std::string n="class_priorities")
std::string type() const override
ClassServiceMapping(std::string jobclass, std::vector< std::string > stations, std::string name="")
void apply(qn::Network< double > &model, const Value &value) const override
Value decode(const std::vector< double > &x) const override
std::string type() const override
virtual Value decode(const std::vector< double > &x) const =0
virtual void apply(qn::Network< double > &, const Value &) const
virtual bool supports_sensitivity() const
virtual double decode_jacobian(double) const
virtual double rate_jacobian(const Value &) const
virtual ~DecisionVariable()=default
DecisionVariable(std::string n, std::size_t d=1)
virtual std::optional< Value > current_value(const lqn::LqnModel< double > &) const
virtual std::map< std::string, std::string > sensitivity_metric_targets(const lqn::LqnModel< double > &) const
static std::size_t cls(const qn::NetworkStruct< double > &s, const std::string &n)
virtual void apply(lqn::LqnModel< double > &, const Value &) const
static std::size_t node(const qn::NetworkStruct< double > &s, const std::string &n)
const std::string & name() const
virtual std::string sensitivity_key(const lqn::LqnModel< double > &) const
virtual std::vector< std::string > layers(const lqn::LqnModel< double > &) const
std::size_t dimension() const
virtual std::string type() const =0
Value decode(const std::vector< double > &x) const override
JobPopulation(std::string c, int lo, int hi, std::string n="")
std::string type() const override
void apply(qn::Network< double > &m, const Value &v) const override
Value decode(const std::vector< double > &x) const override
RoutingProbabilities(std::string c, std::string source, std::vector< std::string >targets, std::string n="")
std::string type() const override
void apply(qn::Network< double > &m, const Value &v) const override
ServerAllocation(std::string station, int lo, int hi, std::string n="")
Value decode(const std::vector< double > &x) const override
void apply(qn::Network< double > &m, const Value &v) const override
std::string type() const override
std::string type() const override
ServiceRate(std::string station, std::string jobclass, double lo, double hi, std::string n="")
void apply(qn::Network< double > &m, const Value &v) const override
Value decode(const std::vector< double > &x) const override
StationReplicas(std::string station, int lo, int hi, std::string n="")
Value decode(const std::vector< double > &x) const override
std::string type() const override
void apply(qn::Network< double > &m, const Value &v) const override
A network plus its refreshed NetworkStruct.
std::vector< JobClass > classes
std::vector< NodeDef > nodes
every node, in creation order
A queueing network under construction.
void set_number_of_servers(std::size_t node, double n)
queue.setNumberOfServers(n).
NetworkStruct< T > & raw_struct()
The struct WITHOUT refreshing it, for a caller that is still building.
void link(const RoutingMatrix< T > &Pm)
model.link(P): install the routing.
void set_service(std::size_t node, std::size_t cls, const Distrib< T > &d)
station.setService(class, dist).
The routing matrix a model script fills in, MATLAB's P cell array.
The exception types the port throws.
.lqnx -> LqnStruct, a port of matlab/src/lang/layered/@LayeredNetwork/parseXML.m followed by ....
double scalar_value(const Value &v)
std::shared_ptr< DecisionVariable > VariablePtr
std::vector< double > Value
The Network constructor API: Queue, Delay, Source, Sink, Router, ClassSwitch, Cache,...
What an evaluation and a solve return.
static Distrib exp_rate(const T &r)
The intermediate model, and the second stage that flattens it.