Hyperiso 1.0.3
Modular flavour-physics calculations, Wilson coefficients and statistical inference
Loading...
Searching...
No Matches
main_more_lazy.cpp
Go to the documentation of this file.
1#include <cassert>
2#include <cmath>
3#include <iostream>
4#include <memory>
5#include <unordered_map>
6#include <unordered_set>
7#include <vector>
8
9#include "BlockAccessor.h"
10#include "Block.h"
11#include "Parameter.h"
12#include "DependentParameter.h"
13#include "Include.h"
14#include "SourcesView.h"
15
16static std::shared_ptr<Parameter> mkp(ParameterType type, const std::string& blk, long code, double v){
17 return std::make_shared<Parameter>(ParamId{type, blk, LhaID(code)}, v, 0.0, 0.0);
18}
19
20static void dump(BlockAccessor& acc, const std::string& name) {
21 std::cout << "\n=== DUMP " << name << " ===\n";
22 if (!acc.contains(name)) { std::cout << "(missing)\n"; return; }
23 auto b = acc.at(name);
24 for (auto& [id, p] : b->getItems()) {
25 std::cout << " " << name << "[" << id.to_string() << "]=" << p->get_val() << "\n";
26 }
27}
28
29static void expect_throw_get(BlockAccessor& acc, const std::string& blk, const LhaID& id) {
30 bool threw = !acc.at(blk)->contains(id);
31 assert(threw);
32}
33
34int main() {
35 std::cout << "== Deep dependency graph TORTURE test ==\n";
36
37 // IDs
38 LhaID ID_X(100);
39 LhaID ID_Y(101);
40 LhaID ID_SUM(300);
41 LhaID ID_P1(200);
42 LhaID ID_P2(201);
43 LhaID ID_POST(400);
44
45 // Sources blocks
46 auto A = std::make_shared<Block>(); A->blockname = "SRC_A";
47 auto B = std::make_shared<Block>(); B->blockname = "SRC_B";
48 A->store(ID_X, mkp(ParameterType::SM, "SRC_A", 100, 1.0));
49 B->store(ID_X, mkp(ParameterType::SM, "SRC_B", 100, 2.0));
50 B->store(ID_Y, mkp(ParameterType::SM, "SRC_B", 101, 5.0));
51
52 auto acc = std::make_shared<BlockAccessor>();
53 acc->emplace("SRC_A", A);
54 acc->emplace("SRC_B", B);
55
56 // DependentBlock SUM: SUM[300] = A[100] + B[100]
57 auto depSUM = std::make_shared<DependentBlock>(
58 std::unordered_map<std::string, std::shared_ptr<Block>>{{"SRC_A", A}, {"SRC_B", B}},
59 [=](const auto& blocks, std::shared_ptr<DependentBlock> self){
60 double v = blocks.get_val("SRC_A", ID_X) + blocks.get_val("SRC_B", ID_X);
61 if (!self->contains(ID_SUM)) self->store(ID_SUM, mkp(ParameterType::SM, "SUM", 300, 0.0));
62 self->assign(ID_SUM, v);
63 }
64 );
65 depSUM->blockname = "SUM";
66 depSUM->init();
67 acc->emplace("SUM", depSUM);
68
69 // Normal block with DependentParameters
70 auto DER = std::make_shared<Block>(); DER->blockname = "DERIVED";
71 acc->emplace("DERIVED", DER);
72
73 // P1 = 10*A
74 auto make_P1 = [&](double factor){
75 ParamId pid{ParameterType::SM, "DERIVED", ID_P1};
76 std::unordered_map<ParamId, std::shared_ptr<Parameter>> srcs;
77 srcs.emplace(ParamId{ParameterType::SM, "SRC_A", ID_X}, A->retrieve(ID_X));
78
79 auto P1 = std::make_shared<DependentParameter>(
80 pid, std::move(srcs),
81 [=](const ParamSrc& s, std::shared_ptr<DependentParameter> self){
82 double a = s.get_val(ParamId{ParameterType::SM, "SRC_A", ID_X});
83 self->set_expected(factor * a);
84 }
85 );
86 P1->init();
87 return P1;
88 };
89
90 // P2 = SUM + P1 + B[101]
91 auto make_P2 = [&](){
92 ParamId pid{ParameterType::SM, "DERIVED", ID_P2};
93 std::unordered_map<ParamId, std::shared_ptr<Parameter>> srcs;
94 srcs.emplace(ParamId{ParameterType::SM, "SUM", ID_SUM}, depSUM->retrieve(ID_SUM));
95 srcs.emplace(ParamId{ParameterType::SM, "DERIVED", ID_P1}, DER->retrieve(ID_P1));
96 srcs.emplace(ParamId{ParameterType::SM, "SRC_B", ID_Y}, B->retrieve(ID_Y));
97
98 auto P2 = std::make_shared<DependentParameter>(
99 pid, std::move(srcs),
100 [=](const ParamSrc& s, std::shared_ptr<DependentParameter> self){
101 double sumv = s.get_val(ParamId{ParameterType::SM, "SUM", ID_SUM});
102 double p1v = s.get_val(ParamId{ParameterType::SM, "DERIVED", ID_P1});
103 double by = s.get_val(ParamId{ParameterType::SM, "SRC_B", ID_Y});
104 self->set_expected(sumv + p1v + by);
105 }
106 );
107 P2->init();
108 return P2;
109 };
110
111 DER->store_or_assign(ID_P1, make_P1(10.0));
112 DER->store_or_assign(ID_P2, make_P2());
113
114 // DependentBlock POST: POST[400] = 3*SUM + P2
115 auto depPOST = std::make_shared<DependentBlock>(
116 std::unordered_map<std::string, std::shared_ptr<Block>>{{"SUM", depSUM}, {"DERIVED", DER}},
117 [=](const auto& blocks, std::shared_ptr<DependentBlock> self){
118 double sumv = blocks.get_val("SUM", ID_SUM);
119 double p2v = blocks.get_val("DERIVED", ID_P2);
120 double v = 3.0 * sumv + p2v;
121 if (!self->contains(ID_POST)) self->store(ID_POST, mkp(ParameterType::SM, "POST", 400, 0.0));
122 self->assign(ID_POST, v);
123 }
124 );
125 depPOST->blockname = "POST";
126 depPOST->init();
127 acc->emplace("POST", depPOST);
128
129 // ------------------------------------------------------------
130 // [1] Basic sanity
131 // ------------------------------------------------------------
132 std::cout << "\n[1] Basic sanity\n";
133 assert(acc->contains("SRC_A"));
134 assert(acc->contains("SUM"));
135 assert(acc->at("SUM")->contains(ID_SUM)); // materialize via contains
136 assert(acc->at("POST")->contains(ID_POST)); // materialize via contains
137
138 double sum0 = acc->getValue("SUM", ID_SUM); // 1+2=3
139 double p1_0 = acc->getValue("DERIVED", ID_P1); // 10
140 double p2_0 = acc->getValue("DERIVED", ID_P2); // SUM + P1 + B[101] = 3+10+5=18
141 double post0= acc->getValue("POST", ID_POST); // 3*3 + 18 = 27
142 std::cout << "sum0=" << sum0 << " p1_0=" << p1_0 << " p2_0=" << p2_0 << " post0=" << post0 << "\n";
143 assert(std::abs(sum0-3.0) < 1e-12);
144 assert(std::abs(p1_0-10.0) < 1e-12);
145 assert(std::abs(p2_0-18.0) < 1e-12);
146 assert(std::abs(post0-27.0) < 1e-12);
147
148 // ------------------------------------------------------------
149 // [2] Freeze/unfreeze behavior on blocks AND on DependentParameter inside DERIVED
150 // ------------------------------------------------------------
151 std::cout << "\n[2] Freeze/unfreeze behavior\n";
152 acc->at("POST")->freeze();
153 acc->setValue("SRC_A", ID_X, 7.0); // SUM=9, P1=70, P2=9+70+5=84, POST should stay 27 (frozen)
154 double post_frozen = acc->getValue("POST", ID_POST);
155 std::cout << "post_frozen=" << post_frozen << " (expected still 27)\n";
156 assert(std::abs(post_frozen-27.0) < 1e-12);
157
158 acc->at("POST")->unfreeze();
159 double post1 = acc->getValue("POST", ID_POST); // now 3*9 + 84 = 111
160 std::cout << "post1=" << post1 << " (expected 111)\n";
161 assert(std::abs(post1-111.0) < 1e-12);
162
163 // freeze DependentParameter P1 only (indirect test)
164 auto p1ptr = std::dynamic_pointer_cast<DependentParameter>(DER->retrieve(ID_P1));
165 assert(p1ptr);
166 p1ptr->freeze();
167 acc->setValue("SRC_A", ID_X, 10.0); // normally P1=100, but frozen => stays 70, impacts P2 & POST
168 double p1_f = acc->getValue("DERIVED", ID_P1);
169 double p2_f = acc->getValue("DERIVED", ID_P2);
170 double post_f = acc->getValue("POST", ID_POST);
171 std::cout << "p1_f=" << p1_f << " (expected still 70)\n";
172 std::cout << "p2_f=" << p2_f << " (expected SUM(12)+70+5=87)\n";
173 std::cout << "post_f=" << post_f << " (expected 3*12+87=123)\n";
174 assert(std::abs(p1_f-70.0) < 1e-12);
175 assert(std::abs(p2_f-87.0) < 1e-12);
176 assert(std::abs(post_f-123.0) < 1e-12);
177
178 p1ptr->unfreeze();
179 double p1_u = acc->getValue("DERIVED", ID_P1); // now 100
180 double post_u = acc->getValue("POST", ID_POST); // SUM=12, P2=12+100+5=117, POST=3*12+117=153
181 std::cout << "p1_u=" << p1_u << " (expected 100), post_u=" << post_u << " (expected 153)\n";
182 assert(std::abs(p1_u-100.0) < 1e-12);
183 assert(std::abs(post_u-153.0) < 1e-12);
184
185 // ------------------------------------------------------------
186 // [3] Remove item in source and observe failures + recovery
187 // ------------------------------------------------------------
188 std::cout << "\n[3] remove_item source + recovery\n";
189 acc->remove_item("SRC_A", ID_X);
190
191 // Anything depending on A[100] should now fail on getValue (SUM / P1 / P2 / POST)
192 expect_throw_get(*acc, "SUM", ID_SUM);
193 expect_throw_get(*acc, "DERIVED", ID_P1);
194 expect_throw_get(*acc, "POST", ID_POST);
195
196 std::cout << "here " << std::endl;
197 // Recover: re-add A[100]
198 acc->setValue("SRC_A", ID_X, 2.0); // A back
199 // double sumR = acc->getValue("SUM", ID_SUM); // 2 + B(2)=4
200 // double postR = acc->getValue("POST", ID_POST);
201 // std::cout << "sumR=" << sumR << " (expected 4)\n";
202 // assert(std::abs(sumR-4.0) < 1e-12);
203
204 // ------------------------------------------------------------
205 // [4] Replace/rebind DependentParameter in place (simule LO puis NLO)
206 // ------------------------------------------------------------
207 std::cout << "\n[4] Rebind DependentParameter (store_or_assign overwrite)\n";
208 // Remplace P1 = 10*A par P1 = 100*A
209 DER->store_or_assign(ID_P1, make_P1(100.0));
210
211 // après overwrite, tout doit suivre
212 acc->setValue("SRC_A", ID_X, 1.0);
213 double p1_new = acc->getValue("DERIVED", ID_P1); // 100
214 double p2_new = acc->getValue("DERIVED", ID_P2); // SUM(1+2=3) + 100 + 5 = 108
215 double post_new= acc->getValue("POST", ID_POST); // 3*3 +108 = 117
216 std::cout << "p1_new=" << p1_new << " p2_new=" << p2_new << " post_new=" << post_new << "\n";
217 assert(std::abs(p1_new-100.0) < 1e-12);
218 assert(std::abs(p2_new-108.0) < 1e-12);
219 assert(std::abs(post_new-117.0) < 1e-12);
220
221 // ------------------------------------------------------------
222 // [5] erase_block and alias cleanup + behavior of dependent blocks afterwards
223 // ------------------------------------------------------------
224 std::cout << "\n[5] erase_block\n";
225 // Remove SRC_B block entirely
226 acc->erase_block("SRC_B");
227 assert(!acc->contains("SRC_B"));
228
229 // SUM depends on SRC_B => should now fail
230 expect_throw_get(*acc, "SUM", ID_SUM);
231
232 // Re-add SRC_B with new values
233 auto B2 = std::make_shared<Block>(); B2->blockname = "SRC_B";
234 B2->store(ID_X, mkp(ParameterType::SM, "SRC_B", 100, 10.0));
235 B2->store(ID_Y, mkp(ParameterType::SM, "SRC_B", 101, 1.0));
236 acc->emplace("SRC_B", B2);
237
238 // IMPORTANT: depSUM still holds old pointer B (the erased one).
239 // This test is here to catch whether your design *expects* pointer stability.
240 // If you expect “erase then re-add” to work, you must rebuild depSUM sources.
241 // Here we just *demonstrate* the effect:
242 bool throws = !acc->at("SUM")->contains(ID_SUM);
243 // try { (void)acc->getValue("SUM", ID_SUM); }
244 // catch(...) { throws = true; }
245 std::cout << "After erase/re-add SRC_B, SUM getValue throws? " << throws << " (expected TRUE unless you rebuild dependencies)\n";
246
247 // ------------------------------------------------------------
248 // [6] Sub-accessor operator[] + merge operators +, >>
249 // ------------------------------------------------------------
250 std::cout << "\n[6] operator[] / + / >>\n";
251 // Build a tiny independent accessor with EXTRA, and a conflicting DERIVED
252 auto EXTRA = std::make_shared<Block>(); EXTRA->blockname = "EXTRA";
253 EXTRA->store(LhaID(1), mkp(ParameterType::SM, "EXTRA", 1, 42.0));
254 auto acc2 = std::make_shared<BlockAccessor>();
255 acc2->emplace("EXTRA", EXTRA);
256
257 // + should merge (and complain if conflicts)
258 auto merged = (acc + acc2);
259 assert(merged->contains("EXTRA"));
260 assert(std::abs(merged->getValue("EXTRA", LhaID(1)) - 42.0) < 1e-12);
261
262 // priority merge: rhs overrides blocks
263 auto acc_override = std::make_shared<BlockAccessor>();
264 auto DER2 = std::make_shared<Block>(); DER2->blockname = "DERIVED";
265 DER2->store(LhaID(999), mkp(ParameterType::SM, "DERIVED", 999, 9.0));
266 acc_override->emplace("DERIVED", DER2);
267
268 auto prio = (acc >> acc_override);
269 assert(prio->contains("DERIVED"));
270 assert(prio->at("DERIVED")->contains(LhaID(999)));
271
272 // sub accessor
273 auto sub = (*prio)[ std::unordered_set<BlockName>{"SRC_A","DERIVED"} ];
274 assert(sub->contains("SRC_A"));
275 assert(sub->contains("DERIVED"));
276 assert(!sub->contains("POST"));
277
278 // ------------------------------------------------------------
279 // Final dumps
280 // ------------------------------------------------------------
281 dump(*acc, "SRC_A");
282 dump(*acc, "SUM");
283 dump(*acc, "DERIVED");
284 dump(*acc, "POST");
285 dump(*merged, "EXTRA");
286
287 std::cout << "\n✅ TORTURE test finished (some checks intentionally demonstrate expected failures).\n";
288 return 0;
289}
Alias-aware façade for accessing and manipulating multiple parameter blocks.
Defines classes used to store parameters and to build derived/dependent parameter blocks.
Defines parameters whose values are lazily computed from other parameters.
ParameterType
Defines the Parameter class used to store individual physical/model parameters.
Alias-aware container / façade over several parameter blocks.
void remove_item(const BlockName &block_name, LhaID id)
Removes one parameter from a block.
std::shared_ptr< Block > & at(const BlockName &block_name)
Alias-aware mutable access to a block.
bool contains(const BlockName &block_name) const
Checks whether a block exists (alias-aware).
scalar_t getValue(const BlockName &blockName, LhaID pdgCode) const
Retrieves the current value of a parameter from a block.
void erase_block(const BlockName &name)
Erases a block and removes all associated aliases from metadata.
void emplace(const BlockName &name, std::shared_ptr< Block > blk)
Inserts or replaces a block, updating alias metadata.
void setValue(const BlockName &blockName, LhaID pdgCode, scalar_t value)
Sets the value of a parameter inside an existing block.
Lightweight view over a set of source parameters keyed by ParamId.
int main()
csl::Expr v
Definition sm.h:110
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