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;
56 return key.empty() ? std::vector<std::string>() : std::vector<std::string>{key};
69public:
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");}
70 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_))};}
72 std::string
type()
const override{
return "server_allocation";}
private:std::string station_;
int lo_,hi_;
75public:
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){}
76 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_))};}
78 std::string
type()
const override{
return "station_replicas";}
private:std::string station_;
int lo_,hi_;
81public:
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){}
82 Value decode(
const std::vector<double>&x)
const override{
return {lo_+x.at(0)*(hi_-lo_)};}
84 std::string
type()
const override{
return "service_rate";}
private:std::string station_,class_;
double lo_,hi_;
88 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_))};}
90 std::string
type()
const override{
return "job_population";}
private:std::string class_;
int lo_,hi_;
93public:
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");}
94 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;}
96 std::string
type()
const override{
return "routing";}
private:std::string class_,source_;std::vector<std::string>targets_;
99public:
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){}
100 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;}
101 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);}
102 std::string
type()
const override{
return "class_priority";}
private:std::vector<std::string>classes_;std::string mode_;
int lo_,hi_;
108 std::string
name =
"")
110 class_(std::move(jobclass)), stations_(std::move(stations)) {}
113 if (stations_.empty())
return {-1.0};
114 const std::size_t index = std::min(
115 static_cast<std::size_t
>(std::floor(std::clamp(x.at(0), 0.0, 1.0) * stations_.size())),
116 stations_.size() - 1);
117 return {
static_cast<double>(index)};
121 if (stations_.empty())
return;
123 const std::size_t mapped_class =
cls(
sn, class_);
124 const std::size_t selected = std::min(
125 static_cast<std::size_t
>(std::max(0.0, std::floor(
scalar_value(value)))),
126 stations_.size() - 1);
127 std::vector<bool> blocked(
sn.nodes.size() + 1,
false);
128 for (std::size_t k = 0; k < stations_.size(); ++k) {
129 const std::size_t station =
node(
sn, stations_[k]);
130 if (k != selected) blocked[station] =
true;
133 std::vector<std::vector<bool>> connected(
134 sn.nodes.size() + 1, std::vector<bool>(
sn.nodes.size() + 1,
false));
135 for (
const auto& block :
sn.P)
136 for (std::size_t i = 1; i <=
sn.nodes.size(); ++i)
137 for (std::size_t j = 1; j <=
sn.nodes.size(); ++j)
138 if (block.second(i - 1, j - 1) > 0.0) connected[i][j] =
true;
141 for (std::size_t r = 1; r <=
sn.classes.size(); ++r) {
142 for (std::size_t i = 1; i <=
sn.nodes.size(); ++i) {
143 std::size_t degree = 0;
144 for (std::size_t j = 1; j <=
sn.nodes.size(); ++j)
145 if (connected[i][j] && (r != mapped_class || !blocked[j])) ++degree;
146 if (degree == 0)
continue;
147 const double probability = 1.0 /
static_cast<double>(degree);
148 for (std::size_t j = 1; j <=
sn.nodes.size(); ++j)
149 if (connected[i][j] && (r != mapped_class || !blocked[j]))
150 routing.set(r, r, i, j, probability);
158 std::string
type()
const override {
return "class_mapping"; }
162 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
virtual std::vector< std::string > sensitivity_keys(const lqn::LqnModel< double > &model) const
Candidate sensitivity-table rows, most specific first; the LN method decides how a layer names its cl...
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
Conservation laws of a layered queueing network, enumerated from its structure.
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.