Mads
Multi-Agent Distributed System
Loading...
Searching...
No Matches
dummy.hpp
Go to the documentation of this file.
1/*
2 ____ _
3 | _ \ _ _ _ __ ___ _ __ ___ _ _ ___| | __ _ ___ ___
4 | | | | | | | '_ ` _ \| '_ ` _ \| | | | / __| |/ _` / __/ __|
5 | |_| | |_| | | | | | | | | | | | |_| | | (__| | (_| \__ \__ \
6 |____/ \__,_|_| |_| |_|_| |_| |_|\__, | \___|_|\__,_|___/___/
7 |___/
8
9Author(s): Paolo Bosetti
10*/
11
12#ifndef DUMMY_HPP
13#define DUMMY_HPP
14
15
16#include "mads.hpp"
17#include "agent.hpp"
18#include <armadillo>
19#include <deque>
20#include <memory>
21#include <sstream>
22#include <vector>
23
24using namespace std;
25
26namespace Mads {
27
28class ARIMA {
29public:
30 ARIMA() : p({0.5}), d(0), q({}) {
31 sigma = 0.5;
32 _mem = new vector<double>();
33 }
34
35 ~ARIMA() {}
36
37 string info() {
38 stringstream ss;
39 ss << "ARIMA(" << p.size() << ", " << d << ", " << q.size() << ")"
40 << " sigma: " << sigma << endl;
41 return ss.str();
42 }
43
44 void reset(double x0 = 0) {
45 _x.clear();
46 _w.clear();
47 _x0 = x0;
48 _mem->clear();
49 _mem->reserve(d+1);
50 for (size_t i = 0; i <= d; i++) {
51 _mem->push_back(0);
52 }
53 }
54
55 void set_sigma(double s) { sigma = s; }
56
57 double next() {
58 double w = arma::randn(arma::distr_param(0.0, sigma));
59 double x, xs = 0, ws = 0;
60 double ret = 0;
61 if (q.size() > 0) {
62 _w.push_back(w);
63 if (_w.size() > q.size() + 1) {
64 _w.pop_front();
65 }
66 for (size_t i = 0; i < _w.size(); i++) {
67 ws += _w[i] * q[_w.size() - 1 - i];
68 }
69 }
70 if (p.size() > 0) {
71 for (size_t i = 0; i < _x.size(); i++) {
72 xs += _x[i] * p[_x.size() - 1 - i];
73 }
74 x = xs + w + ws;
75 _x.push_back(x);
76 if (_x.size() > p.size() + 1) {
77 _x.pop_front();
78 }
79 } else {
80 x = w + ws;
81 }
82 if (d > 0) {
83 (*_mem)[0] = x;
84 for (size_t i = 1; i < _mem->size(); i++) {
85 (*_mem)[i] += (*_mem)[i-1];
86 }
87 ret = _x0 + round(_mem->back() * 1000) / 1000.0;
88 } else {
89 ret = _x0 + round(x * 1000) / 1000.0;
90 }
91 return ret;
92 }
93
94public:
95 double sigma;
96 vector<float> p;
97 unsigned int d;
98 vector<float> q;
99
100private:
101 double _x0 = 0;
102 deque<double> _x = {}, _w = {};
103 vector<double> *_mem;
104};
105
106class Dummy : public Agent {
107
108public:
109 Dummy(std::string name, std::string settings_path)
110 : Agent(name, settings_path) {
111 }
112
113 void load_settings() override {
114 auto cfg = _config[_name];
115 _topics.clear();
116 cfg["active_topics"].as_array()->for_each(
117 [&](auto &e) { _topics.push_back(e.value_or("undefined")); });
118 for (auto &t : _topics) {
119 if (!cfg["topics"][t].is_table()) {
120 cerr << fg::red << "Topic " << t << " is not defined" << fg::reset
121 << endl;
122 continue;
123 }
124 auto tab = cfg["topics"][t];
125 auto type = tab["type"].value_or("undefined");
126 _topic_freqs[t] = tab["frequency"].value_or(1);
127 if (type == "arima"s) {
128 _topic_type[t] = "arima";
129 map<string, ARIMA> m{};
130 tab["content"].as_table()->for_each([&](auto &k, auto &v) {
131 m[static_cast<string>(k)] = ARIMA();
132 m[static_cast<string>(k)].p.clear();
133 m[static_cast<string>(k)].q.clear();
134 v.as_table()->at("p").as_array()->for_each([&](auto &e) {
135 m[static_cast<string>(k)].p.push_back(
136 e.as_floating_point()->value_or(0));
137 });
138 m[static_cast<string>(k)].d = v.as_table()->at("d").value_or(0);
139 v.as_table()->at("q").as_array()->for_each([&](auto &e) {
140 m[static_cast<string>(k)].q.push_back(
141 e.as_floating_point()->value_or(0));
142 });
143 m[static_cast<string>(k)].sigma =
144 v.as_table()->at("s").as_floating_point()->value_or(0.5);
145 if (v.as_table()->contains("start")) {
146 double x0 =
147 v.as_table()->at("start").as_floating_point()->value_or(0);
148 m[static_cast<string>(k)].reset(x0);
149 } else {
150 m[static_cast<string>(k)].reset();
151 }
152 });
153 _topic_data[t] = m;
154 } else if (type == "bits"s) {
155 _topic_type[t] = "bits";
156 map<string, double> m{};
157 tab["content"].as_table()->for_each([&](auto &k, auto &v) {
158 m[static_cast<string>(k)] = v.as_floating_point()->value_or(0.5);
159 });
160 _topic_data[t] = m;
161 } else if (type == "gpio"s) {
162 _topic_type[t] = "gpio";
163 map<string, list<int>> m{{"lines", {}}};
164 tab["content"]["lines"].as_array()->for_each(
165 [&](auto &e) { m["lines"].push_back(e.value_or(0)); });
166 _topic_data[t] = m;
167 } else if (type == "image"s) {
168 _topic_type[t] = "image";
169 map<string, unsigned int> m{};
170 m["width"] = tab["content"]["size"].as_array()->at(0).value_or(0);
171 m["height"] = tab["content"]["size"].as_array()->at(1).value_or(1);
172 m["levels"] = tab["content"]["levels"].value_or(256);
173 _topic_data[t] = m;
174 } else if (type == "matrix"s) {
175 _topic_type[t] = "matrix";
176 map<string, double> m{};
177 m["width"] = tab["content"]["size"].as_array()->at(0).value_or(0);
178 m["height"] = tab["content"]["size"].as_array()->at(1).value_or(1);
179 m["mean"] = tab["content"]["mean"].as_floating_point()->value_or(0);
180 m["std"] = tab["content"]["std"].as_floating_point()->value_or(0);
181 _topic_data[t] = m;
182 } else {
183 cerr << fg::red << "Undefined topic type (topic " << t << ")"
184 << fg::reset << endl;
185 }
186 }
187 }
188
189 nlohmann::json make_data() {
190 nlohmann::json data;
191 for (auto &t : _topics) {
192 if (_topic_type[t] == "arima") {
193 auto m = any_cast<map<string, ARIMA>>(_topic_data[t]);
194 for (auto &e : m) {
195 data[t][e.first] = e.second.next();
196 }
197 } else if (_topic_type[t] == "gpio") {
198 auto m = any_cast<map<string, list<int>>>(_topic_data[t]);
199 for (auto &l : m["lines"]) {
200 data[t][to_string(l)] =
201 static_cast<int>(round(arma::randu(arma::distr_param(0, 1))));
202 }
203 } else if (_topic_type[t] == "image") {
204 auto m = any_cast<map<string, unsigned int>>(_topic_data[t]);
205 data[t]["width"] = m["width"];
206 data[t]["height"] = m["height"];
207 data[t]["levels"] = m["levels"];
208 data[t]["data"] = arma::randi<arma::Mat<unsigned int>>(
209 m["height"], m["width"], arma::distr_param(0, m["levels"]));
210 } else if (_topic_type[t] == "matrix") {
211 auto m = any_cast<map<string, double>>(_topic_data[t]);
212 data[t]["width"] = m["width"];
213 data[t]["height"] = m["height"];
214 data[t]["mean"] = m["mean"];
215 data[t]["std"] = m["std"];
216 data[t]["data"] = arma::randn<arma::Mat<double>>(
217 m["height"], m["width"], arma::distr_param(m["mean"], m["std"]));
218 } else if (_topic_type[t] == "bits") {
219 auto m = any_cast<map<string, double>>(_topic_data[t]);
220 for (auto &[k, v] : m) {
221 data[t][k] = (arma::randu(arma::distr_param(0, 1)) > v ? 1 : 0);
222 }
223 }
224 }
225 return data;
226 }
227
228 void publish(bool echo = false) {
229 static unsigned long int i = 0;
230 nlohmann::json data = make_data();
231 if (echo)
232 cout << "(" << i << ") Publishing ";
233 for (auto &t : _topics) {
234 if ((i % _topic_freqs[t]) == 0) {
235 Agent::publish(data[t], t);
236 if (echo)
237 cout << t << " ";
238 }
239 }
240 i++;
241 if (echo)
242 cout << endl;
243 }
244
245 void info(ostream &out = cout) override {
246 Agent::info(out);
247 out << " Topics published:" << style::bold;
248 for (auto &t : _topics) {
249 out << " " << t << " (" << _topic_freqs[t] << ") ";
250 }
251 out << style::reset << endl;
252 }
253
254private:
255 list<string> _topics = {};
256 map<string, any> _topic_data = {};
257 map<string, string> _topic_type = {};
258 map<string, unsigned int> _topic_freqs = {};
259};
260
261} // namespace Mads
262
263#endif // DUMMY_HPP
string info()
Definition dummy.hpp:37
vector< float > p
Definition dummy.hpp:96
vector< float > q
Definition dummy.hpp:98
void reset(double x0=0)
Definition dummy.hpp:44
unsigned int d
Definition dummy.hpp:97
double next()
Definition dummy.hpp:57
void set_sigma(double s)
Definition dummy.hpp:55
double sigma
Definition dummy.hpp:95
toml::table _config
Definition agent.hpp:1289
std::string name()
Returns the name of the agent.
std::string _name
Definition agent.hpp:1286
virtual void info(std::ostream &out=std::cout)
Prints information about the agent.
void publish(nlohmann::json payload, std::string topic="")
Publishes a message with the given JSON payload.
nlohmann::json make_data()
Definition dummy.hpp:189
void publish(bool echo=false)
Definition dummy.hpp:228
Dummy(std::string name, std::string settings_path)
Definition dummy.hpp:109
void info(ostream &out=cout) override
Prints information about the agent.
Definition dummy.hpp:245
void load_settings() override
Additional settings to be loaded. Virtual function to be implemented by the derived class.
Definition dummy.hpp:113
Definition agent.hpp:67