Hyperiso 1.0.3
Modular flavour-physics calculations, Wilson coefficients and statistical inference
Loading...
Searching...
No Matches
BlockAccessor.cpp
Go to the documentation of this file.
1#include "BlockAccessor.h"
2
3scalar_t BlockAccessor::getValue(const BlockName& blockName, LhaID id) const {
4 return this->at(blockName)->retrieve(id)->get_val();
5}
6
7std::shared_ptr<Parameter> BlockAccessor::getParameter(const BlockName& blockName, LhaID id) const {
8 return this->at(blockName)->retrieve(id);
9}
10
11bool BlockAccessor::has_param(const BlockName& blockName, LhaID id) const {
12 if (!this->contains(blockName)) return false;
13 return this->at(blockName)->contains(id);
14}
15
16void BlockAccessor::setValue(const BlockName& blockName, LhaID id, scalar_t value) {
17 if (!this->contains(blockName)) {
18 throw std::invalid_argument("Block not found " + blockName.to_string());
19 }
20 auto& blk = this->at(blockName);
21 if (blk->contains(id)) {
22 blk->assign(id, value);
23 } else {
24 blk->store(id, std::make_shared<Parameter>(ParamId(blockName, id), value, 0., 0.));
25 }
26}
27
28void BlockAccessor::setParameter(const BlockName &blockName, LhaID id, std::shared_ptr<Parameter> source) {
29 if (this->contains(blockName)) {
30 this->at(blockName)->store_or_assign(id, source);
31 } else {
32 throw std::invalid_argument("Block not found : " + blockName);
33 }
34}
35
36std::map<LhaID, scalar_t> BlockAccessor::getAllValues(BlockName blockName) {
37 if (this->contains(blockName)) {
38 std::map<LhaID, scalar_t> values;
39 for(auto& [id, p] : this->at(blockName)->getItems()) {
40 values.emplace(id, p->get_val());
41 }
42 return values;
43 } else {
44 throw std::invalid_argument("Block not found : " + blockName);
45 }
46}
47
48std::unordered_set<BlockName> BlockAccessor::get_block_names() const {
49 std::unordered_set<BlockName> out;
50 out.reserve(key_to_name_.size());
51 for (auto& [k, bn] : key_to_name_) out.insert(bn);
52 return out;
53}
54
55
56void BlockAccessor::remove_item(const BlockName& block_name, LhaID id) {
57 if (this->contains(block_name)) {
58 this->at(block_name)->remove(id);
59 } else {
60 LOG_WARN("Cannot remove item from non-existing block", block_name);
61 }
62}
63
64
65std::shared_ptr<BlockAccessor> BlockAccessor::operator[](std::unordered_set<BlockName> block_names) {
66 auto sub_block_accessor = std::make_shared<BlockAccessor>();
67
68 for (const auto& block_name : block_names) {
69 if (!this->contains(block_name)) {
70 for (auto elem : *this) {
71 std::cout << elem.first << std::endl;
72 }
73 LOG_ERROR("BlockAccessor", "Block", block_name, "doesn't exist. Cannot extract.");
74 }
75 auto block_ptr = this->at(block_name);
76 sub_block_accessor->emplace(block_ptr->get_name(), block_ptr);
77 }
78
79 return sub_block_accessor;
80}
81
82std::shared_ptr<BlockAccessor> operator+(std::shared_ptr<BlockAccessor> lhs, std::shared_ptr<BlockAccessor> rhs) {
83 auto res = std::make_shared<BlockAccessor>();
84 for (const auto &b : lhs->get_block_names()) {
85 res->emplace(b, std::make_shared<Block>(lhs->at(b)));
86 }
87
88 for (const auto &b : rhs->get_block_names()) {
89 if (res->contains(b)) {
90 LOG_ERROR("BlockAccessor", "Cannot merge blocks with common blocks using no-priority operator +. Use >> for priority-merge.");
91 }
92 res->emplace(b, std::make_shared<Block>(rhs->at(b)));
93 }
94
95 return res;
96}
97
98double BlockAccessor::get_scale(const BlockName& block_name) const {
99 const auto& blk = this->at(block_name);
100 if (!blk->has_scale()) {
101 LOG_ERROR("Block", block_name, "has no scale");
102 }
103 return blk->get_scale();
104}
105
106bool BlockAccessor::has_scale(const BlockName& block_name) const {
107 return this->at(block_name)->has_scale();
108}
109
110std::shared_ptr<BlockAccessor> operator>>(
111 std::shared_ptr<BlockAccessor> lhs,
112 std::shared_ptr<BlockAccessor> rhs
113) {
114 auto res = std::make_shared<BlockAccessor>();
115
116 for (const auto& b : rhs->get_block_names()) {
117 res->emplace(b, std::make_shared<Block>(rhs->at(b)));
118 }
119
120 for (const auto& b : lhs->get_block_names()) {
121 auto lhsBlock = lhs->at(b);
122
123 if (!res->contains(b)) {
124 res->emplace(b, std::make_shared<Block>(*lhsBlock));
125 continue;
126 }
127
128 auto rhsBlock = rhs->at(b);
129 auto resBlock = res->at(b);
130
131 const auto rhsIds = rhsBlock->getAllIDs();
132
133 for (const auto& id : lhsBlock->getAllIDs()) {
134 auto pLhs = lhs->getParameter(b, id);
135
136 bool inRhs = std::find(rhsIds.begin(), rhsIds.end(), id) != rhsIds.end();
137
138 if (!inRhs) {
139 res->setParameter(b, id, pLhs);
140 continue;
141 }
142
143 auto pRhs = rhs->getParameter(b, id);
144
145 auto [statL, systL] = pLhs->get_std();
146 bool lhsHasNoUncert = (statL == 0 && systL == 0);
147
148 if (!lhsHasNoUncert) {
149 res->setParameter(b, id, pLhs);
150 continue;
151 }
152
153 auto [statR, systR] = pRhs->get_std();
154
155 auto merged = std::make_shared<Parameter>(*pLhs);
156 merged->set_std(statR, systR);
157
158 res->setParameter(b, id, merged);
159 }
160 }
161
162 return res;
163}
164
165std::ostream &operator<<(std::ostream &os, std::shared_ptr<BlockAccessor> ba) {
166 for (auto& block_name : ba->get_block_names()) {
167 os << "Block " << block_name << ":\n";
168 for (auto &[id, val] : ba->getAllValues(block_name)) {
169 os << '\t' << id << ": " << val << '\n';
170 }
171 os << '\n';
172 }
173 return os;
174}
175
176std::unordered_map<std::string, std::shared_ptr<Block>>
178 return this->at(block_name)->get_source_blocks();
179}
180
181std::unordered_map<ParamId, std::shared_ptr<Parameter>>
183 return this->at(block_name)->retrieve(id)->get_source_parameters();
184}
185
186std::unordered_set<ParamId>
187BlockAccessor::get_all_source_parameters(const std::unordered_set<ParamId>& param_ids) const
188{
189 enum class VisitState {
190 Visiting,
191 Done
192 };
193
194 std::unordered_set<ParamId> result;
195 std::unordered_map<ParamId, VisitState> state;
196
197 std::function<void(const ParamId&)> dfs = [&](const ParamId& pid)
198 {
199 auto it = state.find(pid);
200 if (it != state.end()) {
201 if (it->second == VisitState::Visiting) {
202 LOG_WARN("Cycle detected while resolving source parameters for",
203 pid.block, pid.code);
204 }
205 return;
206 }
207
208 state.emplace(pid, VisitState::Visiting);
209
210 if (!this->has_param(pid.block, pid.code)) {
211 result.insert(pid);
212 state[pid] = VisitState::Done;
213 return;
214 }
215
216 std::vector<ParamId> next_ids;
217
218 const auto param_sources = this->get_parameter_sources(pid.block, pid.code);
219 for (const auto& [src_id, src_ptr] : param_sources) {
220 if (src_ptr) {
221 next_ids.push_back(src_id);
222 }
223 }
224
225 if (next_ids.empty()) {
226 const auto block_sources = this->get_block_sources(pid.block);
227 for (const auto& [src_block_name, src_block] : block_sources) {
228 if (!src_block) {
229 continue;
230 }
231
232 for (const auto& [lha_id, param_ptr] : src_block->getItems()) {
233 if (!param_ptr) {
234 continue;
235 }
236 next_ids.push_back(param_ptr->get_id());
237 }
238 }
239 }
240
241 if (next_ids.empty()) {
242 result.insert(pid);
243 } else {
244 for (const auto& next_pid : next_ids) {
245 dfs(next_pid);
246 }
247 }
248
249 state[pid] = VisitState::Done;
250 };
251
252 for (const auto& pid : param_ids) {
253 dfs(pid);
254 }
255
256 return result;
257}
258
259namespace {
260std::string block_info_name(const std::shared_ptr<Block>& block, const std::string& fallback = "") {
261 if (!block) {
262 return fallback;
263 }
264
265 const auto name = block->get_name().to_string();
266 return name.empty() ? fallback : name;
267}
268
269std::vector<std::string> sorted_block_info_names(const std::unordered_set<std::string>& names) {
270 std::vector<std::string> out(names.begin(), names.end());
271 std::sort(out.begin(), out.end());
272 return out;
273}
274
275void collect_source_block_names(
276 const std::shared_ptr<Block>& block,
277 std::unordered_set<const Block*>& visited,
278 std::unordered_set<std::string>& out
279) {
280 if (!block) {
281 return;
282 }
283
284 if (!visited.insert(block.get()).second) {
285 return;
286 }
287
288 for (const auto& [fallback_name, source_block] : block->get_source_blocks()) {
289 if (!source_block) {
290 continue;
291 }
292
293 out.insert(block_info_name(source_block, fallback_name));
294 collect_source_block_names(source_block, visited, out);
295 }
296}
297
298void collect_dependent_block_names(
299 const std::shared_ptr<Block>& block,
300 std::unordered_set<const Block*>& visited,
301 std::unordered_set<std::string>& out
302) {
303 if (!block) {
304 return;
305 }
306
307 if (!visited.insert(block.get()).second) {
308 return;
309 }
310
311 for (const auto& observer : block->getObservers()) {
312 if (!observer) {
313 continue;
314 }
315
316 out.insert(block_info_name(observer));
317 collect_dependent_block_names(observer, visited, out);
318 }
319}
320} // namespace
321
322bool BlockAccessor::is_dependent_block(const BlockName& block_name) const {
323 return std::dynamic_pointer_cast<DependentBlock>(this->at(block_name)) != nullptr;
324}
325
326std::vector<std::string> BlockAccessor::get_source_block_names(const BlockName& block_name) const {
327 std::unordered_set<std::string> names;
328 for (const auto& [fallback_name, source_block] : this->at(block_name)->get_source_blocks()) {
329 if (source_block) {
330 names.insert(block_info_name(source_block, fallback_name));
331 }
332 }
333 return sorted_block_info_names(names);
334}
335
336std::vector<std::string> BlockAccessor::get_dependent_block_names(const BlockName& block_name) const {
337 std::unordered_set<std::string> names;
338 for (const auto& observer : this->at(block_name)->getObservers()) {
339 if (observer) {
340 names.insert(block_info_name(observer));
341 }
342 }
343 return sorted_block_info_names(names);
344}
345
346std::vector<std::string> BlockAccessor::get_all_source_block_names(const BlockName& block_name) const {
347 std::unordered_set<const Block*> visited;
348 std::unordered_set<std::string> names;
349 collect_source_block_names(this->at(block_name), visited, names);
350 return sorted_block_info_names(names);
351}
352
353std::vector<std::string> BlockAccessor::get_all_dependent_block_names(const BlockName& block_name) const {
354 std::unordered_set<const Block*> visited;
355 std::unordered_set<std::string> names;
356 collect_dependent_block_names(this->at(block_name), visited, names);
357 return sorted_block_info_names(names);
358}
359
360
361void BlockAccessor::emplace(const BlockName& name, std::shared_ptr<Block> block) {
362 std::string existing_key = key_for(name);
363
364 std::string key;
365 if (!existing_key.empty()) {
366 key = existing_key;
367 } else {
368 std::string best;
369 bool first = true;
370 for (const auto& a : name.get_alias()) {
371 auto an = normalize(a);
372 if (first || an < best) { best = an; first = false; }
373 }
374 key = best;
375 }
376
377 base_t::operator[](key) = std::move(block);
378
379 auto& stored = base_t::operator[](key);
380 if (stored) stored->bind_self(stored);
381
382 merge_name_into_key(key, name);
383}
384
385
386std::shared_ptr<BlockAccessor> BlockAccessor::deep_clone_plain() const {
387 auto clone = std::make_shared<BlockAccessor>();
388 for (const auto& block_name : this->get_block_names()) {
389 const auto& block = this->at(block_name);
390 if (!block) {
391 continue;
392 }
393 clone->emplace(block_name, block->deep_clone_plain());
394 }
395 return clone;
396}
397
398void BlockAccessor::detach_block(const BlockName& block_name) {
399 auto blk = this->at(block_name);
400
401 auto dep = std::dynamic_pointer_cast<DependentBlock>(blk);
402 if (!dep) {
403 return;
404 }
405
406 dep->detach();
407}
408
410 auto blk = this->at(block_name);
411
412 auto dep = std::dynamic_pointer_cast<DependentBlock>(blk);
413 if (!dep) {
414 return;
415 }
416
417 dep->reattach();
418}
419
421 auto param = this->at(block_name)->retrieve(id);
422
423 auto dep = std::dynamic_pointer_cast<DependentParameter>(param);
424 if (!dep) {
425 return;
426 }
427
428 dep->detach();
429}
430
432 auto param = this->at(block_name)->retrieve(id);
433
434 auto dep = std::dynamic_pointer_cast<DependentParameter>(param);
435 if (!dep) {
436 return;
437 }
438
439 dep->reattach();
440}
441
442std::string BlockAccessor::normalize(std::string_view s) {
443 std::string out;
444 out.reserve(s.size());
445 for (unsigned char c : std::string(s)) out.push_back(char(std::toupper(c)));
446 return out;
447}
448
449std::string BlockAccessor::key_for(std::string_view alias) const {
450 const std::string a = normalize(alias);
451
452 if (auto it = alias_to_key_.find(a); it != alias_to_key_.end())
453 return it->second;
454
455 if (base_t::find(a) != base_t::end())
456 return a;
457
458 const std::string raw{alias};
459 if (base_t::find(raw) != base_t::end())
460 return raw;
461
462 return "";
463}
464
465std::string BlockAccessor::key_for(const std::string& alias) const {
466 auto a = normalize(alias);
467 auto it = alias_to_key_.find(a);
468 if (it == alias_to_key_.end()) return "";
469 return it->second;
470}
471
472std::string BlockAccessor::key_for(const BlockName& name) const {
473 for (const auto& a : name.get_alias()) {
474 auto k = key_for(a);
475 if (!k.empty()) return k;
476 }
477 auto one = name.to_string();
478 if (!one.empty()) {
479 auto k = key_for(one);
480 if (!k.empty()) return k;
481 }
482 return "";
483}
484
485std::string BlockAccessor::resolve_key(std::string_view alias) const {
486 return key_for(alias);
487}
488
489std::string BlockAccessor::resolve_key(const BlockName& name) const {
490 return key_for(name);
491}
492
493std::string BlockAccessor::choose_key(const std::unordered_set<std::string>& aliases_norm) {
494 if (aliases_norm.empty()) return "";
495 return *std::min_element(aliases_norm.begin(), aliases_norm.end());
496}
497
498
499
500void BlockAccessor::merge_name_into_key(const std::string& key, const BlockName& name) {
501 auto& full = key_to_name_[key];
502 for (const auto& a : name.get_alias()) full.addAlias(a);
503
504 for (const auto& a : full.get_alias()) {
505 alias_to_key_[ normalize(a) ] = key;
506 }
507}
508
509bool BlockAccessor::contains(std::string_view name) const {
510 return !resolve_key(name).empty();
511}
512
513bool BlockAccessor::contains(const BlockName& name) const {
514 return !resolve_key(name).empty();
515}
516
517std::shared_ptr<Block>& BlockAccessor::at(const BlockName& name) {
518 auto key = resolve_key(name);
519 if (key.empty())
520 throw std::invalid_argument("Block not found " + name.to_string());
521 return std::unordered_map<std::string, std::shared_ptr<Block>>::at(key);
522}
523
524const std::shared_ptr<Block>& BlockAccessor::at(const BlockName& name) const {
525 auto key = resolve_key(name);
526 if (key.empty())
527 throw std::invalid_argument("Block not found " + name.to_string());
528 return std::unordered_map<std::string, std::shared_ptr<Block>>::at(key);
529}
530
531std::shared_ptr<Block>& BlockAccessor::at(std::string_view name) {
532 auto key = resolve_key(name);
533 if (key.empty())
534 throw std::invalid_argument("Block not found " + std::string(name));
535 return std::unordered_map<std::string, std::shared_ptr<Block>>::at(key);
536}
537
538const std::shared_ptr<Block>& BlockAccessor::at(std::string_view name) const {
539 auto key = resolve_key(name);
540 if (key.empty())
541 throw std::invalid_argument("Block not found " + std::string(name));
542 return std::unordered_map<std::string, std::shared_ptr<Block>>::at(key);
543}
544
545bool BlockAccessor::has_param(std::string_view block, const LhaID& id) const {
546 if (!contains(block)) return false;
547 return at(block)->contains(id);
548}
549
550scalar_t BlockAccessor::getValue(std::string_view block, const LhaID& id) const {
551 return at(block)->retrieve(id)->get_val();
552}
553
554void BlockAccessor::setValue(std::string_view block, const LhaID& id, scalar_t value) {
555 auto& blk = at(block);
556 if (blk->contains(id)) {
557 blk->assign(id, value);
558 } else {
559 blk->store(id, std::make_shared<Parameter>(ParamId(std::string(block), id), value, 0, 0));
560 }
561}
562
563void BlockAccessor::remove_item(std::string_view block, const LhaID& id) {
564 at(block)->remove(id);
565}
566
567bool BlockAccessor::has_scale(std::string_view block) const {
568 if (!contains(block)) return false;
569 return at(block)->has_scale();
570}
571
572double BlockAccessor::get_scale(std::string_view block) const {
573 return at(block)->get_scale();
574}
575
576void BlockAccessor::erase_block(std::string_view alias_or_key) {
577 const std::string key = key_for(alias_or_key);
578 if (key.empty()) return;
579
580 std::unordered_map<std::string, std::shared_ptr<Block>>::erase(key);
581
582 auto itn = key_to_name_.find(key);
583 if (itn != key_to_name_.end()) {
584 for (const auto& a : itn->second.get_alias()) {
585 auto ita = alias_to_key_.find(normalize(a));
586 if (ita != alias_to_key_.end() && ita->second == key) {
587 alias_to_key_.erase(ita);
588 }
589 }
590 key_to_name_.erase(itn);
591 }
592}
593
595 for (const auto& a : name.get_alias()) {
596 const std::string key = key_for(a);
597 if (!key.empty()) {
598 erase_block(std::string_view{key});
599 return;
600 }
601 }
602}
std::shared_ptr< BlockAccessor > operator>>(std::shared_ptr< BlockAccessor > lhs, std::shared_ptr< BlockAccessor > rhs)
std::ostream & operator<<(std::ostream &os, std::shared_ptr< BlockAccessor > ba)
std::shared_ptr< BlockAccessor > operator+(std::shared_ptr< BlockAccessor > lhs, std::shared_ptr< BlockAccessor > rhs)
Alias-aware façade for accessing and manipulating multiple parameter blocks.
#define LOG_ERROR(type,...)
Macro for logging error messages and terminating the application.
Definition Logger.h:41
#define LOG_WARN(...)
Macro for logging warning messages.
Definition Logger.h:40
void remove_item(const BlockName &block_name, LhaID id)
Removes one parameter from a block.
std::unordered_map< std::string, std::shared_ptr< Block > > get_block_sources(const BlockName &block_name) const
Returns the source blocks of a given block.
std::shared_ptr< Block > & at(const BlockName &block_name)
Alias-aware mutable access to a block.
void reattach_block(const BlockName &block_name)
Reattaches a previously detached dependent block to its saved sources.
std::vector< std::string > get_source_block_names(const BlockName &block_name) const
Returns the direct source block names of a block.
bool contains(const BlockName &block_name) const
Checks whether a block exists (alias-aware).
bool is_dependent_block(const BlockName &block_name) const
Checks whether a block is implemented as a DependentBlock.
scalar_t getValue(const BlockName &blockName, LhaID pdgCode) const
Retrieves the current value of a parameter from a block.
void detach_parameter(const BlockName &block_name, LhaID id)
Detaches a dependent parameter from its upstream dependencies.
void erase_block(const BlockName &name)
Erases a block and removes all associated aliases from metadata.
void reattach_parameter(const BlockName &block_name, LhaID id)
Reattaches a previously detached dependent parameter.
std::unordered_set< ParamId > get_all_source_parameters(const std::unordered_set< ParamId > &param_ids) const
Recursively finds all leaf source parameters behind a set of parameters.
std::unordered_map< ParamId, std::shared_ptr< Parameter > > get_parameter_sources(const BlockName &block_name, LhaID id) const
Returns the source parameters of a given parameter.
std::vector< std::string > get_all_source_block_names(const BlockName &block_name) const
Returns all transitive source block names of a block.
void emplace(const BlockName &name, std::shared_ptr< Block > blk)
Inserts or replaces a block, updating alias metadata.
void setParameter(const BlockName &blockName, LhaID id, std::shared_ptr< Parameter > source)
Inserts or updates a full Parameter object in a block.
std::unordered_set< BlockName > get_block_names() const
Returns the set of all known block names.
void detach_block(const BlockName &block_name)
Detaches a dependent block from its upstream dependencies.
bool has_param(const BlockName &blockName, LhaID pdgCode) const
Checks whether a given parameter exists inside a named block.
void setValue(const BlockName &blockName, LhaID pdgCode, scalar_t value)
Sets the value of a parameter inside an existing block.
std::shared_ptr< Parameter > getParameter(const BlockName &blockName, LhaID id) const
Retrieves the full Parameter object stored in a block.
std::map< LhaID, scalar_t > getAllValues(BlockName blockName)
Returns all current scalar values stored in a block.
std::vector< std::string > get_dependent_block_names(const BlockName &block_name) const
Returns the direct dependent block names observing a block.
double get_scale(const BlockName &block_name) const
Returns the scale attached to a given block.
std::shared_ptr< BlockAccessor > deep_clone_plain() const
Deep-copy all stored blocks as independent plain blocks.
std::shared_ptr< BlockAccessor > operator[](std::unordered_set< BlockName > block_names)
Extracts a subset of blocks into a new accessor.
std::vector< std::string > get_all_dependent_block_names(const BlockName &block_name) const
Returns all transitive dependent block names observing a block.
bool has_scale(const BlockName &block_name) const
Checks whether a given block has a scale attached.
Block identifier with alias support.
Definition BlockName.h:59
std::string to_string() const
Returns a string representation of the block name.
Definition BlockName.cpp:41
Hash specialization for SymbolId<Tag>.
Definition BlockName.h:353
Represents an identifier of a LHA element, possibly containing several sub-ids.
Definition LhaID.h:56
Composite identifier for a single parameter.
Definition ParamID.h:57