LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
infer_lqn_setparams.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012-2026, QORE Lab, Imperial College London
3 * All rights reserved.
4 */
5#ifndef LINE_API_INFER_INFER_LQN_SETPARAMS_H
6#define LINE_API_INFER_INFER_LQN_SETPARAMS_H
7
8/**
9 * @file
10 * @ingroup api_infer
11 * Apply a parameter vector to a LayeredNetworkStruct, and read it back.
12 *
13 * Templated port of matlab/src/api/infer/infer_lqn_setparams.m, plus the
14 * getparams half that MATLAB keeps as a local function inside infer_lqn.m.
15 * No JAR counterpart. This is the parameter-injection side of the LQN
16 * parameter identification method; the filter itself is in infer_lqn_ekf.h
17 * and the driver in infer_lqn.h.
18 *
19 * A parameter is named by an element name and a kind:
20 * HOSTDEM the mean host demand of an ACTIVITY
21 * THINK the mean think time of a TASK
22 *
23 * Means are injected as EXPONENTIAL laws (SCV 1), which is the assumption of
24 * the CASCON 2005 tracking method. Injecting the mean while keeping the
25 * previous shape would make the observation map depend on a shape the filter
26 * never estimates, so the reference does not do it and neither does this port.
27 *
28 * MATLAB mutates the model objects and then invalidates model.lsn so the next
29 * solve re-reads them. The C++ port operates on the STRUCT directly, which is
30 * what the solvers consume, so there is no cache to invalidate; the caller is
31 * responsible for handing the mutated struct back to the solver.
32 *
33 * The lookup is by declared name over the whole element list, so a name that
34 * denotes both a task and an activity is ambiguous. The kind resolves it:
35 * HOSTDEM searches ACTIVITY elements only and THINK searches TASK elements
36 * only, which is exactly what MATLAB's model.activities and model.tasks lists
37 * do and is stricter than a bare name search over `names`.
38 *
39 * ARITHMETIC: assignment only, so any T works.
40 */
41
42#include <cstddef>
43#include <string>
44#include <vector>
45
48#include "line/num/number.h"
49#include "line/util/error.h"
50
51namespace line {
52namespace infer {
53
54/** The two parameter kinds MATLAB's paramSpec(i).type names. */
55enum class LqnParamType { HOSTDEM, THINK };
56
57/** One row of MATLAB's PARAMSPEC struct array. */
60 std::string name;
61};
62
63namespace detail {
64
65/** Index of the element of the given kind and name, or 0 when absent. */
66template <class T>
67std::size_t lqn_find_element(const lqn::LqnStruct<T>& lsn, lang::LqnElement kind,
68 const std::string& name) {
69 for (std::size_t i = 1; i < lsn.names.size(); ++i)
70 if (lsn.type[i] == kind && lsn.names[i] == name) return i;
71 return 0;
72}
73
74/** Index of the element a parameter row names, throwing when it is absent. */
75template <class T>
76std::size_t lqn_param_index(const lqn::LqnStruct<T>& lsn, const LqnParamSpec& p) {
77 const lang::LqnElement kind =
78 (p.type == LqnParamType::HOSTDEM) ? lang::LqnElement::ACTIVITY : lang::LqnElement::TASK;
79 const std::size_t idx = lqn_find_element(lsn, kind, p.name);
80 if (idx == 0) {
81 if (p.type == LqnParamType::HOSTDEM)
82 throw InputError("infer_lqn_setparams: activity '" + p.name + "' not found");
83 throw InputError("infer_lqn_setparams: task '" + p.name + "' not found");
84 }
85 return idx;
86}
87
88} // namespace detail
89
90/**
91 * Read the current values of the parameters named in `spec`.
92 *
93 * @param lsn layered struct to read
94 * @param spec parameters to read, in order
95 * @return (numel(spec)) current values
96 */
97template <class T>
99 const std::vector<LqnParamSpec>& spec) {
100 std::vector<T> a;
101 a.reserve(spec.size());
102 for (std::size_t i = 0; i < spec.size(); ++i) {
103 const std::size_t idx = detail::lqn_param_index(lsn, spec[i]);
104 a.push_back(spec[i].type == LqnParamType::HOSTDEM ? lsn.hostdem[idx].mean
105 : lsn.think[idx].mean);
106 }
107 return a;
108}
109
110/**
111 * Set the parameters named in `spec` to the values in `a`, in place.
112 *
113 * @param lsn layered struct to mutate
114 * @param spec parameters to set, in order
115 * @param a (numel(spec)) values, injected as exponential means
116 */
117template <class T>
118void infer_lqn_setparams(lqn::LqnStruct<T>& lsn, const std::vector<LqnParamSpec>& spec,
119 const std::vector<T>& a) {
120 if (a.size() != spec.size())
121 throw InputError("infer_lqn_setparams: length of parameter vector does not match spec");
122 for (std::size_t i = 0; i < spec.size(); ++i) {
123 const std::size_t idx = detail::lqn_param_index(lsn, spec[i]);
125 if (spec[i].type == LqnParamType::HOSTDEM)
126 lsn.hostdem[idx] = d;
127 else
128 lsn.think[idx] = d;
129 }
130}
131
132} // namespace infer
133} // namespace line
134
135#endif // LINE_API_INFER_INFER_LQN_SETPARAMS_H
InputError(const std::string &what)
Definition error.h:39
The exception types the port throws.
Enumerations and the minimal distribution descriptor shared by the model layer of the C++ port.
LayeredNetworkStruct, the flattened description of a layered queueing network.
void infer_lqn_setparams(lqn::LqnStruct< T > &lsn, const std::vector< LqnParamSpec > &spec, const std::vector< T > &a)
Set the parameters named in spec to the values in a, in place.
std::vector< T > infer_lqn_getparams(const lqn::LqnStruct< T > &lsn, const std::vector< LqnParamSpec > &spec)
Read the current values of the parameters named in spec.
LqnParamType
The two parameter kinds MATLAB's paramSpec(i).type names.
LqnElement
LQN element kinds, with the values of MATLAB LayeredNetworkElement.
Definition lang_types.h:464
Number-type abstraction for the templated API port.
One row of MATLAB's PARAMSPEC struct array.
static Distrib exp_mean(const T &m)
Definition lang_types.h:799