24 v = std::stod(s, &idx);
25 }
catch (
const std::exception &) {
35void strip(std::string &s)
37 while (!s.empty() && std::isspace(
static_cast<unsigned char>(s.front())))
39 while (!s.empty() && std::isspace(
static_cast<unsigned char>(s.back())))
43bool parse_double(
const std::string &raw,
double &out)
47 if (s.empty())
return false;
50 out = std::stod(s, &idx);
51 return idx == s.size();
52 }
catch (
const std::exception &) {
61 const auto colon = s.find(
':');
62 if (colon == std::string::npos)
return std::nullopt;
64 std::string kind_str = s.substr(0, colon);
65 std::string params = s.substr(colon + 1);
70 if (kind_str ==
"normal" || kind_str ==
"uniform") {
71 const auto comma = params.find(
',');
72 if (comma == std::string::npos)
return std::nullopt;
73 if (!parse_double(params.substr(0, comma), out.
p1))
return std::nullopt;
74 if (!parse_double(params.substr(comma + 1), out.
p2))
return std::nullopt;
78 if (kind_str ==
"exponential") {
79 if (!parse_double(params, out.
p1))
return std::nullopt;
84 if (kind_str ==
"erlang") {
85 const auto comma = params.find(
',');
86 if (comma == std::string::npos)
return std::nullopt;
87 if (!parse_double(params.substr(0, comma), out.
p1))
return std::nullopt;
88 if (!parse_double(params.substr(comma + 1), out.
p2))
return std::nullopt;
110 const double sigma = d.
p2;
111 return sigma * sigma;
114 const double w = d.
p2 - d.
p1;
115 return (w * w) / 12.0;
118 const double lambda = d.
p1;
119 return 1.0 / (lambda * lambda);
122 const double k = d.
p1, lambda = d.
p2;
123 return k / (lambda * lambda);
131double factorial(
unsigned k)
134 for (
unsigned i = 2; i <= k; ++i) r *= static_cast<double>(i);
138double binomial_coeff(
unsigned n,
unsigned k)
140 if (k > n)
return 0.0;
141 if (k > n - k) k = n - k;
143 for (
unsigned i = 1; i <= k; ++i) {
144 r *=
static_cast<double>(n - i + 1);
145 r /=
static_cast<double>(i);
155double double_factorial_minus_one(
unsigned j)
157 if (j == 0)
return 1.0;
159 for (
unsigned i = 1; i < j; i += 2) r *= static_cast<double>(i);
167 if (k == 0)
return 1.0;
171 const double mu = d.
p1;
172 const double sigma = d.
p2;
175 for (
unsigned j = 0; j <= k; j += 2) {
176 total += binomial_coeff(k, j)
177 * std::pow(mu,
static_cast<double>(k - j))
178 * std::pow(sigma,
static_cast<double>(j))
179 * double_factorial_minus_one(j);
184 const double a = d.
p1;
185 const double b = d.
p2;
186 const double kp1 =
static_cast<double>(k + 1);
187 return (std::pow(b, kp1) - std::pow(a, kp1)) / (kp1 * (b - a));
190 const double lambda = d.
p1;
191 return factorial(k) / std::pow(lambda,
static_cast<double>(k));
199 const double s = d.
p1, lambda = d.
p2;
201 for (
unsigned i = 0; i < k; ++i) rising *= (s + static_cast<double>(i));
202 return rising / std::pow(lambda,
static_cast<double>(k));
Generic directed-acyclic-graph circuit template and gate identifier.
Continuous random-variable helpers (distribution parsing, moments).
Exception type thrown by circuit operations on invalid input.
@ Normal
Normal (Gaussian): p1=μ, p2=σ
@ Exponential
Exponential: p1=λ, p2 unused.
@ Uniform
Uniform on [a,b]: p1=a, p2=b.
@ Erlang
Erlang: p1=k (positive integer), p2=λ.
double analytical_variance(const DistributionSpec &d)
Closed-form variance Var(X) for a basic distribution.
double parseDoubleStrict(const std::string &s)
Strictly parse s as a double.
std::optional< DistributionSpec > parse_distribution_spec(const std::string &s)
Parse the on-disk text encoding of a gate_rv distribution.
double analytical_mean(const DistributionSpec &d)
Closed-form expectation E[X] for a basic distribution.
double analytical_raw_moment(const DistributionSpec &d, unsigned k)
Closed-form raw moment for a basic distribution.
Parsed distribution spec (kind + up to two parameters).
double p2
Second parameter (σ or b; unused for Exponential).
double p1
First parameter (μ, a, or λ).