83 void set_seed(
long long seed) { rng_.set_seed(seed); }
87 const std::string&
model_name()
const {
return model_name_; }
91 population_range_ = check_range(r,
"Population range",
true);
95 think_time_range_ = check_range(r,
"Think time range",
false);
99 task_inf_probability_ = check_probability(p,
"Task infinite probability");
103 proc_inf_probability_ = check_probability(p,
"Processor infinite probability");
107 task_multi_range_ = check_range(r,
"Task multiplicity range",
true);
111 proc_multi_range_ = check_range(r,
"Processor multiplicity range",
true);
115 host_demand_range_ = check_range(r,
"Host demand range",
false);
119 synch_call_range_ = check_range(r,
"Synchronous call range",
true);
141 int num_processors) {
142 validate_args(num_clients, num_levels, num_tasks, num_processors);
145 create_clients(b, num_clients);
152 std::vector<TaskSpec> tspec;
153 tspec.reserve(
static_cast<std::size_t
>(num_tasks));
154 for (
int t = 0; t < num_tasks; ++t) {
156 if (choose_boolean(task_inf_probability_)) {
157 s.mult = std::numeric_limits<double>::infinity();
160 s.mult = double(sample_integer(task_multi_range_));
163 s.hostdem = as_distribution(sample_real(host_demand_range_));
167 std::vector<TaskSpec> pspec;
168 pspec.reserve(
static_cast<std::size_t
>(num_processors));
169 for (
int p = 0; p < num_processors; ++p) {
171 if (choose_boolean(proc_inf_probability_)) {
172 s.mult = std::numeric_limits<double>::infinity();
175 s.mult = double(sample_integer(proc_multi_range_));
181 tasks_per_level_ = make_integer_vector(num_levels, num_tasks);
182 tasks_per_processor_ = make_integer_vector(num_processors, num_tasks);
184 for (
int p = 0; p < num_processors; ++p)
185 b.
processor(proc_name(p), pspec[std::size_t(p)].mult, pspec[std::size_t(p)].sched);
191 std::vector<std::string> host(
static_cast<std::size_t
>(num_tasks));
194 for (
int p = 0; p < num_processors; ++p)
195 for (
int k = 0; k < tasks_per_processor_[std::size_t(p)]; ++k)
196 host[std::size_t(filled++)] = proc_name(p);
198 for (
int t = 0; t < num_tasks; ++t) {
199 const TaskSpec& s = tspec[std::size_t(t)];
200 b.
task(task_name(t), s.mult, s.sched, host[std::size_t(t)]);
201 b.
entry(entry_name(t), task_name(t));
202 b.
activity(act_name(t), s.hostdem, task_name(t));
203 b.
bound_to(act_name(t), entry_name(t));
207 connect_clients_to_tasks(b, num_clients);
208 connect_tasks_to_tasks(b, num_levels);
223 static std::string cproc_name(
int c) {
return "c_processor_" + std::to_string(c + 1); }
224 static std::string ctask_name(
int c) {
return "c_task_" + std::to_string(c + 1); }
225 static std::string centry_name(
int c) {
return "c_entry_" + std::to_string(c + 1); }
226 static std::string cact_name(
int c) {
return "c_activity_" + std::to_string(c + 1); }
227 static std::string proc_name(
int p) {
return "processor_" + std::to_string(p + 1); }
228 static std::string task_name(
int t) {
return "task_" + std::to_string(t + 1); }
229 static std::string entry_name(
int t) {
return "entry_" + std::to_string(t + 1); }
230 static std::string act_name(
int t) {
return "activity_" + std::to_string(t + 1); }
236 static Range check_range(
const Range& r,
const std::string& name,
bool strictly_positive) {
237 const bool lower_ok = strictly_positive ? r.lo > 0.0 : r.lo >= 0.0;
238 if (!(lower_ok && r.lo <= r.hi))
239 throw InputError(
"LayeredNetworkGenerator: " + name +
" is not valid");
243 static double check_probability(
double v,
const std::string& name) {
244 if (!(v >= 0.0 && v <= 1.0))
245 throw InputError(
"LayeredNetworkGenerator: " + name +
" is not valid");
249 static void validate_args(
int clients,
int levels,
int tasks,
int procs) {
250 if (clients < 1)
throw InputError(
"LayeredNetworkGenerator: the number of clients is less "
252 if (levels < 1)
throw InputError(
"LayeredNetworkGenerator: the number of levels is less "
254 if (tasks < 1)
throw InputError(
"LayeredNetworkGenerator: the number of tasks is less than "
256 if (procs < 1)
throw InputError(
"LayeredNetworkGenerator: the number of processors is less "
259 throw InputError(
"LayeredNetworkGenerator: the number of levels is greater than that "
262 throw InputError(
"LayeredNetworkGenerator: the number of processors is greater than "
270 void create_clients(lqn::LqnBuilder<T>& b,
int num_clients) {
271 for (
int c = 0; c < num_clients; ++c) {
272 const int population = sample_integer(population_range_);
273 const double think = sample_real(think_time_range_);
274 b.processor(cproc_name(c), std::numeric_limits<double>::infinity(),
277 b.entry(centry_name(c), ctask_name(c));
282 b.activity(cact_name(c), as_distribution(think), ctask_name(c));
283 b.bound_to(cact_name(c), centry_name(c));
292 void connect_clients_to_tasks(lqn::LqnBuilder<T>& b,
int num_clients) {
293 std::vector<bool> connected(
static_cast<std::size_t
>(num_clients),
false);
294 for (
int t = 0; t < tasks_per_level_[0]; ++t) {
295 const double calls = sample_real(synch_call_range_);
296 const int c = sample_integer(
Range(1.0,
double(num_clients))) - 1;
297 b.sync_call(cact_name(c), entry_name(t), num_traits<T>::from_double(calls));
298 connected[std::size_t(c)] =
true;
300 for (
int c = 0; c < num_clients; ++c) {
301 if (connected[std::size_t(c)])
continue;
302 const double calls = sample_real(synch_call_range_);
303 const int t = sample_integer(
Range(1.0,
double(tasks_per_level_[0]))) - 1;
304 b.sync_call(cact_name(c), entry_name(t), num_traits<T>::from_double(calls));
305 connected[std::size_t(c)] =
true;
310 void connect_tasks_to_tasks(lqn::LqnBuilder<T>& b,
int num_levels) {
311 int seen = tasks_per_level_[0];
312 for (
int l = 1; l < num_levels; ++l) {
313 for (
int t2 = seen; t2 < seen + tasks_per_level_[std::size_t(l)]; ++t2) {
314 const double calls = sample_real(synch_call_range_);
316 sample_integer(
Range(
double(seen - tasks_per_level_[std::size_t(l - 1)] + 1),
318 b.sync_call(act_name(t1), entry_name(t2), num_traits<T>::from_double(calls));
320 seen += tasks_per_level_[std::size_t(l)];
329 int sample_integer(
const Range& r) {
330 const int lower =
static_cast<int>(std::ceil(r.lo));
331 const int upper =
static_cast<int>(std::floor(r.hi));
333 throw InputError(
"LayeredNetworkGenerator: an integer range rounds inwards to an "
335 return lower + rng_.next_int(upper - lower + 1);
338 double sample_real(
const Range& r) {
return r.lo + (r.hi - r.lo) * rng_.next_double(); }
340 bool choose_boolean(
double probability) {
return rng_.next_double() < probability; }
349 std::vector<int> make_integer_vector(
int length,
int sum) {
350 if (length < 1)
throw InputError(
"LayeredNetworkGenerator: makeIntegerVector needs a "
353 throw InputError(
"LayeredNetworkGenerator: makeIntegerVector cannot reach a sum below "
355 std::vector<int> v(
static_cast<std::size_t
>(length), 1);
356 for (
int s = 0; s < sum - length; ++s) ++v[std::size_t(rng_.next_int(length))];
361 static lang::Distrib<T> as_distribution(
double mean) {
370 rng::JavaRandom rng_;
371 std::string model_name_ =
"lnw";
372 Range population_range_ =
Range(1.0, 1.0);
373 Range think_time_range_ =
Range(1.0, 1.0);
374 Range task_multi_range_ =
Range(1.0, 1.0);
375 Range proc_multi_range_ =
Range(1.0, 1.0);
376 Range host_demand_range_ =
Range(1.0, 1.0);
377 Range synch_call_range_ =
Range(1.0, 1.0);
378 double task_inf_probability_ = 0.0;
379 double proc_inf_probability_ = 0.0;
381 std::vector<int> tasks_per_level_;
382 std::vector<int> tasks_per_processor_;