4 return this->
at(blockName)->retrieve(
id)->get_val();
8 return this->
at(blockName)->retrieve(
id);
12 if (!this->
contains(blockName))
return false;
13 return this->
at(blockName)->contains(
id);
18 throw std::invalid_argument(
"Block not found " + blockName.
to_string());
20 auto& blk = this->
at(blockName);
21 if (blk->contains(
id)) {
22 blk->assign(
id, value);
24 blk->store(
id, std::make_shared<Parameter>(
ParamId(blockName,
id), value, 0., 0.));
30 this->
at(blockName)->store_or_assign(
id, source);
32 throw std::invalid_argument(
"Block not found : " + blockName);
38 std::map<LhaID, scalar_t> values;
39 for(
auto& [
id, p] : this->
at(blockName)->getItems()) {
40 values.emplace(
id, p->get_val());
44 throw std::invalid_argument(
"Block not found : " + blockName);
49 std::unordered_set<BlockName> out;
50 out.reserve(key_to_name_.size());
51 for (
auto& [k, bn] : key_to_name_) out.insert(bn);
58 this->
at(block_name)->remove(
id);
60 LOG_WARN(
"Cannot remove item from non-existing block", block_name);
66 auto sub_block_accessor = std::make_shared<BlockAccessor>();
68 for (
const auto& block_name : block_names) {
70 for (
auto elem : *
this) {
71 std::cout << elem.first << std::endl;
73 LOG_ERROR(
"BlockAccessor",
"Block", block_name,
"doesn't exist. Cannot extract.");
75 auto block_ptr = this->
at(block_name);
76 sub_block_accessor->emplace(block_ptr->get_name(), block_ptr);
79 return sub_block_accessor;
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)));
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.");
92 res->emplace(b, std::make_shared<Block>(rhs->at(b)));
99 const auto& blk = this->
at(block_name);
100 if (!blk->has_scale()) {
101 LOG_ERROR(
"Block", block_name,
"has no scale");
103 return blk->get_scale();
107 return this->
at(block_name)->has_scale();
111 std::shared_ptr<BlockAccessor> lhs,
112 std::shared_ptr<BlockAccessor> rhs
114 auto res = std::make_shared<BlockAccessor>();
116 for (
const auto& b : rhs->get_block_names()) {
117 res->emplace(b, std::make_shared<Block>(rhs->at(b)));
120 for (
const auto& b : lhs->get_block_names()) {
121 auto lhsBlock = lhs->at(b);
123 if (!res->contains(b)) {
124 res->emplace(b, std::make_shared<Block>(*lhsBlock));
128 auto rhsBlock = rhs->at(b);
129 auto resBlock = res->at(b);
131 const auto rhsIds = rhsBlock->getAllIDs();
133 for (
const auto&
id : lhsBlock->getAllIDs()) {
134 auto pLhs = lhs->getParameter(b,
id);
136 bool inRhs = std::find(rhsIds.begin(), rhsIds.end(),
id) != rhsIds.end();
139 res->setParameter(b,
id, pLhs);
143 auto pRhs = rhs->getParameter(b,
id);
145 auto [statL, systL] = pLhs->get_std();
146 bool lhsHasNoUncert = (statL == 0 && systL == 0);
148 if (!lhsHasNoUncert) {
149 res->setParameter(b,
id, pLhs);
153 auto [statR, systR] = pRhs->get_std();
155 auto merged = std::make_shared<Parameter>(*pLhs);
156 merged->set_std(statR, systR);
158 res->setParameter(b,
id, merged);
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';
176std::unordered_map<std::string, std::shared_ptr<Block>>
178 return this->
at(block_name)->get_source_blocks();
181std::unordered_map<ParamId, std::shared_ptr<Parameter>>
183 return this->
at(block_name)->retrieve(
id)->get_source_parameters();
186std::unordered_set<ParamId>
189 enum class VisitState {
194 std::unordered_set<ParamId> result;
195 std::unordered_map<ParamId, VisitState> state;
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);
208 state.emplace(pid, VisitState::Visiting);
210 if (!this->
has_param(pid.block, pid.code)) {
212 state[pid] = VisitState::Done;
216 std::vector<ParamId> next_ids;
219 for (
const auto& [src_id, src_ptr] : param_sources) {
221 next_ids.push_back(src_id);
225 if (next_ids.empty()) {
227 for (
const auto& [src_block_name, src_block] : block_sources) {
232 for (
const auto& [lha_id, param_ptr] : src_block->getItems()) {
236 next_ids.push_back(param_ptr->get_id());
241 if (next_ids.empty()) {
244 for (
const auto& next_pid : next_ids) {
249 state[pid] = VisitState::Done;
252 for (
const auto& pid : param_ids) {
260std::string block_info_name(
const std::shared_ptr<Block>& block,
const std::string& fallback =
"") {
265 const auto name = block->get_name().to_string();
266 return name.empty() ? fallback :
name;
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());
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
284 if (!visited.insert(block.get()).second) {
288 for (
const auto& [fallback_name, source_block] : block->get_source_blocks()) {
293 out.insert(block_info_name(source_block, fallback_name));
294 collect_source_block_names(source_block, visited, out);
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
307 if (!visited.insert(block.get()).second) {
311 for (
const auto& observer : block->getObservers()) {
316 out.insert(block_info_name(observer));
317 collect_dependent_block_names(observer, visited, out);
323 return std::dynamic_pointer_cast<DependentBlock>(this->
at(block_name)) !=
nullptr;
327 std::unordered_set<std::string> names;
328 for (
const auto& [fallback_name, source_block] : this->
at(block_name)->get_source_blocks()) {
330 names.insert(block_info_name(source_block, fallback_name));
333 return sorted_block_info_names(names);
337 std::unordered_set<std::string> names;
338 for (
const auto& observer : this->
at(block_name)->getObservers()) {
340 names.insert(block_info_name(observer));
343 return sorted_block_info_names(names);
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);
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);
362 std::string existing_key = key_for(name);
365 if (!existing_key.empty()) {
370 for (
const auto& a : name.get_alias()) {
371 auto an = normalize(a);
372 if (first || an < best) { best = an; first =
false; }
377 base_t::operator[](key) = std::move(block);
379 auto& stored = base_t::operator[](key);
380 if (stored) stored->bind_self(stored);
382 merge_name_into_key(key, name);
387 auto clone = std::make_shared<BlockAccessor>();
389 const auto& block = this->
at(block_name);
393 clone->emplace(block_name, block->deep_clone_plain());
399 auto blk = this->
at(block_name);
401 auto dep = std::dynamic_pointer_cast<DependentBlock>(blk);
410 auto blk = this->
at(block_name);
412 auto dep = std::dynamic_pointer_cast<DependentBlock>(blk);
421 auto param = this->
at(block_name)->retrieve(
id);
423 auto dep = std::dynamic_pointer_cast<DependentParameter>(param);
432 auto param = this->
at(block_name)->retrieve(
id);
434 auto dep = std::dynamic_pointer_cast<DependentParameter>(param);
442std::string BlockAccessor::normalize(std::string_view s) {
444 out.reserve(s.size());
445 for (
unsigned char c :
std::string(s)) out.push_back(char(
std::toupper(c)));
449std::string BlockAccessor::key_for(std::string_view alias)
const {
450 const std::string a = normalize(alias);
452 if (
auto it = alias_to_key_.find(a); it != alias_to_key_.end())
455 if (base_t::find(a) != base_t::end())
458 const std::string raw{alias};
459 if (base_t::find(raw) != base_t::end())
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 "";
472std::string BlockAccessor::key_for(
const BlockName& name)
const {
473 for (
const auto& a :
name.get_alias()) {
475 if (!k.empty())
return k;
477 auto one =
name.to_string();
479 auto k = key_for(one);
480 if (!k.empty())
return k;
485std::string BlockAccessor::resolve_key(std::string_view alias)
const {
486 return key_for(alias);
489std::string BlockAccessor::resolve_key(
const BlockName& name)
const {
490 return key_for(name);
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());
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);
504 for (
const auto& a : full.get_alias()) {
505 alias_to_key_[ normalize(a) ] = key;
510 return !resolve_key(name).empty();
514 return !resolve_key(name).empty();
518 auto key = resolve_key(name);
520 throw std::invalid_argument(
"Block not found " + name.to_string());
521 return std::unordered_map<std::string, std::shared_ptr<Block>>
::at(key);
525 auto key = resolve_key(name);
527 throw std::invalid_argument(
"Block not found " + name.to_string());
528 return std::unordered_map<std::string, std::shared_ptr<Block>>
::at(key);
532 auto key = resolve_key(name);
534 throw std::invalid_argument(
"Block not found " + std::string(name));
535 return std::unordered_map<std::string, std::shared_ptr<Block>>
::at(key);
539 auto key = resolve_key(name);
541 throw std::invalid_argument(
"Block not found " + std::string(name));
542 return std::unordered_map<std::string, std::shared_ptr<Block>>
::at(key);
547 return at(block)->contains(
id);
551 return at(block)->retrieve(
id)->get_val();
555 auto& blk =
at(block);
556 if (blk->contains(
id)) {
557 blk->assign(
id, value);
559 blk->store(
id, std::make_shared<Parameter>(
ParamId(std::string(block),
id), value, 0, 0));
564 at(block)->remove(
id);
569 return at(block)->has_scale();
573 return at(block)->get_scale();
577 const std::string key = key_for(alias_or_key);
578 if (key.empty())
return;
580 std::unordered_map<std::string, std::shared_ptr<Block>>::erase(key);
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);
590 key_to_name_.erase(itn);
595 for (
const auto& a : name.get_alias()) {
596 const std::string key = key_for(a);
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.
#define LOG_WARN(...)
Macro for logging warning messages.
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 > ¶m_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.
std::string to_string() const
Returns a string representation of the block name.
Hash specialization for SymbolId<Tag>.
Represents an identifier of a LHA element, possibly containing several sub-ids.
Composite identifier for a single parameter.