From dd6ce13b2a665e2b61aab7033ccd3efa760b2335 Mon Sep 17 00:00:00 2001 From: AlexanderMitrofanov Date: Thu, 8 Oct 2026 12:49:51 +0200 Subject: [PATCH 01/21] docs: plan exact seeded base-pair probabilities --- ChangeLog | 13 + README.md | 4 + doc/Makefile.am | 1 + doc/analysis/base-pair-probabilities-plan.md | 519 +++++++++++++++++++ 4 files changed, 537 insertions(+) create mode 100644 doc/analysis/base-pair-probabilities-plan.md diff --git a/ChangeLog b/ChangeLog index de36b63d..c7f36eda 100644 --- a/ChangeLog +++ b/ChangeLog @@ -42,6 +42,10 @@ ## Technical changes and Optimizations +- document the implementation plan for exact seeded base-pair probabilities, + including algorithm comparison, numerical/output contracts and validation; + no prediction or probability implementation changes (issue #257) + - add an API overview, IntaRNA Doxygen styling, and automated documentation builds and GitHub Pages publishing alongside the user guide (issue #22) @@ -129,6 +133,15 @@ energies, restricted partition sums, and trackers. ################################################################################ ################################################################################ +261008 Alexander Mitrofanov + * doc/analysis/base-pair-probabilities-plan.md : + + specify the stack-seed partition and outside recurrences, sparse domain, + suffix-automaton comparison, numerical policy, output integration and + independent validation for https://github.com/BackofenLab/IntaRNA/issues/257 + + distinguish planned implementation from current supported behavior + * README.md, doc/Makefile.am : + + link the plan and include it in source distributions + 261007 Alexander Mitrofanov * doc/doxygen.cfg, doc/doxygen/* : + introduce the API main page with component links, prediction flow, diff --git a/README.md b/README.md index 8c12ed48..3e0266d5 100644 --- a/README.md +++ b/README.md @@ -2386,6 +2386,10 @@ Doxygen and Graphviz and run `bash doc/build-api.sh`, then open [API documentation build guide](doc/api-documentation.md) for validation, Autotools, and publishing instructions. +The [seeded base-pair probability implementation plan](doc/analysis/base-pair-probabilities-plan.md) +records the proposed algorithms, numerical contracts, integration, and validation +for issue #257. It is a design document; the proposed output is not implemented. + When IntaRNA is build while `pkg-config` is present, according pkg-config information is generated and installed too. diff --git a/doc/Makefile.am b/doc/Makefile.am index cb78b081..5e3ac756 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -5,6 +5,7 @@ EXTRA_DIST = \ conda.txt \ + analysis/base-pair-probabilities-plan.md \ api-documentation.md \ build-api.sh \ check-api.py \ diff --git a/doc/analysis/base-pair-probabilities-plan.md b/doc/analysis/base-pair-probabilities-plan.md new file mode 100644 index 00000000..7080047e --- /dev/null +++ b/doc/analysis/base-pair-probabilities-plan.md @@ -0,0 +1,519 @@ +# Implementation plan: seeded base-pair probabilities + +Status: design only. This document addresses [issue #257](https://github.com/BackofenLab/IntaRNA/issues/257); +it does not implement the recurrences, proposed APIs, or proposed output options. + +The code assessment uses IntaRNA revision +[`5454030a04bbcde79b2e75a0614dadf6f1115e6f`](https://github.com/BackofenLab/IntaRNA/tree/5454030a04bbcde79b2e75a0614dadf6f1115e6f). +The theory assessment uses IntaRNA-probabilities branch +`issue-10-fixed-seed-recursions` at +[`f62778504c8abbec8fc9894da16a357b60707680`](https://github.com/BackofenLab/IntaRNA-probabilities/tree/f62778504c8abbec8fc9894da16a357b60707680), +particularly [Step 5: fixed-length seeds](https://github.com/BackofenLab/IntaRNA-probabilities/blob/f62778504c8abbec8fc9894da16a357b60707680/theory/fixed-length-seeds.md) +and [Step 4: seed extension](https://github.com/BackofenLab/IntaRNA-probabilities/blob/f62778504c8abbec8fc9894da16a357b60707680/theory/seed-extension.md). +Recheck these integration points against the implementation branch before coding. + +## 1. Decision and scope + +Use the maximal-stack formulation as the leading implementation candidate for +stack-only seeds, with the optimized outside pass specified below. It has a +direct uniqueness argument, scalar seeded/seed-free state families, and simple +whole-interaction `noLP` handling. Do not port the reference implementation's +extra loop over every marked pair in every run. + +Compare it with the specialized strict-seed suffix automaton before selecting +the production default. Fewer explicit state families do not prove faster +execution: a long stack can exceed the seed length substantially. Both are +valid stack-only algorithms. A general seed-pattern automaton is a separate, +larger extension for bulged seeds; it is not needed for the initial scope. + +Initially support actual-pair probabilities for the exact seeded +`--model=P --mode=M` path with a stack-only handler. Preserve other prediction +modes; reject requests for the new output when their predictor cannot provide +the stated ensemble. The normal exact seeded path should use the selected new +backend whether or not pair probabilities are requested, so enabling output +does not change its partition function. + +Mixed-length and singleton **stacked** explicit seeds are included. Their run +predicate follows the same uniqueness proof, but extends the fixed-length +Python API and therefore needs independent tests. Computed seeds retain their +existing allowed lengths. Do not extend the computed-seed CLI to length one. + +## 2. Ensemble and output contract + +Let an interaction be its complete ordered intermolecular pair chain. Include +it if it contains at least one admitted seed, satisfies interaction constraints, +and lies wholly in one searched target/query region pair. Count the interaction +once, irrespective of the number or overlap of its seed witnesses. + +The searched ensemble is the union over the selected or automatically derived +nonoverlapping region pairs. `qRegionLenMax`, `tRegionLenMax`, and `outMinPu` +can restrict this union before prediction. Interactions spanning excluded +region boundaries are not included. Preserve model P's rejection of every +nonzero `windowWidth`; overlapping windows cannot be summed as disjoint sets. + +For the full IntaRNA Boltzmann weight $w(I)$, compute + +$$ +Z=\sum_{I\in\mathcal I}w(I),\qquad +M_k=\sum_{I\in\mathcal I:\,k\in I}w(I),\qquad P_k=M_k/Z. +$$ + +These are conditional probabilities given an allowed seeded interaction; +there is no added unbound-state weight. Merge raw region numerators and +denominators before normalizing. Ranked-output controls (`outNumber`, energy +reporting cutoffs, overlap selection, and `outPerRegion`) do not select the +probability ensemble. Structural `noLP`, endpoint `noGUend`, accessibility +limits, seed admission, loop limits, and both interaction span limits do. + +Actual pairing is different from site coverage. Preserve `spotProb`, +`qSpotProb`, and `tSpotProb`: their existing callbacks describe boundaries and +their writers accumulate coverage, not the interior pair chain. No selected-pair +"none of these pairs" probability is implied by $1-\sum_k P_k$, since pair +events can coexist. Per-nucleotide pair profiles, if added later, are row or +column sums of the actual-pair matrix. + +## 3. Establish a numerical policy before the DP + +Use `Z_type` for partition values, adjoints, raw pair masses, and normalization. +Use existing energy units and native energy functions. "Exact" refers to the +enumerated ensemble and disjoint recurrence; ordinary floating-point rounding +still occurs and must be measured against an independent higher-precision +reference. It does not mean exact real-number arithmetic. + +The new nonnegative backend must not use `Z_equal(x,0)` to prune positive DP +or boundary contributions. At the reviewed revision, that macro uses the +absolute threshold `sqrt(float::min())`, approximately $1.08\times10^{-19}$. +`PredictorMfeEns::addPartitionContribution()` currently applies that test. +Calling it unchanged while reversing all positive contributions would make +the denominator inconsistent with the pair numerators. + +Introduce a scoped exact-zero accumulation policy for the new path. Preserve +the virtual `updateZ()` dispatch from `updateCompleteZ()`, legacy tracker +callback behavior, and exception-safe restoration of scoped state. Retain the +existing policy for unrelated predictors. Observing/delegating overrides remain +supported; an override that changes boundary weights must also provide the same +objective coefficients to the reverse calculation. Arbitrary reweighting inside +an old override is not automatically a supported pair-probability backend. + +Use one boundary-admission/weight contract for forward aggregation and outside +initialization. Carry its raw denominator through predictor, region collector, +and final output exactly once per disjoint contribution. There must not be an +independent energy-to-weight reconstruction for the new probabilities. + +Check energy sentinels before exponentiation: a forbidden transition or boundary +is a structural zero. For finite admissible energies and nonnegative arithmetic, +check NaN and infinity, exponential and positive-product underflow to zero, +overflow in sums and region merges, and underflow/overflow in final $M/Z$. +Do not rely on `Z_isINF` alone; its comparison does not identify NaN. A computed +positive subnormal value may need scaling or a numerical-range failure if its +precision cannot meet the declared validation tolerance. Do not claim that +adding a small positive term to a large sum avoids ordinary rounding loss. + +Distinguish successful nonempty, successful empty, and failed computations. +Only a successfully empty ensemble produces undefined probabilities (`NA`). +Numerical failure must be reported as an error, not as emptiness or a valid +matrix of zeros. Do not clamp substantial probability or mass inconsistencies. +Define any roundoff-only endpoint correction through the tested error tolerance. + +Checked arithmetic with explicit range failure is the initial strategy. If +representative supported workloads fail, introduce a tested scaling scheme +before release, with common scales for forward/outside quantities and raw +region merging. A global replacement of all IntaRNA arithmetic is out of scope. + +Follow the exact-zero policy through serialization too. Raw +`OutputHandler::incrementZ()` currently adds small values, but `Eall`, +`EallTotal`, `Zall`, and `P_E` output in `OutputHandlerCsv`, ensemble output in +`OutputHandlerEnsemble`, and ensemble-energy reporting in `OutputHandlerText` +use approximate-zero tests. Carry the new backend's partition status/policy +through collector/hub forwarding so these outputs recognize a small positive +total. Keep unrelated legacy behavior scoped. Existing `P_E` numerators retain +their documented native energy representation; do not use that field as the +independent oracle for actual-pair marginals. + +## 4. SeedHandler capability and active occurrence mask + +Add a proposed virtual `guaranteesStackOnlySeeds() const` method. Its contract +is geometric: every exposed seed is a consecutive diagonal pair chain in +internal coordinates. It does not assert that a seed exists or that all seeds +have the same length. Default to false for an unknown handler. + +| Handler | Planned implementation | +| --- | --- | +| `SeedHandlerNoBulge` | Return true. | +| `SeedHandlerMfe` | Return true when both effective, normalized per-strand unpaired allowances are zero; otherwise return false conservatively. | +| `SeedHandlerExplicit` | Inspect retained accepted patterns after parsing and minimum-energy-per-start selection; both dot-bar strings must contain only paired positions. | +| `SeedHandlerIdxOffset` | Forward to the wrapped handler; offsets do not change geometry. | + +After `fillSeed()`, compile the admitted occurrences in the prediction range. +Check **both complete endpoints**, since explicit `fillSeed()` counts contained +seeds without pruning its stored family and iteration bounds constrain starts. +Do not infer seed acceptance from complementarity or `seedMaxUP` alone. + +Preserve existing policies: explicit patterns ignore computed-seed filters; +competing explicit seeds with the same start retain only the selected minimum- +energy pattern; NoBulge and Mfe differ on equality at their energy thresholds. +Do not replace these contracts with one generic admission test. Explicit +`getConstraint().getBasePairs()` is a minimum, not a common pattern length. + +For a run from $a$ to $q$, define $\chi(a,q)$ as a Boolean: at least one admitted +occurrence is wholly contained in the run. In a backward scan, adding start $a$ +introduces a hit exactly when its retained seed ends no later than $q$ on the +same run. OR this with the flag for the shorter run. This handles variable +lengths and singleton occurrences without counting witnesses. Do not multiply +the seed's standalone accessibility or full energy into the final interaction; +those values determine admission only. + +Move the exact predictor's constructor assertion requiring more than one seed +pair into the legacy paths that require it. Check all other singleton assumptions +in seed annotation, range bounds, and reporting before enabling explicit +singletons in the new exact path. Leave the heuristic's restrictions explicit. + +## 5. Sparse search domain and weight ownership + +Use zero-based internal coordinates, with sequence 2 reversed so both pair +coordinates increase along a path. A stacked successor is $(i_1+1,i_2+1)$. +Pair vertices must pass accessibility/complementarity checks. Transitions must +pass the native internal-loop checks, including internal GU restrictions. + +Preserve the immediate empty-seed return. For an admitted occurrence beginning +at $a$ and ending at $b$, every possible left boundary $p$ obeys + +$$ +\max(0,b_k-W_k+1)\le p_k\le a_k\quad(k=1,2), +$$ + +where $W_k$ is the effective inclusive span limit, clipped to the active region. +Discard occurrences longer than either limit. Enumerate the deduplicated union +of these rectangles intersected with valid pair vertices. Use signed or +saturating arithmetic for lower bounds; avoid unsigned underflow. This is a +necessary-condition filter, not a heuristic seed/path selection. + +For each surviving $p$, compute only states within its two inclusive span +limits. Use on-demand transitions and run scans rather than materializing all +boundary/run incidences. Preserve intermediate states that cannot currently +terminate due to endpoint GU or ED filters; later extension may make their +terminal boundary admissible. Whole-sequence seed preprocessing remains a +separate cost. + +Set + +$$ +d(p)=\operatorname{BW}(E_{\rm init}),\quad +t(r,a)=\operatorname{BW}(E_{\rm interLeft}(r,a)),\quad +T(a,q)=\prod_{b\to b^+\text{ in the stack }a\ldots q}t(b,b^+). +$$ + +The empty stack product is $T(q,q)=1$. For admissible complete boundaries use + +$$ +B(p,q)=\operatorname{BW}(\texttt{energy.getE}(p_1,q_1,p_2,q_2,0)); +$$ + +otherwise $B(p,q)=0$. This includes complete-interval ED, native accessibility- +weighted dangling energies, terminal penalties, and `energyAdd` once. Keep +IntaRNA's existing dangle convention; do not replace it with a different +microstate model. Initiation occurs in $d$ once, and each pair transition owns +one local interaction energy. + +## 6. Maximal-stack forward recurrence + +Fix left boundary $p$. Let $N_p(q)$ and $S_p(q)$ be hybrid weights of seed-free +and seeded paths through $q$. Let $J^0_p(a)$ and $J^1_p(a)$ be contributions +entering a new maximal run at $a$. For **nonstack** transitions $r\rightsquigarrow a$: + +$$ +J^0_p(a)=\mathbf1_{a=p}d(p)+\sum_{r\rightsquigarrow a}N_p(r)t(r,a), +\qquad J^1_p(a)=\sum_{r\rightsquigarrow a}S_p(r)t(r,a). +$$ + +For complete allowed runs with $p\preceq a\preceq q$: + +$$ +N_p(q)=\sum_{a:\chi(a,q)=0}J^0_p(a)T(a,q),\qquad +S_p(q)=\sum_a[J^1_p(a)+\chi(a,q)J^0_p(a)]T(a,q). +$$ + +Visit $q$ in increasing pair order, first computing its entries and then its +completed-run sums. Unreachable states are zero. Under `noLP`, omit completed +runs of length one; keep pending $J$ entries so such runs may later extend. +Without `noLP`, source singletons follow the same equations, including an +admitted singleton seed. Enumerate only runs connected by allowed stack edges. + +Every path has a unique decomposition at its nonstack edges. Each run either +contains an admitted seed or does not; the seeded-before-run and newly-seeded +cases are disjoint. This proves uniqueness even for overlapping, disjoint, +mixed-length, and singleton seed witnesses. Allowing stack edges in the entry +sum would introduce artificial cuts and duplicate paths. + +Accumulate $Z=\sum_{p,q}B(p,q)S_p(q)$. Submit each complete seeded boundary +partition once through `updateCompleteZ(..., S_p(q), true)` with the numerical +policy from section 3. Use the same terminal weight/acceptance for that update +and the outside objective. Cache or recompute coefficients deterministically +without storing every boundary globally. Keep the heuristic's legacy protected +extension methods; its own `predict()` explicitly calls them. + +## 7. Outside pass for every actual-pair numerator + +This differentiates the forward computation after attaching a marker to the +initial pair and every transition's destination pair. Seed masks and boundary +weights are fixed while differentiating. Write $H^0=N$, $H^1=S$ and +$f(c,a,q)=c\lor\chi(a,q)$. + +For each $p$, initialize $\bar H^0_p(q)=0$, $\bar H^1_p(q)=B(p,q)$ for every +terminal $q$, and all $\bar J$ to zero. Reverse $q$ in pair order. For every +forward run term, first accumulate + +$$ +\bar J^c_p(a)\mathrel{+}=\bar H^{f(c,a,q)}_p(q)T(a,q),\qquad +g(a)=\sum_{c=0}^1\bar H^{f(c,a,q)}_p(q)J^c_p(a). +$$ + +Avoid the reference's explicit marking of every pair in every run. For this +$p,q$, reconstruct $T(a,q)=t(a,a^+)T(a^+,q)$ backward from $T(q,q)=1$, with +$O(L)$ scratch. Reverse that product chain from its earliest start toward $q$: + +$$ +M_{a^+}\mathrel{+}=g(a)T(a,q),\qquad +g(a^+)\mathrel{+}=g(a)t(a,a^+). +$$ + +Use the updated, propagated $g$. Stop before $a=q$, since the empty product +has no pair marker. Set the direct $g$ contribution to zero for excluded forward +terms, but retain necessary product-chain nodes. In particular, `noLP` excludes +singleton completed paths, not the $T(q,q)=1$ node needed for longer products. + +After all runs ending at $q$, mark its entry pair and reverse nonstack entries: + +$$ +M_q\mathrel{+}=\sum_{c=0}^1\bar J^c_p(q)J^c_p(q),\qquad +\bar H^c_p(r)\mathrel{+}=\bar J^c_p(q)t(r,q) +\quad(r\rightsquigarrow q). +$$ + +Sum $M$ across left boundaries. Each entry owns a run's first pair; product +edges own the rest. One reverse pass per $p$ covers all right boundaries and +all marked pairs, without division, subtraction, or a global product tape. +Skip reverse storage and computation when pair output is not requested. + +## 8. Algorithm comparison before production integration + +Build correctness-checked numerical kernels for the comparison as an early +implementation milestone, before replacing the production default. Do not +infer production performance from exact-polynomial Python timings. + +Let $V$ be the number of allowed pair vertices, $E$ the number of nonstack +edges, $L$ the maximum run length, and $s$ a common fixed seed length. Bounds +below are conservative before span and eligible-start restrictions: + +| Candidate | Forward plus all-pair outside work | Logical DP values per left boundary | +| --- | --- | --- | +| Literal Step 5 reference | $O(VE+V^2L^2)$ | Depends on retained reference outputs | +| Maximal stacks with section 7 | $O(VE+V^2L)$ | $O(V)$ plus $O(L)$ run scratch | +| Specialized strict-seed suffix automaton | $O(VE+sV^2)$ | $O(sV)$ | + +These are graph-based bounds assuming iteration/storage indexed by allowed +vertices. A dense `Matrix` for an active span rectangle also stores invalid +pair positions: if that rectangle contains $A_p$ cells, physical DP storage is +$O(A_p+L)$ for maximal stacks or $O(sA_p)$ for the suffix candidate. Charge dense +initialization and scanning their actual cell visits: $O(\sum_p A_p)$ for +scalar tables and $O(s\sum_p A_p)$ when every suffix-state table is visited. +Do not substitute the number +of complementary vertices for rectangular cells in reported memory or timing. + +For the suffix candidate, store seed-free suffix run length and one absorbing +seeded family. A stack edge increments the capped run length; a nonstack edge +resets it to one. Accept only if an admitted occurrence ends at the new vertex +and the suffix contains its full length. For fixed length, aggregate seed-free +states before processing nonstack edges, avoiding an $s$ factor on those edges. +Initialize source-pair acceptance explicitly for singleton seeds. + +The same construction can compare mixed lengths by capping at the maximum +admitted length and using the shortest admitted length ending at each vertex; +longer occurrences ending there are redundant for existential acceptance. +With `noLP`, retain whether the current run has length one or at least two, +including after seed acceptance. Allow nonstack departure and final termination +only from runs of length at least two. This adds constant state. Reverse the +same DP transitions, initialize all accepted terminal states with $B$, and mark +each transition's destination and the source once. For mixed lengths, substitute +the maximum admitted length for $s$ in the cost estimate. + +A general prefix-pattern DFA can recognize retained bulged seed paths, but +needs state construction, failure/acceptance transitions, and a decision about +the seed family. Current handlers expose a selected MFE seed per start, not all +bulged structures satisfying constraints. A general DFA does not remove that +semantic limitation automatically. Its state count can be larger than $s$; +do not apply the strict-seed bound to it. + +Benchmark no seeds, one sparse seed amid increasing unrelated sequence, +overlapping/disjoint seeds, dense admission, long stacks with $L\gg s$, small +loop limits, mixed explicit lengths, asymmetric spans, and realistic inputs. +Measure seed preprocessing, partition-only work, added outside work, complete +runtime, and peak memory separately. Use identical inputs, models, numerical +policy, compiler settings, and thread count. Validate both candidates first. + +Keep maximal stacks if its lower state/storage cost and measured runtime meet +the representative workload requirements. Choose the suffix candidate if its +runtime advantage justifies its state/storage cost. Record the cases and +tradeoffs before selecting one production backend; shipping both or an adaptive +selector is not required. Neither the theory nor this plan claims a universal +speedup. Existing legacy results are correctness references only on independently +verified ensembles; elsewhere use them only as performance baselines. + +Report total memory separately: active span grids and run scratch; a full +target-by-query output matrix if requested; optional transition caches; and +legacy boundary-map storage when old trackers are also enabled. Do not retain +all run lists or boundary weights and still claim only $O(V)$ working memory. + +## 9. Raw result API, lifecycle, and output + +Introduce a proposed `BasePairProbabilities` result with raw `Z_type` numerator +storage, raw denominator, region identity, and explicit completion status. Pass +an optional non-owning result sink to the supported predictor; document lifetime +and keep existing constructor calls source-compatible. The pair-level owner +lives outside predictor/range scopes in `IntaRNA.cpp`. + +Do not implement this by attaching an ordinary `PredictionTracker`. Its energy +callbacks lose partition precision and cannot identify interior pairs; moreover, +a non-null tracker currently disables complete-boundary streaming. Retain those +callbacks for old outputs. Pair output alone must not populate `Z_partition`. + +Compute each region result privately and commit its raw masses only after +successful forward/outside completion. Allocate/reset region state on every +`predict()` call. Create one accumulator per target/query sequence pair, merge +disjoint completed regions once, and finalize explicitly after all requested +regions succeed. If one region fails or required work is cancelled, mark the +pair result failed and do not write a valid-looking normalized matrix. A writer +destructor must only release resources. Guard publication even on the existing +OpenMP exception path, where final output code can run before the saved exception +is rethrown. Check finite merged totals before forwarding ordinary exact-path +partition diagnostics as well. + +Store published matrix coordinates as original target/query positions. Convert +local DP pairs once through `InteractionEnergyIdxOffset::getBasePair()`, then +use each original sequence's `getInOutIndex()` only when printing labels. +Rows are target positions in original 5'-to-3' order; columns are query positions +in original 5'-to-3' order. Do not reverse these columns again with the old spot +writer, which expects internally reversed query storage. + +Add proposed `--out=bpProb:FILE`: a CSV-style matrix with the existing separator +and nucleotide/index-label conventions, but its own `bpProb` label and writer. +Use enough significant digits to preserve `Z_type`-appropriate validated +probability precision, including scientific notation for small values. Successful +empty ensembles use `NA`; successful nonempty ensembles use zero for pairs absent +from the searched ensemble. Validate the entire normalized result before writing +its first row. An output I/O failure is an error, not a successful completion. + +Register the output enum, parser lookup, help, validation, filename handling, +and writer together. Require a supported exact stack-seed predictor and +`needZall`; do not turn on `needBPs` merely to compute ensemble marginals. +Reject unsupported heuristic, kinetic, evaluation, unseeded, seed-only, or +bulged-seed requests rather than silently changing model/mode. Reuse multi-FASTA +filenames and buffer complete output blocks for synchronized shared-stream +emission. Keep computation local to each sequence pair; no new within-pair +parallelism is necessary. Check API callers' ranges for disjoint merging too. + +## 10. Validation gates + +### A. Mathematical kernel, independent of native energy rounding + +Use independent exhaustive enumeration of ordered pair chains, not the new +recurrence or the handler's own mask as its expected answer. Compare each +boundary partition, total $Z$, and every $M_k$ before normalization. Include +arbitrary positive heterogeneous weights, zero/forbidden boundaries, overlaps, +disjoint seeds, filtered windows, singleton/mixed lengths, missing edges, +asymmetric spans, `noLP`, and the eligible-start optimization. + +Use all ten fixed-length theory fixtures through a test-weight adapter where +their model matches. In particular, `random03` has two seeded interactions; +its four seed pairs have probability one and extension pair `(10,4)` has +$e/(1+2e)\simeq0.4223187983$ with **unrounded** accessibility. Map its one-based +antiparallel coordinates explicitly. Compare optimized outside marking with +literal run marking or independent forward derivatives on tiny cases. + +### B. Native IntaRNA model + +Extend `PredictorSeedOracle_test.cpp` and reuse appropriate fixtures from +`PredictorTinyOracle_test.cpp`. Existing seeded ensemble assertions cover only +a restricted unique-anchor domain; do not assume legacy multi-anchor output is +the oracle. Independently enumerate the admitted family with each handler's +specified threshold semantics, including exact energy/ED equalities, GU at +seed versus interaction ends, explicit selection, and range-crossing seeds. + +Native `AccessibilityBasePair` converts ED values to integer hundredths via +`Z_2_E`; the theory's decimal is therefore not an exact native end-to-end golden +value. Native Nussinov and nearest-neighbor oracles must use independently +enumerated structures with the production energy/rounding contract, including +initiation, loops, terminal/dangling terms, and full-span accessibility. Do not +loosen tolerances or change energy precision merely to match the theory decimal. + +Check $H_{\rm all}=N+S$ on the same allowed domain, and seeded plus seed-free +partition equality with the independently enumerated unconstrained ensemble. +Production skips starts that cannot contain a seed, so its seed-free tables do +not describe the whole unconstrained ensemble. For this identity either disable +eligible-start pruning in a test-only calculation or restrict both sides of +the comparison to the identical retained-start domain. +For nonempty ensembles verify $0\le P_{ij}\le1$, each row/column sum at most one, +and $\sum_{ij}P_{ij}$ equal to the independently computed expected pair count. +For marker tests, check $\sum_k M_k$ against the derivative that marks only +intermolecular pairs, holding accessibility and seed admission fixed. + +### C. Numerical and integration regressions + +- Tiny positive totals and positive boundary masses below the old epsilon; + both raw APIs and exact-path serialized diagnostics must remain nonempty. +- Exponential/product/normalization underflow, overflowing intermediate or + merged totals, NaN, and successful structural emptiness as distinct cases. +- Invariance of normalized probabilities under a representable constant + `energyAdd` shift with a **fixed admitted seed family**; a shift can otherwise + alter computed-seed admission. Test out-of-range shifts as explicit failures. +- Equal raw $Z$ with pair output off/on, legacy trackers off/on, and no duplicate + denominator increment through predictor, collector, hub, or final writer. +- Virtual update interception and scoped-state restoration after exceptions; + legacy heuristic paths and existing spot semantics remain covered. +- Asymmetric nonpalindromic sequences, nonzero region offsets, positive/negative + display shifts, and known interior pairs to expose double query reversal. +- Several disjoint regions, including a structure crossing a region boundary + that the region-union oracle excludes; `outPerRegion` changes reporting only. +- Injected failure after an earlier successful region: no partial probability + matrix is finalized. Repeated predictions reset all per-region state. +- Multi-FASTA file naming, shared stdout/stderr blocks, supported thread counts, + compressed streams where supported, and simultaneous spot/pair output. +- A bulge whose rectangle covers a coordinate pair that never actually pairs: + spot coverage may be positive while the actual-pair probability is zero. +- Explicit unsupported-mode/window errors and no hidden `Z_partition` retention + from pair output alone. Account separately for legacy trackers' map cost. + +Use justified absolute/relative tolerances with a higher-precision reference; +do not demand bitwise equality after changing sum order or hide model differences +inside a large tolerance. Benchmark after correctness passes, with the same +seed-locality and memory cases used in the early algorithm comparison. + +## 11. Implementation sequence and affected components + +Each milestone has an exit condition; none is implemented by this document. + +| Order | Work | Main files/components | Exit condition | +| --- | --- | --- | --- | +| 1 | Freeze ensemble, weights, numerical outcomes, and independent fixtures | This specification; `tests/PredictorSeedOracle_test.cpp`, `tests/PredictorTinyOracle_test.cpp` | Mathematical and native-model expected results distinguished | +| 2 | Add stack capability and active seed/domain compilation | `SeedHandler*`; proposed seed-domain helper | Handler-specific admission, mixed/singleton, offsets, and sparse boxes tested | +| 3 | Compare forward/outside numerical kernels | Proposed `SeededPartitionFunctionStack` or suffix helper; focused tests | Both compared kernels match oracle; measured default decision recorded | +| 4 | Integrate selected partition backend and scoped numerical policy | `PredictorMfeEns2dSeedExtension`, `PredictorMfeEns`, relevant output status/forwarding | Correct complete boundary sums with output off/on; virtual hooks preserved | +| 5 | Add raw pair result and success-only region aggregation | Proposed `BasePairProbabilities`; `src/bin/IntaRNA.cpp` | Pair numerators, disjoint merges, numerical failures and lifecycle validated | +| 6 | Add writer and CLI support, including tiny-total presentation | `CommandLineParsing.*`, proposed pair writer, `OutputHandlerCsv`, `OutputHandlerEnsemble`, `OutputHandlerText` | Correct indices, formats, statuses and compatibility checks | +| 7 | Finish performance and regression validation, documentation and registration | Library/test `Makefile.am`, README/help, Doxygen, ChangeLog | Required checks pass and intentional output changes are independently explained | + +Use the repository's `Matrix` and existing conventions rather than +introducing a new general matrix library. New helper and method names above +are proposals, not existing public API. Preserve existing predictor constructor +ownership, tracker lifetimes, and legacy subclass dependencies. + +For the implementation, register new headers/sources and tests, bootstrap after +Autotools source changes, and run `make tests -j2` on supported release and debug +builds. Run installed public-header/consumer checks for new public interfaces. +Record toolchain, options, inputs, timings, peak memory, and numerical differences. +An intentionally corrected partition can change ensemble rankings; justify those +changes against the oracle instead of regenerating expected files blindly. + +For this documentation-only plan, validate references, equations, pseudocode +contracts, Markdown structure, distribution registration, and `git diff --check`. +No C++ implementation build or performance result is claimed by this plan. From 88f4369f84a4c2d7759ba2034c47e3ce0f240162 Mon Sep 17 00:00:00 2001 From: AlexanderMitrofanov Date: Thu, 8 Oct 2026 13:47:16 +0200 Subject: [PATCH 02/21] test: establish independent seeded probability oracles (step 1) --- ChangeLog | 10 + tests/Makefile.am | 8 +- tests/SeededChainOracle.h | 71 + tests/SeededPartitionFunction_test.cpp | 41 + tests/SeededTheoryFixtures.h | 55 + tests/data/Makefile.am | 2 +- tests/data/seeded-theory.dat | 5681 ++++++++++++++++++++++++ tests/tools/export-seeded-theory.py | 33 + 8 files changed, 5899 insertions(+), 2 deletions(-) create mode 100644 tests/SeededChainOracle.h create mode 100644 tests/SeededPartitionFunction_test.cpp create mode 100644 tests/SeededTheoryFixtures.h create mode 100644 tests/data/seeded-theory.dat create mode 100644 tests/tools/export-seeded-theory.py diff --git a/ChangeLog b/ChangeLog index c7f36eda..606c5d2b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -42,6 +42,9 @@ ## Technical changes and Optimizations +- establish independent weighted-chain fixtures for seeded pair probabilities + (issue #257, implementation step 1) + - document the implementation plan for exact seeded base-pair probabilities, including algorithm comparison, numerical/output contracts and validation; no prediction or probability implementation changes (issue #257) @@ -133,6 +136,13 @@ energies, restricted partition sums, and trackers. ################################################################################ ################################################################################ +261008 Alexander Mitrofanov + * tests/SeededChainOracle.h, tests/SeededPartitionFunction_test.cpp, tests/Makefile.am : + + independently enumerate weighted chains, raw boundaries and pair masses; + verify overlapping witnesses and singleton/noLP semantics (PR #258, step 1) + + preserve all ten high-precision theory fixtures with an explicit coordinate + conversion and reproducible exporter; do not quantize their accessibility + 261008 Alexander Mitrofanov * doc/analysis/base-pair-probabilities-plan.md : + specify the stack-seed partition and outside recurrences, sparse domain, diff --git a/tests/Makefile.am b/tests/Makefile.am index ea9662b2..90b8432d 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -23,6 +23,9 @@ check_PROGRAMS = runApiTests # test sources runApiTests_SOURCES = \ catch.hpp \ + SeededChainOracle.h \ + SeededTheoryFixtures.h \ + SeededPartitionFunction_test.cpp \ testEasyLoggingSetup.icc \ AccessibilityConstraint_test.cpp \ AccessibilityFromStream_test.cpp \ @@ -73,6 +76,9 @@ LIBS= -L$(top_builddir)/src/IntaRNA -lIntaRNA \ # add source include for compilation runApiTests_CXXFLAGS = -I$(top_builddir)/src \ @AM_CXXFLAGS@ @CXXFLAGS@ \ - -DELPP_NO_LOG_TO_FILE + -DELPP_NO_LOG_TO_FILE \ + -DINTARNA_TEST_DATA_DIR=\"$(abs_srcdir)/data\" + +EXTRA_DIST = tools/export-seeded-theory.py diff --git a/tests/SeededChainOracle.h b/tests/SeededChainOracle.h new file mode 100644 index 00000000..dc6daddf --- /dev/null +++ b/tests/SeededChainOracle.h @@ -0,0 +1,71 @@ +#ifndef INTARNA_TEST_SEEDEDCHAINORACLE_H_ +#define INTARNA_TEST_SEEDEDCHAINORACLE_H_ + +#include +#include +#include +#include +#include + +// Independent exhaustive path enumeration. These test coordinates are zero-based +// with both strands increasing. Weight callbacks return long double, so expected +// values never pass through native integer energy conversion or the tested DP. +namespace seeded_oracle { +using Pair = std::array; +using Boundary = std::array; +using Chain = std::vector; +struct Model { + size_t n, m, span1, span2; + bool noLP = false; + std::vector seeds; + std::function valid; + std::function init; + std::function edge, boundary; +}; +struct Result { + long double z = 0, unseeded = 0, pairCount = 0; + std::map boundaries; + std::map mass; +}; +inline bool stack(Pair a, Pair b) { + return a[0]+1 == b[0] && a[1]+1 == b[1]; +} +inline Result enumerate(const Model & model) { + Result out; + Chain chain; + std::function visit = [&](long double hybrid) { + const Pair p = chain.front(), q = chain.back(); + bool noLP = true; + for (size_t k=0; k0 && stack(chain[k-1], chain[k])) + || (k+1 + +TEST_CASE("seeded chain oracle counts structures instead of seed witnesses", "[SeededPartitionFunction]") { + using namespace seeded_oracle; + Model m{3,3,3,3,false, {{{0,0},{1,1}},{{1,1},{2,2}}}, + [](Pair p){return p[0]==p[1];}, [](Pair){return 2.L;}, + [](Pair a, Pair b){return stack(a,b) ? 3.L : 0.L;}, + [](Pair,Pair){return 5.L;}}; + auto r=enumerate(m); + REQUIRE(r.z == 150.L); // two two-pair chains (30 each), one three-pair (90) + REQUIRE(r.mass[Pair{1,1}] == 150.L); + REQUIRE(r.pairCount == 390.L); + m.seeds={{{1,1}}}; + r=enumerate(m); + REQUIRE(r.z == 160.L); + m.noLP=true; + REQUIRE(enumerate(m).z == 150.L); + m.span1=1; + REQUIRE(enumerate(m).z == 0.L); +} + +#include "SeededTheoryFixtures.h" +TEST_CASE("unrounded fixed-seed theory gold agrees with exhaustive chains", "[SeededPartitionFunction]") { + using namespace seeded_oracle; + auto fixtures=theoryFixtures(); + REQUIRE(fixtures.size()==10); + for (const auto & f:fixtures) { + INFO(f.name); + const auto got=enumerate(f.model); + REQUIRE(double(got.z)==Approx(double(f.expected.z)).epsilon(2e-12)); + for (const auto & [pair, mass]:f.expected.mass) { + auto it=got.mass.find(pair); + REQUIRE(double(it==got.mass.end()?0:it->second)==Approx(double(mass)).epsilon(2e-12)); + } + if (f.name=="random03") { + REQUIRE(double(got.mass.at({9,4})/got.z)==Approx(double(std::exp(1.L)/(1+2*std::exp(1.L)))).epsilon(2e-12)); + } + } +} diff --git a/tests/SeededTheoryFixtures.h b/tests/SeededTheoryFixtures.h new file mode 100644 index 00000000..c7ae833d --- /dev/null +++ b/tests/SeededTheoryFixtures.h @@ -0,0 +1,55 @@ +#ifndef INTARNA_TEST_SEEDEDTHEORYFIXTURES_H_ +#define INTARNA_TEST_SEEDEDTHEORYFIXTURES_H_ +#include "SeededChainOracle.h" +#include +#include +#include +#include + +namespace seeded_oracle { +struct TheoryFixture { + std::string name; + Model model; + Result expected; + std::map terminal, seeded, free; + std::map valid; +}; +inline std::vector theoryFixtures() { + std::ifstream file(std::string(INTARNA_TEST_DATA_DIR)+"/seeded-theory.dat"); + if (!file) throw std::runtime_error("cannot read seeded theory fixtures"); + std::vector fixtures; + std::string tag; + while (file >> tag) { + if (tag == "CASE") { + fixtures.emplace_back(); + auto & f=fixtures.back(); + file >> f.name >> f.model.n >> f.model.m >> f.model.span1; + f.model.span2=f.model.span1; + } else { + auto & f=fixtures.back(); + if (tag == "Z") file >> f.expected.z; + else if (tag == "S") { + Pair p; size_t len; file >> p[0] >> p[1] >> len; + Chain s; for (size_t k=0;k> i; + file >> f.terminal[b] >> f.seeded[b] >> f.free[b]; + f.expected.boundaries[b]=f.terminal[b]*f.seeded[b]; + } else if (tag == "P") { + Pair p; file >> p[0] >> p[1] >> f.valid[p] >> f.expected.mass[p]; + } + } + } + for (auto & f:fixtures) { + f.model.valid=[valid=f.valid](Pair p){return valid.at(p);}; + f.model.init=[](Pair){return std::exp(1.L);}; + f.model.edge=[](Pair,Pair){return std::exp(1.L);}; + f.model.boundary=[b=f.terminal](Pair p,Pair q){ + auto it=b.find({p[0],p[1],q[0],q[1]});return it==b.end()?0.L:it->second; + }; + } + return fixtures; +} +} +#endif diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am index d4543cbd..d23825de 100644 --- a/tests/data/Makefile.am +++ b/tests/data/Makefile.am @@ -1,2 +1,2 @@ -EXTRA_DIST = *.parameter *.testresult +EXTRA_DIST = seeded-theory.dat *.parameter *.testresult diff --git a/tests/data/seeded-theory.dat b/tests/data/seeded-theory.dat new file mode 100644 index 00000000..95616c24 --- /dev/null +++ b/tests/data/seeded-theory.dat @@ -0,0 +1,5681 @@ +CASE random01 8 9 4 +Z 4.3717640897331911104894599604574021786328514418407E+0 +S 2 3 4 +S 3 4 4 +B 0 2 0 2 1.0000000000000000000000000000000000000000000000000 0 2.7182818284590452353602874713526624977572470937000 +B 0 2 1 5 0.063101141649108249235116865494813374931987528975394 0 7.3890560989306502272304274605750078131803155705521 +B 0 2 2 3 0.40615451504869061867617848450614858263192501276200 0 7.3890560989306502272304274605750078131803155705521 +B 0 2 2 4 0.40615451504869061867617848450614858263192501276200 0 7.3890560989306502272304274605750078131803155705521 +B 0 2 3 3 0.10923177257303592801426772675922287394788751914298 0 7.3890560989306502272304274605750078131803155705521 +B 0 2 3 4 0.10923177257303592801426772675922287394788751914298 0 27.474593022118317968158957115156725710168223409107 +B 0 3 0 3 1.0000000000000000000000000000000000000000000000000 0 2.7182818284590452353602874713526624977572470937000 +B 0 3 1 5 0.063101141649108249235116865494813374931987528975394 0 7.3890560989306502272304274605750078131803155705521 +B 0 3 2 4 0.40615451504869061867617848450614858263192501276200 0 7.3890560989306502272304274605750078131803155705521 +B 0 3 3 4 0.10923177257303592801426772675922287394788751914298 0 7.3890560989306502272304274605750078131803155705521 +B 0 3 3 6 0.016970510725180570455966004230403875916087538807804 0 47.560129945305985709087486769738443607156131247662 +B 0 4 0 4 1.0000000000000000000000000000000000000000000000000 0 2.7182818284590452353602874713526624977572470937000 +B 0 4 1 5 0.063101141649108249235116865494813374931987528975394 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 3 6 0.016970510725180570455966004230403875916087538807804 0 27.474593022118317968158957115156725710168223409107 +B 0 4 3 7 0.016970510725180570455966004230403875916087538807804 0 27.474593022118317968158957115156725710168223409107 +B 1 5 1 5 0.063101141649108249235116865494813374931987528975394 0 2.7182818284590452353602874713526624977572470937000 +B 1 5 3 6 0.016970510725180570455966004230403875916087538807804 0 7.3890560989306502272304274605750078131803155705521 +B 1 5 3 7 0.016970510725180570455966004230403875916087538807804 0 7.3890560989306502272304274605750078131803155705521 +B 1 5 3 8 0.016970510725180570455966004230403875916087538807804 0 7.3890560989306502272304274605750078131803155705521 +B 2 2 2 2 1.0000000000000000000000000000000000000000000000000 0 2.7182818284590452353602874713526624977572470937000 +B 2 2 3 3 0.70307725752434530933808924225307429131596250638101 0 7.3890560989306502272304274605750078131803155705521 +B 2 2 3 4 0.70307725752434530933808924225307429131596250638101 0 7.3890560989306502272304274605750078131803155705521 +B 2 2 4 5 0.10923177257303592801426772675922287394788751914298 0 47.560129945305985709087486769738443607156131247662 +B 2 2 5 3 0.40615451504869061867617848450614858263192501276200 0 7.3890560989306502272304274605750078131803155705521 +B 2 2 5 4 0.40615451504869061867617848450614858263192501276200 0 27.474593022118317968158957115156725710168223409107 +B 2 3 2 3 1.0000000000000000000000000000000000000000000000000 0 2.7182818284590452353602874713526624977572470937000 +B 2 3 3 4 0.70307725752434530933808924225307429131596250638101 0 7.3890560989306502272304274605750078131803155705521 +B 2 3 3 6 0.10923177257303592801426772675922287394788751914298 0 7.3890560989306502272304274605750078131803155705521 +B 2 3 4 5 0.10923177257303592801426772675922287394788751914298 0 27.474593022118317968158957115156725710168223409107 +B 2 3 5 4 0.40615451504869061867617848450614858263192501276200 0 7.3890560989306502272304274605750078131803155705521 +B 2 3 5 6 0.063101141649108249235116865494813374931987528975394 54.598150033144239078110261202860878402790737038617 47.560129945305985709087486769738443607156131247662 +B 2 4 2 4 1.0000000000000000000000000000000000000000000000000 0 2.7182818284590452353602874713526624977572470937000 +B 2 4 3 6 0.10923177257303592801426772675922287394788751914298 0 7.3890560989306502272304274605750078131803155705521 +B 2 4 3 7 0.10923177257303592801426772675922287394788751914298 0 7.3890560989306502272304274605750078131803155705521 +B 2 4 4 5 0.10923177257303592801426772675922287394788751914298 0 7.3890560989306502272304274605750078131803155705521 +B 2 4 5 6 0.063101141649108249235116865494813374931987528975394 0 27.474593022118317968158957115156725710168223409107 +B 2 4 5 7 0.063101141649108249235116865494813374931987528975394 0 47.560129945305985709087486769738443607156131247662 +B 3 0 3 0 0.40615451504869061867617848450614858263192501276200 0 2.7182818284590452353602874713526624977572470937000 +B 3 0 5 1 0.063101141649108249235116865494813374931987528975394 0 7.3890560989306502272304274605750078131803155705521 +B 3 0 5 2 0.063101141649108249235116865494813374931987528975394 0 7.3890560989306502272304274605750078131803155705521 +B 3 0 5 3 0.063101141649108249235116865494813374931987528975394 0 7.3890560989306502272304274605750078131803155705521 +B 3 0 6 1 0.016970510725180570455966004230403875916087538807804 0 7.3890560989306502272304274605750078131803155705521 +B 3 0 6 2 0.016970510725180570455966004230403875916087538807804 0 27.474593022118317968158957115156725710168223409107 +B 3 0 6 3 0.016970510725180570455966004230403875916087538807804 0 47.560129945305985709087486769738443607156131247662 +B 3 1 3 1 0.40615451504869061867617848450614858263192501276200 0 2.7182818284590452353602874713526624977572470937000 +B 3 1 5 2 0.23462782834889943395564767500048097878195627086869 0 7.3890560989306502272304274605750078131803155705521 +B 3 1 5 3 0.23462782834889943395564767500048097878195627086869 0 7.3890560989306502272304274605750078131803155705521 +B 3 1 5 4 0.23462782834889943395564767500048097878195627086869 0 7.3890560989306502272304274605750078131803155705521 +B 3 1 6 2 0.063101141649108249235116865494813374931987528975394 0 7.3890560989306502272304274605750078131803155705521 +B 3 1 6 3 0.063101141649108249235116865494813374931987528975394 0 27.474593022118317968158957115156725710168223409107 +B 3 1 6 4 0.063101141649108249235116865494813374931987528975394 0 47.560129945305985709087486769738443607156131247662 +B 3 2 3 2 0.70307725752434530933808924225307429131596250638101 0 2.7182818284590452353602874713526624977572470937000 +B 3 2 4 5 0.10923177257303592801426772675922287394788751914298 0 7.3890560989306502272304274605750078131803155705521 +B 3 2 5 3 0.40615451504869061867617848450614858263192501276200 0 7.3890560989306502272304274605750078131803155705521 +B 3 2 5 4 0.40615451504869061867617848450614858263192501276200 0 7.3890560989306502272304274605750078131803155705521 +B 3 2 6 3 0.10923177257303592801426772675922287394788751914298 0 7.3890560989306502272304274605750078131803155705521 +B 3 2 6 4 0.10923177257303592801426772675922287394788751914298 0 27.474593022118317968158957115156725710168223409107 +B 3 3 3 3 0.70307725752434530933808924225307429131596250638101 0 2.7182818284590452353602874713526624977572470937000 +B 3 3 4 5 0.10923177257303592801426772675922287394788751914298 0 7.3890560989306502272304274605750078131803155705521 +B 3 3 5 4 0.40615451504869061867617848450614858263192501276200 0 7.3890560989306502272304274605750078131803155705521 +B 3 3 5 6 0.063101141649108249235116865494813374931987528975394 0 27.474593022118317968158957115156725710168223409107 +B 3 3 6 4 0.10923177257303592801426772675922287394788751914298 0 7.3890560989306502272304274605750078131803155705521 +B 3 3 6 6 0.016970510725180570455966004230403875916087538807804 0 47.560129945305985709087486769738443607156131247662 +B 3 4 3 4 0.70307725752434530933808924225307429131596250638101 0 2.7182818284590452353602874713526624977572470937000 +B 3 4 4 5 0.10923177257303592801426772675922287394788751914298 0 7.3890560989306502272304274605750078131803155705521 +B 3 4 5 6 0.063101141649108249235116865494813374931987528975394 0 27.474593022118317968158957115156725710168223409107 +B 3 4 5 7 0.063101141649108249235116865494813374931987528975394 0 27.474593022118317968158957115156725710168223409107 +B 3 4 6 6 0.016970510725180570455966004230403875916087538807804 0 27.474593022118317968158957115156725710168223409107 +B 3 4 6 7 0.016970510725180570455966004230403875916087538807804 54.598150033144239078110261202860878402790737038617 47.560129945305985709087486769738443607156131247662 +B 3 6 3 6 0.70307725752434530933808924225307429131596250638101 0 2.7182818284590452353602874713526624977572470937000 +B 3 6 5 7 0.40615451504869061867617848450614858263192501276200 0 7.3890560989306502272304274605750078131803155705521 +B 3 6 5 8 0.40615451504869061867617848450614858263192501276200 0 7.3890560989306502272304274605750078131803155705521 +B 3 6 6 7 0.10923177257303592801426772675922287394788751914298 0 7.3890560989306502272304274605750078131803155705521 +B 3 6 6 8 0.10923177257303592801426772675922287394788751914298 0 27.474593022118317968158957115156725710168223409107 +B 3 7 3 7 0.70307725752434530933808924225307429131596250638101 0 2.7182818284590452353602874713526624977572470937000 +B 3 7 5 8 0.40615451504869061867617848450614858263192501276200 0 7.3890560989306502272304274605750078131803155705521 +B 3 7 6 8 0.10923177257303592801426772675922287394788751914298 0 7.3890560989306502272304274605750078131803155705521 +B 3 8 3 8 0.70307725752434530933808924225307429131596250638101 0 2.7182818284590452353602874713526624977572470937000 +B 4 5 4 5 0.15536240349696360679341858802363237296378750931057 0 2.7182818284590452353602874713526624977572470937000 +B 4 5 5 6 0.10923177257303592801426772675922287394788751914298 0 7.3890560989306502272304274605750078131803155705521 +B 4 5 5 7 0.10923177257303592801426772675922287394788751914298 0 7.3890560989306502272304274605750078131803155705521 +B 4 5 5 8 0.10923177257303592801426772675922287394788751914298 0 7.3890560989306502272304274605750078131803155705521 +B 4 5 6 6 0.063101141649108249235116865494813374931987528975394 0 7.3890560989306502272304274605750078131803155705521 +B 4 5 6 7 0.063101141649108249235116865494813374931987528975394 0 27.474593022118317968158957115156725710168223409107 +B 4 5 6 8 0.063101141649108249235116865494813374931987528975394 0 47.560129945305985709087486769738443607156131247662 +B 5 0 5 0 0.40615451504869061867617848450614858263192501276200 0 2.7182818284590452353602874713526624977572470937000 +B 5 0 6 1 0.063101141649108249235116865494813374931987528975394 0 7.3890560989306502272304274605750078131803155705521 +B 5 0 6 2 0.063101141649108249235116865494813374931987528975394 0 7.3890560989306502272304274605750078131803155705521 +B 5 0 6 3 0.063101141649108249235116865494813374931987528975394 0 7.3890560989306502272304274605750078131803155705521 +B 5 1 5 1 0.40615451504869061867617848450614858263192501276200 0 2.7182818284590452353602874713526624977572470937000 +B 5 1 6 2 0.23462782834889943395564767500048097878195627086869 0 7.3890560989306502272304274605750078131803155705521 +B 5 1 6 3 0.23462782834889943395564767500048097878195627086869 0 7.3890560989306502272304274605750078131803155705521 +B 5 1 6 4 0.23462782834889943395564767500048097878195627086869 0 7.3890560989306502272304274605750078131803155705521 +B 5 2 5 2 0.70307725752434530933808924225307429131596250638101 0 2.7182818284590452353602874713526624977572470937000 +B 5 2 6 3 0.40615451504869061867617848450614858263192501276200 0 7.3890560989306502272304274605750078131803155705521 +B 5 2 6 4 0.40615451504869061867617848450614858263192501276200 0 7.3890560989306502272304274605750078131803155705521 +B 5 2 7 5 0.016970510725180570455966004230403875916087538807804 0 47.560129945305985709087486769738443607156131247662 +B 5 3 5 3 0.70307725752434530933808924225307429131596250638101 0 2.7182818284590452353602874713526624977572470937000 +B 5 3 6 4 0.40615451504869061867617848450614858263192501276200 0 7.3890560989306502272304274605750078131803155705521 +B 5 3 6 6 0.063101141649108249235116865494813374931987528975394 0 7.3890560989306502272304274605750078131803155705521 +B 5 3 7 5 0.016970510725180570455966004230403875916087538807804 0 27.474593022118317968158957115156725710168223409107 +B 5 4 5 4 0.70307725752434530933808924225307429131596250638101 0 2.7182818284590452353602874713526624977572470937000 +B 5 4 6 6 0.063101141649108249235116865494813374931987528975394 0 7.3890560989306502272304274605750078131803155705521 +B 5 4 6 7 0.063101141649108249235116865494813374931987528975394 0 7.3890560989306502272304274605750078131803155705521 +B 5 4 7 5 0.016970510725180570455966004230403875916087538807804 0 7.3890560989306502272304274605750078131803155705521 +B 5 6 5 6 0.70307725752434530933808924225307429131596250638101 0 2.7182818284590452353602874713526624977572470937000 +B 5 6 6 7 0.40615451504869061867617848450614858263192501276200 0 7.3890560989306502272304274605750078131803155705521 +B 5 6 6 8 0.40615451504869061867617848450614858263192501276200 0 7.3890560989306502272304274605750078131803155705521 +B 5 7 5 7 0.70307725752434530933808924225307429131596250638101 0 2.7182818284590452353602874713526624977572470937000 +B 5 7 6 8 0.40615451504869061867617848450614858263192501276200 0 7.3890560989306502272304274605750078131803155705521 +B 5 8 5 8 0.70307725752434530933808924225307429131596250638101 0 2.7182818284590452353602874713526624977572470937000 +B 6 0 6 0 0.40615451504869061867617848450614858263192501276200 0 2.7182818284590452353602874713526624977572470937000 +B 6 1 6 1 0.40615451504869061867617848450614858263192501276200 0 2.7182818284590452353602874713526624977572470937000 +B 6 2 6 2 0.70307725752434530933808924225307429131596250638101 0 2.7182818284590452353602874713526624977572470937000 +B 6 2 7 5 0.063101141649108249235116865494813374931987528975394 0 7.3890560989306502272304274605750078131803155705521 +B 6 3 6 3 0.70307725752434530933808924225307429131596250638101 0 2.7182818284590452353602874713526624977572470937000 +B 6 3 7 5 0.063101141649108249235116865494813374931987528975394 0 7.3890560989306502272304274605750078131803155705521 +B 6 4 6 4 0.70307725752434530933808924225307429131596250638101 0 2.7182818284590452353602874713526624977572470937000 +B 6 4 7 5 0.063101141649108249235116865494813374931987528975394 0 7.3890560989306502272304274605750078131803155705521 +B 6 6 6 6 0.70307725752434530933808924225307429131596250638101 0 2.7182818284590452353602874713526624977572470937000 +B 6 7 6 7 0.70307725752434530933808924225307429131596250638101 0 2.7182818284590452353602874713526624977572470937000 +B 6 8 6 8 0.70307725752434530933808924225307429131596250638101 0 2.7182818284590452353602874713526624977572470937000 +B 7 5 7 5 0.10923177257303592801426772675922287394788751914298 0 2.7182818284590452353602874713526624977572470937000 +P 0 8 0 0E+0 +P 0 7 0 0E+0 +P 0 6 0 0E+0 +P 0 5 0 0E+0 +P 0 4 1 0E+0 +P 0 3 1 0E+0 +P 0 2 1 0E+0 +P 0 1 0 0E+0 +P 0 0 0 0E+0 +P 1 8 0 0E+0 +P 1 7 0 0E+0 +P 1 6 0 0E+0 +P 1 5 1 0E+0 +P 1 4 0 0E+0 +P 1 3 0 0E+0 +P 1 2 0 0E+0 +P 1 1 0 0E+0 +P 1 0 0 0E+0 +P 2 8 0 0E+0 +P 2 7 0 0E+0 +P 2 6 0 0E+0 +P 2 5 0 0E+0 +P 2 4 1 0E+0 +P 2 3 1 3.4452055990206988828960404957464942375988941032730E+0 +P 2 2 1 0E+0 +P 2 1 0 0E+0 +P 2 0 0 0E+0 +P 3 8 1 0E+0 +P 3 7 1 0E+0 +P 3 6 1 0E+0 +P 3 5 0 0E+0 +P 3 4 1 4.3717640897331911104894599604574021786328514418407E+0 +P 3 3 1 0E+0 +P 3 2 1 0E+0 +P 3 1 1 0E+0 +P 3 0 1 0E+0 +P 4 8 0 0E+0 +P 4 7 0 0E+0 +P 4 6 0 0E+0 +P 4 5 1 4.3717640897331911104894599604574021786328514418407E+0 +P 4 4 0 0E+0 +P 4 3 0 0E+0 +P 4 2 0 0E+0 +P 4 1 0 0E+0 +P 4 0 0 0E+0 +P 5 8 1 0E+0 +P 5 7 1 0E+0 +P 5 6 1 4.3717640897331911104894599604574021786328514418407E+0 +P 5 5 0 0E+0 +P 5 4 1 0E+0 +P 5 3 1 0E+0 +P 5 2 1 0E+0 +P 5 1 1 0E+0 +P 5 0 1 0E+0 +P 6 8 1 0E+0 +P 6 7 1 9.2655849071249222759341946471090794103395733856771E-1 +P 6 6 1 0E+0 +P 6 5 0 0E+0 +P 6 4 1 0E+0 +P 6 3 1 0E+0 +P 6 2 1 0E+0 +P 6 1 1 0E+0 +P 6 0 1 0E+0 +P 7 8 0 0E+0 +P 7 7 0 0E+0 +P 7 6 0 0E+0 +P 7 5 1 0E+0 +P 7 4 0 0E+0 +P 7 3 0 0E+0 +P 7 2 0 0E+0 +P 7 1 0 0E+0 +P 7 0 0 0E+0 +END +CASE random02 9 10 5 +Z 3.4453836971469803747340139789231149788453585142410E-1 +S 1 4 4 +B 0 4 0 4 0.64368963917561258281984974273198181802045240680428 0 2.7182818284590452353602874713526624977572470937000 +B 0 4 1 6 0.070311360274050071345075243426508353200351240335493 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 2 5 0.070311360274050071345075243426508353200351240335493 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 2 6 0.010923741925317344826835743905415879904841140758756 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 3 6 0.010923741925317344826835743905415879904841140758756 0 27.474593022118317968158957115156725710168223409107 +B 0 4 4 7 0.0063104403630075981217993771193317378549505262491940 0 142.32935382482556026905480728176275780392268396339 +B 0 4 4 8 0.0016971388006978514167630103332475958050599117396321 0 142.32935382482556026905480728176275780392268396339 +B 0 6 0 6 0.32082507158997030168823957604942531476922839540182 0 2.7182818284590452353602874713526624977572470937000 +B 0 6 4 7 0.032690598855965146513950168964815211303554587417283 0 7.3890560989306502272304274605750078131803155705521 +B 0 6 4 8 0.010923741925317344826835743905415879904841140758756 0 7.3890560989306502272304274605750078131803155705521 +B 0 6 4 9 0.0063104403630075981217993771193317378549505262491940 0 7.3890560989306502272304274605750078131803155705521 +B 1 4 1 4 0.91553187403921065692767711750444543210662546514449 0 2.7182818284590452353602874713526624977572470937000 +B 1 4 2 5 0.26143745324123757517000007652833284147371829582510 0 7.3890560989306502272304274605750078131803155705521 +B 1 4 2 6 0.040617551099683708085955493665962116552596190547125 0 7.3890560989306502272304274605750078131803155705521 +B 1 4 3 6 0.040617551099683708085955493665962116552596190547125 0 27.474593022118317968158957115156725710168223409107 +B 1 4 4 7 0.0063104403630075981217993771193317378549505262491940 54.598150033144239078110261202860878402790737038617 67.645666868493653450016016424320161504144039086217 +B 1 4 4 8 0.0016971388006978514167630103332475958050599117396321 0 122.24381690163789252812627762718103990693477612483 +B 1 4 5 5 0.070311360274050071345075243426508353200351240335493 0 7.3890560989306502272304274605750078131803155705521 +B 1 4 5 6 0.010923741925317344826835743905415879904841140758756 0 27.474593022118317968158957115156725710168223409107 +B 1 6 1 6 0.45631553027280385178434525045507277182765388331963 0 2.7182818284590452353602874713526624977572470937000 +B 1 6 4 7 0.032690598855965146513950168964815211303554587417283 0 7.3890560989306502272304274605750078131803155705521 +B 1 6 4 8 0.010923741925317344826835743905415879904841140758756 0 7.3890560989306502272304274605750078131803155705521 +B 1 6 4 9 0.0063104403630075981217993771193317378549505262491940 0 7.3890560989306502272304274605750078131803155705521 +B 2 0 2 0 0.092078217204697873032189668485907684599064686994020 0 2.7182818284590452353602874713526624977572470937000 +B 2 0 3 4 0.0063104403630075981217993771193317378549505262491940 0 7.3890560989306502272304274605750078131803155705521 +B 2 0 4 1 0.015537043487627091531872110691500021954731755268318 0 7.3890560989306502272304274605750078131803155705521 +B 2 0 4 2 0.010923741925317344826835743905415879904841140758756 0 7.3890560989306502272304274605750078131803155705521 +B 2 0 4 3 0.010923741925317344826835743905415879904841140758756 0 7.3890560989306502272304274605750078131803155705521 +B 2 0 5 4 0.0016971388006978514167630103332475958050599117396321 0 67.645666868493653450016016424320161504144039086217 +B 2 0 6 1 0.015537043487627091531872110691500021954731755268318 0 7.3890560989306502272304274605750078131803155705521 +B 2 0 6 2 0.010923741925317344826835743905415879904841140758756 0 27.474593022118317968158957115156725710168223409107 +B 2 0 6 3 0.010923741925317344826835743905415879904841140758756 0 47.560129945305985709087486769738443607156131247662 +B 2 4 2 4 0.37184740431201450871202236795951820393427934846407 0 2.7182818284590452353602874713526624977572470937000 +B 2 4 3 6 0.040617551099683708085955493665962116552596190547125 0 7.3890560989306502272304274605750078131803155705521 +B 2 4 4 7 0.0063104403630075981217993771193317378549505262491940 0 27.474593022118317968158957115156725710168223409107 +B 2 4 4 8 0.0016971388006978514167630103332475958050599117396321 0 27.474593022118317968158957115156725710168223409107 +B 2 4 5 5 0.070311360274050071345075243426508353200351240335493 0 7.3890560989306502272304274605750078131803155705521 +B 2 4 5 6 0.010923741925317344826835743905415879904841140758756 0 7.3890560989306502272304274605750078131803155705521 +B 2 4 6 7 0.0063104403630075981217993771193317378549505262491940 0 67.645666868493653450016016424320161504144039086217 +B 2 4 6 8 0.0016971388006978514167630103332475958050599117396321 0 142.32935382482556026905480728176275780392268396339 +B 2 5 2 5 0.29574456397791368513415619307496322017136396012302 0 2.7182818284590452353602874713526624977572470937000 +B 2 5 3 6 0.074924661836359818050111610212592495250241854845055 0 7.3890560989306502272304274605750078131803155705521 +B 2 5 4 7 0.015537043487627091531872110691500021954731755268318 0 27.474593022118317968158957115156725710168223409107 +B 2 5 4 8 0.0063104403630075981217993771193317378549505262491940 0 27.474593022118317968158957115156725710168223409107 +B 2 5 4 9 0.0016971388006978514167630103332475958050599117396321 0 27.474593022118317968158957115156725710168223409107 +B 2 5 5 6 0.020150345049936838236908477477584164004622369777880 0 7.3890560989306502272304274605750078131803155705521 +B 2 5 6 7 0.015537043487627091531872110691500021954731755268318 0 47.560129945305985709087486769738443607156131247662 +B 2 5 6 8 0.0063104403630075981217993771193317378549505262491940 0 122.24381690163789252812627762718103990693477612483 +B 2 6 2 6 0.18533461290713675159213390164377785771080290748405 0 2.7182818284590452353602874713526624977572470937000 +B 2 6 4 7 0.032690598855965146513950168964815211303554587417283 0 7.3890560989306502272304274605750078131803155705521 +B 2 6 4 8 0.010923741925317344826835743905415879904841140758756 0 7.3890560989306502272304274605750078131803155705521 +B 2 6 4 9 0.0063104403630075981217993771193317378549505262491940 0 7.3890560989306502272304274605750078131803155705521 +B 2 6 6 7 0.032690598855965146513950168964815211303554587417283 0 7.3890560989306502272304274605750078131803155705521 +B 2 6 6 8 0.010923741925317344826835743905415879904841140758756 0 27.474593022118317968158957115156725710168223409107 +B 3 4 3 4 0.91553187403921065692767711750444543210662546514449 0 2.7182818284590452353602874713526624977572470937000 +B 3 4 4 7 0.040617551099683708085955493665962116552596190547125 0 7.3890560989306502272304274605750078131803155705521 +B 3 4 4 8 0.010923741925317344826835743905415879904841140758756 0 7.3890560989306502272304274605750078131803155705521 +B 3 4 5 5 0.45256354620842507899492490963015732974708535131468 0 7.3890560989306502272304274605750078131803155705521 +B 3 4 5 6 0.070311360274050071345075243426508353200351240335493 0 7.3890560989306502272304274605750078131803155705521 +B 3 4 6 7 0.023463995731345653103877435392646927203773358398159 0 47.560129945305985709087486769738443607156131247662 +B 3 4 6 8 0.0063104403630075981217993771193317378549505262491940 0 67.645666868493653450016016424320161504144039086217 +B 3 4 7 6 0.040617551099683708085955493665962116552596190547125 0 27.474593022118317968158957115156725710168223409107 +B 3 6 3 6 0.45631553027280385178434525045507277182765388331963 0 2.7182818284590452353602874713526624977572470937000 +B 3 6 4 7 0.21041512051919336814621728461823995230866734276285 0 7.3890560989306502272304274605750078131803155705521 +B 3 6 4 8 0.070311360274050071345075243426508353200351240335493 0 7.3890560989306502272304274605750078131803155705521 +B 3 6 4 9 0.040617551099683708085955493665962116552596190547125 0 7.3890560989306502272304274605750078131803155705521 +B 3 6 6 7 0.12155285968757925733008372679152758180611096509006 0 7.3890560989306502272304274605750078131803155705521 +B 3 6 6 8 0.040617551099683708085955493665962116552596190547125 0 27.474593022118317968158957115156725710168223409107 +B 4 1 4 1 0.32082507158997030168823957604942531476922839540182 0 2.7182818284590452353602874713526624977572470937000 +B 4 1 5 4 0.070311360274050071345075243426508353200351240335493 0 7.3890560989306502272304274605750078131803155705521 +B 4 1 5 5 0.070311360274050071345075243426508353200351240335493 0 7.3890560989306502272304274605750078131803155705521 +B 4 1 6 2 0.074924661836359818050111610212592495250241854845055 0 7.3890560989306502272304274605750078131803155705521 +B 4 1 6 3 0.074924661836359818050111610212592495250241854845055 0 7.3890560989306502272304274605750078131803155705521 +B 4 1 7 4 0.040617551099683708085955493665962116552596190547125 0 47.560129945305985709087486769738443607156131247662 +B 4 1 8 2 0.020150345049936838236908477477584164004622369777880 0 7.3890560989306502272304274605750078131803155705521 +B 4 1 8 3 0.020150345049936838236908477477584164004622369777880 0 27.474593022118317968158957115156725710168223409107 +B 4 2 4 2 0.51195116455715780551316440915124980304259545089142 0 2.7182818284590452353602874713526624977572470937000 +B 4 2 5 4 0.45256354620842507899492490963015732974708535131468 0 7.3890560989306502272304274605750078131803155705521 +B 4 2 5 5 0.26143745324123757517000007652833284147371829582510 0 7.3890560989306502272304274605750078131803155705521 +B 4 2 5 6 0.070311360274050071345075243426508353200351240335493 0 7.3890560989306502272304274605750078131803155705521 +B 4 2 6 3 0.29574456397791368513415619307496322017136396012302 0 7.3890560989306502272304274605750078131803155705521 +B 4 2 7 4 0.26143745324123757517000007652833284147371829582510 0 27.474593022118317968158957115156725710168223409107 +B 4 2 7 6 0.040617551099683708085955493665962116552596190547125 0 67.645666868493653450016016424320161504144039086217 +B 4 2 8 3 0.079537963398669564755147976998676637300132469354617 0 7.3890560989306502272304274605750078131803155705521 +B 4 3 4 3 0.70307725752434530933808924225307429131596250638102 0 2.7182818284590452353602874713526624977572470937000 +B 4 3 5 4 0.64368963917561258281984974273198181802045240680428 0 7.3890560989306502272304274605750078131803155705521 +B 4 3 5 5 0.45256354620842507899492490963015732974708535131468 0 7.3890560989306502272304274605750078131803155705521 +B 4 3 5 6 0.070311360274050071345075243426508353200351240335493 0 7.3890560989306502272304274605750078131803155705521 +B 4 3 6 7 0.023463995731345653103877435392646927203773358398159 0 67.645666868493653450016016424320161504144039086217 +B 4 3 7 4 0.37184740431201450871202236795951820393427934846407 0 7.3890560989306502272304274605750078131803155705521 +B 4 3 7 6 0.040617551099683708085955493665962116552596190547125 0 47.560129945305985709087486769738443607156131247662 +B 4 3 8 7 0.0063104403630075981217993771193317378549505262491940 0 217.01304078115746708809359813920535410370132884056 +B 4 7 4 7 0.43123502266074723523026186748061067722978944804081 0 2.7182818284590452353602874713526624977572470937000 +B 4 7 6 8 0.074924661836359818050111610212592495250241854845055 0 7.3890560989306502272304274605750078131803155705521 +B 4 7 8 8 0.020150345049936838236908477477584164004622369777880 0 7.3890560989306502272304274605750078131803155705521 +B 4 8 4 8 0.40154121348638087197114211772006444058203439825245 0 2.7182818284590452353602874713526624977572470937000 +B 4 9 4 9 0.67338344834997894607896949249252805466820745659266 0 2.7182818284590452353602874713526624977572470937000 +B 5 0 5 0 0.22670735838960044921267931693038644168816809240718 0 2.7182818284590452353602874713526624977572470937000 +B 5 0 6 1 0.10000516944841643460419499318705458984810629012386 0 7.3890560989306502272304274605750078131803155705521 +B 5 0 6 2 0.070311360274050071345075243426508353200351240335493 0 7.3890560989306502272304274605750078131803155705521 +B 5 0 6 3 0.070311360274050071345075243426508353200351240335493 0 7.3890560989306502272304274605750078131803155705521 +B 5 0 7 4 0.010923741925317344826835743905415879904841140758756 0 67.645666868493653450016016424320161504144039086217 +B 5 0 8 1 0.057771106468021763068033551939277305901419022696090 0 7.3890560989306502272304274605750078131803155705521 +B 5 0 8 2 0.040617551099683708085955493665962116552596190547125 0 27.474593022118317968158957115156725710168223409107 +B 5 0 8 3 0.040617551099683708085955493665962116552596190547125 0 47.560129945305985709087486769738443607156131247662 +B 5 4 5 4 0.91553187403921065692767711750444543210662546514449 0 2.7182818284590452353602874713526624977572470937000 +B 5 4 6 7 0.040617551099683708085955493665962116552596190547125 0 7.3890560989306502272304274605750078131803155705521 +B 5 4 6 8 0.010923741925317344826835743905415879904841140758756 0 7.3890560989306502272304274605750078131803155705521 +B 5 4 7 6 0.070311360274050071345075243426508353200351240335493 0 7.3890560989306502272304274605750078131803155705521 +B 5 4 8 7 0.023463995731345653103877435392646927203773358398159 0 27.474593022118317968158957115156725710168223409107 +B 5 4 8 8 0.0063104403630075981217993771193317378549505262491940 0 47.560129945305985709087486769738443607156131247662 +B 5 5 5 5 0.72815776513640192589217262522753638591382694165984 0 2.7182818284590452353602874713526624977572470937000 +B 5 5 6 7 0.10000516944841643460419499318705458984810629012386 0 7.3890560989306502272304274605750078131803155705521 +B 5 5 6 8 0.040617551099683708085955493665962116552596190547125 0 7.3890560989306502272304274605750078131803155705521 +B 5 5 7 6 0.12969897862278279786331474294760082649586133991223 0 7.3890560989306502272304274605750078131803155705521 +B 5 5 8 7 0.057771106468021763068033551939277305901419022696090 0 27.474593022118317968158957115156725710168223409107 +B 5 5 8 8 0.023463995731345653103877435392646927203773358398159 0 47.560129945305985709087486769738443607156131247662 +B 5 6 5 6 0.45631553027280385178434525045507277182765388331963 0 2.7182818284590452353602874713526624977572470937000 +B 5 6 6 7 0.21041512051919336814621728461823995230866734276285 0 7.3890560989306502272304274605750078131803155705521 +B 5 6 6 8 0.070311360274050071345075243426508353200351240335493 0 7.3890560989306502272304274605750078131803155705521 +B 5 6 8 7 0.12155285968757925733008372679152758180611096509006 0 7.3890560989306502272304274605750078131803155705521 +B 5 6 8 8 0.040617551099683708085955493665962116552596190547125 0 27.474593022118317968158957115156725710168223409107 +B 6 1 6 1 0.32082507158997030168823957604942531476922839540182 0 2.7182818284590452353602874713526624977572470937000 +B 6 1 7 4 0.070311360274050071345075243426508353200351240335493 0 7.3890560989306502272304274605750078131803155705521 +B 6 1 8 2 0.074924661836359818050111610212592495250241854845055 0 7.3890560989306502272304274605750078131803155705521 +B 6 1 8 3 0.074924661836359818050111610212592495250241854845055 0 7.3890560989306502272304274605750078131803155705521 +B 6 2 6 2 0.51195116455715780551316440915124980304259545089142 0 2.7182818284590452353602874713526624977572470937000 +B 6 2 7 4 0.45256354620842507899492490963015732974708535131468 0 7.3890560989306502272304274605750078131803155705521 +B 6 2 7 6 0.070311360274050071345075243426508353200351240335493 0 7.3890560989306502272304274605750078131803155705521 +B 6 2 8 3 0.29574456397791368513415619307496322017136396012302 0 7.3890560989306502272304274605750078131803155705521 +B 6 3 6 3 0.70307725752434530933808924225307429131596250638102 0 2.7182818284590452353602874713526624977572470937000 +B 6 3 7 4 0.64368963917561258281984974273198181802045240680428 0 7.3890560989306502272304274605750078131803155705521 +B 6 3 7 6 0.070311360274050071345075243426508353200351240335493 0 7.3890560989306502272304274605750078131803155705521 +B 6 3 8 7 0.023463995731345653103877435392646927203773358398159 0 47.560129945305985709087486769738443607156131247662 +B 6 7 6 7 0.43123502266074723523026186748061067722978944804081 0 2.7182818284590452353602874713526624977572470937000 +B 6 7 8 8 0.074924661836359818050111610212592495250241854845055 0 7.3890560989306502272304274605750078131803155705521 +B 6 8 6 8 0.40154121348638087197114211772006444058203439825245 0 2.7182818284590452353602874713526624977572470937000 +B 7 4 7 4 0.91553187403921065692767711750444543210662546514449 0 2.7182818284590452353602874713526624977572470937000 +B 7 4 8 7 0.040617551099683708085955493665962116552596190547125 0 7.3890560989306502272304274605750078131803155705521 +B 7 4 8 8 0.010923741925317344826835743905415879904841140758756 0 7.3890560989306502272304274605750078131803155705521 +B 7 6 7 6 0.45631553027280385178434525045507277182765388331963 0 2.7182818284590452353602874713526624977572470937000 +B 7 6 8 7 0.21041512051919336814621728461823995230866734276285 0 7.3890560989306502272304274605750078131803155705521 +B 7 6 8 8 0.070311360274050071345075243426508353200351240335493 0 7.3890560989306502272304274605750078131803155705521 +B 8 1 8 1 0.32082507158997030168823957604942531476922839540182 0 2.7182818284590452353602874713526624977572470937000 +B 8 2 8 2 0.51195116455715780551316440915124980304259545089142 0 2.7182818284590452353602874713526624977572470937000 +B 8 3 8 3 0.70307725752434530933808924225307429131596250638102 0 2.7182818284590452353602874713526624977572470937000 +B 8 7 8 7 0.43123502266074723523026186748061067722978944804081 0 2.7182818284590452353602874713526624977572470937000 +B 8 8 8 8 0.40154121348638087197114211772006444058203439825245 0 2.7182818284590452353602874713526624977572470937000 +P 0 9 0 0E+0 +P 0 8 0 0E+0 +P 0 7 0 0E+0 +P 0 6 1 0E+0 +P 0 5 0 0E+0 +P 0 4 1 0E+0 +P 0 3 0 0E+0 +P 0 2 0 0E+0 +P 0 1 0 0E+0 +P 0 0 0 0E+0 +P 1 9 0 0E+0 +P 1 8 0 0E+0 +P 1 7 0 0E+0 +P 1 6 1 0E+0 +P 1 5 0 0E+0 +P 1 4 1 3.4453836971469803747340139789231149788453585142410E-1 +P 1 3 0 0E+0 +P 1 2 0 0E+0 +P 1 1 0 0E+0 +P 1 0 0 0E+0 +P 2 9 0 0E+0 +P 2 8 0 0E+0 +P 2 7 0 0E+0 +P 2 6 1 0E+0 +P 2 5 1 3.4453836971469803747340139789231149788453585142410E-1 +P 2 4 1 0E+0 +P 2 3 0 0E+0 +P 2 2 0 0E+0 +P 2 1 0 0E+0 +P 2 0 1 0E+0 +P 3 9 0 0E+0 +P 3 8 0 0E+0 +P 3 7 0 0E+0 +P 3 6 1 3.4453836971469803747340139789231149788453585142410E-1 +P 3 5 0 0E+0 +P 3 4 1 0E+0 +P 3 3 0 0E+0 +P 3 2 0 0E+0 +P 3 1 0 0E+0 +P 3 0 0 0E+0 +P 4 9 1 0E+0 +P 4 8 1 0E+0 +P 4 7 1 3.4453836971469803747340139789231149788453585142410E-1 +P 4 6 0 0E+0 +P 4 5 0 0E+0 +P 4 4 0 0E+0 +P 4 3 1 0E+0 +P 4 2 1 0E+0 +P 4 1 1 0E+0 +P 4 0 0 0E+0 +P 5 9 0 0E+0 +P 5 8 0 0E+0 +P 5 7 0 0E+0 +P 5 6 1 0E+0 +P 5 5 1 0E+0 +P 5 4 1 0E+0 +P 5 3 0 0E+0 +P 5 2 0 0E+0 +P 5 1 0 0E+0 +P 5 0 1 0E+0 +P 6 9 0 0E+0 +P 6 8 1 0E+0 +P 6 7 1 0E+0 +P 6 6 0 0E+0 +P 6 5 0 0E+0 +P 6 4 0 0E+0 +P 6 3 1 0E+0 +P 6 2 1 0E+0 +P 6 1 1 0E+0 +P 6 0 0 0E+0 +P 7 9 0 0E+0 +P 7 8 0 0E+0 +P 7 7 0 0E+0 +P 7 6 1 0E+0 +P 7 5 0 0E+0 +P 7 4 1 0E+0 +P 7 3 0 0E+0 +P 7 2 0 0E+0 +P 7 1 0 0E+0 +P 7 0 0 0E+0 +P 8 9 0 0E+0 +P 8 8 1 0E+0 +P 8 7 1 0E+0 +P 8 6 0 0E+0 +P 8 5 0 0E+0 +P 8 4 0 0E+0 +P 8 3 1 0E+0 +P 8 2 1 0E+0 +P 8 1 1 0E+0 +P 8 0 0 0E+0 +END +CASE random03 10 8 6 +Z 2.9540220251089651886087158590910771970452262871571E-1 +S 4 0 4 +B 0 0 0 0 0.38127651940768643182745377510846918653532856223429 0 2.7182818284590452353602874713526624977572470937000 +B 0 0 1 1 0.077196739831867753680885816355357498659562345705573 0 7.3890560989306502272304274605750078131803155705521 +B 0 0 2 1 0.068700661285486509402040381565801256596481347716195 0 7.3890560989306502272304274605750078131803155705521 +B 0 0 3 1 0.028613768266935144985171934442014724360261013318583 0 7.3890560989306502272304274605750078131803155705521 +B 0 0 3 2 0.028613768266935144985171934442014724360261013318583 0 47.560129945305985709087486769738443607156131247662 +B 0 0 3 5 0.0076954275084611998521571809025063660433028978954380 0 47.560129945305985709087486769738443607156131247662 +B 0 0 4 1 0.020117689720553900706326499652458482297180015329205 0 7.3890560989306502272304274605750078131803155705521 +B 0 0 5 1 0.011621611174172656427481064862902240234099017339828 0 7.3890560989306502272304274605750078131803155705521 +B 0 0 5 2 0.011621611174172656427481064862902240234099017339828 0 87.731203791681321190944546078901879401131946924772 +B 0 0 5 5 0.0031255326277914121486356300733459981710180193504505 0 217.01304078115746708809359813920535410370132884056 +B 0 1 0 1 0.44392298941008830410090008431757976734316069222693 0 2.7182818284590452353602874713526624977572470937000 +B 0 1 1 6 0.077196739831867753680885816355357498659562345705573 0 7.3890560989306502272304274605750078131803155705521 +B 0 1 2 6 0.068700661285486509402040381565801256596481347716195 0 7.3890560989306502272304274605750078131803155705521 +B 0 1 3 2 0.14823073610763090710757960894460982738743325741082 0 7.3890560989306502272304274605750078131803155705521 +B 0 1 3 5 0.028613768266935144985171934442014724360261013318583 0 7.3890560989306502272304274605750078131803155705521 +B 0 1 3 6 0.028613768266935144985171934442014724360261013318583 0 7.3890560989306502272304274605750078131803155705521 +B 0 1 4 6 0.020117689720553900706326499652458482297180015329205 0 47.560129945305985709087486769738443607156131247662 +B 0 1 5 2 0.060204582739105265123194946776245014533400349726817 0 7.3890560989306502272304274605750078131803155705521 +B 0 1 5 5 0.011621611174172656427481064862902240234099017339828 0 27.474593022118317968158957115156725710168223409107 +B 0 1 5 6 0.011621611174172656427481064862902240234099017339828 0 47.560129945305985709087486769738443607156131247662 +B 0 6 0 6 0.50656945941249017637434639352669034815099282221959 0 2.7182818284590452353602874713526624977572470937000 +B 1 0 1 0 0.38127651940768643182745377510846918653532856223429 0 2.7182818284590452353602874713526624977572470937000 +B 1 0 2 1 0.077196739831867753680885816355357498659562345705573 0 7.3890560989306502272304274605750078131803155705521 +B 1 0 3 1 0.037109846813316389264017369231570966423342011307960 0 7.3890560989306502272304274605750078131803155705521 +B 1 0 3 2 0.037109846813316389264017369231570966423342011307960 0 27.474593022118317968158957115156725710168223409107 +B 1 0 3 5 0.0099803749487960937039179563170865499794453371679317 0 27.474593022118317968158957115156725710168223409107 +B 1 0 4 1 0.028613768266935144985171934442014724360261013318583 0 7.3890560989306502272304274605750078131803155705521 +B 1 0 5 1 0.020117689720553900706326499652458482297180015329205 0 7.3890560989306502272304274605750078131803155705521 +B 1 0 5 2 0.020117689720553900706326499652458482297180015329205 0 67.645666868493653450016016424320161504144039086217 +B 1 0 5 5 0.0054104800681263060003964054879261821071604586229443 0 142.32935382482556026905480728176275780392268396339 +B 1 0 6 1 0.011621611174172656427481064862902240234099017339828 0 7.3890560989306502272304274605750078131803155705521 +B 1 0 6 2 0.011621611174172656427481064862902240234099017339828 0 87.731203791681321190944546078901879401131946924772 +B 1 0 6 5 0.0031255326277914121486356300733459981710180193504505 0 346.29487777063361298524265019950882880627071075635 +B 1 1 1 1 0.44392298941008830410090008431757976734316069222693 0 2.7182818284590452353602874713526624977572470937000 +B 1 1 2 6 0.077196739831867753680885816355357498659562345705573 0 7.3890560989306502272304274605750078131803155705521 +B 1 1 3 2 0.19224381279189372809977194002879223381444971125283 0 7.3890560989306502272304274605750078131803155705521 +B 1 1 3 5 0.037109846813316389264017369231570966423342011307960 0 7.3890560989306502272304274605750078131803155705521 +B 1 1 3 6 0.037109846813316389264017369231570966423342011307960 0 7.3890560989306502272304274605750078131803155705521 +B 1 1 4 6 0.028613768266935144985171934442014724360261013318583 0 47.560129945305985709087486769738443607156131247662 +B 1 1 5 2 0.10421765942336808611538727786042742096041680356882 0 7.3890560989306502272304274605750078131803155705521 +B 1 1 5 5 0.020117689720553900706326499652458482297180015329205 0 27.474593022118317968158957115156725710168223409107 +B 1 1 5 6 0.020117689720553900706326499652458482297180015329205 0 47.560129945305985709087486769738443607156131247662 +B 1 1 6 2 0.060204582739105265123194946776245014533400349726817 0 7.3890560989306502272304274605750078131803155705521 +B 1 1 6 5 0.011621611174172656427481064862902240234099017339828 0 47.560129945305985709087486769738443607156131247662 +B 1 1 6 6 0.011621611174172656427481064862902240234099017339828 0 142.32935382482556026905480728176275780392268396339 +B 1 6 1 6 0.50656945941249017637434639352669034815099282221959 0 2.7182818284590452353602874713526624977572470937000 +B 2 0 2 0 0.38127651940768643182745377510846918653532856223429 0 2.7182818284590452353602874713526624977572470937000 +B 2 0 3 1 0.045605925359697633542862804021127208486423009297338 0 7.3890560989306502272304274605750078131803155705521 +B 2 0 3 2 0.045605925359697633542862804021127208486423009297338 0 7.3890560989306502272304274605750078131803155705521 +B 2 0 3 5 0.012265322389130987555678731731666733915587776440425 0 7.3890560989306502272304274605750078131803155705521 +B 2 0 4 1 0.037109846813316389264017369231570966423342011307960 0 7.3890560989306502272304274605750078131803155705521 +B 2 0 5 1 0.028613768266935144985171934442014724360261013318583 0 7.3890560989306502272304274605750078131803155705521 +B 2 0 5 2 0.028613768266935144985171934442014724360261013318583 0 47.560129945305985709087486769738443607156131247662 +B 2 0 5 5 0.0076954275084611998521571809025063660433028978954380 0 67.645666868493653450016016424320161504144039086217 +B 2 0 6 1 0.020117689720553900706326499652458482297180015329205 0 7.3890560989306502272304274605750078131803155705521 +B 2 0 6 2 0.020117689720553900706326499652458482297180015329205 0 67.645666868493653450016016424320161504144039086217 +B 2 0 6 5 0.0054104800681263060003964054879261821071604586229443 0 217.01304078115746708809359813920535410370132884056 +B 2 0 7 3 0.00084058518745651829687485465876581423487558007795681 0 420.97856472696551980428144105695142510604935563351 +B 2 0 7 4 0.00084058518745651829687485465876581423487558007795681 0 420.97856472696551980428144105695142510604935563351 +B 2 1 2 1 0.44392298941008830410090008431757976734316069222693 0 2.7182818284590452353602874713526624977572470937000 +B 2 1 3 2 0.23625688947615654909196427111297464024146616509483 0 7.3890560989306502272304274605750078131803155705521 +B 2 1 3 5 0.045605925359697633542862804021127208486423009297338 0 7.3890560989306502272304274605750078131803155705521 +B 2 1 3 6 0.045605925359697633542862804021127208486423009297338 0 7.3890560989306502272304274605750078131803155705521 +B 2 1 4 6 0.037109846813316389264017369231570966423342011307960 0 47.560129945305985709087486769738443607156131247662 +B 2 1 5 2 0.14823073610763090710757960894460982738743325741082 0 7.3890560989306502272304274605750078131803155705521 +B 2 1 5 5 0.028613768266935144985171934442014724360261013318583 0 27.474593022118317968158957115156725710168223409107 +B 2 1 5 6 0.028613768266935144985171934442014724360261013318583 0 47.560129945305985709087486769738443607156131247662 +B 2 1 6 2 0.10421765942336808611538727786042742096041680356882 0 7.3890560989306502272304274605750078131803155705521 +B 2 1 6 5 0.020117689720553900706326499652458482297180015329205 0 47.560129945305985709087486769738443607156131247662 +B 2 1 6 6 0.020117689720553900706326499652458482297180015329205 0 142.32935382482556026905480728176275780392268396339 +B 2 1 7 3 0.0054104800681263060003964054879261821071604586229443 0 67.645666868493653450016016424320161504144039086217 +B 2 1 7 4 0.0031255326277914121486356300733459981710180193504505 0 67.645666868493653450016016424320161504144039086217 +B 2 6 2 6 0.50656945941249017637434639352669034815099282221959 0 2.7182818284590452353602874713526624977572470937000 +B 2 6 7 7 0.0076954275084611998521571809025063660433028978954380 0 7.3890560989306502272304274605750078131803155705521 +B 3 0 3 0 0.24071823208380637366988787053272051397070882736303 0 2.7182818284590452353602874713526624977572470937000 +B 3 0 4 1 0.045605925359697633542862804021127208486423009297338 0 7.3890560989306502272304274605750078131803155705521 +B 3 0 5 1 0.037109846813316389264017369231570966423342011307960 0 7.3890560989306502272304274605750078131803155705521 +B 3 0 5 2 0.037109846813316389264017369231570966423342011307960 0 27.474593022118317968158957115156725710168223409107 +B 3 0 5 5 0.0099803749487960937039179563170865499794453371679317 0 27.474593022118317968158957115156725710168223409107 +B 3 0 6 1 0.028613768266935144985171934442014724360261013318583 0 7.3890560989306502272304274605750078131803155705521 +B 3 0 6 2 0.028613768266935144985171934442014724360261013318583 0 47.560129945305985709087486769738443607156131247662 +B 3 0 6 5 0.0076954275084611998521571809025063660433028978954380 0 122.24381690163789252812627762718103990693477612483 +B 3 0 7 3 0.00084058518745651829687485465876581423487558007795681 0 271.61119081430170616620385934206623250649206587918 +B 3 0 7 4 0.00084058518745651829687485465876581423487558007795681 0 271.61119081430170616620385934206623250649206587918 +B 3 0 8 1 0.0031255326277914121486356300733459981710180193504505 0 7.3890560989306502272304274605750078131803155705521 +B 3 1 3 1 0.28026996616041937008415660219715704666848261893682 0 2.7182818284590452353602874713526624977572470937000 +B 3 1 4 6 0.045605925359697633542862804021127208486423009297338 0 7.3890560989306502272304274605750078131803155705521 +B 3 1 5 2 0.19224381279189372809977194002879223381444971125283 0 7.3890560989306502272304274605750078131803155705521 +B 3 1 5 5 0.037109846813316389264017369231570966423342011307960 0 7.3890560989306502272304274605750078131803155705521 +B 3 1 5 6 0.037109846813316389264017369231570966423342011307960 0 7.3890560989306502272304274605750078131803155705521 +B 3 1 6 2 0.14823073610763090710757960894460982738743325741082 0 7.3890560989306502272304274605750078131803155705521 +B 3 1 6 5 0.028613768266935144985171934442014724360261013318583 0 27.474593022118317968158957115156725710168223409107 +B 3 1 6 6 0.028613768266935144985171934442014724360261013318583 0 47.560129945305985709087486769738443607156131247662 +B 3 1 7 3 0.0054104800681263060003964054879261821071604586229443 0 47.560129945305985709087486769738443607156131247662 +B 3 1 7 4 0.0031255326277914121486356300733459981710180193504505 0 47.560129945305985709087486769738443607156131247662 +B 3 1 8 6 0.0031255326277914121486356300733459981710180193504505 0 400.89302780377785206335291140236970720906144779496 +B 3 2 3 2 0.57439895436264836895197840231235810811534467594186 0 2.7182818284590452353602874713526624977572470937000 +B 3 2 4 6 0.078946528330264279530046876310587683057258242154251 0 7.3890560989306502272304274605750078131803155705521 +B 3 2 5 5 0.064239318677836684824116782146055382867238685447990 0 7.3890560989306502272304274605750078131803155705521 +B 3 2 5 6 0.064239318677836684824116782146055382867238685447990 0 7.3890560989306502272304274605750078131803155705521 +B 3 2 6 5 0.049532109025409090118186687981523082677219128741729 0 7.3890560989306502272304274605750078131803155705521 +B 3 2 6 6 0.049532109025409090118186687981523082677219128741729 0 27.474593022118317968158957115156725710168223409107 +B 3 2 7 3 0.016191506054842444131002615692062608106383895884815 0 7.3890560989306502272304274605750078131803155705521 +B 3 2 7 4 0.0054104800681263060003964054879261821071604586229443 0 7.3890560989306502272304274605750078131803155705521 +B 3 2 7 7 0.00084058518745651829687485465876581423487558007795681 0 162.41489074801322800998333693634447570091059180195 +B 3 2 8 6 0.0054104800681263060003964054879261821071604586229443 0 87.731203791681321190944546078901879401131946924772 +B 3 5 3 5 0.57439895436264836895197840231235810811534467594186 0 2.7182818284590452353602874713526624977572470937000 +B 3 5 4 6 0.26959749244672319507914834340243511481230139795174 0 7.3890560989306502272304274605750078131803155705521 +B 3 5 5 6 0.21937328465641402365987135294327665025834638539285 0 7.3890560989306502272304274605750078131803155705521 +B 3 5 6 6 0.16914907686610485224059436248411818570439137283397 0 7.3890560989306502272304274605750078131803155705521 +B 3 5 7 7 0.0076954275084611998521571809025063660433028978954380 0 67.645666868493653450016016424320161504144039086217 +B 3 5 8 6 0.018476453495177337982763391106642792042526335157309 0 7.3890560989306502272304274605750078131803155705521 +B 3 6 3 6 0.31982170023703236649842533386159357936625641051063 0 2.7182818284590452353602874713526624977572470937000 +B 3 6 7 7 0.0076954275084611998521571809025063660433028978954380 0 7.3890560989306502272304274605750078131803155705521 +B 4 0 4 0 0.27852017766202284423499554224192686227078672248815 0 2.7182818284590452353602874713526624977572470937000 +B 4 0 5 1 0.054102003906078877821708238810683450549504007286716 0 7.3890560989306502272304274605750078131803155705521 +B 4 0 5 2 0.054102003906078877821708238810683450549504007286716 0 7.3890560989306502272304274605750078131803155705521 +B 4 0 5 5 0.014550269829465881407439507146246917851730215712919 0 7.3890560989306502272304274605750078131803155705521 +B 4 0 6 1 0.045605925359697633542862804021127208486423009297338 0 7.3890560989306502272304274605750078131803155705521 +B 4 0 6 2 0.045605925359697633542862804021127208486423009297338 0 27.474593022118317968158957115156725710168223409107 +B 4 0 6 5 0.012265322389130987555678731731666733915587776440425 0 47.560129945305985709087486769738443607156131247662 +B 4 0 7 3 0.0031255326277914121486356300733459981710180193504505 54.598150033144239078110261202860878402790737038617 87.731203791681321190944546078901879401131946924772 +B 4 0 7 4 0.0031255326277914121486356300733459981710180193504505 0 142.32935382482556026905480728176275780392268396339 +B 4 0 8 1 0.011621611174172656427481064862902240234099017339828 0 7.3890560989306502272304274605750078131803155705521 +B 4 0 9 4 0.00084058518745651829687485465876581423487558007795681 148.41315910257660342111558004055227962348766759389 400.89302780377785206335291140236970720906144779496 +B 4 1 4 1 0.32428304284468219107634893328133945309549907277882 0 2.7182818284590452353602874713526624977572470937000 +B 4 1 5 2 0.28026996616041937008415660219715704666848261893682 0 7.3890560989306502272304274605750078131803155705521 +B 4 1 5 5 0.054102003906078877821708238810683450549504007286716 0 7.3890560989306502272304274605750078131803155705521 +B 4 1 5 6 0.054102003906078877821708238810683450549504007286716 0 7.3890560989306502272304274605750078131803155705521 +B 4 1 6 2 0.23625688947615654909196427111297464024146616509483 0 7.3890560989306502272304274605750078131803155705521 +B 4 1 6 5 0.045605925359697633542862804021127208486423009297338 0 27.474593022118317968158957115156725710168223409107 +B 4 1 6 6 0.045605925359697633542862804021127208486423009297338 0 47.560129945305985709087486769738443607156131247662 +B 4 1 7 3 0.020117689720553900706326499652458482297180015329205 0 47.560129945305985709087486769738443607156131247662 +B 4 1 7 4 0.011621611174172656427481064862902240234099017339828 0 47.560129945305985709087486769738443607156131247662 +B 4 1 8 6 0.011621611174172656427481064862902240234099017339828 0 400.89302780377785206335291140236970720906144779496 +B 4 1 9 4 0.0031255326277914121486356300733459981710180193504505 0 176.84196693478213160623653883004191830972551316345 +B 4 6 4 6 0.37004590802734153791770232432075204392021142306951 0 2.7182818284590452353602874713526624977572470937000 +B 4 6 7 7 0.028613768266935144985171934442014724360261013318583 0 7.3890560989306502272304274605750078131803155705521 +B 5 0 5 0 0.38127651940768643182745377510846918653532856223429 0 2.7182818284590452353602874713526624977572470937000 +B 5 0 6 1 0.077196739831867753680885816355357498659562345705573 0 7.3890560989306502272304274605750078131803155705521 +B 5 0 6 2 0.077196739831867753680885816355357498659562345705573 0 7.3890560989306502272304274605750078131803155705521 +B 5 0 6 5 0.020761400935512231834524166521222975978668774429803 0 7.3890560989306502272304274605750078131803155705521 +B 5 0 7 3 0.0031255326277914121486356300733459981710180193504505 0 47.560129945305985709087486769738443607156131247662 +B 5 0 7 4 0.0031255326277914121486356300733459981710180193504505 0 47.560129945305985709087486769738443607156131247662 +B 5 0 8 1 0.011621611174172656427481064862902240234099017339828 0 7.3890560989306502272304274605750078131803155705521 +B 5 0 9 4 0.00084058518745651829687485465876581423487558007795681 0 196.92750385796979934716506848462363620671342100200 +B 5 1 5 1 0.44392298941008830410090008431757976734316069222693 0 2.7182818284590452353602874713526624977572470937000 +B 5 1 6 2 0.39990991272582548310870775323339736091614423838493 0 7.3890560989306502272304274605750078131803155705521 +B 5 1 6 5 0.077196739831867753680885816355357498659562345705573 0 7.3890560989306502272304274605750078131803155705521 +B 5 1 6 6 0.077196739831867753680885816355357498659562345705573 0 7.3890560989306502272304274605750078131803155705521 +B 5 1 7 3 0.020117689720553900706326499652458482297180015329205 0 27.474593022118317968158957115156725710168223409107 +B 5 1 7 4 0.011621611174172656427481064862902240234099017339828 0 27.474593022118317968158957115156725710168223409107 +B 5 1 8 6 0.011621611174172656427481064862902240234099017339828 0 196.92750385796979934716506848462363620671342100200 +B 5 1 9 4 0.0031255326277914121486356300733459981710180193504505 0 102.15827997845022478719774797259932200994686828628 +B 5 2 5 2 0.90979745146415942728945251382646949735286686932027 0 2.7182818284590452353602874713526624977572470937000 +B 5 2 6 5 0.13363207872822327552724746618949202134045591698134 0 7.3890560989306502272304274605750078131803155705521 +B 5 2 6 6 0.13363207872822327552724746618949202134045591698134 0 7.3890560989306502272304274605750078131803155705521 +B 5 2 7 3 0.060204582739105265123194946776245014533400349726817 0 7.3890560989306502272304274605750078131803155705521 +B 5 2 7 4 0.020117689720553900706326499652458482297180015329205 0 7.3890560989306502272304274605750078131803155705521 +B 5 2 7 7 0.0031255326277914121486356300733459981710180193504505 0 47.560129945305985709087486769738443607156131247662 +B 5 2 8 6 0.020117689720553900706326499652458482297180015329205 0 67.645666868493653450016016424320161504144039086217 +B 5 2 9 4 0.0054104800681263060003964054879261821071604586229443 0 27.474593022118317968158957115156725710168223409107 +B 5 5 5 5 0.90979745146415942728945251382646949735286686932027 0 2.7182818284590452353602874713526624977572470937000 +B 5 5 6 6 0.45634525162218100495506940306753188359703780966070 0 7.3890560989306502272304274605750078131803155705521 +B 5 5 7 7 0.028613768266935144985171934442014724360261013318583 0 27.474593022118317968158957115156725710168223409107 +B 5 5 8 6 0.068700661285486509402040381565801256596481347716195 0 7.3890560989306502272304274605750078131803155705521 +B 5 6 5 6 0.50656945941249017637434639352669034815099282221959 0 2.7182818284590452353602874713526624977572470937000 +B 5 6 7 7 0.028613768266935144985171934442014724360261013318583 0 7.3890560989306502272304274605750078131803155705521 +B 6 0 6 0 0.38127651940768643182745377510846918653532856223429 0 2.7182818284590452353602874713526624977572470937000 +B 6 0 7 3 0.0054104800681263060003964054879261821071604586229443 0 7.3890560989306502272304274605750078131803155705521 +B 6 0 7 4 0.0054104800681263060003964054879261821071604586229443 0 7.3890560989306502272304274605750078131803155705521 +B 6 0 8 1 0.020117689720553900706326499652458482297180015329205 0 7.3890560989306502272304274605750078131803155705521 +B 6 0 9 4 0.00084058518745651829687485465876581423487558007795681 0 47.560129945305985709087486769738443607156131247662 +B 6 1 6 1 0.44392298941008830410090008431757976734316069222693 0 2.7182818284590452353602874713526624977572470937000 +B 6 1 7 3 0.034824899372981495412256593816990782487199572035467 0 7.3890560989306502272304274605750078131803155705521 +B 6 1 7 4 0.020117689720553900706326499652458482297180015329205 0 7.3890560989306502272304274605750078131803155705521 +B 6 1 8 6 0.020117689720553900706326499652458482297180015329205 0 47.560129945305985709087486769738443607156131247662 +B 6 1 9 4 0.0031255326277914121486356300733459981710180193504505 0 27.474593022118317968158957115156725710168223409107 +B 6 2 6 2 0.90979745146415942728945251382646949735286686932027 0 2.7182818284590452353602874713526624977572470937000 +B 6 2 7 3 0.10421765942336808611538727786042742096041680356882 0 7.3890560989306502272304274605750078131803155705521 +B 6 2 7 4 0.034824899372981495412256593816990782487199572035467 0 7.3890560989306502272304274605750078131803155705521 +B 6 2 7 7 0.0054104800681263060003964054879261821071604586229443 0 7.3890560989306502272304274605750078131803155705521 +B 6 2 8 6 0.034824899372981495412256593816990782487199572035467 0 47.560129945305985709087486769738443607156131247662 +B 6 2 9 4 0.0054104800681263060003964054879261821071604586229443 0 27.474593022118317968158957115156725710168223409107 +B 6 5 6 5 0.90979745146415942728945251382646949735286686932027 0 2.7182818284590452353602874713526624977572470937000 +B 6 5 7 7 0.049532109025409090118186687981523082677219128741729 0 7.3890560989306502272304274605750078131803155705521 +B 6 5 8 6 0.11892486907579568082131737202495972115043636027508 0 7.3890560989306502272304274605750078131803155705521 +B 6 6 6 6 0.50656945941249017637434639352669034815099282221959 0 2.7182818284590452353602874713526624977572470937000 +B 6 6 7 7 0.049532109025409090118186687981523082677219128741729 0 7.3890560989306502272304274605750078131803155705521 +B 7 3 7 3 0.14823073610763090710757960894460982738743325741082 0 2.7182818284590452353602874713526624977572470937000 +B 7 3 8 6 0.049532109025409090118186687981523082677219128741729 0 7.3890560989306502272304274605750078131803155705521 +B 7 3 9 4 0.0054104800681263060003964054879261821071604586229443 0 7.3890560989306502272304274605750078131803155705521 +B 7 4 7 4 0.20509268167290483383094302282867985546373115523362 0 2.7182818284590452353602874713526624977572470937000 +B 7 4 8 6 0.070450449783883035251201441521031440994177244164873 0 7.3890560989306502272304274605750078131803155705521 +B 7 7 7 7 0.091368790542356980384216195060539799311135359588014 0 2.7182818284590452353602874713526624977572470937000 +B 8 0 8 0 0.41907846498590290239256144681767553483540645735939 0 2.7182818284590452353602874713526624977572470937000 +B 8 0 9 4 0.012265322389130987555678731731666733915587776440425 0 7.3890560989306502272304274605750078131803155705521 +B 8 1 8 1 0.48793606609435112509309241540176217377017714606894 0 2.7182818284590452353602874713526624977572470937000 +B 8 1 9 4 0.045605925359697633542862804021127208486423009297338 0 7.3890560989306502272304274605750078131803155705521 +B 8 6 8 6 0.55679366720279934779362338398584881270494783477848 0 2.7182818284590452353602874713526624977572470937000 +B 9 4 9 4 0.32688604468091552667951352133644064828400362232158 0 2.7182818284590452353602874713526624977572470937000 +P 0 7 0 0E+0 +P 0 6 1 0E+0 +P 0 5 0 0E+0 +P 0 4 0 0E+0 +P 0 3 0 0E+0 +P 0 2 0 0E+0 +P 0 1 1 0E+0 +P 0 0 1 0E+0 +P 1 7 0 0E+0 +P 1 6 1 0E+0 +P 1 5 0 0E+0 +P 1 4 0 0E+0 +P 1 3 0 0E+0 +P 1 2 0 0E+0 +P 1 1 1 0E+0 +P 1 0 1 0E+0 +P 2 7 0 0E+0 +P 2 6 1 0E+0 +P 2 5 0 0E+0 +P 2 4 0 0E+0 +P 2 3 0 0E+0 +P 2 2 0 0E+0 +P 2 1 1 0E+0 +P 2 0 1 0E+0 +P 3 7 0 0E+0 +P 3 6 1 0E+0 +P 3 5 1 0E+0 +P 3 4 0 0E+0 +P 3 3 0 0E+0 +P 3 2 1 0E+0 +P 3 1 1 0E+0 +P 3 0 1 0E+0 +P 4 7 0 0E+0 +P 4 6 1 0E+0 +P 4 5 0 0E+0 +P 4 4 0 0E+0 +P 4 3 0 0E+0 +P 4 2 0 0E+0 +P 4 1 1 0E+0 +P 4 0 1 2.9540220251089651886087158590910771970452262871571E-1 +P 5 7 0 0E+0 +P 5 6 1 0E+0 +P 5 5 1 0E+0 +P 5 4 0 0E+0 +P 5 3 0 0E+0 +P 5 2 1 0E+0 +P 5 1 1 2.9540220251089651886087158590910771970452262871571E-1 +P 5 0 1 0E+0 +P 6 7 0 0E+0 +P 6 6 1 0E+0 +P 6 5 1 0E+0 +P 6 4 0 0E+0 +P 6 3 0 0E+0 +P 6 2 1 2.9540220251089651886087158590910771970452262871571E-1 +P 6 1 1 0E+0 +P 6 0 1 0E+0 +P 7 7 1 0E+0 +P 7 6 0 0E+0 +P 7 5 0 0E+0 +P 7 4 1 0E+0 +P 7 3 1 2.9540220251089651886087158590910771970452262871571E-1 +P 7 2 0 0E+0 +P 7 1 0 0E+0 +P 7 0 0 0E+0 +P 8 7 0 0E+0 +P 8 6 1 0E+0 +P 8 5 0 0E+0 +P 8 4 0 0E+0 +P 8 3 0 0E+0 +P 8 2 0 0E+0 +P 8 1 1 0E+0 +P 8 0 1 0E+0 +P 9 7 0 0E+0 +P 9 6 0 0E+0 +P 9 5 0 0E+0 +P 9 4 1 1.2475390316525342899588838346331771175813934339619E-1 +P 9 3 0 0E+0 +P 9 2 0 0E+0 +P 9 1 0 0E+0 +P 9 0 0 0E+0 +END +CASE random04 11 12 5 +Z 4.2051121195017988214604692705439839562640994090340E-1 +S 0 7 5 +B 0 1 0 1 0.48060774049313025816104798385354726236898721348287 0 2.7182818284590452353602874713526624977572470937000 +B 0 1 1 4 0.092017172313518417729031029431501717897376517568992 0 7.3890560989306502272304274605750078131803155705521 +B 0 1 1 5 0.030725539140698490152564039530968011265493947691560 0 7.3890560989306502272304274605750078131803155705521 +B 0 2 0 2 0.48060774049313025816104798385354726236898721348287 0 2.7182818284590452353602874713526624977572470937000 +B 0 2 1 4 0.13506258279493981269200065021219566658827158987854 0 7.3890560989306502272304274605750078131803155705521 +B 0 2 1 5 0.048971761832097022766061408650807769206481445259439 0 7.3890560989306502272304274605750078131803155705521 +B 0 2 4 6 0.0064231540300114684215800634069327115033256607582047 0 47.560129945305985709087486769738443607156131247662 +B 0 3 0 3 0.48060774049313025816104798385354726236898721348287 0 2.7182818284590452353602874713526624977572470937000 +B 0 3 1 4 0.20290718106638407000444252265374380602907423692976 0 7.3890560989306502272304274605750078131803155705521 +B 0 3 1 5 0.092017172313518417729031029431501717897376517568992 0 7.3890560989306502272304274605750078131803155705521 +B 0 3 1 7 0.073770949622119885115533660311661959956389020001113 0 7.3890560989306502272304274605750078131803155705521 +B 0 3 4 6 0.012069005669068176965533234970090402048423646718757 0 47.560129945305985709087486769738443607156131247662 +B 0 4 0 4 0.30706105014530774912917828826972240059256810995884 0 2.7182818284590452353602874713526624977572470937000 +B 0 4 1 5 0.15986177058496267504147290187304985733817916462021 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 1 7 0.14161554789356414242797553275321009939719166705233 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 1 8 0.13249243654786487612122684819329022042669791826839 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 4 6 0.020967527766268286670255814782678072261514711432371 0 27.474593022118317968158957115156725710168223409107 +B 0 5 0 5 0.30706105014530774912917828826972240059256810995884 0 2.7182818284590452353602874713526624977572470937000 +B 0 5 1 7 0.25250555664642979470338702597545218752888938641310 0 7.3890560989306502272304274605750078131803155705521 +B 0 5 1 8 0.24338244530073052839663834141553230855839563762916 0 7.3890560989306502272304274605750078131803155705521 +B 0 5 2 9 0.035119784368805717004796390597273011144945461061960 0 47.560129945305985709087486769738443607156131247662 +B 0 5 3 9 0.018294741516362994684917007881629317399913101168150 0 47.560129945305985709087486769738443607156131247662 +B 0 5 4 6 0.038764571960668506079700974407853412687696840859601 0 7.3890560989306502272304274605750078131803155705521 +B 0 5 4 9 0.0076197446204681221131719450637965669418781143619490 0 47.560129945305985709087486769738443607156131247662 +B 0 7 0 7 0.53213769973877894858490242827417628628147189252259 0 2.7182818284590452353602874713526624977572470937000 +B 0 7 1 8 0.50306758079373335476888334460289954118953880543994 0 7.3890560989306502272304274605750078131803155705521 +B 0 7 2 9 0.096640385022910298575248131239402880151336392475680 0 27.474593022118317968158957115156725710168223409107 +B 0 7 2 10 0.039081213470056506477222631682993651053206781362791 0 27.474593022118317968158957115156725710168223409107 +B 0 7 3 9 0.050342304083345502451509102209278951792448241413070 0 27.474593022118317968158957115156725710168223409107 +B 0 7 3 10 0.020358345343815705504546836432245902635497119592909 0 102.15827997845022478719774797259932200994686828628 +B 0 7 4 9 0.020967527766268286670255814782678072261514711432371 0 27.474593022118317968158957115156725710168223409107 +B 0 7 4 10 0.0084792338976982158907575899994988357327662859075236 0 176.84196693478213160623653883004191830972551316345 +B 0 7 4 11 0.0028333822586415073468044184363411451876682999469722 148.41315910257660342111558004055227962348766759389 380.80749088059018432242438174778798931207353995641 +B 0 8 0 8 0.59314606528986585788891005385577420521343910476475 0 2.7182818284590452353602874713526624977572470937000 +B 0 8 2 9 0.13765411879231335295554929166748945948893034675150 0 7.3890560989306502272304274605750078131803155705521 +B 0 8 2 10 0.080094947239459560857523792111080230390800735638607 0 7.3890560989306502272304274605750078131803155705521 +B 0 8 3 9 0.071707345794667174295903831761045374720805001576355 0 7.3890560989306502272304274605750078131803155705521 +B 0 8 3 10 0.041723387055137377348941565984012325563853879756189 0 27.474593022118317968158957115156725710168223409107 +B 0 8 4 9 0.029866049863468396374978394595265742474605776145985 0 7.3890560989306502272304274605750078131803155705521 +B 0 8 4 10 0.017377755994898325595480169812086505945857350621138 0 47.560129945305985709087486769738443607156131247662 +B 0 8 4 11 0.0040299728490981610383963000932050006262207535507164 0 142.32935382482556026905480728176275780392268396339 +B 1 4 1 4 0.46674189723930631205746042832167461857450953729802 0 2.7182818284590452353602874713526624977572470937000 +B 1 4 4 6 0.056568039930640320170892875120817867143937695862467 0 7.3890560989306502272304274605750078131803155705521 +B 1 5 1 5 0.46674189723930631205746042832167461857450953729802 0 2.7182818284590452353602874713526624977572470937000 +B 1 5 2 9 0.068769870073691161644555156028560398635010180849580 0 7.3890560989306502272304274605750078131803155705521 +B 1 5 3 9 0.051944827221248439324675773312916704889977820955769 0 7.3890560989306502272304274605750078131803155705521 +B 1 5 4 6 0.10458247052344540560312020282638806202194541297582 0 7.3890560989306502272304274605750078131803155705521 +B 1 5 4 9 0.020557216986036506096722379341640220985431908027446 0 7.3890560989306502272304274605750078131803155705521 +B 1 5 5 9 0.0076197446204681221131719450637965669418781143619490 0 27.474593022118317968158957115156725710168223409107 +B 1 7 1 7 0.80886507569456835329336004612668505966089000497876 0 2.7182818284590452353602874713526624977572470937000 +B 1 7 2 9 0.18923654690203989082272618929965073686911269460091 0 7.3890560989306502272304274605750078131803155705521 +B 1 7 2 10 0.076526949722538108422574222184489147888626104902552 0 7.3890560989306502272304274605750078131803155705521 +B 1 7 3 9 0.14293846596247509469898716026952680851022454353830 0 7.3890560989306502272304274605750078131803155705521 +B 1 7 3 10 0.057804081596297307449898426933741399470916443132675 0 27.474593022118317968158957115156725710168223409107 +B 1 7 4 9 0.056568039930640320170892875120817867143937695862467 0 7.3890560989306502272304274605750078131803155705521 +B 1 7 4 10 0.022876022726812794631998185239619095329373122393352 0 47.560129945305985709087486769738443607156131247662 +B 1 7 4 11 0.0076441477761365289996810113037553218180176214775342 0 142.32935382482556026905480728176275780392268396339 +B 1 7 5 9 0.020967527766268286670255814782678072261514711432371 0 7.3890560989306502272304274605750078131803155705521 +B 1 7 5 10 0.0084792338976982158907575899994988357327662859075236 0 67.645666868493653450016016424320161504144039086217 +B 1 8 1 8 0.90159959956631436762742822715891628392837909468430 0 2.7182818284590452353602874713526624977572470937000 +B 1 8 2 9 0.26954766478760571027484021148037762902518103710180 0 7.3890560989306502272304274605750078131803155705521 +B 1 8 2 10 0.15683806760810392787468824436521604004469444740344 0 7.3890560989306502272304274605750078131803155705521 +B 1 8 3 9 0.20360089178995953161519475157393354425705569192665 0 7.3890560989306502272304274605750078131803155705521 +B 1 8 3 10 0.11846650742378174436610601823814813521774759152102 0 27.474593022118317968158957115156725710168223409107 +B 1 8 4 9 0.080575255227042862887006538973602964582941554419145 0 7.3890560989306502272304274605750078131803155705521 +B 1 8 4 10 0.046883238023215337348111849092404192768376980950031 0 47.560129945305985709087486769738443607156131247662 +B 1 8 4 11 0.010872415078611523273941353313226546609871193115012 0 142.32935382482556026905480728176275780392268396339 +B 1 8 5 9 0.029866049863468396374978394595265742474605776145985 0 7.3890560989306502272304274605750078131803155705521 +B 1 8 5 10 0.017377755994898325595480169812086505945857350621138 0 67.645666868493653450016016424320161504144039086217 +B 2 9 2 9 0.31464163117694788935653505689558724093937334128523 0 2.7182818284590452353602874713526624977572470937000 +B 2 9 3 10 0.14713069382138105500055031246265098265070355266469 0 7.3890560989306502272304274605750078131803155705521 +B 2 9 4 10 0.070618372210391858812522771315918707229027529725415 0 7.3890560989306502272304274605750078131803155705521 +B 2 9 4 11 0.019871030222227007836422452379500943763593846305997 0 27.474593022118317968158957115156725710168223409107 +B 2 9 5 10 0.039081213470056506477222631682993651053206781362791 0 7.3890560989306502272304274605750078131803155705521 +B 2 9 6 10 0.0075440547297211541419224920500685948773860330001643 0 7.3890560989306502272304274605750078131803155705521 +B 2 9 6 11 0.0021227923391636021999954252342431130896907311099376 0 67.645666868493653450016016424320161504144039086217 +B 2 10 2 10 0.31464163117694788935653505689558724093937334128523 0 2.7182818284590452353602874713526624977572470937000 +B 2 10 4 11 0.054984227265010343668935128664895779774113557449177 0 7.3890560989306502272304274605750078131803155705521 +B 2 10 6 11 0.0058738824865977803597693346585815670478887041401850 0 7.3890560989306502272304274605750078131803155705521 +B 3 9 3 9 0.31464163117694788935653505689558724093937334128523 0 2.7182818284590452353602874713526624977572470937000 +B 3 9 4 10 0.096640385022910298575248131239402880151336392475680 0 7.3890560989306502272304274605750078131803155705521 +B 3 9 4 11 0.027193263613563104389639587694216987613004165881765 0 7.3890560989306502272304274605750078131803155705521 +B 3 9 5 10 0.050111505325690331622372191101875417560230552587508 0 7.3890560989306502272304274605750078131803155705521 +B 3 9 6 10 0.018574346585354979287072051468950361384409804224883 0 7.3890560989306502272304274605750078131803155705521 +B 3 9 6 11 0.0052265634395548147299881817500688560647732071544603 0 47.560129945305985709087486769738443607156131247662 +B 3 10 3 10 0.31464163117694788935653505689558724093937334128523 0 2.7182818284590452353602874713526624977572470937000 +B 3 10 4 11 0.075245247472524773329044193855434613198406059210649 0 7.3890560989306502272304274605750078131803155705521 +B 3 10 6 11 0.014462186849981484348716998283818112925528553926244 0 7.3890560989306502272304274605750078131803155705521 +B 4 0 4 0 0.40781086898459409115064573960881507135908474151129 0 2.7182818284590452353602874713526624977572470937000 +B 4 0 7 4 0.012548796830890911283205317064784899914183526730228 0 7.3890560989306502272304274605750078131803155705521 +B 4 6 4 6 0.56380989204633384920865668216236769341726155160635 0 2.7182818284590452353602874713526624977572470937000 +B 4 6 5 9 0.085942816247717535952146162547418746674871225843164 0 7.3890560989306502272304274605750078131803155705521 +B 4 6 5 10 0.034755134172930284245787431672366162232103956078736 0 7.3890560989306502272304274605750078131803155705521 +B 4 6 6 9 0.050342304083345502451509102209278951792448241413070 0 7.3890560989306502272304274605750078131803155705521 +B 4 6 6 10 0.020358345343815705504546836432245902635497119592909 0 27.474593022118317968158957115156725710168223409107 +B 4 6 7 7 0.16129472029485928331274240706934423690540007907899 0 7.3890560989306502272304274605750078131803155705521 +B 4 6 7 8 0.15842174795212324161188656166092202816253529186003 0 7.3890560989306502272304274605750078131803155705521 +B 4 6 8 9 0.044116568236050684732125329297740036440958786963678 0 47.560129945305985709087486769738443607156131247662 +B 4 6 8 10 0.017840667960818616377095487624872709941621116792465 0 87.731203791681321190944546078901879401131946924772 +B 4 9 4 9 0.23020462008708659738850287321160631384346535045502 0 2.7182818284590452353602874713526624977572470937000 +B 4 9 5 10 0.076133518138208771385097551025359590482539415337778 0 7.3890560989306502272304274605750078131803155705521 +B 4 9 6 10 0.044596359397873419049797411392434534306718666975150 0 7.3890560989306502272304274605750078131803155705521 +B 4 9 6 11 0.012548796830890911283205317064784899914183526730228 0 27.474593022118317968158957115156725710168223409107 +B 4 9 8 10 0.039081213470056506477222631682993651053206781362791 0 7.3890560989306502272304274605750078131803155705521 +B 4 10 4 10 0.23020462008708659738850287321160631384346535045502 0 2.7182818284590452353602874713526624977572470937000 +B 4 10 6 11 0.034723207057495914008826063474356946349821055687712 0 7.3890560989306502272304274605750078131803155705521 +B 4 11 4 11 0.41667877841696977974174844682137266122122129435408 0 2.7182818284590452353602874713526624977572470937000 +B 5 9 5 9 0.23020462008708659738850287321160631384346535045502 0 2.7182818284590452353602874713526624977572470937000 +B 5 9 6 10 0.091125239095093386002673351529961996897824506863322 0 7.3890560989306502272304274605750078131803155705521 +B 5 9 6 11 0.025641378063367498124643209436304116125462927859503 0 7.3890560989306502272304274605750078131803155705521 +B 5 9 8 10 0.085610093167276473430098571820521113644312621250965 0 7.3890560989306502272304274605750078131803155705521 +B 5 10 5 10 0.23020462008708659738850287321160631384346535045502 0 2.7182818284590452353602874713526624977572470937000 +B 5 10 6 11 0.070951095290832921334570362042816340259586134317620 0 7.3890560989306502272304274605750078131803155705521 +B 6 0 6 0 0.54105323335349216459044120152888834961654236503303 0 2.7182818284590452353602874713526624977572470937000 +B 6 0 7 4 0.051389346168678737035754238204494234959725859582515 0 7.3890560989306502272304274605750078131803155705521 +B 6 0 9 1 0.10690127626422169413839600872436693636588662734173 0 7.3890560989306502272304274605750078131803155705521 +B 6 0 9 2 0.074118720622092874338485854954660514999234411144191 0 7.3890560989306502272304274605750078131803155705521 +B 6 0 9 3 0.050111505325690331622372191101875417560230552587508 0 7.3890560989306502272304274605750078131803155705521 +B 6 0 9 4 0.014100682381086517548201695322697771401724764752490 0 7.3890560989306502272304274605750078131803155705521 +B 6 0 10 1 0.027858776307118462678819000482617127997444165227837 0 7.3890560989306502272304274605750078131803155705521 +B 6 0 10 2 0.019315549169657305547500917271078473833341884932740 0 27.474593022118317968158957115156725710168223409107 +B 6 0 10 3 0.013059200657538066714497271759509478130897918612524 0 47.560129945305985709087486769738443607156131247662 +B 6 0 10 4 0.0036746778893592084649918034921559845772319691321991 0 67.645666868493653450016016424320161504144039086217 +B 6 6 6 6 0.74802117424652612703284434096262053576050112076509 0 2.7182818284590452353602874713526624977572470937000 +B 6 6 7 7 0.66052788391700048718449603764475223991046127960132 0 7.3890560989306502272304274605750078131803155705521 +B 6 6 7 8 0.64876259898622035000602841878381368642932043242399 0 7.3890560989306502272304274605750078131803155705521 +B 6 6 8 9 0.19993411567723265344582815799163487034557786123343 0 47.560129945305985709087486769738443607156131247662 +B 6 6 8 10 0.080853029019664330654009422195116636709728930186610 0 47.560129945305985709087486769738443607156131247662 +B 6 6 9 7 0.18124172789420561082201280618070110302683941737768 0 7.3890560989306502272304274605750078131803155705521 +B 6 6 9 8 0.17801346059173061654775246417122987823498584574020 0 27.474593022118317968158957115156725710168223409107 +B 6 6 10 7 0.047232109207382695239769604605664094787307039792913 0 7.3890560989306502272304274605750078131803155705521 +B 6 6 10 8 0.046390813576664994121582219549849255397743370607686 0 47.560129945305985709087486769738443607156131247662 +B 6 9 6 9 0.30541842678483324819202785308198063502824800402392 0 2.7182818284590452353602874713526624977572470937000 +B 6 9 8 10 0.17711413573515028423570191347185579548127373571579 0 7.3890560989306502272304274605750078131803155705521 +B 6 10 6 10 0.30541842678483324819202785308198063502824800402392 0 2.7182818284590452353602874713526624977572470937000 +B 6 11 6 11 0.55281851828427230176890882038982690309768321221036 0 2.7182818284590452353602874713526624977572470937000 +B 7 4 7 4 0.50953962976717009265523637371305673916319080694188 0 2.7182818284590452353602874713526624977572470937000 +B 7 4 9 5 0.10909185671749993401401567706248071085431530137447 0 7.3890560989306502272304274605750078131803155705521 +B 7 4 9 7 0.096640385022910298575248131239402880151336392475680 0 7.3890560989306502272304274605750078131803155705521 +B 7 4 9 8 0.090414649175615480855864358327863964799846938026293 0 7.3890560989306502272304274605750078131803155705521 +B 7 4 10 5 0.027193263613563104389639587694216987613004165881765 0 7.3890560989306502272304274605750078131803155705521 +B 7 4 10 7 0.024089492513171891859646831178391244637921689837242 0 27.474593022118317968158957115156725710168223409107 +B 7 4 10 8 0.022537606962976285594650452920478373150380451814981 0 47.560129945305985709087486769738443607156131247662 +B 7 5 7 5 0.50953962976717009265523637371305673916319080694188 0 2.7182818284590452353602874713526624977572470937000 +B 7 5 8 9 0.091744958882681733712568858642015035667039913831001 0 7.3890560989306502272304274605750078131803155705521 +B 7 5 9 7 0.17231324227955231048024044769612768804115807351900 0 7.3890560989306502272304274605750078131803155705521 +B 7 5 9 8 0.16608750643225749276085667478458877268966861906960 0 7.3890560989306502272304274605750078131803155705521 +B 7 5 10 7 0.042952421586788968989305480606713633211070172520023 0 7.3890560989306502272304274605750078131803155705521 +B 7 5 10 8 0.041400536036593362724309102348800761723528934497762 0 27.474593022118317968158957115156725710168223409107 +B 7 7 7 7 0.88303367158335228634779205036765146953610436766750 0 2.7182818284590452353602874713526624977572470937000 +B 7 7 8 9 0.25245793246409226728895095993329771405595546674544 0 7.3890560989306502272304274605750078131803155705521 +B 7 7 8 10 0.10209357452890222075413656625323757782131459475694 0 7.3890560989306502272304274605750078131803155705521 +B 7 7 9 8 0.34330019142382498672076344086245187354721802660439 0 7.3890560989306502272304274605750078131803155705521 +B 7 7 10 8 0.085574238855879743993314024570464955542644478368014 0 7.3890560989306502272304274605750078131803155705521 +B 7 8 7 8 0.98427145469159855651395397968753343475288850523259 0 2.7182818284590452353602874713526624977572470937000 +B 7 8 8 9 0.35959991485169928967320569412748616631523250202172 0 7.3890560989306502272304274605750078131803155705521 +B 7 8 8 10 0.20923555691650924313839130044742603008059163003322 0 7.3890560989306502272304274605750078131803155705521 +B 8 9 8 9 0.37400737336756029772339224728944339430702044759246 0 2.7182818284590452353602874713526624977572470937000 +B 8 10 8 10 0.37400737336756029772339224728944339430702044759246 0 2.7182818284590452353602874713526624977572470937000 +B 9 1 9 1 0.38266574147096875641337345367076969742404110291581 0 2.7182818284590452353602874713526624977572470937000 +B 9 1 10 2 0.11650103304476322880432311941519480581310254032768 0 7.3890560989306502272304274605750078131803155705521 +B 9 1 10 3 0.095135991333441556959928389863428382884745780164388 0 7.3890560989306502272304274605750078131803155705521 +B 9 1 10 4 0.028977262372023830607114372657512528864091481249791 0 7.3890560989306502272304274605750078131803155705521 +B 9 1 10 5 0.0096758244881548695823494716563626911713187395112680 0 7.3890560989306502272304274605750078131803155705521 +B 9 2 9 2 0.38266574147096875641337345367076969742404110291581 0 2.7182818284590452353602874713526624977572470937000 +B 9 2 10 3 0.11650103304476322880432311941519480581310254032768 0 7.3890560989306502272304274605750078131803155705521 +B 9 2 10 4 0.042532755570420708230167582841817949071134648550391 0 7.3890560989306502272304274605750078131803155705521 +B 9 2 10 5 0.015421769173626952984061162473207108657048313949189 0 7.3890560989306502272304274605750078131803155705521 +B 9 3 9 3 0.38266574147096875641337345367076969742404110291581 0 2.7182818284590452353602874713526624977572470937000 +B 9 3 10 4 0.063897797281742380074562312393584371999491408713673 0 7.3890560989306502272304274605750078131803155705521 +B 9 3 10 5 0.028977262372023830607114372657512528864091481249791 0 7.3890560989306502272304274605750078131803155705521 +B 9 3 10 7 0.023231317686551747205402681840668111378361906811869 0 7.3890560989306502272304274605750078131803155705521 +B 9 4 9 4 0.24448575112449330685926968051411068816077287314354 0 2.7182818284590452353602874713526624977572470937000 +B 9 4 10 5 0.050342304083345502451509102209278951792448241413070 0 7.3890560989306502272304274605750078131803155705521 +B 9 4 10 7 0.044596359397873419049797411392434534306718666975150 0 7.3890560989306502272304274605750078131803155705521 +B 9 4 10 8 0.041723387055137377348941565984012325563853879756189 0 7.3890560989306502272304274605750078131803155705521 +B 9 5 9 5 0.24448575112449330685926968051411068816077287314354 0 2.7182818284590452353602874713526624977572470937000 +B 9 5 10 7 0.079516894307591968517245351128506377442118594439033 0 7.3890560989306502272304274605750078131803155705521 +B 9 5 10 8 0.076643921964855926816389505720084168699253807220073 0 7.3890560989306502272304274605750078131803155705521 +B 9 7 9 7 0.42369452315990373749457921801495719877392184374251 0 2.7182818284590452353602874713526624977572470937000 +B 9 7 10 8 0.15842174795212324161188656166092202816253529186003 0 7.3890560989306502272304274605750078131803155705521 +B 9 8 9 8 0.47227012748867397173102822242119295273061558821529 0 2.7182818284590452353602874713526624977572470937000 +B 10 1 10 1 0.26670831851506389288133846547555590877032518360643 0 2.7182818284590452353602874713526624977572470937000 +B 10 2 10 2 0.26670831851506389288133846547555590877032518360643 0 2.7182818284590452353602874713526624977572470937000 +B 10 3 10 3 0.26670831851506389288133846547555590877032518360643 0 2.7182818284590452353602874713526624977572470937000 +B 10 4 10 4 0.17040036908622230512653943124492271135619398509205 0 2.7182818284590452353602874713526624977572470937000 +B 10 5 10 5 0.17040036908622230512653943124492271135619398509205 0 2.7182818284590452353602874713526624977572470937000 +B 10 7 10 7 0.29530433898168219889498560864438124514493245666375 0 2.7182818284590452353602874713526624977572470937000 +B 10 8 10 8 0.32916030346279383976556155417528517566469441939229 0 2.7182818284590452353602874713526624977572470937000 +P 0 11 0 0E+0 +P 0 10 0 0E+0 +P 0 9 0 0E+0 +P 0 8 1 0E+0 +P 0 7 1 4.2051121195017988214604692705439839562640994090340E-1 +P 0 6 0 0E+0 +P 0 5 1 0E+0 +P 0 4 1 0E+0 +P 0 3 1 0E+0 +P 0 2 1 0E+0 +P 0 1 1 0E+0 +P 0 0 0 0E+0 +P 1 11 0 0E+0 +P 1 10 0 0E+0 +P 1 9 0 0E+0 +P 1 8 1 4.2051121195017988214604692705439839562640994090340E-1 +P 1 7 1 0E+0 +P 1 6 0 0E+0 +P 1 5 1 0E+0 +P 1 4 1 0E+0 +P 1 3 0 0E+0 +P 1 2 0 0E+0 +P 1 1 0 0E+0 +P 1 0 0 0E+0 +P 2 11 0 0E+0 +P 2 10 1 0E+0 +P 2 9 1 4.2051121195017988214604692705439839562640994090340E-1 +P 2 8 0 0E+0 +P 2 7 0 0E+0 +P 2 6 0 0E+0 +P 2 5 0 0E+0 +P 2 4 0 0E+0 +P 2 3 0 0E+0 +P 2 2 0 0E+0 +P 2 1 0 0E+0 +P 2 0 0 0E+0 +P 3 11 0 0E+0 +P 3 10 1 4.2051121195017988214604692705439839562640994090340E-1 +P 3 9 1 0E+0 +P 3 8 0 0E+0 +P 3 7 0 0E+0 +P 3 6 0 0E+0 +P 3 5 0 0E+0 +P 3 4 0 0E+0 +P 3 3 0 0E+0 +P 3 2 0 0E+0 +P 3 1 0 0E+0 +P 3 0 0 0E+0 +P 4 11 1 4.2051121195017988214604692705439839562640994090340E-1 +P 4 10 1 0E+0 +P 4 9 1 0E+0 +P 4 8 0 0E+0 +P 4 7 0 0E+0 +P 4 6 1 0E+0 +P 4 5 0 0E+0 +P 4 4 0 0E+0 +P 4 3 0 0E+0 +P 4 2 0 0E+0 +P 4 1 0 0E+0 +P 4 0 1 0E+0 +P 5 11 0 0E+0 +P 5 10 1 0E+0 +P 5 9 1 0E+0 +P 5 8 0 0E+0 +P 5 7 0 0E+0 +P 5 6 0 0E+0 +P 5 5 0 0E+0 +P 5 4 0 0E+0 +P 5 3 0 0E+0 +P 5 2 0 0E+0 +P 5 1 0 0E+0 +P 5 0 0 0E+0 +P 6 11 1 0E+0 +P 6 10 1 0E+0 +P 6 9 1 0E+0 +P 6 8 0 0E+0 +P 6 7 0 0E+0 +P 6 6 1 0E+0 +P 6 5 0 0E+0 +P 6 4 0 0E+0 +P 6 3 0 0E+0 +P 6 2 0 0E+0 +P 6 1 0 0E+0 +P 6 0 1 0E+0 +P 7 11 0 0E+0 +P 7 10 0 0E+0 +P 7 9 0 0E+0 +P 7 8 1 0E+0 +P 7 7 1 0E+0 +P 7 6 0 0E+0 +P 7 5 1 0E+0 +P 7 4 1 0E+0 +P 7 3 0 0E+0 +P 7 2 0 0E+0 +P 7 1 0 0E+0 +P 7 0 0 0E+0 +P 8 11 0 0E+0 +P 8 10 1 0E+0 +P 8 9 1 0E+0 +P 8 8 0 0E+0 +P 8 7 0 0E+0 +P 8 6 0 0E+0 +P 8 5 0 0E+0 +P 8 4 0 0E+0 +P 8 3 0 0E+0 +P 8 2 0 0E+0 +P 8 1 0 0E+0 +P 8 0 0 0E+0 +P 9 11 0 0E+0 +P 9 10 0 0E+0 +P 9 9 0 0E+0 +P 9 8 1 0E+0 +P 9 7 1 0E+0 +P 9 6 0 0E+0 +P 9 5 1 0E+0 +P 9 4 1 0E+0 +P 9 3 1 0E+0 +P 9 2 1 0E+0 +P 9 1 1 0E+0 +P 9 0 0 0E+0 +P 10 11 0 0E+0 +P 10 10 0 0E+0 +P 10 9 0 0E+0 +P 10 8 1 0E+0 +P 10 7 1 0E+0 +P 10 6 0 0E+0 +P 10 5 1 0E+0 +P 10 4 1 0E+0 +P 10 3 1 0E+0 +P 10 2 1 0E+0 +P 10 1 1 0E+0 +P 10 0 0 0E+0 +END +CASE random05 12 10 6 +Z 1.3554498903412247165130335441381304398879900228361E+1 +S 4 4 5 +S 5 5 5 +S 5 2 5 +S 6 3 5 +S 7 4 5 +B 0 4 0 4 0.38521465009432587930693741340357162008529055176591 0 2.7182818284590452353602874713526624977572470937000 +B 0 4 1 7 0.020887907892673245671178530399523389494097771969937 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 2 7 0.0097710522738542818372395632581124933737795929144156 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 3 7 0.0050688394171512309551667391368252496922671519365775 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 4 7 0.0013632208775449096771870834230216176521610922514038 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 5 5 0.0033564095117383688853734202379888409349738548367327 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 5 6 0.0033564095117383688853734202379888409349738548367327 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 5 8 0.00036662656044818007309391501553800601075471095873930 0 87.731203791681321190944546078901879401131946924772 +B 0 4 5 9 0.00036662656044818007309391501553800601075471095873930 0 87.731203791681321190944546078901879401131946924772 +B 0 7 0 7 0.15645666939871197139807804494347790419547472188796 0 2.7182818284590452353602874713526624977572470937000 +B 0 7 5 8 0.0013632208775449096771870834230216176521610922514038 0 7.3890560989306502272304274605750078131803155705521 +B 0 7 5 9 0.00036662656044818007309391501553800601075471095873930 0 7.3890560989306502272304274605750078131803155705521 +B 1 4 1 4 0.45306338041001536949408190386615944798240780667743 0 2.7182818284590452353602874713526624977572470937000 +B 1 4 2 7 0.022881096526866704879364867214490612776910534555266 0 7.3890560989306502272304274605750078131803155705521 +B 1 4 3 7 0.012760835225144470649519068480563328297998736792409 0 7.3890560989306502272304274605750078131803155705521 +B 1 4 4 7 0.0090552166855381493715394127667596962578926771072353 0 7.3890560989306502272304274605750078131803155705521 +B 1 4 5 5 0.039851077450240387388383941543763532284995520717500 0 7.3890560989306502272304274605750078131803155705521 +B 1 4 5 6 0.039851077450240387388383941543763532284995520717500 0 7.3890560989306502272304274605750078131803155705521 +B 1 4 5 8 0.0043530038288350984894665886454724525763802361293972 0 67.645666868493653450016016424320161504144039086217 +B 1 4 5 9 0.0043530038288350984894665886454724525763802361293972 0 67.645666868493653450016016424320161504144039086217 +B 1 4 6 5 0.030727410465614882762631311217319859447490104247309 0 7.3890560989306502272304274605750078131803155705521 +B 1 4 6 6 0.030727410465614882762631311217319859447490104247309 0 27.474593022118317968158957115156725710168223409107 +B 1 4 6 8 0.0033564095117383688853734202379888409349738548367327 0 107.81674071486898893187307573348359729811985476333 +B 1 4 6 9 0.0033564095117383688853734202379888409349738548367327 0 291.69672773748937390713238899664795040347997371773 +B 1 7 1 7 0.18401373755675022983109908271607868954798855310536 0 2.7182818284590452353602874713526624977572470937000 +B 1 7 5 8 0.016185695035970194789105706278236145812585330992098 0 7.3890560989306502272304274605750078131803155705521 +B 1 7 5 9 0.0043530038288350984894665886454724525763802361293972 0 7.3890560989306502272304274605750078131803155705521 +B 1 7 6 8 0.012480076496363873511126050564432513772479271306925 0 7.3890560989306502272304274605750078131803155705521 +B 1 7 6 9 0.0033564095117383688853734202379888409349738548367327 0 27.474593022118317968158957115156725710168223409107 +B 2 4 2 4 0.41044879140587531000824036301351580831767738430577 0 2.7182818284590452353602874713526624977572470937000 +B 2 4 3 7 0.032004763511492209505117497540934285614415951025458 0 7.3890560989306502272304274605750078131803155705521 +B 2 4 4 7 0.028299144971885888227137841827130653574309891340284 0 7.3890560989306502272304274605750078131803155705521 +B 2 4 5 5 0.19122556927021310360473990704734575635277782505588 0 7.3890560989306502272304274605750078131803155705521 +B 2 4 5 6 0.19122556927021310360473990704734575635277782505588 0 7.3890560989306502272304274605750078131803155705521 +B 2 4 5 8 0.020887907892673245671178530399523389494097771969937 0 47.560129945305985709087486769738443607156131247662 +B 2 4 5 9 0.020887907892673245671178530399523389494097771969937 0 47.560129945305985709087486769738443607156131247662 +B 2 4 6 5 0.098576140781304372949775801679907687344607359158817 0 7.3890560989306502272304274605750078131803155705521 +B 2 4 6 6 0.098576140781304372949775801679907687344607359158817 0 27.474593022118317968158957115156725710168223409107 +B 2 4 6 8 0.010767646590951011441332731665596105015185974207080 0 87.731203791681321190944546078901879401131946924772 +B 2 4 6 9 0.010767646590951011441332731665596105015185974207080 0 217.01304078115746708809359813920535410370132884056 +B 2 4 7 7 0.010767646590951011441332731665596105015185974207080 0 142.32935382482556026905480728176275780392268396339 +B 2 7 2 7 0.16670562982577446027531331005862632976724407955580 0 2.7182818284590452353602874713526624977572470937000 +B 2 7 5 8 0.077667128351853198315698989282130845113657789665252 0 7.3890560989306502272304274605750078131803155705521 +B 2 7 5 9 0.020887907892673245671178530399523389494097771969937 0 7.3890560989306502272304274605750078131803155705521 +B 2 7 6 8 0.040037144654402131944147088337033299124993102524327 0 7.3890560989306502272304274605750078131803155705521 +B 2 7 6 9 0.010767646590951011441332731665596105015185974207080 0 27.474593022118317968158957115156725710168223409107 +B 3 4 3 4 0.46917385473693929556963222314965996337728922274709 0 2.7182818284590452353602874713526624977572470937000 +B 3 4 4 7 0.047543073258233627082736270887501610890727105573334 0 7.3890560989306502272304274605750078131803155705521 +B 3 4 5 5 0.34260006109018581982109587255092798042056012939426 0 7.3890560989306502272304274605750078131803155705521 +B 3 4 5 6 0.34260006109018581982109587255092798042056012939426 0 7.3890560989306502272304274605750078131803155705521 +B 3 4 5 8 0.037422811956511392852890472153574326411815307810476 0 27.474593022118317968158957115156725710168223409107 +B 3 4 5 9 0.037422811956511392852890472153574326411815307810476 0 27.474593022118317968158957115156725710168223409107 +B 3 4 6 5 0.24995063260127708916613176718348991141238966349720 0 7.3890560989306502272304274605750078131803155705521 +B 3 4 6 6 0.24995063260127708916613176718348991141238966349720 0 27.474593022118317968158957115156725710168223409107 +B 3 4 6 8 0.027302550654789158623044673419647041932903510047620 0 67.645666868493653450016016424320161504144039086217 +B 3 4 6 9 0.027302550654789158623044673419647041932903510047620 0 142.32935382482556026905480728176275780392268396339 +B 3 4 7 7 0.027302550654789158623044673419647041932903510047620 0 142.32935382482556026905480728176275780392268396339 +B 3 4 8 5 0.098576140781304372949775801679907687344607359158817 0 7.3890560989306502272304274605750078131803155705521 +B 3 4 8 6 0.098576140781304372949775801679907687344607359158817 0 47.560129945305985709087486769738443607156131247662 +B 3 4 8 8 0.010767646590951011441332731665596105015185974207080 0 549.30618690635445548446849144292198683254911538885 +B 3 4 8 9 0.010767646590951011441332731665596105015185974207080 0 807.86986088530674727876659556352893623768787922043 +B 3 7 3 7 0.19055707944420639743035469211742348307965185108803 0 2.7182818284590452353602874713526624977572470937000 +B 3 7 5 8 0.13914856166773620184229227228602554441473024833840 0 7.3890560989306502272304274605750078131803155705521 +B 3 7 5 9 0.037422811956511392852890472153574326411815307810476 0 7.3890560989306502272304274605750078131803155705521 +B 3 7 6 8 0.10151857797028513547074037134092799842606556119748 0 7.3890560989306502272304274605750078131803155705521 +B 3 7 6 9 0.027302550654789158623044673419647041932903510047620 0 27.474593022118317968158957115156725710168223409107 +B 3 7 8 8 0.040037144654402131944147088337033299124993102524327 0 7.3890560989306502272304274605750078131803155705521 +B 3 7 8 9 0.010767646590951011441332731665596105015185974207080 0 47.560129945305985709087486769738443607156131247662 +B 4 4 4 4 0.73713158694237960244180523951534260332162796085950 0 2.7182818284590452353602874713526624977572470937000 +B 4 4 5 5 0.61968146028025163131902151924305429320240428397687 0 7.3890560989306502272304274605750078131803155705521 +B 4 4 5 6 0.61968146028025163131902151924305429320240428397687 0 7.3890560989306502272304274605750078131803155705521 +B 4 4 5 8 0.067688904337059242959797997232495132163028817420385 0 7.3890560989306502272304274605750078131803155705521 +B 4 4 5 9 0.067688904337059242959797997232495132163028817420385 0 7.3890560989306502272304274605750078131803155705521 +B 4 4 6 5 0.52703203179134290066405741387561622419423381807982 0 7.3890560989306502272304274605750078131803155705521 +B 4 4 6 6 0.52703203179134290066405741387561622419423381807982 0 27.474593022118317968158957115156725710168223409107 +B 4 4 6 8 0.057568643035337008729952198498567847684117019657527 0 47.560129945305985709087486769738443607156131247662 +B 4 4 6 9 0.057568643035337008729952198498567847684117019657527 0 67.645666868493653450016016424320161504144039086217 +B 4 4 7 7 0.057568643035337008729952198498567847684117019657527 0 142.32935382482556026905480728176275780392268396339 +B 4 4 8 5 0.10769980776592987757552843200635136018211277562901 0 7.3890560989306502272304274605750078131803155705521 +B 4 4 8 6 0.10769980776592987757552843200635136018211277562901 0 47.560129945305985709087486769738443607156131247662 +B 4 4 8 8 0.011764240908047741045425900073079716656592355499745 148.41315910257660342111558004055227962348766759389 380.80749088059018432242438174778798931207353995641 +B 4 4 8 9 0.011764240908047741045425900073079716656592355499745 0 678.58802389583060138161754350322546153511849730464 +B 4 4 9 5 0.039851077450240387388383941543763532284995520717500 0 7.3890560989306502272304274605750078131803155705521 +B 4 4 9 6 0.039851077450240387388383941543763532284995520717500 0 67.645666868493653450016016424320161504144039086217 +B 4 4 9 8 0.0043530038288350984894665886454724525763802361293972 0 678.58802389583060138161754350322546153511849730464 +B 4 4 9 9 0.0043530038288350984894665886454724525763802361293972 403.42879349273512260838718054338827960589989735717 1863.0974804102862952567528610897581621630557180601 +B 4 7 4 7 0.29938932222165391338962193535360915913430284933701 0 2.7182818284590452353602874713526624977572470937000 +B 4 7 5 8 0.25168642298479003907953917123601485250948730627255 0 7.3890560989306502272304274605750078131803155705521 +B 4 7 5 9 0.067688904337059242959797997232495132163028817420385 0 7.3890560989306502272304274605750078131803155705521 +B 4 7 6 8 0.21405643928733897270798727029091730652082261913163 0 7.3890560989306502272304274605750078131803155705521 +B 4 7 6 9 0.057568643035337008729952198498567847684117019657527 0 27.474593022118317968158957115156725710168223409107 +B 4 7 8 8 0.043742763194008453222126744050836931165099162209500 0 7.3890560989306502272304274605750078131803155705521 +B 4 7 8 9 0.011764240908047741045425900073079716656592355499745 0 47.560129945305985709087486769738443607156131247662 +B 4 7 9 8 0.016185695035970194789105706278236145812585330992098 0 7.3890560989306502272304274605750078131803155705521 +B 4 7 9 9 0.0043530038288350984894665886454724525763802361293972 0 67.645666868493653450016016424320161504144039086217 +B 5 0 5 0 0.62880512726487713594477414956949796603990970044708 0 2.7182818284590452353602874713526624977572470937000 +B 5 0 6 1 0.37695887830145684963788848510339041779633395668342 0 7.3890560989306502272304274605750078131803155705521 +B 5 0 6 2 0.21776205782694529398596692600472093856092867881680 0 7.3890560989306502272304274605750078131803155705521 +B 5 0 6 3 0.21776205782694529398596692600472093856092867881680 0 7.3890560989306502272304274605750078131803155705521 +B 5 0 6 5 0.058565237352433738334045366906051459325523400950192 0 7.3890560989306502272304274605750078131803155705521 +B 5 0 7 4 0.058565237352433738334045366906051459325523400950192 0 67.645666868493653450016016424320161504144039086217 +B 5 0 8 1 0.082135928242085078350693731048717798112411706996935 0 7.3890560989306502272304274605750078131803155705521 +B 5 0 8 2 0.047448381733614774500106399764640563205205221894673 0 27.474593022118317968158957115156725710168223409107 +B 5 0 8 3 0.047448381733614774500106399764640563205205221894673 0 47.560129945305985709087486769738443607156131247662 +B 5 0 8 5 0.012760835225144470649519068480563328297998736792409 0 251.52565389111403842527532968748451460950415804062 +B 5 0 9 3 0.019891313575576516067085361992039777852691390677272 0 142.32935382482556026905480728176275780392268396339 +B 5 0 9 5 0.0053495981459318280935597570529560642177866174220617 0 475.57671476010975888239170225981230350884009267213 +B 5 0 10 4 0.0053495981459318280935597570529560642177866174220617 0 678.58802389583060138161754350322546153511849730464 +B 5 1 5 1 0.62880512726487713594477414956949796603990970044708 0 2.7182818284590452353602874713526624977572470937000 +B 5 1 6 2 0.37695887830145684963788848510339041779633395668342 0 7.3890560989306502272304274605750078131803155705521 +B 5 1 6 3 0.37695887830145684963788848510339041779633395668342 0 7.3890560989306502272304274605750078131803155705521 +B 5 1 6 5 0.21776205782694529398596692600472093856092867881680 0 7.3890560989306502272304274605750078131803155705521 +B 5 1 6 6 0.21776205782694529398596692600472093856092867881680 0 7.3890560989306502272304274605750078131803155705521 +B 5 1 7 4 0.21776205782694529398596692600472093856092867881680 0 47.560129945305985709087486769738443607156131247662 +B 5 1 8 2 0.082135928242085078350693731048717798112411706996935 0 7.3890560989306502272304274605750078131803155705521 +B 5 1 8 3 0.082135928242085078350693731048717798112411706996935 0 27.474593022118317968158957115156725710168223409107 +B 5 1 8 5 0.047448381733614774500106399764640563205205221894673 0 176.84196693478213160623653883004191830972551316345 +B 5 1 8 6 0.047448381733614774500106399764640563205205221894673 0 196.92750385796979934716506848462363620671342100200 +B 5 1 9 3 0.034433029005221204040610966931123491487596163932483 0 47.560129945305985709087486769738443607156131247662 +B 5 1 9 5 0.019891313575576516067085361992039777852691390677272 0 271.61119081430170616620385934206623250649206587918 +B 5 1 9 6 0.019891313575576516067085361992039777852691390677272 0 772.40303296526296572462286234091686275581542785991 +B 5 1 10 4 0.019891313575576516067085361992039777852691390677272 0 271.61119081430170616620385934206623250649206587918 +B 5 2 5 2 0.62880512726487713594477414956949796603990970044708 0 2.7182818284590452353602874713526624977572470937000 +B 5 2 6 3 0.53615569877596840528981004420205989703173923455000 0 7.3890560989306502272304274605750078131803155705521 +B 5 2 6 5 0.37695887830145684963788848510339041779633395668342 0 7.3890560989306502272304274605750078131803155705521 +B 5 2 6 6 0.37695887830145684963788848510339041779633395668342 0 7.3890560989306502272304274605750078131803155705521 +B 5 2 7 4 0.37695887830145684963788848510339041779633395668342 0 27.474593022118317968158957115156725710168223409107 +B 5 2 7 7 0.058565237352433738334045366906051459325523400950192 0 67.645666868493653450016016424320161504144039086217 +B 5 2 8 3 0.11682347475055538220128106233279503301961819209920 0 7.3890560989306502272304274605750078131803155705521 +B 5 2 8 5 0.082135928242085078350693731048717798112411706996935 0 102.15827997845022478719774797259932200994686828628 +B 5 2 8 6 0.082135928242085078350693731048717798112411706996935 0 122.24381690163789252812627762718103990693477612483 +B 5 2 9 3 0.048974744434865892014136571870207205122500937187693 0 7.3890560989306502272304274605750078131803155705521 +B 5 2 9 5 0.034433029005221204040610966931123491487596163932483 0 122.24381690163789252812627762718103990693477612483 +B 5 2 9 6 0.034433029005221204040610966931123491487596163932483 148.41315910257660342111558004055227962348766759389 271.61119081430170616620385934206623250649206587918 +B 5 2 10 4 0.034433029005221204040610966931123491487596163932483 0 67.645666868493653450016016424320161504144039086217 +B 5 2 10 7 0.0053495981459318280935597570529560642177866174220617 403.42879349273512260838718054338827960589989735717 1863.0974804102862952567528610897581621630557180601 +B 5 3 5 3 0.81551167013511752373840181087933770678506786769174 0 2.7182818284590452353602874713526624977572470937000 +B 5 3 6 5 0.53615569877596840528981004420205989703173923455000 0 7.3890560989306502272304274605750078131803155705521 +B 5 3 6 6 0.53615569877596840528981004420205989703173923455000 0 7.3890560989306502272304274605750078131803155705521 +B 5 3 6 8 0.058565237352433738334045366906051459325523400950192 0 7.3890560989306502272304274605750078131803155705521 +B 5 3 7 4 0.53615569877596840528981004420205989703173923455000 0 7.3890560989306502272304274605750078131803155705521 +B 5 3 7 7 0.058565237352433738334045366906051459325523400950192 0 47.560129945305985709087486769738443607156131247662 +B 5 3 8 5 0.11682347475055538220128106233279503301961819209920 0 27.474593022118317968158957115156725710168223409107 +B 5 3 8 6 0.11682347475055538220128106233279503301961819209920 0 47.560129945305985709087486769738443607156131247662 +B 5 3 8 8 0.012760835225144470649519068480563328297998736792409 0 196.92750385796979934716506848462363620671342100200 +B 5 3 9 5 0.048974744434865892014136571870207205122500937187693 0 27.474593022118317968158957115156725710168223409107 +B 5 3 9 6 0.048974744434865892014136571870207205122500937187693 0 122.24381690163789252812627762718103990693477612483 +B 5 3 9 8 0.0053495981459318280935597570529560642177866174220617 0 400.89302780377785206335291140236970720906144779496 +B 5 3 10 4 0.048974744434865892014136571870207205122500937187693 0 7.3890560989306502272304274605750078131803155705521 +B 5 3 10 7 0.0053495981459318280935597570529560642177866174220617 0 678.58802389583060138161754350322546153511849730464 +B 5 5 5 5 0.81551167013511752373840181087933770678506786769174 0 2.7182818284590452353602874713526624977572470937000 +B 5 5 6 6 0.69535251925047996094173160330072937626714451241661 0 7.3890560989306502272304274605750078131803155705521 +B 5 5 6 8 0.21776205782694529398596692600472093856092867881680 0 7.3890560989306502272304274605750078131803155705521 +B 5 5 6 9 0.058565237352433738334045366906051459325523400950192 0 7.3890560989306502272304274605750078131803155705521 +B 5 5 7 7 0.21776205782694529398596692600472093856092867881680 0 27.474593022118317968158957115156725710168223409107 +B 5 5 8 6 0.15151102125902568605186839361687226792682467720146 0 7.3890560989306502272304274605750078131803155705521 +B 5 5 8 8 0.047448381733614774500106399764640563205205221894673 0 102.15827997845022478719774797259932200994686828628 +B 5 5 8 9 0.012760835225144470649519068480563328297998736792409 0 122.24381690163789252812627762718103990693477612483 +B 5 5 9 6 0.063516459864510579987662176809290918757405710442904 0 7.3890560989306502272304274605750078131803155705521 +B 5 5 9 8 0.019891313575576516067085361992039777852691390677272 0 122.24381690163789252812627762718103990693477612483 +B 5 5 9 9 0.0053495981459318280935597570529560642177866174220617 148.41315910257660342111558004055227962348766759389 271.61119081430170616620385934206623250649206587918 +B 5 5 10 7 0.019891313575576516067085361992039777852691390677272 0 67.645666868493653450016016424320161504144039086217 +B 5 6 5 6 0.81551167013511752373840181087933770678506786769174 0 2.7182818284590452353602874713526624977572470937000 +B 5 6 6 8 0.21776205782694529398596692600472093856092867881680 0 7.3890560989306502272304274605750078131803155705521 +B 5 6 6 9 0.058565237352433738334045366906051459325523400950192 0 7.3890560989306502272304274605750078131803155705521 +B 5 6 7 7 0.21776205782694529398596692600472093856092867881680 0 7.3890560989306502272304274605750078131803155705521 +B 5 6 8 8 0.047448381733614774500106399764640563205205221894673 0 27.474593022118317968158957115156725710168223409107 +B 5 6 8 9 0.012760835225144470649519068480563328297998736792409 0 47.560129945305985709087486769738443607156131247662 +B 5 6 9 8 0.019891313575576516067085361992039777852691390677272 0 27.474593022118317968158957115156725710168223409107 +B 5 6 9 9 0.0053495981459318280935597570529560642177866174220617 0 122.24381690163789252812627762718103990693477612483 +B 5 6 10 7 0.019891313575576516067085361992039777852691390677272 0 7.3890560989306502272304274605750078131803155705521 +B 5 8 5 8 0.81551167013511752373840181087933770678506786769174 0 2.7182818284590452353602874713526624977572470937000 +B 5 8 6 9 0.53615569877596840528981004420205989703173923455000 0 7.3890560989306502272304274605750078131803155705521 +B 5 8 8 9 0.11682347475055538220128106233279503301961819209920 0 7.3890560989306502272304274605750078131803155705521 +B 5 8 9 9 0.048974744434865892014136571870207205122500937187693 0 7.3890560989306502272304274605750078131803155705521 +B 5 9 5 9 0.62880512726487713594477414956949796603990970044708 0 2.7182818284590452353602874713526624977572470937000 +B 6 0 6 0 0.67840652361131561688041337937919844826201612241818 0 2.7182818284590452353602874713526624977572470937000 +B 6 0 7 4 0.074103547099175155911664140252618784601834555498070 0 7.3890560989306502272304274605750078131803155705521 +B 6 0 8 1 0.18214924804789702527030221228233260735803335042502 0 7.3890560989306502272304274605750078131803155705521 +B 6 0 8 2 0.10522419650989145674872002705473163046617162088265 0 7.3890560989306502272304274605750078131803155705521 +B 6 0 8 3 0.10522419650989145674872002705473163046617162088265 0 7.3890560989306502272304274605750078131803155705521 +B 6 0 8 5 0.028299144971885888227137841827130653574309891340284 0 27.474593022118317968158957115156725710168223409107 +B 6 0 9 3 0.077667128351853198315698989282130845113657789665252 0 47.560129945305985709087486769738443607156131247662 +B 6 0 9 5 0.020887907892673245671178530399523389494097771969937 0 87.731203791681321190944546078901879401131946924772 +B 6 0 10 4 0.0063461924630285576976529254604396758591929987147261 0 196.92750385796979934716506848462363620671342100200 +B 6 0 11 1 0.0087744579567575522331463948506288817323732116217511 0 7.3890560989306502272304274605750078131803155705521 +B 6 0 11 2 0.0050688394171512309551667391368252496922671519365775 0 27.474593022118317968158957115156725710168223409107 +B 6 0 11 3 0.0050688394171512309551667391368252496922671519365775 0 47.560129945305985709087486769738443607156131247662 +B 6 0 11 5 0.0013632208775449096771870834230216176521610922514038 0 752.31749604207529798369433268633514485882752002136 +B 6 1 6 1 0.67840652361131561688041337937919844826201612241818 0 2.7182818284590452353602874713526624977572470937000 +B 6 1 7 4 0.27553787260322197623458055329481200582189507780477 0 7.3890560989306502272304274605750078131803155705521 +B 6 1 8 2 0.18214924804789702527030221228233260735803335042502 0 7.3890560989306502272304274605750078131803155705521 +B 6 1 8 3 0.18214924804789702527030221228233260735803335042502 0 7.3890560989306502272304274605750078131803155705521 +B 6 1 8 5 0.10522419650989145674872002705473163046617162088265 0 27.474593022118317968158957115156725710168223409107 +B 6 1 8 6 0.10522419650989145674872002705473163046617162088265 0 27.474593022118317968158957115156725710168223409107 +B 6 1 9 3 0.13444634881103315096021944816473830073321780736057 0 27.474593022118317968158957115156725710168223409107 +B 6 1 9 5 0.077667128351853198315698989282130845113657789665252 0 67.645666868493653450016016424320161504144039086217 +B 6 1 9 6 0.077667128351853198315698989282130845113657789665252 0 142.32935382482556026905480728176275780392268396339 +B 6 1 10 4 0.023596932115182837345065017705843409892797450362446 0 122.24381690163789252812627762718103990693477612483 +B 6 1 11 2 0.0087744579567575522331463948506288817323732116217511 0 7.3890560989306502272304274605750078131803155705521 +B 6 1 11 3 0.0087744579567575522331463948506288817323732116217511 0 27.474593022118317968158957115156725710168223409107 +B 6 1 11 5 0.0050688394171512309551667391368252496922671519365775 0 474.62249995002254866542970058547939053277047051169 +B 6 1 11 6 0.0050688394171512309551667391368252496922671519365775 0 733.18617392897484045972780470608633993790923434326 +B 6 2 6 2 0.67840652361131561688041337937919844826201612241818 0 2.7182818284590452353602874713526624977572470937000 +B 6 2 7 4 0.47697219810726879655749696633700522704195560011149 0 7.3890560989306502272304274605750078131803155705521 +B 6 2 7 7 0.074103547099175155911664140252618784601834555498070 0 7.3890560989306502272304274605750078131803155705521 +B 6 2 8 3 0.25907429958590259379188439750993358424989507996739 0 7.3890560989306502272304274605750078131803155705521 +B 6 2 8 5 0.18214924804789702527030221228233260735803335042502 0 27.474593022118317968158957115156725710168223409107 +B 6 2 8 6 0.18214924804789702527030221228233260735803335042502 0 27.474593022118317968158957115156725710168223409107 +B 6 2 9 3 0.19122556927021310360473990704734575635277782505588 0 7.3890560989306502272304274605750078131803155705521 +B 6 2 9 5 0.13444634881103315096021944816473830073321780736057 0 47.560129945305985709087486769738443607156131247662 +B 6 2 9 6 0.13444634881103315096021944816473830073321780736057 0 122.24381690163789252812627762718103990693477612483 +B 6 2 10 4 0.040847671767337116992477109951247143926401902010164 0 47.560129945305985709087486769738443607156131247662 +B 6 2 10 7 0.0063461924630285576976529254604396758591929987147261 0 678.58802389583060138161754350322546153511849730464 +B 6 2 11 3 0.012480076496363873511126050564432513772479271306925 0 7.3890560989306502272304274605750078131803155705521 +B 6 2 11 5 0.0087744579567575522331463948506288817323732116217511 0 196.92750385796979934716506848462363620671342100200 +B 6 2 11 6 0.0087744579567575522331463948506288817323732116217511 0 400.89302780377785206335291140236970720906144779496 +B 6 3 6 3 0.87984084911536243720332979242139166948207664472488 0 2.7182818284590452353602874713526624977572470937000 +B 6 3 7 4 0.67840652361131561688041337937919844826201612241818 0 7.3890560989306502272304274605750078131803155705521 +B 6 3 7 7 0.074103547099175155911664140252618784601834555498070 0 7.3890560989306502272304274605750078131803155705521 +B 6 3 8 5 0.25907429958590259379188439750993358424989507996739 0 27.474593022118317968158957115156725710168223409107 +B 6 3 8 6 0.25907429958590259379188439750993358424989507996739 0 27.474593022118317968158957115156725710168223409107 +B 6 3 8 8 0.028299144971885888227137841827130653574309891340284 0 47.560129945305985709087486769738443607156131247662 +B 6 3 9 5 0.19122556927021310360473990704734575635277782505588 0 27.474593022118317968158957115156725710168223409107 +B 6 3 9 6 0.19122556927021310360473990704734575635277782505588 0 102.15827997845022478719774797259932200994686828628 +B 6 3 9 8 0.020887907892673245671178530399523389494097771969937 0 196.92750385796979934716506848462363620671342100200 +B 6 3 10 4 0.058098411419491396639889202196650877960006353657887 0 7.3890560989306502272304274605750078131803155705521 +B 6 3 10 7 0.0063461924630285576976529254604396758591929987147261 148.41315910257660342111558004055227962348766759389 380.80749088059018432242438174778798931207353995641 +B 6 3 11 5 0.012480076496363873511126050564432513772479271306925 0 47.560129945305985709087486769738443607156131247662 +B 6 3 11 6 0.012480076496363873511126050564432513772479271306925 0 196.92750385796979934716506848462363620671342100200 +B 6 3 11 8 0.0013632208775449096771870834230216176521610922514038 403.42879349273512260838718054338827960589989735717 1604.5338064313340034624547569691512127579169542285 +B 6 5 6 5 0.87984084911536243720332979242139166948207664472488 0 2.7182818284590452353602874713526624977572470937000 +B 6 5 7 7 0.27553787260322197623458055329481200582189507780477 0 7.3890560989306502272304274605750078131803155705521 +B 6 5 8 6 0.33599935112390816231346658273753456114175680950975 0 7.3890560989306502272304274605750078131803155705521 +B 6 5 8 8 0.10522419650989145674872002705473163046617162088265 0 27.474593022118317968158957115156725710168223409107 +B 6 5 8 9 0.028299144971885888227137841827130653574309891340284 0 27.474593022118317968158957115156725710168223409107 +B 6 5 9 6 0.24800478972939305624926036592995321197233784275120 0 7.3890560989306502272304274605750078131803155705521 +B 6 5 9 8 0.077667128351853198315698989282130845113657789665252 0 47.560129945305985709087486769738443607156131247662 +B 6 5 9 9 0.020887907892673245671178530399523389494097771969937 0 122.24381690163789252812627762718103990693477612483 +B 6 5 10 7 0.023596932115182837345065017705843409892797450362446 0 47.560129945305985709087486769738443607156131247662 +B 6 5 11 6 0.016185695035970194789105706278236145812585330992098 0 7.3890560989306502272304274605750078131803155705521 +B 6 5 11 8 0.0050688394171512309551667391368252496922671519365775 0 196.92750385796979934716506848462363620671342100200 +B 6 5 11 9 0.0013632208775449096771870834230216176521610922514038 0 400.89302780377785206335291140236970720906144779496 +B 6 6 6 6 0.87984084911536243720332979242139166948207664472488 0 2.7182818284590452353602874713526624977572470937000 +B 6 6 7 7 0.27553787260322197623458055329481200582189507780477 0 7.3890560989306502272304274605750078131803155705521 +B 6 6 8 8 0.10522419650989145674872002705473163046617162088265 0 27.474593022118317968158957115156725710168223409107 +B 6 6 8 9 0.028299144971885888227137841827130653574309891340284 0 27.474593022118317968158957115156725710168223409107 +B 6 6 9 8 0.077667128351853198315698989282130845113657789665252 0 27.474593022118317968158957115156725710168223409107 +B 6 6 9 9 0.020887907892673245671178530399523389494097771969937 0 102.15827997845022478719774797259932200994686828628 +B 6 6 10 7 0.023596932115182837345065017705843409892797450362446 0 7.3890560989306502272304274605750078131803155705521 +B 6 6 11 8 0.0050688394171512309551667391368252496922671519365775 0 47.560129945305985709087486769738443607156131247662 +B 6 6 11 9 0.0013632208775449096771870834230216176521610922514038 0 196.92750385796979934716506848462363620671342100200 +B 6 8 6 8 0.87984084911536243720332979242139166948207664472488 0 2.7182818284590452353602874713526624977572470937000 +B 6 8 8 9 0.25907429958590259379188439750993358424989507996739 0 7.3890560989306502272304274605750078131803155705521 +B 6 8 9 9 0.19122556927021310360473990704734575635277782505588 0 7.3890560989306502272304274605750078131803155705521 +B 6 8 11 9 0.012480076496363873511126050564432513772479271306925 0 7.3890560989306502272304274605750078131803155705521 +B 6 9 6 9 0.67840652361131561688041337937919844826201612241818 0 2.7182818284590452353602874713526624977572470937000 +B 7 4 7 4 0.77105595210022434753537748474663651727018658831526 0 2.7182818284590452353602874713526624977572470937000 +B 7 4 8 5 0.32692302990159208397902888797252141214701233487889 0 7.3890560989306502272304274605750078131803155705521 +B 7 4 8 6 0.32692302990159208397902888797252141214701233487889 0 7.3890560989306502272304274605750078131803155705521 +B 7 4 8 8 0.035710382051098530783097153254737917654522010710632 0 7.3890560989306502272304274605750078131803155705521 +B 7 4 8 9 0.035710382051098530783097153254737917654522010710632 0 7.3890560989306502272304274605750078131803155705521 +B 7 4 9 5 0.23427360141268335332406478260508334313884186898183 0 7.3890560989306502272304274605750078131803155705521 +B 7 4 9 6 0.23427360141268335332406478260508334313884186898183 0 27.474593022118317968158957115156725710168223409107 +B 7 4 9 8 0.025590120749376296553251354520810633175610212947775 0 47.560129945305985709087486769738443607156131247662 +B 7 4 9 9 0.025590120749376296553251354520810633175610212947775 0 67.645666868493653450016016424320161504144039086217 +B 7 4 10 7 0.011048405319731608579725749581726919540705439692564 0 142.32935382482556026905480728176275780392268396339 +B 7 4 11 5 0.030727410465614882762631311217319859447490104247309 0 7.3890560989306502272304274605750078131803155705521 +B 7 4 11 6 0.030727410465614882762631311217319859447490104247309 0 47.560129945305985709087486769738443607156131247662 +B 7 4 11 8 0.0033564095117383688853734202379888409349738548367327 148.41315910257660342111558004055227962348766759389 380.80749088059018432242438174778798931207353995641 +B 7 4 11 9 0.0033564095117383688853734202379888409349738548367327 0 678.58802389583060138161754350322546153511849730464 +B 7 7 7 7 0.31316785630067304260613245423990955181055976494570 0 2.7182818284590452353602874713526624977572470937000 +B 7 7 8 8 0.13278126466792971518174106482733241581868545210005 0 7.3890560989306502272304274605750078131803155705521 +B 7 7 8 9 0.035710382051098530783097153254737917654522010710632 0 7.3890560989306502272304274605750078131803155705521 +B 7 7 9 8 0.095151280970478648810189163882234869830020764959125 0 7.3890560989306502272304274605750078131803155705521 +B 7 7 9 9 0.025590120749376296553251354520810633175610212947775 0 27.474593022118317968158957115156725710168223409107 +B 7 7 11 8 0.012480076496363873511126050564432513772479271306925 0 7.3890560989306502272304274605750078131803155705521 +B 7 7 11 9 0.0033564095117383688853734202379888409349738548367327 0 47.560129945305985709087486769738443607156131247662 +B 8 0 8 0 0.32692302990159208397902888797252141214701233487889 0 2.7182818284590452353602874713526624977572470937000 +B 8 0 9 3 0.095151280970478648810189163882234869830020764959125 0 7.3890560989306502272304274605750078131803155705521 +B 8 0 9 5 0.025590120749376296553251354520810633175610212947775 0 7.3890560989306502272304274605750078131803155705521 +B 8 0 10 4 0.011048405319731608579725749581726919540705439692564 0 27.474593022118317968158957115156725710168223409107 +B 8 0 11 1 0.021603743480989378136878680890876186609984687777117 0 7.3890560989306502272304274605750078131803155705521 +B 8 0 11 2 0.012480076496363873511126050564432513772479271306925 0 7.3890560989306502272304274605750078131803155705521 +B 8 0 11 3 0.012480076496363873511126050564432513772479271306925 0 7.3890560989306502272304274605750078131803155705521 +B 8 0 11 5 0.0033564095117383688853734202379888409349738548367327 0 102.15827997845022478719774797259932200994686828628 +B 8 1 8 1 0.32692302990159208397902888797252141214701233487889 0 2.7182818284590452353602874713526624977572470937000 +B 8 1 9 3 0.16471244119158100106712697324365910648443131697048 0 7.3890560989306502272304274605750078131803155705521 +B 8 1 9 5 0.095151280970478648810189163882234869830020764959125 0 7.3890560989306502272304274605750078131803155705521 +B 8 1 9 6 0.095151280970478648810189163882234869830020764959125 0 7.3890560989306502272304274605750078131803155705521 +B 8 1 10 4 0.041081084733808287839555192305947434609160425656318 0 27.474593022118317968158957115156725710168223409107 +B 8 1 11 2 0.021603743480989378136878680890876186609984687777117 0 7.3890560989306502272304274605750078131803155705521 +B 8 1 11 3 0.021603743480989378136878680890876186609984687777117 0 7.3890560989306502272304274605750078131803155705521 +B 8 1 11 5 0.012480076496363873511126050564432513772479271306925 0 102.15827997845022478719774797259932200994686828628 +B 8 1 11 6 0.012480076496363873511126050564432513772479271306925 0 122.24381690163789252812627762718103990693477612483 +B 8 2 8 2 0.32692302990159208397902888797252141214701233487889 0 2.7182818284590452353602874713526624977572470937000 +B 8 2 9 3 0.23427360141268335332406478260508334313884186898183 0 7.3890560989306502272304274605750078131803155705521 +B 8 2 9 5 0.16471244119158100106712697324365910648443131697048 0 7.3890560989306502272304274605750078131803155705521 +B 8 2 9 6 0.16471244119158100106712697324365910648443131697048 0 7.3890560989306502272304274605750078131803155705521 +B 8 2 10 4 0.071113764147884967099384635030167949677615411620077 0 27.474593022118317968158957115156725710168223409107 +B 8 2 10 7 0.011048405319731608579725749581726919540705439692564 0 67.645666868493653450016016424320161504144039086217 +B 8 2 11 3 0.030727410465614882762631311217319859447490104247309 0 7.3890560989306502272304274605750078131803155705521 +B 8 2 11 5 0.021603743480989378136878680890876186609984687777117 0 102.15827997845022478719774797259932200994686828628 +B 8 2 11 6 0.021603743480989378136878680890876186609984687777117 0 122.24381690163789252812627762718103990693477612483 +B 8 3 8 3 0.42399391251842326837767279954511591031117577626830 0 2.7182818284590452353602874713526624977572470937000 +B 8 3 9 5 0.23427360141268335332406478260508334313884186898183 0 7.3890560989306502272304274605750078131803155705521 +B 8 3 9 6 0.23427360141268335332406478260508334313884186898183 0 7.3890560989306502272304274605750078131803155705521 +B 8 3 9 8 0.025590120749376296553251354520810633175610212947775 0 7.3890560989306502272304274605750078131803155705521 +B 8 3 10 4 0.10114644356196164635921407775438846474607039758383 0 7.3890560989306502272304274605750078131803155705521 +B 8 3 10 7 0.011048405319731608579725749581726919540705439692564 0 47.560129945305985709087486769738443607156131247662 +B 8 3 11 5 0.030727410465614882762631311217319859447490104247309 0 27.474593022118317968158957115156725710168223409107 +B 8 3 11 6 0.030727410465614882762631311217319859447490104247309 0 47.560129945305985709087486769738443607156131247662 +B 8 3 11 8 0.0033564095117383688853734202379888409349738548367327 0 196.92750385796979934716506848462363620671342100200 +B 8 5 8 5 0.42399391251842326837767279954511591031117577626830 0 2.7182818284590452353602874713526624977572470937000 +B 8 5 9 6 0.30383476163378570558100259196650757979325242099318 0 7.3890560989306502272304274605750078131803155705521 +B 8 5 9 8 0.095151280970478648810189163882234869830020764959125 0 7.3890560989306502272304274605750078131803155705521 +B 8 5 9 9 0.025590120749376296553251354520810633175610212947775 0 7.3890560989306502272304274605750078131803155705521 +B 8 5 10 7 0.041081084733808287839555192305947434609160425656318 0 27.474593022118317968158957115156725710168223409107 +B 8 5 11 6 0.039851077450240387388383941543763532284995520717500 0 7.3890560989306502272304274605750078131803155705521 +B 8 5 11 8 0.012480076496363873511126050564432513772479271306925 0 102.15827997845022478719774797259932200994686828628 +B 8 5 11 9 0.0033564095117383688853734202379888409349738548367327 0 122.24381690163789252812627762718103990693477612483 +B 8 6 8 6 0.42399391251842326837767279954511591031117577626830 0 2.7182818284590452353602874713526624977572470937000 +B 8 6 9 8 0.095151280970478648810189163882234869830020764959125 0 7.3890560989306502272304274605750078131803155705521 +B 8 6 9 9 0.025590120749376296553251354520810633175610212947775 0 7.3890560989306502272304274605750078131803155705521 +B 8 6 10 7 0.041081084733808287839555192305947434609160425656318 0 7.3890560989306502272304274605750078131803155705521 +B 8 6 11 8 0.012480076496363873511126050564432513772479271306925 0 27.474593022118317968158957115156725710168223409107 +B 8 6 11 9 0.0033564095117383688853734202379888409349738548367327 0 47.560129945305985709087486769738443607156131247662 +B 8 8 8 8 0.42399391251842326837767279954511591031117577626830 0 2.7182818284590452353602874713526624977572470937000 +B 8 8 9 9 0.23427360141268335332406478260508334313884186898183 0 7.3890560989306502272304274605750078131803155705521 +B 8 8 11 9 0.030727410465614882762631311217319859447490104247309 0 7.3890560989306502272304274605750078131803155705521 +B 8 9 8 9 0.32692302990159208397902888797252141214701233487889 0 2.7182818284590452353602874713526624977572470937000 +B 9 0 9 0 0.44437315656372005510181260824480972226623601176154 0 2.7182818284590452353602874713526624977572470937000 +B 9 0 10 4 0.033997952145685668713303834355901508897228713610787 0 7.3890560989306502272304274605750078131803155705521 +B 9 0 11 1 0.064699121385769054147518492010044297238809673542392 0 7.3890560989306502272304274605750078131803155705521 +B 9 0 11 2 0.037375466194201966561575536592143802569054365971145 0 7.3890560989306502272304274605750078131803155705521 +B 9 0 11 3 0.037375466194201966561575536592143802569054365971145 0 7.3890560989306502272304274605750078131803155705521 +B 9 0 11 5 0.010051811002634878975632581174243307899299058399900 0 27.474593022118317968158957115156725710168223409107 +B 9 3 9 3 0.57631765289318328790680699789475122217760352006005 0 2.7182818284590452353602874713526624977572470937000 +B 9 3 10 4 0.31124599871299834813696190339411484387346454036352 0 7.3890560989306502272304274605750078131803155705521 +B 9 3 10 7 0.033997952145685668713303834355901508897228713610787 0 7.3890560989306502272304274605750078131803155705521 +B 9 3 11 5 0.092022776577336141733461447427944791908564981113642 0 27.474593022118317968158957115156725710168223409107 +B 9 3 11 6 0.092022776577336141733461447427944791908564981113642 0 27.474593022118317968158957115156725710168223409107 +B 9 3 11 8 0.010051811002634878975632581174243307899299058399900 0 47.560129945305985709087486769738443607156131247662 +B 9 5 9 5 0.57631765289318328790680699789475122217760352006005 0 2.7182818284590452353602874713526624977572470937000 +B 9 5 10 7 0.12641396766812322852118985736863928722264065586170 0 7.3890560989306502272304274605750078131803155705521 +B 9 5 11 6 0.11934643176890322931940440284584528657832028868488 0 7.3890560989306502272304274605750078131803155705521 +B 9 5 11 8 0.037375466194201966561575536592143802569054365971145 0 27.474593022118317968158957115156725710168223409107 +B 9 5 11 9 0.010051811002634878975632581174243307899299058399900 0 27.474593022118317968158957115156725710168223409107 +B 9 6 9 6 0.57631765289318328790680699789475122217760352006005 0 2.7182818284590452353602874713526624977572470937000 +B 9 6 10 7 0.12641396766812322852118985736863928722264065586170 0 7.3890560989306502272304274605750078131803155705521 +B 9 6 11 8 0.037375466194201966561575536592143802569054365971145 0 27.474593022118317968158957115156725710168223409107 +B 9 6 11 9 0.010051811002634878975632581174243307899299058399900 0 27.474593022118317968158957115156725710168223409107 +B 9 8 9 8 0.57631765289318328790680699789475122217760352006005 0 2.7182818284590452353602874713526624977572470937000 +B 9 8 11 9 0.092022776577336141733461447427944791908564981113642 0 7.3890560989306502272304274605750078131803155705521 +B 9 9 9 9 0.44437315656372005510181260824480972226623601176154 0 2.7182818284590452353602874713526624977572470937000 +B 10 4 10 4 0.63792879424950264057052677989594163887741511691725 0 2.7182818284590452353602874713526624977572470937000 +B 10 4 11 5 0.23427360141268335332406478260508334313884186898183 0 7.3890560989306502272304274605750078131803155705521 +B 10 4 11 6 0.23427360141268335332406478260508334313884186898183 0 7.3890560989306502272304274605750078131803155705521 +B 10 4 11 8 0.025590120749376296553251354520810633175610212947775 0 7.3890560989306502272304274605750078131803155705521 +B 10 4 11 9 0.025590120749376296553251354520810633175610212947775 0 7.3890560989306502272304274605750078131803155705521 +B 10 7 10 7 0.25909766006400268163549848266362211658969942564290 0 2.7182818284590452353602874713526624977572470937000 +B 10 7 11 8 0.095151280970478648810189163882234869830020764959125 0 7.3890560989306502272304274605750078131803155705521 +B 10 7 11 9 0.025590120749376296553251354520810633175610212947775 0 7.3890560989306502272304274605750078131803155705521 +B 11 0 11 0 0.24339726839730885794981741293152701597634728545202 0 2.7182818284590452353602874713526624977572470937000 +B 11 1 11 1 0.24339726839730885794981741293152701597634728545202 0 2.7182818284590452353602874713526624977572470937000 +B 11 2 11 2 0.24339726839730885794981741293152701597634728545202 0 2.7182818284590452353602874713526624977572470937000 +B 11 3 11 3 0.31566745284092080188064170959927127302945751585588 0 2.7182818284590452353602874713526624977572470937000 +B 11 5 11 5 0.31566745284092080188064170959927127302945751585588 0 2.7182818284590452353602874713526624977572470937000 +B 11 6 11 6 0.31566745284092080188064170959927127302945751585588 0 2.7182818284590452353602874713526624977572470937000 +B 11 8 11 8 0.31566745284092080188064170959927127302945751585588 0 2.7182818284590452353602874713526624977572470937000 +B 11 9 11 9 0.24339726839730885794981741293152701597634728545202 0 2.7182818284590452353602874713526624977572470937000 +P 0 9 0 0E+0 +P 0 8 0 0E+0 +P 0 7 1 0E+0 +P 0 6 0 0E+0 +P 0 5 0 0E+0 +P 0 4 1 0E+0 +P 0 3 0 0E+0 +P 0 2 0 0E+0 +P 0 1 0 0E+0 +P 0 0 0 0E+0 +P 1 9 0 0E+0 +P 1 8 0 0E+0 +P 1 7 1 0E+0 +P 1 6 0 0E+0 +P 1 5 0 0E+0 +P 1 4 1 0E+0 +P 1 3 0 0E+0 +P 1 2 0 0E+0 +P 1 1 0 0E+0 +P 1 0 0 0E+0 +P 2 9 0 0E+0 +P 2 8 0 0E+0 +P 2 7 1 0E+0 +P 2 6 0 0E+0 +P 2 5 0 0E+0 +P 2 4 1 0E+0 +P 2 3 0 0E+0 +P 2 2 0 0E+0 +P 2 1 0 0E+0 +P 2 0 0 0E+0 +P 3 9 0 0E+0 +P 3 8 0 0E+0 +P 3 7 1 0E+0 +P 3 6 0 0E+0 +P 3 5 0 0E+0 +P 3 4 1 0E+0 +P 3 3 0 0E+0 +P 3 2 0 0E+0 +P 3 1 0 0E+0 +P 3 0 0 0E+0 +P 4 9 0 0E+0 +P 4 8 0 0E+0 +P 4 7 1 0E+0 +P 4 6 0 0E+0 +P 4 5 0 0E+0 +P 4 4 1 3.5020952403433299004983682717362182959262569839776E+0 +P 4 3 0 0E+0 +P 4 2 0 0E+0 +P 4 1 0 0E+0 +P 4 0 0 0E+0 +P 5 9 1 0E+0 +P 5 8 1 0E+0 +P 5 7 0 0E+0 +P 5 6 1 0E+0 +P 5 5 1 4.2960460011103591139861036928632289586591870736370E+0 +P 5 4 0 0E+0 +P 5 3 1 0E+0 +P 5 2 1 7.2684965378197797127166071620893066858645768976523E+0 +P 5 1 1 0E+0 +P 5 0 1 0E+0 +P 6 9 1 0E+0 +P 6 8 1 0E+0 +P 6 7 0 0E+0 +P 6 6 1 4.2960460011103591139861036928632289586591870736370E+0 +P 6 5 1 0E+0 +P 6 4 0 0E+0 +P 6 3 1 8.7603175634228600559542067129517878373394534928670E+0 +P 6 2 1 0E+0 +P 6 1 1 0E+0 +P 6 0 1 0E+0 +P 7 9 0 0E+0 +P 7 8 0 0E+0 +P 7 7 1 4.2960460011103591139861036928632289586591870736370E+0 +P 7 6 0 0E+0 +P 7 5 0 0E+0 +P 7 4 1 9.2584529023018880511442317485180754402207131547235E+0 +P 7 3 0 0E+0 +P 7 2 0 0E+0 +P 7 1 0 0E+0 +P 7 0 0 0E+0 +P 8 9 1 0E+0 +P 8 8 1 4.2960460011103591139861036928632289586591870736370E+0 +P 8 7 0 0E+0 +P 8 6 1 0E+0 +P 8 5 1 9.2584529023018880511442317485180754402207131547235E+0 +P 8 4 0 0E+0 +P 8 3 1 0E+0 +P 8 2 1 0E+0 +P 8 1 1 0E+0 +P 8 0 1 0E+0 +P 9 9 1 2.5500778435032294684452055906063619082198696145711E+0 +P 9 8 1 0E+0 +P 9 7 0 0E+0 +P 9 6 1 9.2584529023018880511442317485180754402207131547235E+0 +P 9 5 1 0E+0 +P 9 4 0 0E+0 +P 9 3 1 0E+0 +P 9 2 0 0E+0 +P 9 1 0 0E+0 +P 9 0 1 0E+0 +P 10 9 0 0E+0 +P 10 8 0 0E+0 +P 10 7 1 4.1481382901663585048372485000828674287333518597356E+0 +P 10 6 0 0E+0 +P 10 5 0 0E+0 +P 10 4 1 0E+0 +P 10 3 0 0E+0 +P 10 2 0 0E+0 +P 10 1 0 0E+0 +P 10 0 0 0E+0 +P 11 9 1 0E+0 +P 11 8 1 1.0480978927710785157910339725213965616973709535105E+0 +P 11 7 0 0E+0 +P 11 6 1 0E+0 +P 11 5 1 0E+0 +P 11 4 0 0E+0 +P 11 3 1 0E+0 +P 11 2 1 0E+0 +P 11 1 1 0E+0 +P 11 0 1 0E+0 +END +CASE random06 13 11 6 +Z 2.5150136397711549006246480727112924889328760111822E-1 +S 0 0 6 +S 1 1 6 +B 0 0 0 0 0.046729393361575581163417810823464253799132512611304 0 2.7182818284590452353602874713526624977572470937000 +B 0 0 1 1 0.030882999876246950515976910702814984295798243422244 0 7.3890560989306502272304274605750078131803155705521 +B 0 0 1 3 0.015853005880646567252489310842023896357395341113773 0 7.3890560989306502272304274605750078131803155705521 +B 0 0 2 2 0.0034373297264915744931036693550953455804132477925726 0 27.474593022118317968158957115156725710168223409107 +B 0 0 2 4 0.00066352605966593570520956714377171482603815969863381 0 47.560129945305985709087486769738443607156131247662 +B 0 0 2 5 0.00017844964160258893841979848919338350054363859425489 0 47.560129945305985709087486769738443607156131247662 +B 0 0 3 1 0.0046608323101952050932054722382797769584187852125004 0 7.3890560989306502272304274605750078131803155705521 +B 0 0 3 3 0.0023925202317881613336630295471741533922529162845302 0 102.15827997845022478719774797259932200994686828628 +B 0 0 4 4 0.00046184091966346339518652299049314719424411944910338 0 420.02434991687830958731943938261851212997973347307 +B 0 0 5 2 0.00052433979410189638506118410071219765925963324920310 0 47.560129945305985709087486769738443607156131247662 +B 0 0 5 4 0.00010121610237886270475870577805320138413821301891487 0 420.02434991687830958731943938261851212997973347307 +B 0 0 5 5 0.000027221202439302280203104128826486698148282049992599 403.42879349273512260838718054338827960589989735717 1287.6219513029931288792950672334649356139537112022 +B 0 2 0 2 0.11852666887923602260431736696687762770955667326735 0 2.7182818284590452353602874713526624977572470937000 +B 0 2 1 3 0.084007604289244019748180443372117754697109738921813 0 7.3890560989306502272304274605750078131803155705521 +B 0 2 1 6 0.0097717248919536502390946798101695994997806685343951 0 7.3890560989306502272304274605750078131803155705521 +B 0 2 1 7 0.0075345466402267836765714376029354017295836111021214 0 7.3890560989306502272304274605750078131803155705521 +B 0 2 2 4 0.011485431043859607231096956556773523446354435009720 0 27.474593022118317968158957115156725710168223409107 +B 0 2 2 5 0.0026038317319193227723686417620850401280162441161494 0 27.474593022118317968158957115156725710168223409107 +B 0 2 3 3 0.012678345948981180537566929734386244443033573859959 0 7.3890560989306502272304274605750078131803155705521 +B 0 2 3 6 0.0014747392185105008583843313937669992987153357267336 0 176.84196693478213160623653883004191830972551316345 +B 0 2 3 7 0.0011371064522281550373183952593423819305582636341902 0 196.92750385796979934716506848462363620671342100200 +B 0 2 4 4 0.0079943235970235011732543287174837759644120353511435 0 47.560129945305985709087486769738443607156131247662 +B 0 2 5 4 0.0017520194534423396919063559232866028029875627735769 0 47.560129945305985709087486769738443607156131247662 +B 0 2 5 5 0.00039719570213710440298111237496006012809793689460398 0 251.52565389111403842527532968748451460950415804062 +B 0 4 0 4 0.17316373647984517714469883132854205154579578086291 0 2.7182818284590452353602874713526624977572470937000 +B 0 4 1 6 0.052970945579291752007032192622997973956059876307482 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 1 7 0.030252746109759267841801815112966687842821743704801 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 1 8 0.013615827628919700689966068634789698587198283681499 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 1 9 0.0030601901367730505515249531884670061891894962375745 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 2 5 0.017729881530528694714775678856284733208909576341686 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 3 6 0.0079943235970235011732543287174837759644120353511435 0 27.474593022118317968158957115156725710168223409107 +B 0 4 3 7 0.0045657150246258281052863619884130789474851494926666 0 47.560129945305985709087486769738443607156131247662 +B 0 4 3 8 0.0020548874655058155125970934127495360240958441919867 0 67.645666868493653450016016424320161504144039086217 +B 0 4 3 9 0.00046184091966346339518652299049314719424411944910338 0 87.731203791681321190944546078901879401131946924772 +B 0 4 5 5 0.0027045652209388701675602527216554410435739340055070 0 7.3890560989306502272304274605750078131803155705521 +B 0 5 0 5 0.18248311308899896218691145311130337999988721737004 0 2.7182818284590452353602874713526624977572470937000 +B 0 5 1 6 0.10053823989456143260074968328202260594804198498153 0 7.3890560989306502272304274605750078131803155705521 +B 0 5 1 7 0.077820040425028948435519305771991319834803852378853 0 7.3890560989306502272304274605750078131803155705521 +B 0 5 1 8 0.024171465121066350828407184081112390985207071125423 0 7.3890560989306502272304274605750078131803155705521 +B 0 5 1 9 0.0052973683884999171140481953957012039593865536698482 0 7.3890560989306502272304274605750078131803155705521 +B 0 5 3 6 0.015173133399878574727120104933943882042988941507204 0 7.3890560989306502272304274605750078131803155705521 +B 0 5 3 7 0.011744524827480901659152138204873185026062055648728 0 27.474593022118317968158957115156725710168223409107 +B 0 5 3 8 0.0036479340113481676300076638350059248539475689348702 0 47.560129945305985709087486769738443607156131247662 +B 0 5 3 9 0.00079947368594580921625245912491776456240119154164673 0 67.645666868493653450016016424320161504144039086217 +B 1 1 1 1 0.41839453959996411141767694978925033137359882285075 0 2.7182818284590452353602874713526624977572470937000 +B 1 1 2 2 0.051364021094052568118684046005612072638839318592649 0 7.3890560989306502272304274605750078131803155705521 +B 1 1 2 4 0.020327362384100300377535795256492291897789455978320 0 7.3890560989306502272304274605750078131803155705521 +B 1 1 2 5 0.012008903143680516801617922017403797269977725966669 0 7.3890560989306502272304274605750078131803155705521 +B 1 1 3 3 0.027624685449931052803662528291985896491957735112422 0 27.474593022118317968158957115156725710168223409107 +B 1 1 3 6 0.0052554457515931807841496721078224214046723316946508 0 67.645666868493653450016016424320161504144039086217 +B 1 1 4 4 0.010932496715148176824510285433437971373959197140896 0 102.15827997845022478719774797259932200994686828628 +B 1 1 5 2 0.010419544620163786608788925033674840544298047109725 0 7.3890560989306502272304274605750078131803155705521 +B 1 1 5 4 0.0041235451364592736665291113846525291230593962204728 0 102.15827997845022478719774797259932200994686828628 +B 1 1 5 5 0.0024360885203221128630010484475297497445030424470775 0 399.93881299369064184639090972803679423299182563451 +B 1 1 6 3 0.0031337999557909394711074310160945975081236080438004 0 47.560129945305985709087486769738443607156131247662 +B 1 1 6 6 0.00059618835095353080728603624462487574411889546372571 403.42879349273512260838718054338827960589989735717 1401.5224972956131609632289157257380547316385495960 +B 1 3 1 3 0.51341428536807012211359485220471830802316602815455 0 2.7182818284590452353602874713526624977572470937000 +B 1 3 2 4 0.12273246847312838839107147177047773361299483183035 0 7.3890560989306502272304274605750078131803155705521 +B 1 3 2 5 0.081770426037517153185657201164883556926912681489541 0 7.3890560989306502272304274605750078131803155705521 +B 1 3 3 6 0.028488924317936362298190973262470026653925461507902 0 47.560129945305985709087486769738443607156131247662 +B 1 3 3 7 0.016270583522821060722941301640754796553384004219931 0 47.560129945305985709087486769738443607156131247662 +B 1 3 3 8 0.0073228876434859119151361591670894065184698428528222 0 47.560129945305985709087486769738443607156131247662 +B 1 3 4 4 0.066008185571287576518468433098099847117517559767297 0 7.3890560989306502272304274605750078131803155705521 +B 1 3 5 4 0.024897124570075383000925674446806158871537060778113 0 7.3890560989306502272304274605750078131803155705521 +B 1 3 5 5 0.016587692796628939267167049221944706972145994955057 0 47.560129945305985709087486769738443607156131247662 +B 1 3 6 6 0.0032318409536244409605809216920512464079082162527492 0 217.01304078115746708809359813920535410370132884056 +B 1 3 6 7 0.0018457677650999891767183475886151785005108334737265 0 346.29487777063361298524265019950882880627071075635 +B 1 3 6 8 0.00083072312316502571118978968002728979490894844169664 0 475.57671476010975888239170225981230350884009267213 +B 1 6 1 6 0.41188250605738609685555606021484825420196564330405 0 2.7182818284590452353602874713526624977572470937000 +B 1 6 3 7 0.060612937526186697488184875820144181061962796142796 0 7.3890560989306502272304274605750078131803155705521 +B 1 6 3 8 0.028488924317936362298190973262470026653925461507902 0 7.3890560989306502272304274605750078131803155705521 +B 1 6 3 9 0.0073228876434859119151361591670894065184698428528222 0 7.3890560989306502272304274605750078131803155705521 +B 1 6 6 7 0.0068760537123291274719159996466609033628597674516444 0 7.3890560989306502272304274605750078131803155705521 +B 1 6 6 8 0.0032318409536244409605809216920512464079082162527492 0 27.474593022118317968158957115156725710168223409107 +B 1 6 6 9 0.00083072312316502571118978968002728979490894844169664 0 47.560129945305985709087486769738443607156131247662 +B 1 7 1 7 0.41188250605738609685555606021484825420196564330405 0 2.7182818284590452353602874713526624977572470937000 +B 1 7 3 8 0.040707265113051663873440644884185256754466918795875 0 7.3890560989306502272304274605750078131803155705521 +B 1 7 3 9 0.016270583522821060722941301640754796553384004219931 0 7.3890560989306502272304274605750078131803155705521 +B 1 7 6 8 0.0046179141421488927444434957954873143153055990317719 0 7.3890560989306502272304274605750078131803155705521 +B 1 7 6 9 0.0018457677650999891767183475886151785005108334737265 0 27.474593022118317968158957115156725710168223409107 +B 1 8 1 8 0.30414806401526423797605240924304370891672290746881 0 2.7182818284590452353602874713526624977572470937000 +B 1 8 3 9 0.028488924317936362298190973262470026653925461507902 0 7.3890560989306502272304274605750078131803155705521 +B 1 8 6 9 0.0032318409536244409605809216920512464079082162527492 0 7.3890560989306502272304274605750078131803155705521 +B 1 9 1 9 0.26223294558247502496041271453221527195391611761927 0 2.7182818284590452353602874713526624977572470937000 +B 2 0 2 0 0.074785171074994790505935291363176664568858418112029 0 2.7182818284590452353602874713526624977572470937000 +B 2 0 3 1 0.047912569980766533352401435869317358881755670510503 0 7.3890560989306502272304274605750078131803155705521 +B 2 0 3 3 0.024594704423328423806627792475009486696867436760065 0 7.3890560989306502272304274605750078131803155705521 +B 2 0 4 4 0.0047476467529102113550530161255897855677458500109699 0 47.560129945305985709087486769738443607156131247662 +B 2 0 5 2 0.0066684302345235879577919608702774487312684855059644 0 27.474593022118317968158957115156725710168223409107 +B 2 0 5 4 0.0012872425951952018887603480631098479036687943264343 0 47.560129945305985709087486769738443607156131247662 +B 2 0 5 5 0.00034619285319979884778739180374867388405684026332678 0 176.84196693478213160623653883004191830972551316345 +B 2 0 6 1 0.0086100594240512934275620371876664037356092865842054 0 7.3890560989306502272304274605750078131803155705521 +B 2 0 6 3 0.0044197559572955939605877781240355867400970109048686 0 102.15827997845022478719774797259932200994686828628 +B 2 0 7 4 0.00085316902606916067716429997974290282221536985333265 0 420.02434991687830958731943938261851212997973347307 +B 2 2 2 2 0.18968868567362153065467411881254712183555169772146 0 2.7182818284590452353602874713526624977572470937000 +B 2 2 3 3 0.13033125782967449689262457167713520468786213047378 0 7.3890560989306502272304274605750078131803155705521 +B 2 2 3 6 0.015160070413969902637649617260254298735045791014989 0 7.3890560989306502272304274605750078131803155705521 +B 2 2 3 7 0.011689262526950005543450750215366127679279144013649 0 7.3890560989306502272304274605750078131803155705521 +B 2 2 4 4 0.082180298131180720934115269683449939673275606489464 0 27.474593022118317968158957115156725710168223409107 +B 2 2 5 4 0.022281771527220681811274549793781364633923492646325 0 27.474593022118317968158957115156725710168223409107 +B 2 2 5 5 0.0050514415631768140526521731005545439821166105788646 0 102.15827997845022478719774797259932200994686828628 +B 2 2 6 3 0.023420991092218903656832682116568947370788453184880 0 7.3890560989306502272304274605750078131803155705521 +B 2 2 6 6 0.0027243186326569592278166427377573020551072737367343 0 454.53696302683488092450117093089767263578256267313 +B 2 2 6 7 0.0021006020971276930442658618184191689774766391089337 0 474.62249995002254866542970058547939053277047051169 +B 2 2 7 4 0.014768092187076566175095797813441409397937600628941 0 47.560129945305985709087486769738443607156131247662 +B 2 4 2 4 0.27712920551797846431053042668004958697704065804896 0 2.7182818284590452353602874713526624977572470937000 +B 2 4 3 6 0.082180298131180720934115269683449939673275606489464 0 7.3890560989306502272304274605750078131803155705521 +B 2 4 3 7 0.046934780329065363238783009949408033676277375251556 0 7.3890560989306502272304274605750078131803155705521 +B 2 4 3 8 0.021123896536308526712428925430121315641100789758725 0 7.3890560989306502272304274605750078131803155705521 +B 2 4 3 9 0.0047476467529102113550530161255897855677458500109699 0 7.3890560989306502272304274605750078131803155705521 +B 2 4 5 5 0.034396024664580195677671438428840027748202716733372 0 7.3890560989306502272304274605750078131803155705521 +B 2 4 6 6 0.014768092187076566175095797813441409397937600628941 0 27.474593022118317968158957115156725710168223409107 +B 2 4 6 7 0.0084343471421021296096808298159302891877071198689376 0 47.560129945305985709087486769738443607156131247662 +B 2 4 6 8 0.0037960394217663277770369972046974536624663762770680 0 67.645666868493653450016016424320161504144039086217 +B 2 4 6 9 0.00085316902606916067716429997974290282221536985333265 0 87.731203791681321190944546078901879401131946924772 +B 2 5 2 5 0.29204382614305502063953220013456158695599018269226 0 2.7182818284590452353602874713526624977572470937000 +B 2 5 3 6 0.15597725201547547071257541767163990426397169563479 0 7.3890560989306502272304274605750078131803155705521 +B 2 5 3 7 0.12073173421336011301724315793759799826697346439688 0 7.3890560989306502272304274605750078131803155705521 +B 2 5 3 8 0.037500146319706842069804834734652845714455729506481 0 7.3890560989306502272304274605750078131803155705521 +B 2 5 3 9 0.0082184546399301084492518831704779566235124970123097 0 7.3890560989306502272304274605750078131803155705521 +B 2 5 6 6 0.028029667563075323543381453717532034084078489788417 0 7.3890560989306502272304274605750078131803155705521 +B 2 5 6 7 0.021695922518100886977966485720020913873848009028414 0 27.474593022118317968158957115156725710168223409107 +B 2 5 6 8 0.0067389098174634948769096944296520045027173827008036 0 47.560129945305985709087486769738443607156131247662 +B 2 5 6 9 0.0014768855615984268607150808990810358998460044811332 0 67.645666868493653450016016424320161504144039086217 +B 3 1 3 1 0.46124777565031448500943818890915423891244863250889 0 2.7182818284590452353602874713526624977572470937000 +B 3 1 4 4 0.065229694795963474640526789667015628485253032714740 0 7.3890560989306502272304274605750078131803155705521 +B 3 1 5 2 0.090290055905611646329918903406270201447827770751349 0 7.3890560989306502272304274605750078131803155705521 +B 3 1 5 4 0.035732379338317794844262160094463219798648550218463 0 7.3890560989306502272304274605750078131803155705521 +B 3 1 5 5 0.021109806302402956649024379868133353772557046435141 0 27.474593022118317968158957115156725710168223409107 +B 3 1 6 3 0.034876345111472217592173215331967725466333535917903 0 27.474593022118317968158957115156725710168223409107 +B 3 1 6 6 0.0066350344542164454605238808098538868976300598515149 0 142.32935382482556026905480728176275780392268396339 +B 3 1 7 4 0.013802348231570391579708716487306328755232548838754 0 102.15827997845022478719774797259932200994686828628 +B 3 1 8 2 0.027590600447099370454491721314387482430159096851979 0 7.3890560989306502272304274605750078131803155705521 +B 3 1 8 4 0.010919007541410123867660183061018384880098435367044 0 102.15827997845022478719774797259932200994686828628 +B 3 1 8 5 0.0064506797051286485120941001394244521921131514111467 0 420.02434991687830958731943938261851212997973347307 +B 3 3 3 3 0.56599973159195230420368813736405779764105512715290 0 2.7182818284590452353602874713526624977572470937000 +B 3 3 4 4 0.39384359410640353905760326134666186740652739819268 0 7.3890560989306502272304274605750078131803155705521 +B 3 3 5 4 0.21574481911338535481988508755428638563815316096423 0 7.3890560989306502272304274605750078131803155705521 +B 3 3 5 5 0.14373984320335833082963591657035711930235131666592 0 27.474593022118317968158957115156725710168223409107 +B 3 3 6 6 0.035967452305214996939938175917301470748488849809298 0 122.24381690163789252812627762718103990693477612483 +B 3 3 6 7 0.020541717556764325353803543977062841751128557943426 0 122.24381690163789252812627762718103990693477612483 +B 3 3 6 8 0.0092451932938620165011438101682173063236471675168708 0 122.24381690163789252812627762718103990693477612483 +B 3 3 7 4 0.083335763744309791046107032323351103022725039298310 0 7.3890560989306502272304274605750078131803155705521 +B 3 3 8 4 0.065926740691265705846823492554861043181072951318959 0 7.3890560989306502272304274605750078131803155705521 +B 3 3 8 5 0.043923647431323473055158168757323979860683144938196 0 67.645666868493653450016016424320161504144039086217 +B 3 6 3 6 0.45406875990755118159227487575168645754472119173597 0 2.7182818284590452353602874713526624977572470937000 +B 3 6 6 7 0.076524227984962213852100408988840403495412727970386 0 7.3890560989306502272304274605750078131803155705521 +B 3 6 6 8 0.035967452305214996939938175917301470748488849809298 0 7.3890560989306502272304274605750078131803155705521 +B 3 6 6 9 0.0092451932938620165011438101682173063236471675168708 0 7.3890560989306502272304274605750078131803155705521 +B 3 7 3 7 0.45406875990755118159227487575168645754472119173597 0 2.7182818284590452353602874713526624977572470937000 +B 3 7 6 8 0.051393187053665668526072807857540099745849141675168 0 7.3890560989306502272304274605750078131803155705521 +B 3 7 6 9 0.020541717556764325353803543977062841751128557943426 0 7.3890560989306502272304274605750078131803155705521 +B 3 8 3 8 0.33529982998707882959135128016820040098999996587001 0 2.7182818284590452353602874713526624977572470937000 +B 3 8 6 9 0.035967452305214996939938175917301470748488849809298 0 7.3890560989306502272304274605750078131803155705521 +B 3 9 3 9 0.28909163816476571986335331289175830867792090354865 0 2.7182818284590452353602874713526624977572470937000 +B 4 0 4 0 0.18777629057366756975990551077022844521583120113516 0 2.7182818284590452353602874713526624977572470937000 +B 4 0 5 2 0.055280259174418474074173268845403982462648447568410 0 7.3890560989306502272304274605750078131803155705521 +B 4 0 5 4 0.010671042776205278612574158054218120184628103516691 0 7.3890560989306502272304274605750078131803155705521 +B 4 0 5 5 0.0028698854117326663782647195029580033418309277525133 0 7.3890560989306502272304274605750078131803155705521 +B 4 0 6 1 0.074372726995430485134181052438303163916374156608107 0 7.3890560989306502272304274605750078131803155705521 +B 4 0 6 3 0.038177355928596490014498642879212708041882447841595 0 27.474593022118317968158957115156725710168223409107 +B 4 0 7 4 0.0073695782957723975266862630508995606988629140128138 0 122.24381690163789252812627762718103990693477612483 +B 4 0 8 2 0.012780960660435721466123922457241270821390914985392 0 27.474593022118317968158957115156725710168223409107 +B 4 0 8 4 0.0024671768903648809595241320459386829294242055838148 0 122.24381690163789252812627762718103990693477612483 +B 4 0 8 5 0.00066352605966593570520956714377171482603815969863381 0 474.62249995002254866542970058547939053277047051169 +B 4 0 9 1 0.014142789099577822604410902976582797575701648016060 0 7.3890560989306502272304274605750078131803155705521 +B 4 0 9 3 0.0072598426209493590218741272785706406388119161267136 0 122.24381690163789252812627762718103990693477612483 +B 4 4 4 4 0.69583706868316724147040700680472549993913095890443 0 2.7182818284590452353602874713526624977572470937000 +B 4 4 5 5 0.28513774473993976407375761783835417242329367722198 0 7.3890560989306502272304274605750078131803155705521 +B 4 4 6 6 0.12756512288459812087112018525145074237931401773273 0 27.474593022118317968158957115156725710168223409107 +B 4 4 6 7 0.072854944024195161830773253881952460070560640810504 0 27.474593022118317968158957115156725710168223409107 +B 4 4 6 8 0.032789762494586587382628613148435399510410272903864 0 27.474593022118317968158957115156725710168223409107 +B 4 4 6 9 0.0073695782957723975266862630508995606988629140128138 0 27.474593022118317968158957115156725710168223409107 +B 4 4 8 5 0.065924696315696490430601608311291263574598290125607 0 7.3890560989306502272304274605750078131803155705521 +B 4 4 9 6 0.024257906121009205606011062538797957369522735109740 0 47.560129945305985709087486769738443607156131247662 +B 4 4 9 7 0.013854166033995856816369525579957644178699327949763 0 122.24381690163789252812627762718103990693477612483 +B 4 4 9 8 0.0062353326860621548260772482650510248768273372759076 0 196.92750385796979934716506848462363620671342100200 +B 4 4 9 9 0.0014014060772080996351342305940780994639067630881736 0 271.61119081430170616620385934206623250649206587918 +B 5 0 5 0 0.11549179030157689400439125673911007842626314314849 0 2.7182818284590452353602874713526624977572470937000 +B 5 0 6 1 0.074372726995430485134181052438303163916374156608107 0 7.3890560989306502272304274605750078131803155705521 +B 5 0 6 3 0.038177355928596490014498642879212708041882447841595 0 7.3890560989306502272304274605750078131803155705521 +B 5 0 7 4 0.0073695782957723975266862630508995606988629140128138 0 47.560129945305985709087486769738443607156131247662 +B 5 0 8 2 0.012780960660435721466123922457241270821390914985392 0 27.474593022118317968158957115156725710168223409107 +B 5 0 8 4 0.0024671768903648809595241320459386829294242055838148 0 47.560129945305985709087486769738443607156131247662 +B 5 0 8 5 0.00066352605966593570520956714377171482603815969863381 0 176.84196693478213160623653883004191830972551316345 +B 5 0 9 1 0.014142789099577822604410902976582797575701648016060 0 7.3890560989306502272304274605750078131803155705521 +B 5 0 9 3 0.0072598426209493590218741272785706406388119161267136 0 102.15827997845022478719774797259932200994686828628 +B 5 0 10 2 0.0015691492888053095445018239086333898474199647572455 0 47.560129945305985709087486769738443607156131247662 +B 5 0 10 4 0.00030290124238133501478174993133176901593225326844532 0 420.02434991687830958731943938261851212997973347307 +B 5 0 10 5 0.000081462690660773644502315761951340372604873287687543 0 678.58802389583060138161754350322546153511849730464 +B 5 2 5 2 0.29293890210441237630806705638961428926609085298616 0 2.7182818284590452353602874713526624977572470937000 +B 5 2 6 3 0.20230789250980536713553943698770755496814257860828 0 7.3890560989306502272304274605750078131803155705521 +B 5 2 6 6 0.023532358597802105422296352243231486293279438826007 0 7.3890560989306502272304274605750078131803155705521 +B 5 2 6 7 0.018144765163792202790426322512454177761807263888276 0 7.3890560989306502272304274605750078131803155705521 +B 5 2 7 4 0.12756512288459812087112018525145074237931401773273 0 27.474593022118317968158957115156725710168223409107 +B 5 2 8 4 0.042706069542402580947348095687750593040591911371105 0 27.474593022118317968158957115156725710168223409107 +B 5 2 8 5 0.0096817802131606619767823916546065553429683891245388 0 102.15827997845022478719774797259932200994686828628 +B 5 2 9 3 0.038471062881989405390798738155091580211282137606645 0 7.3890560989306502272304274605750078131803155705521 +B 5 2 9 6 0.0044749358818697122225248676346369467498604996405918 0 454.53696302683488092450117093089767263578256267313 +B 5 2 9 7 0.0034504259469825080267279886211173309878759207897857 0 474.62249995002254866542970058547939053277047051169 +B 5 2 10 4 0.0052431269002784457497489837625763502849299624321531 0 47.560129945305985709087486769738443607156131247662 +B 5 2 10 5 0.0011886554492635804958994866088534835892417731914764 0 196.92750385796979934716506848462363620671342100200 +B 5 4 5 4 0.42797452529765714109440126576530747660666092930547 0 2.7182818284590452353602874713526624977572470937000 +B 5 4 6 6 0.12756512288459812087112018525145074237931401773273 0 7.3890560989306502272304274605750078131803155705521 +B 5 4 6 7 0.072854944024195161830773253881952460070560640810504 0 7.3890560989306502272304274605750078131803155705521 +B 5 4 6 8 0.032789762494586587382628613148435399510410272903864 0 7.3890560989306502272304274605750078131803155705521 +B 5 4 6 9 0.0073695782957723975266862630508995606988629140128138 0 7.3890560989306502272304274605750078131803155705521 +B 5 4 8 5 0.065924696315696490430601608311291263574598290125607 0 7.3890560989306502272304274605750078131803155705521 +B 5 4 9 6 0.024257906121009205606011062538797957369522735109740 0 27.474593022118317968158957115156725710168223409107 +B 5 4 9 7 0.013854166033995856816369525579957644178699327949763 0 47.560129945305985709087486769738443607156131247662 +B 5 4 9 8 0.0062353326860621548260772482650510248768273372759076 0 67.645666868493653450016016424320161504144039086217 +B 5 4 9 9 0.0014014060772080996351342305940780994639067630881736 0 87.731203791681321190944546078901879401131946924772 +B 5 4 10 5 0.0080937335687687301658349379779785471776070085797762 0 7.3890560989306502272304274605750078131803155705521 +B 5 5 5 5 0.45100738345521314866918943498008592278077398896434 0 2.7182818284590452353602874713526624977572470937000 +B 5 5 6 6 0.24211712263193496382353140419155615325319291573815 0 7.3890560989306502272304274605750078131803155705521 +B 5 5 6 7 0.18740694377153200478318447282205787094443953881592 0 7.3890560989306502272304274605750078131803155705521 +B 5 5 6 8 0.058209946693400777238570963245971238321957631794917 0 7.3890560989306502272304274605750078131803155705521 +B 5 5 6 9 0.012757171729782300158556292781676869230335088950545 0 7.3890560989306502272304274605750078131803155705521 +B 5 5 9 6 0.046041224264782744899625460026150564466394589310766 0 7.3890560989306502272304274605750078131803155705521 +B 5 5 9 7 0.035637484177769396109983923067310251275571182150790 0 27.474593022118317968158957115156725710168223409107 +B 5 5 9 8 0.011069259294916210017020265936023950289747911463641 0 47.560129945305985709087486769738443607156131247662 +B 5 5 9 9 0.0024259160120953038309311096075977152258913419389796 0 67.645666868493653450016016424320161504144039086217 +B 6 1 6 1 0.56384780438140809934121964163769815335761348137836 0 2.7182818284590452353602874713526624977572470937000 +B 6 1 7 4 0.079739398502936260842900832661924497097557660351279 0 7.3890560989306502272304274605750078131803155705521 +B 6 1 8 2 0.11725377025128962965307652078591212983890444714250 0 7.3890560989306502272304274605750078131803155705521 +B 6 1 8 4 0.046403296082206151208835068293702717134744427419974 0 7.3890560989306502272304274605750078131803155705521 +B 6 1 8 5 0.027413920097898011268344286855374725170836820206813 0 27.474593022118317968158957115156725710168223409107 +B 6 1 9 3 0.033475500419930068604618477140232721977824363522447 0 27.474593022118317968158957115156725710168223409107 +B 6 1 9 6 0.0063685313913616457391517206923669590100588249356294 0 142.32935382482556026905480728176275780392268396339 +B 6 1 10 2 0.015037552780683379477788996850506099643363038044358 0 7.3890560989306502272304274605750078131803155705521 +B 6 1 10 4 0.0059511264545131206878434352423113320037011739413271 0 102.15827997845022478719774797259932200994686828628 +B 6 1 10 5 0.0035157783797834353207350169716507255162511100336067 0 142.32935382482556026905480728176275780392268396339 +B 6 1 11 3 0.0050840716124572780714260806321768726700791508471420 0 47.560129945305985709087486769738443607156131247662 +B 6 1 11 6 0.00096721689754301912562005243947305494591439321071866 0 901.68486995473911162177191440122033745838480977571 +B 6 3 6 3 0.69190080209847190885166124305093136582420050053340 0 2.7182818284590452353602874713526624977572470937000 +B 6 3 7 4 0.48145022595173290267647825590091925264107566460519 0 7.3890560989306502272304274605750078131803155705521 +B 6 3 8 4 0.28017363816533743713898005725759704507865444431613 0 7.3890560989306502272304274605750078131803155705521 +B 6 3 8 5 0.18666550133208492276692206167203931390109043755767 0 27.474593022118317968158957115156725710168223409107 +B 6 3 9 6 0.034522782157898376665695159474045338284990700046115 0 122.24381690163789252812627762718103990693477612483 +B 6 3 9 7 0.019716638096672448450420661923912725933126967291923 0 122.24381690163789252812627762718103990693477612483 +B 6 3 9 8 0.0088738504852450793042339593447664207460207518571955 0 122.24381690163789252812627762718103990693477612483 +B 6 3 10 4 0.035931687847973574409588594557743846214068217278629 0 7.3890560989306502272304274605750078131803155705521 +B 6 3 10 5 0.023939463290589392920890530831570840529921399943708 0 47.560129945305985709087486769738443607156131247662 +B 6 3 11 6 0.0052431269002784457497489837625763502849299624321531 0 271.61119081430170616620385934206623250649206587918 +B 6 3 11 7 0.0029944526230504517525448010163344882937584878310570 0 603.90433693949869456257875264578286523533985242747 +B 6 3 11 8 0.0013477107370847481742223897392529612040925847764877 0 936.19748306469568295895364594949949796418763897576 +B 6 6 6 6 0.55507188723260549269009333213805059428573500798393 0 2.7182818284590452353602874713526624977572470937000 +B 6 6 9 7 0.073450552741628484864639040785843560132331375135003 0 7.3890560989306502272304274605750078131803155705521 +B 6 6 9 8 0.034522782157898376665695159474045338284990700046115 0 7.3890560989306502272304274605750078131803155705521 +B 6 6 9 9 0.0088738504852450793042339593447664207460207518571955 0 7.3890560989306502272304274605750078131803155705521 +B 6 6 11 7 0.011155258784143056597400721301894029719649293782379 0 7.3890560989306502272304274605750078131803155705521 +B 6 6 11 8 0.0052431269002784457497489837625763502849299624321531 0 27.474593022118317968158957115156725710168223409107 +B 6 6 11 9 0.0013477107370847481742223897392529612040925847764877 0 47.560129945305985709087486769738443607156131247662 +B 6 7 6 7 0.55507188723260549269009333213805059428573500798393 0 2.7182818284590452353602874713526624977572470937000 +B 6 7 9 8 0.049328926219124304880969657024177950636854432800309 0 7.3890560989306502272304274605750078131803155705521 +B 6 7 9 9 0.019716638096672448450420661923912725933126967291923 0 7.3890560989306502272304274605750078131803155705521 +B 6 7 11 8 0.0074918011775064397469531665088182122761014370332492 0 7.3890560989306502272304274605750078131803155705521 +B 6 7 11 9 0.0029944526230504517525448010163344882937584878310570 0 27.474593022118317968158957115156725710168223409107 +B 6 8 6 8 0.40988397761077618096088908075276786060425053714882 0 2.7182818284590452353602874713526624977572470937000 +B 6 8 9 9 0.034522782157898376665695159474045338284990700046115 0 7.3890560989306502272304274605750078131803155705521 +B 6 8 11 9 0.0052431269002784457497489837625763502849299624321531 0 7.3890560989306502272304274605750078131803155705521 +B 6 9 6 9 0.35339722823466909316603665448768604017448864545016 0 2.7182818284590452353602874713526624977572470937000 +B 7 0 7 0 0.18777629057366756975990551077022844521583120113516 0 2.7182818284590452353602874713526624977572470937000 +B 7 0 8 2 0.055530294064121447275470925423063600249778942561848 0 7.3890560989306502272304274605750078131803155705521 +B 7 0 8 4 0.010719308342311721590528917463574071967582074313221 0 7.3890560989306502272304274605750078131803155705521 +B 7 0 8 5 0.0028828660216845606139709086977418893127546553453732 0 7.3890560989306502272304274605750078131803155705521 +B 7 0 9 1 0.056632798641208863020446742680727857420933620988199 0 7.3890560989306502272304274605750078131803155705521 +B 7 0 9 3 0.029071012968111373091436947845758924691286104110701 0 27.474593022118317968158957115156725710168223409107 +B 7 0 10 2 0.0068898687862441493280713950396578773745958654867223 0 27.474593022118317968158957115156725710168223409107 +B 7 0 10 4 0.0013299880579155458183786191572270373571509683953068 0 122.24381690163789252812627762718103990693477612483 +B 7 0 10 5 0.00035768887870092628246833234275633810503125743214932 0 142.32935382482556026905480728176275780392268396339 +B 7 0 11 1 0.0062648287334405647419096124212441145946025141981971 0 7.3890560989306502272304274605750078131803155705521 +B 7 0 11 3 0.0032158911747710131228242351857149169370858678118148 0 122.24381690163789252812627762718103990693477612483 +B 7 0 12 1 0.0026254548090098501386234042555622462565547134341105 0 7.3890560989306502272304274605750078131803155705521 +B 7 0 12 3 0.0013477107370847481742223897392529612040925847764877 0 142.32935382482556026905480728176275780392268396339 +B 7 4 7 4 0.69583706868316724147040700680472549993913095890443 0 2.7182818284590452353602874713526624977572470937000 +B 7 4 8 5 0.28642743450661143695567280421016133638334753950685 0 7.3890560989306502272304274605750078131803155705521 +B 7 4 9 6 0.097137354105737990217609674993112827862402383092255 0 27.474593022118317968158957115156725710168223409107 +B 7 4 9 7 0.055477048396951892500507494622024124071766482698546 0 27.474593022118317968158957115156725710168223409107 +B 7 4 9 8 0.024968507837060735884444227432377115251455439086822 0 27.474593022118317968158957115156725710168223409107 +B 7 4 9 9 0.0056117324260645203694198734241718014014692522570807 0 27.474593022118317968158957115156725710168223409107 +B 7 4 10 5 0.035538213398479951125280068063180053984966298120001 0 7.3890560989306502272304274605750078131803155705521 +B 7 4 11 6 0.010745520293768556596759673672391201643894108270133 0 47.560129945305985709087486769738443607156131247662 +B 7 4 11 7 0.0061369774262012044580279229604916696012118111542763 0 122.24381690163789252812627762718103990693477612483 +B 7 4 11 8 0.0027620641939268828509717970862461108440991036074858 0 196.92750385796979934716506848462363620671342100200 +B 7 4 11 9 0.00062078059694559177559129604965452537255598562976137 0 271.61119081430170616620385934206623250649206587918 +B 7 4 12 6 0.0045032161501873951154117008781940284824696356925669 0 47.560129945305985709087486769738443607156131247662 +B 7 4 12 7 0.0025718750794255379756296934719752074332794805267779 0 251.52565389111403842527532968748451460950415804062 +B 7 4 12 8 0.0011575216225834032988802861249820577932729616957798 0 658.50248697264293364068901384864374363813058946609 +B 7 4 12 9 0.00026015577966099108516347883721457956245007919957291 0 1268.4906291898926713553285392532161306930354255241 +B 8 0 8 0 0.11601416442718549491352895091421749384163064874617 0 2.7182818284590452353602874713526624977572470937000 +B 8 0 9 1 0.056632798641208863020446742680727857420933620988199 0 7.3890560989306502272304274605750078131803155705521 +B 8 0 9 3 0.029071012968111373091436947845758924691286104110701 0 7.3890560989306502272304274605750078131803155705521 +B 8 0 10 2 0.0068898687862441493280713950396578773745958654867223 0 27.474593022118317968158957115156725710168223409107 +B 8 0 10 4 0.0013299880579155458183786191572270373571509683953068 0 47.560129945305985709087486769738443607156131247662 +B 8 0 10 5 0.00035768887870092628246833234275633810503125743214932 0 47.560129945305985709087486769738443607156131247662 +B 8 0 11 1 0.0062648287334405647419096124212441145946025141981971 0 7.3890560989306502272304274605750078131803155705521 +B 8 0 11 3 0.0032158911747710131228242351857149169370858678118148 0 102.15827997845022478719774797259932200994686828628 +B 8 0 12 1 0.0026254548090098501386234042555622462565547134341105 0 7.3890560989306502272304274605750078131803155705521 +B 8 0 12 3 0.0013477107370847481742223897392529612040925847764877 0 122.24381690163789252812627762718103990693477612483 +B 8 2 8 2 0.29426387682723859793223081297599351903817495847470 0 2.7182818284590452353602874713526624977572470937000 +B 8 2 9 3 0.15405193009446966624274348895902503606319380529182 0 7.3890560989306502272304274605750078131803155705521 +B 8 2 9 6 0.017919247819216431990398034664317229720961247328719 0 7.3890560989306502272304274605750078131803155705521 +B 8 2 9 7 0.013816742688165794783405314250935420281130582304839 0 7.3890560989306502272304274605750078131803155705521 +B 8 2 10 4 0.023021682277311732445611832678163686436383819385911 0 27.474593022118317968158957115156725710168223409107 +B 8 2 10 5 0.0052191847747740239620197664151098343656298122479367 0 27.474593022118317968158957115156725710168223409107 +B 8 2 11 3 0.017041519777473069539019487321413513065132759159386 0 7.3890560989306502272304274605750078131803155705521 +B 8 2 11 6 0.0019822615394779825911486103480609436515162782427485 0 176.84196693478213160623653883004191830972551316345 +B 8 2 11 7 0.0015284345586338523192961722485921375585295140384195 0 196.92750385796979934716506848462363620671342100200 +B 8 2 12 3 0.0071417339493703195935684119579094243516630502738551 0 7.3890560989306502272304274605750078131803155705521 +B 8 2 12 6 0.00083072312316502571118978968002728979490894844169664 0 196.92750385796979934716506848462363620671342100200 +B 8 2 12 7 0.00064053400866368083584768606575638638408932536098874 0 697.71934600893105890558407148347426645603678298274 +B 8 4 8 4 0.42991027170743521544039671171378358359929004551304 0 2.7182818284590452353602874713526624977572470937000 +B 8 4 9 6 0.097137354105737990217609674993112827862402383092255 0 7.3890560989306502272304274605750078131803155705521 +B 8 4 9 7 0.055477048396951892500507494622024124071766482698546 0 7.3890560989306502272304274605750078131803155705521 +B 8 4 9 8 0.024968507837060735884444227432377115251455439086822 0 7.3890560989306502272304274605750078131803155705521 +B 8 4 9 9 0.0056117324260645203694198734241718014014692522570807 0 7.3890560989306502272304274605750078131803155705521 +B 8 4 10 5 0.035538213398479951125280068063180053984966298120001 0 7.3890560989306502272304274605750078131803155705521 +B 8 4 11 6 0.010745520293768556596759673672391201643894108270133 0 27.474593022118317968158957115156725710168223409107 +B 8 4 11 7 0.0061369774262012044580279229604916696012118111542763 0 47.560129945305985709087486769738443607156131247662 +B 8 4 11 8 0.0027620641939268828509717970862461108440991036074858 0 67.645666868493653450016016424320161504144039086217 +B 8 4 11 9 0.00062078059694559177559129604965452537255598562976137 0 87.731203791681321190944546078901879401131946924772 +B 8 4 12 6 0.0045032161501873951154117008781940284824696356925669 0 27.474593022118317968158957115156725710168223409107 +B 8 4 12 7 0.0025718750794255379756296934719752074332794805267779 0 122.24381690163789252812627762718103990693477612483 +B 8 4 12 8 0.0011575216225834032988802861249820577932729616957798 0 271.61119081430170616620385934206623250649206587918 +B 8 4 12 9 0.00026015577966099108516347883721457956245007919957291 0 475.57671476010975888239170225981230350884009267213 +B 8 5 8 5 0.45304730843135427273105215252662343931831720437654 0 2.7182818284590452353602874713526624977572470937000 +B 8 5 9 6 0.18436557065395366357628500807565933511386513721616 0 7.3890560989306502272304274605750078131803155705521 +B 8 5 9 7 0.14270526494516756585918282770457063132322923682245 0 7.3890560989306502272304274605750078131803155705521 +B 8 5 9 8 0.044325283248056951399468581440582429101441625916563 0 7.3890560989306502272304274605750078131803155705521 +B 8 5 9 9 0.0097142375571151575764125938375536108412999172809602 0 7.3890560989306502272304274605750078131803155705521 +B 8 5 11 6 0.020394872798138673694603031504314404169339732325084 0 7.3890560989306502272304274605750078131803155705521 +B 8 5 11 7 0.015786329930571321555871280792414872126657435209227 0 27.474593022118317968158957115156725710168223409107 +B 8 5 11 8 0.0049033477909081739263522981228376963156422215852101 0 47.560129945305985709087486769738443607156131247662 +B 8 5 11 9 0.0010746075777897220474437341491233314655427498340904 0 67.645666868493653450016016424320161504144039086217 +B 8 5 12 6 0.0085470519858267017165434628998116527476567386031124 0 7.3890560989306502272304274605750078131803155705521 +B 8 5 12 7 0.0066157109150648445767614554935928316984665834373233 0 47.560129945305985709087486769738443607156131247662 +B 8 5 12 8 0.0020548874655058155125970934127495360240958441919867 0 142.32935382482556026905480728176275780392268396339 +B 8 5 12 9 0.00045034489416233596050558245148548297326970228028084 0 291.69672773748937390713238899664795040347997371773 +B 9 1 9 1 0.41865381945102072095198187501083658703890757658169 0 2.7182818284590452353602874713526624977572470937000 +B 9 1 10 2 0.065183960572779664376513454478507435874235653136106 0 7.3890560989306502272304274605750078131803155705521 +B 9 1 10 4 0.025796617164523788484628664457049114045854027367030 0 7.3890560989306502272304274605750078131803155705521 +B 9 1 10 5 0.015240003651712530266306213532585900420832963680061 0 7.3890560989306502272304274605750078131803155705521 +B 9 1 11 3 0.036826616768138556192491864948050000628289078721245 0 27.474593022118317968158957115156725710168223409107 +B 9 1 11 6 0.0070060630008059337788578970047020660994255575985079 0 67.645666868493653450016016424320161504144039086217 +B 9 1 12 3 0.0077518081163105323401075028329258566071885989784338 0 27.474593022118317968158957115156725710168223409107 +B 9 1 12 6 0.0014747392185105008583843313937669992987153357267336 0 142.32935382482556026905480728176275780392268396339 +B 9 3 9 3 0.51373244912701364409895109265903112964681656505992 0 2.7182818284590452353602874713526624977572470937000 +B 9 3 10 4 0.15575471342680109194541529156005199170414369288356 0 7.3890560989306502272304274605750078131803155705521 +B 9 3 10 5 0.10377147492189017056110064071885084064082782667695 0 7.3890560989306502272304274605750078131803155705521 +B 9 3 11 6 0.037978738251869001729106237987826574625510595988702 0 47.560129945305985709087486769738443607156131247662 +B 9 3 11 7 0.021690402414714787929629997404782151544376212300756 0 47.560129945305985709087486769738443607156131247662 +B 9 3 11 8 0.0097621809077817389641764102274429777328308038516618 0 47.560129945305985709087486769738443607156131247662 +B 9 3 12 6 0.0079943235970235011732543287174837759644120353511435 0 47.560129945305985709087486769738443607156131247662 +B 9 3 12 7 0.0045657150246258281052863619884130789474851494926666 0 176.84196693478213160623653883004191830972551316345 +B 9 3 12 8 0.0020548874655058155125970934127495360240958441919867 0 306.12380392425827750338559089034539301229489507924 +B 9 6 9 6 0.41213775038950737414254974577697196928775191073136 0 2.7182818284590452353602874713526624977572470937000 +B 9 6 11 7 0.080803433056776142977585130644073529852202254301119 0 7.3890560989306502272304274605750078131803155705521 +B 9 6 11 8 0.037978738251869001729106237987826574625510595988702 0 7.3890560989306502272304274605750078131803155705521 +B 9 6 11 9 0.0097621809077817389641764102274429777328308038516618 0 7.3890560989306502272304274605750078131803155705521 +B 9 6 12 7 0.017008695426433895677677501240758190230064102622798 0 7.3890560989306502272304274605750078131803155705521 +B 9 6 12 8 0.0079943235970235011732543287174837759644120353511435 0 27.474593022118317968158957115156725710168223409107 +B 9 6 12 9 0.0020548874655058155125970934127495360240958441919867 0 47.560129945305985709087486769738443607156131247662 +B 9 7 9 7 0.41213775038950737414254974577697196928775191073136 0 2.7182818284590452353602874713526624977572470937000 +B 9 7 11 8 0.054267074089023215528582478570870997706644979676645 0 7.3890560989306502272304274605750078131803155705521 +B 9 7 11 9 0.021690402414714787929629997404782151544376212300756 0 7.3890560989306502272304274605750078131803155705521 +B 9 7 12 8 0.011422932169421174241222295446554472981338921209620 0 7.3890560989306502272304274605750078131803155705521 +B 9 7 12 9 0.0045657150246258281052863619884130789474851494926666 0 27.474593022118317968158957115156725710168223409107 +B 9 8 9 8 0.30433654511927776802722549064339434302634973909677 0 2.7182818284590452353602874713526624977572470937000 +B 9 8 11 9 0.037978738251869001729106237987826574625510595988702 0 7.3890560989306502272304274605750078131803155705521 +B 9 8 12 9 0.0079943235970235011732543287174837759644120353511435 0 7.3890560989306502272304274605750078131803155705521 +B 9 9 9 9 0.26239545181197259068277852604379775533249274419528 0 2.7182818284590452353602874713526624977572470937000 +B 10 0 10 0 0.070926116176272661720612924710718478195105834923484 0 2.7182818284590452353602874713526624977572470937000 +B 10 0 11 1 0.039192341320324203684356129057906860342577720032800 0 7.3890560989306502272304274605750078131803155705521 +B 10 0 11 3 0.020118395878545474521818637104260048702448769409429 0 7.3890560989306502272304274605750078131803155705521 +B 10 0 12 1 0.015005551255457813216166758576089183707062333601445 0 7.3890560989306502272304274605750078131803155705521 +B 10 0 12 3 0.0077027197243904817624329956173314979254666760882290 0 27.474593022118317968158957115156725710168223409107 +B 10 2 10 2 0.17990039420943700148272755131041771054080274924108 0 2.7182818284590452353602874713526624977572470937000 +B 10 2 11 3 0.10661058556487932754250565439524537331253045565575 0 7.3890560989306502272304274605750078131803155705521 +B 10 2 11 6 0.012400893008723373284901199856191367749130334701261 0 7.3890560989306502272304274605750078131803155705521 +B 10 2 11 7 0.0095617823657342163034961861797968350774277057224601 0 7.3890560989306502272304274605750078131803155705521 +B 10 2 12 3 0.040817939224227349275890658533990683149824814180003 0 7.3890560989306502272304274605750078131803155705521 +B 10 2 12 6 0.0047479234306256990513853931535284770518713891786358 0 27.474593022118317968158957115156725710168223409107 +B 10 2 12 7 0.0036609146213000618657138530297898108248712965277300 0 47.560129945305985709087486769738443607156131247662 +B 10 4 10 4 0.26282881945533682190000074924725539219597730553084 0 2.7182818284590452353602874713526624977572470937000 +B 10 4 11 6 0.067223242156623451650620864373787051484148829886673 0 7.3890560989306502272304274605750078131803155705521 +B 10 4 11 7 0.038392512261178833977058525276791943280788267804567 0 7.3890560989306502272304274605750078131803155705521 +B 10 4 11 8 0.017279285235556317540413623427865516030746140430629 0 7.3890560989306502272304274605750078131803155705521 +B 10 4 11 9 0.0038835610797559023406861588270077697340224477648591 0 7.3890560989306502272304274605750078131803155705521 +B 10 4 12 6 0.025737727621191306874685628307562600974443388588912 0 7.3890560989306502272304274605750078131803155705521 +B 10 4 12 7 0.014699321121245684370199740668676205899657342558321 0 27.474593022118317968158957115156725710168223409107 +B 10 4 12 8 0.0066157109150648445767614554935928316984665834373233 0 47.560129945305985709087486769738443607156131247662 +B 10 4 12 9 0.0014868970026487874943707727823124783708711112259184 0 67.645666868493653450016016424320161504144039086217 +B 10 5 10 5 0.27697381772134882363147131343543532187065470506453 0 2.7182818284590452353602874713526624977572470937000 +B 10 5 11 6 0.12758893337699727784886582726762047341407825405343 0 7.3890560989306502272304274605750078131803155705521 +B 10 5 11 7 0.098758203481552660175303488170625365210717691971320 0 7.3890560989306502272304274605750078131803155705521 +B 10 5 11 8 0.030675009391356732740141088028723262327469833096399 0 7.3890560989306502272304274605750078131803155705521 +B 10 5 11 9 0.0067226717227450593220911725034023024057250767436595 0 7.3890560989306502272304274605750078131803155705521 +B 10 5 12 6 0.048849908296366292985812890953673978804357413483192 0 7.3890560989306502272304274605750078131803155705521 +B 10 5 12 7 0.037811501796420670481327003314787583729571367452602 0 27.474593022118317968158957115156725710168223409107 +B 10 5 12 8 0.011744524827480901659152138204873185026062055648728 0 47.560129945305985709087486769738443607156131247662 +B 10 5 12 9 0.0025739058119744246800423129060511445978712038768242 0 67.645666868493653450016016424320161504144039086217 +B 11 1 11 1 0.41293688481743127002245369280696459174100319568668 0 2.7182818284590452353602874713526624977572470937000 +B 11 1 12 3 0.044112361432511403330173358965630243664463517787169 0 7.3890560989306502272304274605750078131803155705521 +B 11 1 12 6 0.0083921361893303855627204711081381340068229403775310 0 7.3890560989306502272304274605750078131803155705521 +B 11 3 11 3 0.50671716658483070225978364744093712639969809678109 0 2.7182818284590452353602874713526624977572470937000 +B 11 3 12 6 0.045492417592013117365284989968166529861496488006085 0 7.3890560989306502272304274605750078131803155705521 +B 11 3 12 7 0.025981612075816003210939572776658642645077189981306 0 7.3890560989306502272304274605750078131803155705521 +B 11 3 12 8 0.011693521978543596103958417633661798782020959017451 0 7.3890560989306502272304274605750078131803155705521 +B 11 6 11 6 0.40650979605219582341618197464249717806169195135171 0 2.7182818284590452353602874713526624977572470937000 +B 11 6 12 7 0.096789511413171750263623412177034977229821398312691 0 7.3890560989306502272304274605750078131803155705521 +B 11 6 12 8 0.045492417592013117365284989968166529861496488006085 0 7.3890560989306502272304274605750078131803155705521 +B 11 6 12 9 0.011693521978543596103958417633661798782020959017451 0 7.3890560989306502272304274605750078131803155705521 +B 11 7 11 7 0.40650979605219582341618197464249717806169195135171 0 2.7182818284590452353602874713526624977572470937000 +B 11 7 12 8 0.065003223108210231519630407159674417077915786030865 0 7.3890560989306502272304274605750078131803155705521 +B 11 7 12 9 0.025981612075816003210939572776658642645077189981306 0 7.3890560989306502272304274605750078131803155705521 +B 11 8 11 8 0.30018067204653034665965337461259486117244290384573 0 2.7182818284590452353602874713526624977572470937000 +B 11 8 12 9 0.045492417592013117365284989968166529861496488006085 0 7.3890560989306502272304274605750078131803155705521 +B 11 9 11 9 0.25881230608042930580095836186032539910137819680698 0 2.7182818284590452353602874713526624977572470937000 +B 12 1 12 1 0.37972071765696628957177865409888515462882326636653 0 2.7182818284590452353602874713526624977572470937000 +B 12 3 12 3 0.46595742162816408873120075396412087589836608947983 0 2.7182818284590452353602874713526624977572470937000 +B 12 6 12 6 0.37381061650565056542853953599364341235869565836635 0 2.7182818284590452353602874713526624977572470937000 +B 12 7 12 7 0.37381061650565056542853953599364341235869565836635 0 2.7182818284590452353602874713526624977572470937000 +B 12 8 12 8 0.27603448470497908709227700810211260311268533280197 0 2.7182818284590452353602874713526624977572470937000 +B 12 9 12 9 0.23799374242571053294256469729287326924279163875654 0 2.7182818284590452353602874713526624977572470937000 +P 0 10 0 0E+0 +P 0 9 0 0E+0 +P 0 8 0 0E+0 +P 0 7 0 0E+0 +P 0 6 0 0E+0 +P 0 5 1 0E+0 +P 0 4 1 0E+0 +P 0 3 0 0E+0 +P 0 2 1 0E+0 +P 0 1 0 0E+0 +P 0 0 1 1.0981816857509217185963430779588650543172142442905E-2 +P 1 10 0 0E+0 +P 1 9 1 0E+0 +P 1 8 1 0E+0 +P 1 7 1 0E+0 +P 1 6 1 0E+0 +P 1 5 0 0E+0 +P 1 4 0 0E+0 +P 1 3 1 0E+0 +P 1 2 0 0E+0 +P 1 1 1 2.5150136397711549006246480727112924889328760111822E-1 +P 1 0 0 0E+0 +P 2 10 0 0E+0 +P 2 9 0 0E+0 +P 2 8 0 0E+0 +P 2 7 0 0E+0 +P 2 6 0 0E+0 +P 2 5 1 0E+0 +P 2 4 1 0E+0 +P 2 3 0 0E+0 +P 2 2 1 2.5150136397711549006246480727112924889328760111822E-1 +P 2 1 0 0E+0 +P 2 0 1 0E+0 +P 3 10 0 0E+0 +P 3 9 1 0E+0 +P 3 8 1 0E+0 +P 3 7 1 0E+0 +P 3 6 1 0E+0 +P 3 5 0 0E+0 +P 3 4 0 0E+0 +P 3 3 1 2.5150136397711549006246480727112924889328760111822E-1 +P 3 2 0 0E+0 +P 3 1 1 0E+0 +P 3 0 0 0E+0 +P 4 10 0 0E+0 +P 4 9 0 0E+0 +P 4 8 0 0E+0 +P 4 7 0 0E+0 +P 4 6 0 0E+0 +P 4 5 0 0E+0 +P 4 4 1 2.5150136397711549006246480727112924889328760111822E-1 +P 4 3 0 0E+0 +P 4 2 0 0E+0 +P 4 1 0 0E+0 +P 4 0 1 0E+0 +P 5 10 0 0E+0 +P 5 9 0 0E+0 +P 5 8 0 0E+0 +P 5 7 0 0E+0 +P 5 6 0 0E+0 +P 5 5 1 2.5150136397711549006246480727112924889328760111822E-1 +P 5 4 1 0E+0 +P 5 3 0 0E+0 +P 5 2 1 0E+0 +P 5 1 0 0E+0 +P 5 0 1 0E+0 +P 6 10 0 0E+0 +P 6 9 1 0E+0 +P 6 8 1 0E+0 +P 6 7 1 0E+0 +P 6 6 1 2.4051954711960627287650137649154059835011545867532E-1 +P 6 5 0 0E+0 +P 6 4 0 0E+0 +P 6 3 1 0E+0 +P 6 2 0 0E+0 +P 6 1 1 0E+0 +P 6 0 0 0E+0 +P 7 10 0 0E+0 +P 7 9 0 0E+0 +P 7 8 0 0E+0 +P 7 7 0 0E+0 +P 7 6 0 0E+0 +P 7 5 0 0E+0 +P 7 4 1 0E+0 +P 7 3 0 0E+0 +P 7 2 0 0E+0 +P 7 1 0 0E+0 +P 7 0 1 0E+0 +P 8 10 0 0E+0 +P 8 9 0 0E+0 +P 8 8 0 0E+0 +P 8 7 0 0E+0 +P 8 6 0 0E+0 +P 8 5 1 0E+0 +P 8 4 1 0E+0 +P 8 3 0 0E+0 +P 8 2 1 0E+0 +P 8 1 0 0E+0 +P 8 0 1 0E+0 +P 9 10 0 0E+0 +P 9 9 1 0E+0 +P 9 8 1 0E+0 +P 9 7 1 0E+0 +P 9 6 1 0E+0 +P 9 5 0 0E+0 +P 9 4 0 0E+0 +P 9 3 1 0E+0 +P 9 2 0 0E+0 +P 9 1 1 0E+0 +P 9 0 0 0E+0 +P 10 10 0 0E+0 +P 10 9 0 0E+0 +P 10 8 0 0E+0 +P 10 7 0 0E+0 +P 10 6 0 0E+0 +P 10 5 1 0E+0 +P 10 4 1 0E+0 +P 10 3 0 0E+0 +P 10 2 1 0E+0 +P 10 1 0 0E+0 +P 10 0 1 0E+0 +P 11 10 0 0E+0 +P 11 9 1 0E+0 +P 11 8 1 0E+0 +P 11 7 1 0E+0 +P 11 6 1 0E+0 +P 11 5 0 0E+0 +P 11 4 0 0E+0 +P 11 3 1 0E+0 +P 11 2 0 0E+0 +P 11 1 1 0E+0 +P 11 0 0 0E+0 +P 12 10 0 0E+0 +P 12 9 1 0E+0 +P 12 8 1 0E+0 +P 12 7 1 0E+0 +P 12 6 1 0E+0 +P 12 5 0 0E+0 +P 12 4 0 0E+0 +P 12 3 1 0E+0 +P 12 2 0 0E+0 +P 12 1 1 0E+0 +P 12 0 0 0E+0 +END +CASE random07 14 12 7 +Z 1.1005735584612756575783984806581962556404642459653E-1 +S 8 0 6 +B 0 1 0 1 0.28787207124492078972027134949890465179142467604531 0 2.7182818284590452353602874713526624977572470937000 +B 0 1 1 4 0.010287353917632803474997973338684448901847326234077 0 7.3890560989306502272304274605750078131803155705521 +B 0 1 1 7 0.0026214932884024457366620019893298472816561111576930 0 7.3890560989306502272304274605750078131803155705521 +B 0 1 2 2 0.029534581420289705891794767982719417043698612070614 0 7.3890560989306502272304274605750078131803155705521 +B 0 1 2 5 0.0040170315884195951750837270070215176099629934351512 0 27.474593022118317968158957115156725710168223409107 +B 0 1 3 2 0.016983576103595267733735356778379507902851971139091 0 7.3890560989306502272304274605750078131803155705521 +B 0 1 3 5 0.0023099552596198998304264358190189811819490389360955 0 47.560129945305985709087486769738443607156131247662 +B 0 1 3 6 0.0017811047520151427806254120018830462204546725418322 0 122.24381690163789252812627762718103990693477612483 +B 0 1 4 4 0.0016746444785290838109931241646192086417092650356364 0 47.560129945305985709087486769738443607156131247662 +B 0 1 4 7 0.00042674426252600380928982714781560755887036889053714 0 603.90433693949869456257875264578286523533985242747 +B 0 1 5 4 0.00087837101606835309988102348313458593089921752917721 0 47.560129945305985709087486769738443607156131247662 +B 0 1 5 7 0.00022383245893811728508678024261944341721731871497476 0 733.18617392897484045972780470608633993790923434326 +B 0 1 6 3 0.0013253935264534320619722720610317978051918826703252 0 47.560129945305985709087486769738443607156131247662 +B 0 1 6 4 0.00025054900983013057028847221879289676140447419979848 0 47.560129945305985709087486769738443607156131247662 +B 0 1 6 7 0.000063846597768914237508574036897839039581500210285449 0 862.46801091845098635687685676638981464047861625905 +B 0 3 0 3 0.41113017732442481860982064223758401612400696922743 0 2.7182818284590452353602874713526624977572470937000 +B 0 3 1 4 0.068580529989743774680728280570708206155975477675479 0 7.3890560989306502272304274605750078131803155705521 +B 0 3 1 7 0.011663916015001750571540502878170921444825857376544 0 7.3890560989306502272304274605750078131803155705521 +B 0 3 2 5 0.021071403037996587244308891173405531352105192452063 0 27.474593022118317968158957115156725710168223409107 +B 0 3 2 8 0.0021776806436314998312305625199586284518701545564168 0 47.560129945305985709087486769738443607156131247662 +B 0 3 3 5 0.012116907025453730879232087818450988190599575492067 0 27.474593022118317968158957115156725710168223409107 +B 0 3 3 6 0.011588056517848973829431064001315053229105209097803 0 102.15827997845022478719774797259932200994686828628 +B 0 3 3 8 0.0012522542444103857308243881847471112589603061475688 0 122.24381690163789252812627762718103990693477612483 +B 0 3 3 9 0.0012522542444103857308243881847471112589603061475688 0 251.52565389111403842527532968748451460950415804062 +B 0 3 4 4 0.011163998711570529501722107295443517323227784851601 0 7.3890560989306502272304274605750078131803155705521 +B 0 3 4 7 0.0018987304907503662623968678466908383195266452106253 0 454.53696302683488092450117093089767263578256267313 +B 0 3 5 4 0.0058556505678633127495375444498334391441615225091760 0 7.3890560989306502272304274605750078131803155705521 +B 0 3 5 7 0.00099590680397146585516395111951777917419401758574162 0 474.62249995002254866542970058547939053277047051169 +B 0 3 6 4 0.0016702821755849305457807080193925488125077209821747 0 7.3890560989306502272304274605750078131803155705521 +B 0 3 6 7 0.00028407524730839171231336622218020266077362070232964 0 494.70803687321021640635823024006110842975837835024 +B 0 4 0 4 0.27017387191398526623675453454172319148767967464155 0 2.7182818284590452353602874713526624977572470937000 +B 0 4 1 7 0.023999365996277591937545526143837118556021938506957 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 1 10 0.00070502813109485630207800915199119687660830738859689 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 2 5 0.026990952759767091087523360295564283921015887391246 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 2 8 0.0021776806436314998312305625199586284518701545564168 0 27.474593022118317968158957115156725710168223409107 +B 0 4 3 5 0.015520886982645194330158806149723152390078125345683 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 3 6 0.014992036475040437280357782332587217428583758951420 0 27.474593022118317968158957115156725710168223409107 +B 0 4 3 8 0.0012522542444103857308243881847471112589603061475688 0 47.560129945305985709087486769738443607156131247662 +B 0 4 3 9 0.0012522542444103857308243881847471112589603061475688 0 122.24381690163789252812627762718103990693477612483 +B 0 4 4 7 0.0039067777851967811673334764818385990287100257419770 0 122.24381690163789252812627762718103990693477612483 +B 0 4 4 10 0.00011476920852523380886400289361470728816064485426232 0 678.58802389583060138161754350322546153511849730464 +B 0 4 5 7 0.0020491515761904861342226104429280938028859912166235 0 122.24381690163789252812627762718103990693477612483 +B 0 4 5 10 0.000060197819655558331388219432490657788796844011424152 0 1010.8811700210275897779924368069420942639662838529 +B 0 4 6 7 0.00058450573734143441233802695632363661179063119428323 0 122.24381690163789252812627762718103990693477612483 +B 0 4 6 10 0.000017170994753610154313599491424074609125756712907190 0 1343.1743161462245781743673301106587269928140704012 +B 0 7 0 7 0.29886730264461325030958744208802836560853266212940 0 2.7182818284590452353602874713526624977572470937000 +B 0 7 1 10 0.0064544236030176246058299876640071480917517186958852 0 7.3890560989306502272304274605750078131803155705521 +B 0 7 2 8 0.027695230475501610547941603495656527885605773191880 0 7.3890560989306502272304274605750078131803155705521 +B 0 7 3 8 0.015925875088385753634133309144107637979863238350564 0 7.3890560989306502272304274605750078131803155705521 +B 0 7 3 9 0.012521895131194290183206590812835473780384688496948 0 27.474593022118317968158957115156725710168223409107 +B 0 7 3 11 0.0012522542444103857308243881847471112589603061475688 0 47.560129945305985709087486769738443607156131247662 +B 0 7 4 10 0.0010506943705275438101414756562174081002898169630868 0 122.24381690163789252812627762718103990693477612483 +B 0 7 5 10 0.00055110173750323519248390186287701467405826812207598 0 122.24381690163789252812627762718103990693477612483 +B 0 7 6 10 0.00015719780379952240389852312784536790049298720504197 0 122.24381690163789252812627762718103990693477612483 +B 0 10 0 10 0.13592053443478877675788914921392011333798939537533 0 2.7182818284590452353602874713526624977572470937000 +B 0 10 3 11 0.0073004867396256344307562256016989502659106879725027 0 7.3890560989306502272304274605750078131803155705521 +B 1 4 1 4 0.34835680034766501355734813390623980763178210194426 0 2.7182818284590452353602874713526624977572470937000 +B 1 4 2 5 0.12276508442622560213436889346748117649982960243600 0 7.3890560989306502272304274605750078131803155705521 +B 1 4 2 8 0.0099049170456584256150755267461028130332982227480385 0 7.3890560989306502272304274605750078131803155705521 +B 1 4 3 5 0.028573475737949122413453587233789115852926152995131 0 7.3890560989306502272304274605750078131803155705521 +B 1 4 3 6 0.027599878213210800482440545398148028738958288864820 0 27.474593022118317968158957115156725710168223409107 +B 1 4 3 8 0.0023053615628032772252259953635375406463448485205334 0 27.474593022118317968158957115156725710168223409107 +B 1 4 3 9 0.0023053615628032772252259953635375406463448485205334 0 47.560129945305985709087486769738443607156131247662 +B 1 4 4 7 0.0068914243185609776969461888312384737712235562284028 0 122.24381690163789252812627762718103990693477612483 +B 1 4 4 10 0.00020244901505524302550314946612552640487963070450215 0 346.29487777063361298524265019950882880627071075635 +B 1 4 5 7 0.0046408177393974393526090402400219205106708472000359 0 122.24381690163789252812627762718103990693477612483 +B 1 4 5 10 0.00013633306221784024762620248494401058582311631734276 0 678.58802389583060138161754350322546153511849730464 +B 1 4 6 7 0.0029796817154697659751113154772644393022111499261890 0 122.24381690163789252812627762718103990693477612483 +B 1 4 6 10 0.000087533955332028420351000783848694246305672246665189 0 1010.8811700210275897779924368069420942639662838529 +B 1 4 7 5 0.0024602501182057279512389655481052560943535590198154 0 7.3890560989306502272304274605750078131803155705521 +B 1 4 7 6 0.0023764208547556040416197320631856650597269406237248 0 47.560129945305985709087486769738443607156131247662 +B 1 4 7 8 0.00019849758949209301803345713694227490713340762270913 0 1119.1232552772288577172509575383309380934781357697 +B 1 4 7 9 0.00019849758949209301803345713694227490713340762270913 0 1213.8924791567484322772182780503552522902446884854 +B 1 7 1 7 0.38535353748404211297178706570270347661564044486368 0 2.7182818284590452353602874713526624977572470937000 +B 1 7 2 8 0.12596840644309551269338783323163118288340451393679 0 7.3890560989306502272304274605750078131803155705521 +B 1 7 3 8 0.029319046389064298932714786757045236848260188039077 0 7.3890560989306502272304274605750078131803155705521 +B 1 7 3 9 0.023052423944868204471349109826488856354765285224596 0 27.474593022118317968158957115156725710168223409107 +B 1 7 3 11 0.0023053615628032772252259953635375406463448485205334 0 27.474593022118317968158957115156725710168223409107 +B 1 7 4 10 0.0018533894514975393898434819667451709353885773936017 0 122.24381690163789252812627762718103990693477612483 +B 1 7 5 10 0.0012481081191526349431137131150960308564907606286142 0 122.24381690163789252812627762718103990693477612483 +B 1 7 6 10 0.00080135983578862423999223685091001075659234574959176 0 122.24381690163789252812627762718103990693477612483 +B 1 7 7 8 0.0025244456784294591304434056910207608084039610237214 0 7.3890560989306502272304274605750078131803155705521 +B 1 7 7 9 0.0019848732879201795571505352949609348503996318715136 0 47.560129945305985709087486769738443607156131247662 +B 1 7 7 11 0.00019849758949209301803345713694227490713340762270913 0 1119.1232552772288577172509575383309380934781357697 +B 1 10 1 10 0.17525322542041371387671569767171919209989707742101 0 2.7182818284590452353602874713526624977572470937000 +B 1 10 3 11 0.013439971630690981341656881472299356709679071986566 0 7.3890560989306502272304274605750078131803155705521 +B 1 10 7 11 0.0011572162972519921394224949576000560382708287553703 0 7.3890560989306502272304274605750078131803155705521 +B 2 2 2 2 0.31721481351967889514050820887518694225007701167454 0 2.7182818284590452353602874713526624977572470937000 +B 2 2 3 5 0.013400485231136175438769461377613526720273138503508 0 7.3890560989306502272304274605750078131803155705521 +B 2 2 3 6 0.011743273015809120012245964175262087221238708239022 0 7.3890560989306502272304274605750078131803155705521 +B 2 2 3 8 0.0022668665190040605185811093493655790213234057126708 0 7.3890560989306502272304274605750078131803155705521 +B 2 2 4 4 0.020405911485139318206172792279031209665001765882510 0 7.3890560989306502272304274605750078131803155705521 +B 2 2 4 7 0.0049518740225321634904023129109951873361083678626186 0 47.560129945305985709087486769738443607156131247662 +B 2 2 5 4 0.016310204873818347387953068589822828584816594014751 0 7.3890560989306502272304274605750078131803155705521 +B 2 2 5 7 0.0039579746229741689976586776522666590516834206480795 0 67.645666868493653450016016424320161504144039086217 +B 2 2 6 3 0.027705140265838097159824708722030997624379929860296 0 7.3890560989306502272304274605750078131803155705521 +B 2 2 6 4 0.013201095313148235635509726351030647993922653923479 0 7.3890560989306502272304274605750078131803155705521 +B 2 2 6 7 0.0032034913509134796371530243691657145486400423559201 0 87.731203791681321190944546078901879401131946924772 +B 2 2 7 5 0.0014055953669469972871921406098928681350167726702346 0 87.731203791681321190944546078901879401131946924772 +B 2 2 7 6 0.0012317680934017556366125506563730771698861454134430 0 107.81674071486898893187307573348359729811985476333 +B 2 2 7 8 0.00023777475379742058853794323200965342036598309472089 0 679.54223870591781159857954517755837451118811946510 +B 2 2 8 5 0.00020387340681482648709349767331913233094873070242022 0 87.731203791681321190944546078901879401131946924772 +B 2 2 8 6 0.00017866077500886414221094347758264778250160304047850 0 346.29487777063361298524265019950882880627071075635 +B 2 2 8 8 0.000034487840705201104915344771510274088664827029389006 0 1211.0966628505912987834289553124697159302805684898 +B 2 5 2 5 0.34827281410972790226471604753697180764402930269888 0 2.7182818284590452353602874713526624977572470937000 +B 2 5 3 6 0.076131921207398299813260315718970085924532422325098 0 7.3890560989306502272304274605750078131803155705521 +B 2 5 3 8 0.017905255081960068652863824596455716423085150236401 0 7.3890560989306502272304274605750078131803155705521 +B 2 5 3 9 0.0072385031649852267981516009564198975184266965061280 0 7.3890560989306502272304274605750078131803155705521 +B 2 5 3 11 0.0022668665190040605185811093493655790213234057126708 0 7.3890560989306502272304274605750078131803155705521 +B 2 5 4 7 0.026672533929335412667538469209587590158496668696992 0 27.474593022118317968158957115156725710168223409107 +B 2 5 4 10 0.0023053615628032772252259953635375406463448485205334 0 67.645666868493653450016016424320161504144039086217 +B 2 5 5 7 0.021319042435724921653174870124935914893595424286450 0 27.474593022118317968158957115156725710168223409107 +B 2 5 5 10 0.0018426483631927201750229081959317820498899243161095 0 142.32935382482556026905480728176275780392268396339 +B 2 5 6 7 0.017255130352827415274853578574406288222210077294708 0 27.474593022118317968158957115156725710168223409107 +B 2 5 6 10 0.0014913961448866226040925978466635032659476248078230 0 217.01304078115746708809359813920535410370132884056 +B 2 5 7 6 0.0079855821546858923464146475997464769484105491180581 0 7.3890560989306502272304274605750078131803155705521 +B 2 5 7 8 0.0018781068859156073835279781736969189891450532185822 0 251.52565389111403842527532968748451460950415804062 +B 2 5 7 9 0.00075925657443314554027671309256902631575786486509551 0 271.61119081430170616620385934206623250649206587918 +B 2 5 7 11 0.00023777475379742058853794323200965342036598309472089 0 1452.3706162125130563305878525163804837983955444785 +B 2 5 8 6 0.0011582620984385235389523600502663387387442185997151 0 7.3890560989306502272304274605750078131803155705521 +B 2 5 8 8 0.00027240844570060248974143379218205237944412372768453 0 271.61119081430170616620385934206623250649206587918 +B 2 5 8 9 0.00011012573612308813956300735871972773400621001521419 0 975.41434210098380822384870358433002078209383249242 +B 2 5 8 11 0.000034487840705201104915344771510274088664827029389006 0 2894.4895318958338317830592725491872208554019069050 +B 2 8 2 8 0.29249034760996381347681676171278741446381277417650 0 2.7182818284590452353602874713526624977572470937000 +B 2 8 3 9 0.062229474965186491498236216358950431540753395421982 0 7.3890560989306502272304274605750078131803155705521 +B 2 8 3 11 0.011743273015809120012245964175262087221238708239022 0 7.3890560989306502272304274605750078131803155705521 +B 2 8 4 10 0.014139289040943223744807115348474829171506863068031 0 27.474593022118317968158957115156725710168223409107 +B 2 8 5 10 0.011301367311911773122731267054709742276037763743052 0 27.474593022118317968158957115156725710168223409107 +B 2 8 6 10 0.0091470602734690559961658741276550077656352305522511 0 27.474593022118317968158957115156725710168223409107 +B 2 8 7 9 0.0065273354053906964071126284517282806478244338893205 0 7.3890560989306502272304274605750078131803155705521 +B 2 8 7 11 0.0012317680934017556366125506563730771698861454134430 0 251.52565389111403842527532968748451460950415804062 +B 2 8 8 9 0.00094675191581662223533769372176783550964290623950756 0 7.3890560989306502272304274605750078131803155705521 +B 2 8 8 11 0.00017866077500886414221094347758264778250160304047850 0 271.61119081430170616620385934206623250649206587918 +B 3 0 3 0 0.17258650495914689625426572123874791215589906247585 0 2.7182818284590452353602874713526624977572470937000 +B 3 0 4 4 0.011997918809232958832350254865320720371226791050124 0 7.3890560989306502272304274605750078131803155705521 +B 3 0 5 4 0.010175739230318596539936789668063532149778015410555 0 7.3890560989306502272304274605750078131803155705521 +B 3 0 6 1 0.022017602759543309011086856550066898917842620524090 0 7.3890560989306502272304274605750078131803155705521 +B 3 0 6 3 0.011320278413092031990802422054884608004838724428130 0 7.3890560989306502272304274605750078131803155705521 +B 3 0 6 4 0.0032297443105943604564945670825419377957755445681689 0 7.3890560989306502272304274605750078131803155705521 +B 3 0 7 2 0.0051470412261804911712394536620239055373644669761487 0 27.474593022118317968158957115156725710168223409107 +B 3 0 7 5 0.00095182375437734303079972745060367730794329565561531 0 107.81674071486898893187307573348359729811985476333 +B 3 0 7 6 0.00054985069028145528941354672780257710672956275863961 0 107.81674071486898893187307573348359729811985476333 +B 3 0 8 2 0.0019509400394401405106855927659814272528674585946029 0 27.474593022118317968158957115156725710168223409107 +B 3 0 8 5 0.00036078029906960736821188357040459955257132133517946 0 182.50042767120089575091186659092619359789849964050 +B 3 0 8 6 0.00020841599673370745594471396662208846944930991382445 0 475.57671476010975888239170225981230350884009267213 +B 3 0 9 1 0.0021523798254394210395899988610296091068954018318933 0 7.3890560989306502272304274605750078131803155705521 +B 3 0 9 3 0.0011066390442590611128583831623565791286191065996852 0 176.84196693478213160623653883004191830972551316345 +B 3 0 9 4 0.00031573085278041614750681571530848787949238909100709 0 196.92750385796979934716506848462363620671342100200 +B 3 2 3 2 0.24863500742224039581367051387457547438719243613021 0 2.7182818284590452353602874713526624977572470937000 +B 3 2 4 4 0.074666521505962468923286140649694188187536059391991 0 7.3890560989306502272304274605750078131803155705521 +B 3 2 4 7 0.018119220426271016307016868597116004639020384696962 0 7.3890560989306502272304274605750078131803155705521 +B 3 2 5 4 0.063326570562801095997664874085466996275044226106916 0 7.3890560989306502272304274605750078131803155705521 +B 3 2 5 7 0.015367370378645146866132635755265363304085609960794 0 27.474593022118317968158957115156725710168223409107 +B 3 2 6 3 0.042183103543612187787826043827719863046215465768048 0 7.3890560989306502272304274605750078131803155705521 +B 3 2 6 4 0.020099633683149668636183725932291279717054788932111 0 7.3890560989306502272304274605750078131803155705521 +B 3 2 6 7 0.0048775500163511457550195812964937488993223450081770 0 47.560129945305985709087486769738443607156131247662 +B 3 2 7 5 0.0032504190223268609717126809177143415232607477643697 0 87.731203791681321190944546078901879401131946924772 +B 3 2 7 6 0.0028484459582309732303265001949132413220470148673941 0 87.731203791681321190944546078901879401131946924772 +B 3 2 7 8 0.00054985069028145528941354672780257710672956275863961 0 311.78226466067704164806091865122966830046788155628 +B 3 2 8 5 0.0012320423204228238955823229700842689442803956755686 0 87.731203791681321190944546078901879401131946924772 +B 3 2 8 6 0.0010796780180869239833151533663017578611583842542137 0 326.20934084744594524431412054492711090928280291780 +B 3 2 8 8 0.00020841599673370745594471396662208846944930991382445 0 788.73853877220628975480006758328013131676959354234 +B 3 2 9 3 0.0041237032947349024643113172516029894048274872710155 0 7.3890560989306502272304274605750078131803155705521 +B 3 2 9 4 0.0019648844840559443445290182318307999130103604574812 0 27.474593022118317968158957115156725710168223409107 +B 3 2 9 7 0.00047681577179039276135637365233402201169944612733108 0 1689.8945384581904701669954253080728023304767783111 +B 3 5 3 5 0.27297846768358701504131828668295713944235550343696 0 2.7182818284590452353602874713526624977572470937000 +B 3 5 4 7 0.097596489610551658111820307155083772215570346721562 0 7.3890560989306502272304274605750078131803155705521 +B 3 5 4 10 0.0084354638523952674192832751847210485404110910381601 0 7.3890560989306502272304274605750078131803155705521 +B 3 5 5 7 0.082774058056404112592306184253668761368235494522448 0 7.3890560989306502272304274605750078131803155705521 +B 3 5 5 10 0.0071543308313352912258535836701308312215859889722030 0 27.474593022118317968158957115156725710168223409107 +B 3 5 6 7 0.026272198709253699795588450286858330725330137200094 0 7.3890560989306502272304274605750078131803155705521 +B 3 5 6 10 0.0022707597723975402690430017736541281953816287721798 0 47.560129945305985709087486769738443607156131247662 +B 3 5 7 6 0.018466543608722440366473821694297468964090575686445 0 7.3890560989306502272304274605750078131803155705521 +B 3 5 7 8 0.0043430950979887156884670922164217051349370011821973 0 67.645666868493653450016016424320161504144039086217 +B 3 5 7 9 0.0017557698825691185135720888962058777103707614495665 0 67.645666868493653450016016424320161504144039086217 +B 3 5 7 11 0.00054985069028145528941354672780257710672956275863961 0 291.69672773748937390713238899664795040347997371773 +B 3 5 8 6 0.0069995785409822692479518212566682337328936592489788 0 7.3890560989306502272304274605750078131803155705521 +B 3 5 8 8 0.0016462114347683406861512535584164050866234357518929 0 87.731203791681321190944546078901879401131946924772 +B 3 5 8 9 0.00066550890374140719274622277796962171881534417788948 0 271.61119081430170616620385934206623250649206587918 +B 3 5 8 11 0.00020841599673370745594471396662208846944930991382445 0 679.54223870591781159857954517755837451118811946510 +B 3 5 9 7 0.0025682973341511126148196050496800819682520365917474 0 47.560129945305985709087486769738443607156131247662 +B 3 5 9 10 0.00022198318208867779997632540070908328254986840380107 0 1452.3706162125130563305878525163804837983955444785 +B 3 6 3 6 0.32069231647327487890372796356512669800804268205624 0 2.7182818284590452353602874713526624977572470937000 +B 3 6 4 7 0.13377266924585428760115504675346798417302962772190 0 7.3890560989306502272304274605750078131803155705521 +B 3 6 4 10 0.011997918809232958832350254865320720371226791050124 0 7.3890560989306502272304274605750078131803155705521 +B 3 6 5 7 0.11345599349630029014130975250493775947211841036492 0 7.3890560989306502272304274605750078131803155705521 +B 3 6 5 10 0.010175739230318596539936789668063532149778015410555 0 27.474593022118317968158957115156725710168223409107 +B 3 6 6 7 0.036010538517508156628421319473152812037940117500064 0 7.3890560989306502272304274605750078131803155705521 +B 3 6 6 10 0.0032297443105943604564945670825419377957755445681689 0 47.560129945305985709087486769738443607156131247662 +B 3 6 7 8 0.0084250694531660553215026875581459963723932272296310 0 67.645666868493653450016016424320161504144039086217 +B 3 6 7 9 0.0058377442377464581466076842379301689478269874970004 0 67.645666868493653450016016424320161504144039086217 +B 3 6 7 11 0.00095182375437734303079972745060367730794329565561531 0 291.69672773748937390713238899664795040347997371773 +B 3 6 8 8 0.0031934473824766908823923845309778356798965788235755 0 67.645666868493653450016016424320161504144039086217 +B 3 6 8 9 0.0022127448514497573889873537505310523120884872495722 0 251.52565389111403842527532968748451460950415804062 +B 3 6 8 11 0.00036078029906960736821188357040459955257132133517946 0 659.45670178273014385765101552297665661420021162654 +B 3 6 9 7 0.0035202904446397341940207304337537073495858111367495 0 7.3890560989306502272304274605750078131803155705521 +B 3 6 9 10 0.00031573085278041614750681571530848787949238909100709 0 1303.0032422998492426925102708014952911988382547241 +B 3 8 3 8 0.22925581230595816764825595274606391948711145254599 0 2.7182818284590452353602874713526624977572470937000 +B 3 8 4 10 0.051736553401373279734751974144304604159501772062423 0 7.3890560989306502272304274605750078131803155705521 +B 3 8 5 10 0.043879083069198079403023563917265231181852957691384 0 7.3890560989306502272304274605750078131803155705521 +B 3 8 6 10 0.013927068657045637476779001577724228708779440664128 0 7.3890560989306502272304274605750078131803155705521 +B 3 8 7 9 0.015094369023762992129433286220086115034415693009696 0 7.3890560989306502272304274605750078131803155705521 +B 3 8 7 11 0.0028484459582309732303265001949132413220470148673941 0 67.645666868493653450016016424320161504144039086217 +B 3 8 8 9 0.0057213858612119745720385462839860496409778134692616 0 7.3890560989306502272304274605750078131803155705521 +B 3 8 8 11 0.0010796780180869239833151533663017578611583842542137 0 87.731203791681321190944546078901879401131946924772 +B 3 8 9 10 0.0013614716339607760742384314139815178577686843232152 0 47.560129945305985709087486769738443607156131247662 +B 3 9 3 9 0.33485964330997769675222552144195569984084577957377 0 2.7182818284590452353602874713526624977572470937000 +B 3 9 4 10 0.072107674845762102861686506598498575750558165757118 0 7.3890560989306502272304274605750078131803155705521 +B 3 9 5 10 0.061156347813457850985552233996197866048928657995030 0 7.3890560989306502272304274605750078131803155705521 +B 3 9 6 10 0.019410812515589703525110277027227278213901904288092 0 7.3890560989306502272304274605750078131803155705521 +B 3 9 7 11 0.0051470412261804911712394536620239055373644669761487 0 67.645666868493653450016016424320161504144039086217 +B 3 9 8 11 0.0019509400394401405106855927659814272528674585946029 0 67.645666868493653450016016424320161504144039086217 +B 3 9 9 10 0.0018975472357377060782099506094046703777458241083634 0 7.3890560989306502272304274605750078131803155705521 +B 3 11 3 11 0.30131312135699265073831340243661514310796169847203 0 2.7182818284590452353602874713526624977572470937000 +B 4 4 4 4 0.39245482389313331185439465295841062700329170772577 0 2.7182818284590452353602874713526624977572470937000 +B 4 4 5 7 0.089933761114754616424631654351049852959758998788484 0 7.3890560989306502272304274605750078131803155705521 +B 4 4 5 10 0.0026419794394110758308738395177038813707302718918188 0 7.3890560989306502272304274605750078131803155705521 +B 4 4 6 7 0.021513844220185642375126215488947745272393176195361 0 7.3890560989306502272304274605750078131803155705521 +B 4 4 6 10 0.00063201108669187189310089418564719429201351429616443 0 27.474593022118317968158957115156725710168223409107 +B 4 4 7 5 0.028935870261180911795282233685571600073332685817482 0 7.3890560989306502272304274605750078131803155705521 +B 4 4 7 6 0.027949924696811954478287438580628969205478047676021 0 7.3890560989306502272304274605750078131803155705521 +B 4 4 7 8 0.0023346002319834289660407181954435842926189757542381 0 47.560129945305985709087486769738443607156131247662 +B 4 4 7 9 0.0023346002319834289660407181954435842926189757542381 0 47.560129945305985709087486769738443607156131247662 +B 4 4 8 5 0.017725264528651818715155003986902881499676692275801 0 7.3890560989306502272304274605750078131803155705521 +B 4 4 8 6 0.017121303224514513926924872541631215895646515617283 0 27.474593022118317968158957115156725710168223409107 +B 4 4 8 8 0.0014301075553298167773361467744364613219179329761234 0 87.731203791681321190944546078901879401131946924772 +B 4 4 8 9 0.0014301075553298167773361467744364613219179329761234 0 217.01304078115746708809359813920535410370132884056 +B 4 4 9 7 0.0034415127155571412468891239646704262790474463871942 0 142.32935382482556026905480728176275780392268396339 +B 4 4 9 10 0.00010110114068699876438261221793568905940623073664181 0 1269.4448439999798815722905409275490436691050476845 +B 4 4 10 5 0.0078961460632038518874034378272820965929147243149443 0 7.3890560989306502272304274605750078131803155705521 +B 4 4 10 8 0.00063707585998066406790435217176681816372951489414601 0 569.39172382954212322539702109750370472953702322740 +B 4 7 4 7 0.43413492872526722044131030827932170022329449564019 0 2.7182818284590452353602874713526624977572470937000 +B 4 7 5 10 0.024186913543351703410601410456324446092234036535550 0 7.3890560989306502272304274605750078131803155705521 +B 4 7 6 10 0.0057859638437093809341835960379824474991851416657967 0 7.3890560989306502272304274605750078131803155705521 +B 4 7 7 8 0.029690896909988649473951621440392305910598060859690 0 7.3890560989306502272304274605750078131803155705521 +B 4 7 7 9 0.023344795522671823005471293181626440940030608654057 0 7.3890560989306502272304274605750078131803155705521 +B 4 7 7 11 0.0023346002319834289660407181954435842926189757542381 0 47.560129945305985709087486769738443607156131247662 +B 4 7 8 8 0.018187771685184544560713494082670910458714233364569 0 7.3890560989306502272304274605750078131803155705521 +B 4 7 8 9 0.014300336304789515008984222978248130976530246596716 0 27.474593022118317968158957115156725710168223409107 +B 4 7 8 11 0.0014301075553298167773361467744364613219179329761234 0 87.731203791681321190944546078901879401131946924772 +B 4 7 9 10 0.00092556532138484928638730816220091005902277814932887 0 142.32935382482556026905480728176275780392268396339 +B 4 7 10 8 0.0081021810172862699364828794163616675692152475144901 0 7.3890560989306502272304274605750078131803155705521 +B 4 10 4 10 0.19743829789006464000837338728139373675689751865692 0 2.7182818284590452353602874713526624977572470937000 +B 4 10 7 11 0.013610429441145042019495021978922603602459618667174 0 7.3890560989306502272304274605750078131803155705521 +B 4 10 8 11 0.0083373494564113702702160751052175688242528030365627 0 7.3890560989306502272304274605750078131803155705521 +B 5 4 5 4 0.50561165838015400492810092053499836996424575641445 0 2.7182818284590452353602874713526624977572470937000 +B 5 4 6 7 0.080811935140666440236566155845209972421127577545818 0 7.3890560989306502272304274605750078131803155705521 +B 5 4 6 10 0.0023740080305129656516232180259328100726260902553717 0 7.3890560989306502272304274605750078131803155705521 +B 5 4 7 5 0.081172543411961831859005527057926893419518085420935 0 7.3890560989306502272304274605750078131803155705521 +B 5 4 7 6 0.078406713029008483810414927822727596307007445445324 0 7.3890560989306502272304274605750078131803155705521 +B 5 4 7 8 0.0065491529015625700883681075163534272188864450973905 0 27.474593022118317968158957115156725710168223409107 +B 5 4 7 9 0.0065491529015625700883681075163534272188864450973905 0 27.474593022118317968158957115156725710168223409107 +B 5 4 8 5 0.018355167205611950069846034403409711510241532278453 0 7.3890560989306502272304274605750078131803155705521 +B 5 4 8 6 0.017729742930265303543303482608400766024202739784500 0 27.474593022118317968158957115156725710168223409107 +B 5 4 8 8 0.0014809292836028716482417963895613061548432219924564 0 67.645666868493653450016016424320161504144039086217 +B 5 4 8 9 0.0014809292836028716482417963895613061548432219924564 0 142.32935382482556026905480728176275780392268396339 +B 5 4 9 7 0.0037102876001181595117203352056855750113456884904703 0 142.32935382482556026905480728176275780392268396339 +B 5 4 9 10 0.00010899692654137015866342113358597412831428808210172 0 882.55354784163865409780538642097153253746652409761 +B 5 4 10 5 0.0085260487401639832420944682437889266034795643175974 0 7.3890560989306502272304274605750078131803155705521 +B 5 4 10 8 0.00068789758825371893881000178689166299665480391047897 0 549.30618690635445548446849144292198683254911538885 +B 5 4 11 7 0.0014427511771383176440086620257978573961818850520794 0 162.41489074801322800998333693634447570091059180195 +B 5 4 11 10 0.000042383626559572499196153687160559157572884374848920 0 2782.6994070508387912367742482000274276031635209199 +B 5 7 5 7 0.55930942342883231672274139141717600777451960983724 0 2.7182818284590452353602874713526624977572470937000 +B 5 7 6 10 0.021733676700390689024552045329400598418531347896607 0 7.3890560989306502272304274605750078131803155705521 +B 5 7 7 8 0.083290586963938724230732027699866316091215315403150 0 7.3890560989306502272304274605750078131803155705521 +B 5 7 7 9 0.065488143639821359719436347271587742429388417814519 0 7.3890560989306502272304274605750078131803155705521 +B 5 7 7 11 0.0065491529015625700883681075163534272188864450973905 0 27.474593022118317968158957115156725710168223409107 +B 5 7 8 8 0.018834110477698396307628921599994752277973141169708 0 7.3890560989306502272304274605750078131803155705521 +B 5 7 8 9 0.014808527316847838406053416194890863490210057622372 0 27.474593022118317968158957115156725710168223409107 +B 5 7 8 11 0.0014809292836028716482417963895613061548432219924564 0 67.645666868493653450016016424320161504144039086217 +B 5 7 9 10 0.00099785002086724589560537812706303477395668300109839 0 142.32935382482556026905480728176275780392268396339 +B 5 7 10 8 0.0087485198098001216833983069336855093884741553196296 0 7.3890560989306502272304274605750078131803155705521 +B 5 7 11 10 0.00038801555226281275672488568017061259442629394277659 0 162.41489074801322800998333693634447570091059180195 +B 5 10 5 10 0.25436585091162920727703149605910911940553161133544 0 2.7182818284590452353602874713526624977572470937000 +B 5 10 7 11 0.038180748140446674842616784120628486443266542564084 0 7.3890560989306502272304274605750078131803155705521 +B 5 10 8 11 0.0086336338211866621825300607697099223728002680095612 0 7.3890560989306502272304274605750078131803155705521 +B 6 1 6 1 0.38539354268831773478837074109149968779780706941187 0 2.7182818284590452353602874713526624977572470937000 +B 6 1 7 2 0.14785532322492902754447732139949853859932010303048 0 7.3890560989306502272304274605750078131803155705521 +B 6 1 7 5 0.020109968563918903732448351819800135588636775783598 0 7.3890560989306502272304274605750078131803155705521 +B 6 1 7 6 0.015505910957758071646495041478872257519684893501812 0 7.3890560989306502272304274605750078131803155705521 +B 6 1 8 2 0.020774223763324224584254293406811044833326865633628 0 7.3890560989306502272304274605750078131803155705521 +B 6 1 8 5 0.0028255255049879030488573902941786017238633276675700 0 27.474593022118317968158957115156725710168223409107 +B 6 1 8 6 0.0021786382584319147840024181494323763558159193381797 0 47.560129945305985709087486769738443607156131247662 +B 6 1 9 3 0.0090227064023955481911524996385767986620206838791813 0 47.560129945305985709087486769738443607156131247662 +B 6 1 9 4 0.0017056293923189098060762601203844263500027494697387 0 47.560129945305985709087486769738443607156131247662 +B 6 1 9 7 0.00043464004838037520357063606346589262777842623599705 0 291.69672773748937390713238899664795040347997371773 +B 6 1 10 2 0.010018808710315513431165382959411151749152511197318 0 7.3890560989306502272304274605750078131803155705521 +B 6 1 10 5 0.0013626694245283138105672999104183083709995409993616 0 306.12380392425827750338559089034539301229489507924 +B 6 1 11 3 0.0038809637230430513212719771474579005441591236160580 0 67.645666868493653450016016424320161504144039086217 +B 6 1 11 4 0.00073364747796605301425361767318066603127970351070427 0 196.92750385796979934716506848462363620671342100200 +B 6 1 11 7 0.00018695302552436571763229361688480858744069407838792 0 1402.4767121057003711801909174000709677077081717564 +B 6 1 12 3 0.0017709440192499050287648798287810273918594408732012 0 67.645666868493653450016016424320161504144039086217 +B 6 1 12 4 0.00033477473794138466104824692736436353206212628833871 0 380.80749088059018432242438174778798931207353995641 +B 6 1 12 7 0.000085309568978255975820994386635118921590116045721982 0 2121.6611543892385870510509652103651115681944818916 +B 6 3 6 3 0.55040739054651169531242963233175912370812230385804 0 2.7182818284590452353602874713526624977572470937000 +B 6 3 7 5 0.10548715970104907017724712236763256345805974420939 0 7.3890560989306502272304274605750078131803155705521 +B 6 3 7 6 0.10088310209488823809129381202670468538910786192760 0 7.3890560989306502272304274605750078131803155705521 +B 6 3 7 8 0.010901853351597239560541731137944379450733011220026 0 7.3890560989306502272304274605750078131803155705521 +B 6 3 7 9 0.010901853351597239560541731137944379450733011220026 0 7.3890560989306502272304274605750078131803155705521 +B 6 3 8 5 0.014821338941265995173115325114131543427464191954287 0 7.3890560989306502272304274605750078131803155705521 +B 6 3 8 6 0.014174451694710006908260352969385318059416783624897 0 27.474593022118317968158957115156725710168223409107 +B 6 3 8 8 0.0015317510118759265191474460046861509877685110087893 0 47.560129945305985709087486769738443607156131247662 +B 6 3 8 9 0.0015317510118759265191474460046861509877685110087893 0 67.645666868493653450016016424320161504144039086217 +B 6 3 9 4 0.011370559293271771932045508805046862715665491226025 0 7.3890560989306502272304274605750078131803155705521 +B 6 3 9 7 0.0019338615297979430451906788721071364302896751636823 0 142.32935382482556026905480728176275780392268396339 +B 6 3 10 5 0.0071479041226776996918488900251479959048610237888983 0 27.474593022118317968158957115156725710168223409107 +B 6 3 10 8 0.00073871931652677380971565140201650782958009292681195 0 549.30618690635445548446849144292198683254911538885 +B 6 3 11 4 0.0048908527175595017774968270765222092159142857695839 0 7.3890560989306502272304274605750078131803155705521 +B 6 3 11 7 0.00083181765069311093885681784760150546208025746212282 0 237.09857770434513482902212779378707200068923667911 +B 6 3 12 4 0.0022317720512993478199945712269771427362139513898871 0 7.3890560989306502272304274605750078131803155705521 +B 6 3 12 7 0.00037957131236630484450453213709794397672973607306546 0 257.18411462753280256995065744836878989767714451766 +B 6 4 6 4 0.36169978278359199411403004611018355478661440662463 0 2.7182818284590452353602874713526624977572470937000 +B 6 4 7 5 0.13512146956322118508727770959209322517625463488023 0 7.3890560989306502272304274605750078131803155705521 +B 6 4 7 6 0.13051741195706035300132439925116534710730275259844 0 7.3890560989306502272304274605750078131803155705521 +B 6 4 7 8 0.010901853351597239560541731137944379450733011220026 0 7.3890560989306502272304274605750078131803155705521 +B 6 4 7 9 0.010901853351597239560541731137944379450733011220026 0 7.3890560989306502272304274605750078131803155705521 +B 6 4 8 5 0.018985069882572081424537064819916541520806372281107 0 7.3890560989306502272304274605750078131803155705521 +B 6 4 8 6 0.018338182636016093159682092675170316152758963951716 0 27.474593022118317968158957115156725710168223409107 +B 6 4 8 8 0.0015317510118759265191474460046861509877685110087893 0 47.560129945305985709087486769738443607156131247662 +B 6 4 8 9 0.0015317510118759265191474460046861509877685110087893 0 67.645666868493653450016016424320161504144039086217 +B 6 4 9 7 0.0039790624846791777765515464467007237436439305937465 0 142.32935382482556026905480728176275780392268396339 +B 6 4 9 10 0.00011689271239574155294423004923625919722234542756163 0 495.66225168329742662332023191439402140582800051069 +B 6 4 10 5 0.0091559514171241145967854986602957566140444043202498 0 7.3890560989306502272304274605750078131803155705521 +B 6 4 10 8 0.00073871931652677380971565140201650782958009292681195 0 529.22064998316678774353996178834026893556120755030 +B 6 4 11 7 0.0017115260616993359088398732668130061284801271553554 0 162.41489074801322800998333693634447570091059180195 +B 6 4 11 10 0.000050279412413943893476962602810844226480941720308835 0 2341.2099608593533246841788324905890380687342602944 +B 6 4 12 7 0.00078099592242005606795116823247666062915496844578987 0 162.41489074801322800998333693634447570091059180195 +B 6 4 12 10 0.000022943276737473804514181251452807768972113485067795 0 2782.6994070508387912367742482000274276031635209199 +B 6 7 6 7 0.40011359233912273310488145628968609456472467938206 0 2.7182818284590452353602874713526624977572470937000 +B 6 7 7 8 0.13864720801260736337257070071764278246141633846691 0 7.3890560989306502272304274605750078131803155705521 +B 6 7 7 9 0.10901289815043524846254011349318212074322144779609 0 7.3890560989306502272304274605750078131803155705521 +B 6 7 7 11 0.010901853351597239560541731137944379450733011220026 0 7.3890560989306502272304274605750078131803155705521 +B 6 7 8 8 0.019480449270212248054544349117318594097232048974847 0 7.3890560989306502272304274605750078131803155705521 +B 6 7 8 9 0.015316718328906161803122609411533596003889868648028 0 27.474593022118317968158957115156725710168223409107 +B 6 7 8 11 0.0015317510118759265191474460046861509877685110087893 0 47.560129945305985709087486769738443607156131247662 +B 6 7 9 10 0.0010701347203496425048234480919251594888905878528679 0 142.32935382482556026905480728176275780392268396339 +B 6 7 10 8 0.0093948586023139734303137344510093512077330631247683 0 7.3890560989306502272304274605750078131803155705521 +B 6 7 11 10 0.00046030025174520936594295564503273730936019879454610 0 162.41489074801322800998333693634447570091059180195 +B 6 7 12 10 0.00021004215345982031843462065699974122682612116703035 0 162.41489074801322800998333693634447570091059180195 +B 6 10 6 10 0.18196588527459303527346043967173771210938156220829 0 2.7182818284590452353602874713526624977572470937000 +B 6 10 7 11 0.063556451244573514900338870067044431513687313299784 0 7.3890560989306502272304274605750078131803155705521 +B 6 10 8 11 0.0089299181859619540948440464342022759213477329825605 0 7.3890560989306502272304274605750078131803155705521 +B 7 0 7 0 0.23694583858617247096911274000267642277945249855587 0 2.7182818284590452353602874713526624977572470937000 +B 7 0 8 2 0.025597240442751239471104316506347200499584556343643 0 7.3890560989306502272304274605750078131803155705521 +B 7 0 8 5 0.0047336052751998441385731614688678645431231858429478 0 7.3890560989306502272304274605750078131803155705521 +B 7 0 8 6 0.0027345147839803988899335100767158728829919003289940 0 7.3890560989306502272304274605750078131803155705521 +B 7 0 9 1 0.034322376988042304026463227792501912941287607262700 0 7.3890560989306502272304274605750078131803155705521 +B 7 0 9 3 0.017646737819144899325568161103164698899427261721479 0 27.474593022118317968158957115156725710168223409107 +B 7 0 9 4 0.0050347216731011521411944189750535672842361281170699 0 27.474593022118317968158957115156725710168223409107 +B 7 0 10 2 0.0078072990084825749536939203151856806925333424830207 0 27.474593022118317968158957115156725710168223409107 +B 7 0 10 5 0.0014437756231680518218175374501154795506723470937439 0 196.92750385796979934716506848462363620671342100200 +B 7 0 11 1 0.0076554998455001896419005090744353383866441046429336 0 7.3890560989306502272304274605750078131803155705521 +B 7 0 11 3 0.0039360501953321071516188777647847631354228788691141 0 122.24381690163789252812627762718103990693477612483 +B 7 0 11 4 0.0011229790700099404193595456210795328152237218148563 0 196.92750385796979934716506848462363620671342100200 +B 7 0 12 1 0.0036307034750011617433713796829657418046308085054100 0 7.3890560989306502272304274605750078131803155705521 +B 7 0 12 3 0.0018667143113288864199258180574099604822098065060627 0 142.32935382482556026905480728176275780392268396339 +B 7 0 12 4 0.00053258495122760597516102560989486202429410364631560 0 549.30618690635445548446849144292198683254911538885 +B 7 0 13 2 0.00024892285310401770779856552841524400402766294659259 0 67.645666868493653450016016424320161504144039086217 +B 7 0 13 5 0.000046032404672928405316508291567740408357540573710217 0 3059.4401883328043303380768786265502689531509482692 +B 7 0 13 6 0.000026592054850829710634535855859989019756769683929092 0 3614.8301805169098289746061428282617776052650472886 +B 7 2 7 2 0.34135363219440200404812251467252588642736741774850 0 2.7182818284590452353602874713526624977572470937000 +B 7 2 8 5 0.016164968104585264429158564683683528351419513850272 0 7.3890560989306502272304274605750078131803155705521 +B 7 2 8 6 0.014165877613365819180518913291531536691288228336318 0 7.3890560989306502272304274605750078131803155705521 +B 7 2 8 8 0.0027345147839803988899335100767158728829919003289940 0 7.3890560989306502272304274605750078131803155705521 +B 7 2 9 3 0.065757584881575528076333228391523801102540563974237 0 7.3890560989306502272304274605750078131803155705521 +B 7 2 9 4 0.031332530254484682592242499122062601766719134108843 0 7.3890560989306502272304274605750078131803155705521 +B 7 2 9 7 0.0076034213291759989406053792010599941236211034769525 0 47.560129945305985709087486769738443607156131247662 +B 7 2 10 5 0.0049304041088858976069710854853007795035411115037212 0 47.560129945305985709087486769738443607156131247662 +B 7 2 10 8 0.00083404203704688338338682424481508078679581366306608 0 217.01304078115746708809359813920535410370132884056 +B 7 2 11 3 0.014667025569841823425533092443929113209235265423289 0 7.3890560989306502272304274605750078131803155705521 +B 7 2 11 4 0.0069886237950799661644240198665589780812074248995109 0 27.474593022118317968158957115156725710168223409107 +B 7 2 11 7 0.0016959195696457444386436001830866975935274506627068 0 217.01304078115746708809359813920535410370132884056 +B 7 2 12 3 0.0069559952686376530190722666568730103421046388696420 0 7.3890560989306502272304274605750078131803155705521 +B 7 2 12 4 0.0033144303063616346184358769553432533186940721183787 0 47.560129945305985709087486769738443607156131247662 +B 7 2 12 7 0.00080430817047883729137404342412430064583103459240012 0 311.78226466067704164806091865122966830046788155628 +B 7 2 13 5 0.00015719780379952240389852312784536790049298720504197 0 291.69672773748937390713238899664795040347997371773 +B 7 2 13 6 0.00013775745397742370921655069213761651189221631526084 0 441.06410165015318754520997071153314300303726347207 +B 7 2 13 8 0.000026592054850829710634535855859989019756769683929092 0 2027.8461453198062227080456463726737103474975513364 +B 7 5 7 5 0.37477502633573018979982205384131263657617328893638 0 2.7182818284590452353602874713526624977572470937000 +B 7 5 8 6 0.091837725039905008213540020278419445814733565271210 0 7.3890560989306502272304274605750078131803155705521 +B 7 5 8 8 0.021599059460312348973825013722043217179321985315736 0 7.3890560989306502272304274605750078131803155705521 +B 7 5 8 9 0.0087317862576387346358524642531718478633857568708557 0 7.3890560989306502272304274605750078131803155705521 +B 7 5 8 11 0.0027345147839803988899335100767158728829919003289940 0 7.3890560989306502272304274605750078131803155705521 +B 7 5 9 7 0.040954699666970808342395512579734422207341794559393 0 27.474593022118317968158957115156725710168223409107 +B 7 5 9 10 0.0035397983063223414240840546398339116969518915401412 0 67.645666868493653450016016424320161504144039086217 +B 7 5 10 8 0.0065878318362402380768324939045848831647802756216650 0 102.15827997845022478719774797259932200994686828628 +B 7 5 11 7 0.0091348188699819094192068628023878480959699022103462 0 27.474593022118317968158957115156725710168223409107 +B 7 5 11 10 0.00078954104479982868062130101714135266250538194314495 0 420.02434991687830958731943938261851212997973347307 +B 7 5 12 7 0.0043322864978233879382651666752358632906730385910946 0 27.474593022118317968158957115156725710168223409107 +B 7 5 12 10 0.00037444836690784241269327424608361778132573545279998 0 494.70803687321021640635823024006110842975837835024 +B 7 5 13 6 0.00089308488509311954389227925147988686012702149114237 0 7.3890560989306502272304274605750078131803155705521 +B 7 5 13 8 0.00021004215345982031843462065699974122682612116703035 0 251.52565389111403842527532968748451460950415804062 +B 7 5 13 9 0.000084913104317125794680453162983243185559082353272462 0 549.30618690635445548446849144292198683254911538885 +B 7 5 13 11 0.000026592054850829710634535855859989019756769683929092 0 3239.7721357666309427063096882719436726357845331552 +B 7 6 7 6 0.44028187414125576872768599292105984758875117696195 0 2.7182818284590452353602874713526624977572470937000 +B 7 6 8 8 0.041899514509932493105103663621426266983291970740031 0 7.3890560989306502272304274605750078131803155705521 +B 7 6 8 9 0.029032241307258878767131114152554897667355742295152 0 7.3890560989306502272304274605750078131803155705521 +B 7 6 8 11 0.0047336052751998441385731614688678645431231858429478 0 7.3890560989306502272304274605750078131803155705521 +B 7 6 9 7 0.056135415469089402326180214933851980661917903523685 0 7.3890560989306502272304274605750078131803155705521 +B 7 6 9 10 0.0050347216731011521411944189750535672842361281170699 0 47.560129945305985709087486769738443607156131247662 +B 7 6 10 8 0.012779582190545596363278145573037991676250834836852 0 27.474593022118317968158957115156725710168223409107 +B 7 6 11 7 0.012520830494939880170750249508100243194472788112454 0 7.3890560989306502272304274605750078131803155705521 +B 7 6 11 10 0.0011229790700099404193595456210795328152237218148563 0 142.32935382482556026905480728176275780392268396339 +B 7 6 12 7 0.0059381390771758996992429769369804003701256723969262 0 7.3890560989306502272304274605750078131803155705521 +B 7 6 12 10 0.00053258495122760597516102560989486202429410364631560 0 162.41489074801322800998333693634447570091059180195 +B 7 6 13 8 0.00040745590208491145140685811587836398302706483255771 0 67.645666868493653450016016424320161504144039086217 +B 7 6 13 9 0.00028232685294221692765269062186186594176002601879984 0 162.41489074801322800998333693634447570091059180195 +B 7 6 13 11 0.000046032404672928405316508291567740408357540573710217 0 1140.1630070105037356751414888672455689665356657687 +B 7 8 7 8 0.31474773019158037927140441118288092805012656088998 0 2.7182818284590452353602874713526624977572470937000 +B 7 8 8 9 0.075067242762226251574354862989680686103198184609205 0 7.3890560989306502272304274605750078131803155705521 +B 7 8 8 11 0.014165877613365819180518913291531536691288228336318 0 7.3890560989306502272304274605750078131803155705521 +B 7 8 9 10 0.021710360841998556842089485664390781326096473658290 0 27.474593022118317968158957115156725710168223409107 +B 7 8 11 10 0.0048424287201780229096411769307301080664449475886758 0 27.474593022118317968158957115156725710168223409107 +B 7 8 12 10 0.0022965741148998812986065872354506433467151056456628 0 27.474593022118317968158957115156725710168223409107 +B 7 8 13 9 0.00072999869985269710813326306877348478049504731184297 0 7.3890560989306502272304274605750078131803155705521 +B 7 8 13 11 0.00013775745397742370921655069213761651189221631526084 0 251.52565389111403842527532968748451460950415804062 +B 7 9 7 9 0.45973234704260774580325891071611097390641969254549 0 2.7182818284590452353602874713526624977572470937000 +B 7 9 8 11 0.025597240442751239471104316506347200499584556343643 0 7.3890560989306502272304274605750078131803155705521 +B 7 9 9 10 0.030258753965188646509941903231275830514618395325888 0 7.3890560989306502272304274605750078131803155705521 +B 7 9 11 10 0.0067491213206542738838782099084899934556220359233716 0 7.3890560989306502272304274605750078131803155705521 +B 7 9 12 10 0.0032008436714301668646906105049250589401255093658098 0 7.3890560989306502272304274605750078131803155705521 +B 7 9 13 11 0.00024892285310401770779856552841524400402766294659259 0 67.645666868493653450016016424320161504144039086217 +B 7 11 7 11 0.41367597213843414395096788943141488921151032010344 0 2.7182818284590452353602874713526624977572470937000 +B 8 0 8 0 0.18064917999119894528175659760368629565509148375776 0 2.7182818284590452353602874713526624977572470937000 +B 8 0 9 1 0.088496560770353507791517217924432783588185706746473 0 7.3890560989306502272304274605750078131803155705521 +B 8 0 9 3 0.045500217142726736998350562522596905213866185340009 0 7.3890560989306502272304274605750078131803155705521 +B 8 0 9 4 0.012981488801333331153900140811566936785854766707214 0 7.3890560989306502272304274605750078131803155705521 +B 8 0 10 2 0.036526270221190266034038441850727985895829221152911 0 27.474593022118317968158957115156725710168223409107 +B 8 0 10 5 0.0067546713009590928696018369106802365166186243400251 0 67.645666868493653450016016424320161504144039086217 +B 8 0 11 1 0.027400346464051814947842117173955603235705534896692 0 7.3890560989306502272304274605750078131803155705521 +B 8 0 11 3 0.014087798475417771608421835793623714224173442678604 0 102.15827997845022478719774797259932200994686828628 +B 8 0 11 4 0.0040193346236219062937387595996717172270288594535091 0 122.24381690163789252812627762718103990693477612483 +B 8 0 12 1 0.0088687685193565882727925780075257031673990976382018 0 7.3890560989306502272304274605750078131803155705521 +B 8 0 12 3 0.0045598483139526408156715228694160558640848601098619 0 122.24381690163789252812627762718103990693477612483 +B 8 0 12 4 0.0013009524688129328576498106442504041828238945906025 0 420.02434991687830958731943938261851212997973347307 +B 8 0 13 2 0.0014752081085167496343904387917110573921004764244536 0 67.645666868493653450016016424320161504144039086217 +B 8 0 13 5 0.00027280491036173267088197501583392811547515742013404 403.42879349273512260838718054338827960589989735717 1863.0974804102862952567528610897581621630557180601 +B 8 0 13 6 0.00015759426846065258503906435149724363652402089749148 0 2450.4062609256418028403993548963107948743157343716 +B 8 2 8 2 0.26025041887582941854941717937570141672787011897961 0 2.7182818284590452353602874713526624977572470937000 +B 8 2 9 3 0.16954886628660484639720948997968625223593923488575 0 7.3890560989306502272304274605750078131803155705521 +B 8 2 9 4 0.080787562257735723826838581704820684564588898022817 0 7.3890560989306502272304274605750078131803155705521 +B 8 2 9 7 0.019604604831257804120277056392566797220364465119049 0 7.3890560989306502272304274605750078131803155705521 +B 8 2 10 5 0.023066783094277210997883065895175592838634032882232 0 47.560129945305985709087486769738443607156131247662 +B 8 2 10 8 0.0039020466345540297774759838817372732517984040684978 0 67.645666868493653450016016424320161504144039086217 +B 8 2 11 3 0.052495799140665400631141664026076322648664474673709 0 7.3890560989306502272304274605750078131803155705521 +B 8 2 11 4 0.025013482745305475437703006626494127923459158070617 0 27.474593022118317968158957115156725710168223409107 +B 8 2 11 7 0.0060699869010869145634064095123208715852931800334636 0 176.84196693478213160623653883004191830972551316345 +B 8 2 12 3 0.016991503790947084073036662664318779479874949369162 0 7.3890560989306502272304274605750078131803155705521 +B 8 2 12 4 0.0080962037696157689662438937413405962092961499708021 0 47.560129945305985709087486769738443607156131247662 +B 8 2 12 7 0.0019646944542067627034748114241018463258256927659829 0 271.61119081430170616620385934206623250649206587918 +B 8 2 13 5 0.00093161183038978119555766223594083499326338518361512 0 291.69672773748937390713238899664795040347997371773 +B 8 2 13 6 0.00081640118848870110971475157160415051431224866097255 0 420.97856472696551980428144105695142510604935563351 +B 8 2 13 8 0.00015759426846065258503906435149724363652402089749148 0 1660.0861712745654527575270198463450041367773134276 +B 8 5 8 5 0.28573112569819406573190697029718370575367150326291 0 2.7182818284590452353602874713526624977572470937000 +B 8 5 9 7 0.10559729208651134570661036719623855396900350793196 0 7.3890560989306502272304274605750078131803155705521 +B 8 5 9 10 0.0091269895450244391715608227017608872740563623453887 0 7.3890560989306502272304274605750078131803155705521 +B 8 5 10 8 0.030821020888380139849786735792842059366188780609857 0 27.474593022118317968158957115156725710168223409107 +B 8 5 11 7 0.032695082878355001242246972272984649608357364469638 0 7.3890560989306502272304274605750078131803155705521 +B 8 5 11 10 0.0028259027642487365386692043259409795709056710404717 0 102.15827997845022478719774797259932200994686828628 +B 8 5 12 7 0.010582534865014657617716921700321140932454167822661 0 7.3890560989306502272304274605750078131803155705521 +B 8 5 12 10 0.00091467009394252320437546851115785070377242075690283 0 122.24381690163789252812627762718103990693477612483 +B 8 5 13 6 0.0052927485269204270460862493692981991804770766193931 0 7.3890560989306502272304274605750078131803155705521 +B 8 5 13 8 0.0012447868247145894627046174630376884341982033791685 0 67.645666868493653450016016424320161504144039086217 +B 8 5 13 9 0.00050322619416389284256779634450729707337743046541915 0 142.32935382482556026905480728176275780392268396339 +B 8 5 13 11 0.00015759426846065258503906435149724363652402089749148 0 772.40303296526296572462286234091686275581542785991 +B 8 6 8 6 0.33567400889245942649795480291621132256082276269534 0 2.7182818284590452353602874713526624977572470937000 +B 8 6 9 7 0.14473913645782922451743770448826838283152462497659 0 7.3890560989306502272304274605750078131803155705521 +B 8 6 9 10 0.012981488801333331153900140811566936785854766707214 0 7.3890560989306502272304274605750078131803155705521 +B 8 6 10 8 0.059788983603499052589749451543727385478493464335787 0 27.474593022118317968158957115156725710168223409107 +B 8 6 11 7 0.044814199007615874826597698379585800963766268274688 0 7.3890560989306502272304274605750078131803155705521 +B 8 6 11 10 0.0040193346236219062937387595996717172270288594535091 0 102.15827997845022478719774797259932200994686828628 +B 8 6 12 7 0.014505172695548195421563634705338234756716931517301 0 7.3890560989306502272304274605750078131803155705521 +B 8 6 12 10 0.0013009524688129328576498106442504041828238945906025 0 122.24381690163789252812627762718103990693477612483 +B 8 6 13 8 0.0024147330914911744358313044730016177149049310111137 0 67.645666868493653450016016424320161504144039086217 +B 8 6 13 9 0.0016731724609404778156944833544712263540841580973644 0 142.32935382482556026905480728176275780392268396339 +B 8 6 13 11 0.00027280491036173267088197501583392811547515742013404 0 772.40303296526296572462286234091686275581542785991 +B 8 8 8 8 0.23996589137192917028498209590966130418634623533661 0 2.7182818284590452353602874713526624977572470937000 +B 8 8 9 10 0.055977832428960101947066796213402815160174288113670 0 7.3890560989306502272304274605750078131803155705521 +B 8 8 11 10 0.017331882612255949633159040980003606238560951671596 0 7.3890560989306502272304274605750078131803155705521 +B 8 8 12 10 0.0056098726742168803147708657823600514861381321189421 0 7.3890560989306502272304274605750078131803155705521 +B 8 8 13 9 0.0043262399888184560290948126014959383564324315568083 0 7.3890560989306502272304274605750078131803155705521 +B 8 8 13 11 0.00081640118848870110971475157160415051431224866097255 0 67.645666868493653450016016424320161504144039086217 +B 8 9 8 9 0.35050318673764198274876117749270507469363645059004 0 2.7182818284590452353602874713526624977572470937000 +B 8 9 9 10 0.078018945484120142842800984233626873641877603972805 0 7.3890560989306502272304274605750078131803155705521 +B 8 9 11 10 0.024156262327213636923104911987575711221318025903699 0 7.3890560989306502272304274605750078131803155705521 +B 8 9 12 10 0.0078187441590923487736932350945817075453458256291214 0 7.3890560989306502272304274605750078131803155705521 +B 8 9 13 11 0.0014752081085167496343904387917110573921004764244536 0 67.645666868493653450016016424320161504144039086217 +B 8 11 8 11 0.31538948138855917823351971945017121001929887905233 0 2.7182818284590452353602874713526624977572470937000 +B 9 1 9 1 0.45864551887399724426219143266873814012488375979667 0 2.7182818284590452353602874713526624977572470937000 +B 9 1 10 2 0.28960869226246130524416723696068783130239318180897 0 7.3890560989306502272304274605750078131803155705521 +B 9 1 10 5 0.039390003485879270796907432056185853723190515037699 0 7.3890560989306502272304274605750078131803155705521 +B 9 1 11 3 0.089781791464158297465236921125893124672468484002009 0 27.474593022118317968158957115156725710168223409107 +B 9 1 11 4 0.016972120734822743126837717390219876988142723075541 0 27.474593022118317968158957115156725710168223409107 +B 9 1 11 7 0.0043249509011285008217692540624630550146765253336753 0 47.560129945305985709087486769738443607156131247662 +B 9 1 12 3 0.025574500946424421817291165687570501751016697617350 0 27.474593022118317968158957115156725710168223409107 +B 9 1 12 4 0.0048345383926631925642507424732207035556285579645936 0 102.15827997845022478719774797259932200994686828628 +B 9 1 12 7 0.0012319698583682850375121091395571240011938566687308 0 196.92750385796979934716506848462363620671342100200 +B 9 1 13 2 0.011715859240087181199824680662651841929334248023129 0 7.3890560989306502272304274605750078131803155705521 +B 9 1 13 5 0.0015934871729916041633936624627435530649328477370962 0 529.22064998316678774353996178834026893556120755030 +B 9 1 13 6 0.0012286677693305362484317406793882794678899897388330 0 549.30618690635445548446849144292198683254911538885 +B 9 3 9 3 0.65502364535839396692047218695068043500478156882186 0 2.7182818284590452353602874713526624977572470937000 +B 9 3 10 5 0.20662088929342905134595595219794251521686260258080 0 7.3890560989306502272304274605750078131803155705521 +B 9 3 10 8 0.021353789796192323403420074557504559224221256143955 0 7.3890560989306502272304274605750078131803155705521 +B 9 3 11 4 0.11314445331262584207806318596026684838512671328838 0 7.3890560989306502272304274605750078131803155705521 +B 9 3 11 7 0.019243178803067237979065020070329526817246704659551 0 27.474593022118317968158957115156725710168223409107 +B 9 3 12 4 0.032229396196461281771253400782545817339993203728505 0 7.3890560989306502272304274605750078131803155705521 +B 9 3 12 7 0.0054814532711537847617816815036298021556902699390757 0 47.560129945305985709087486769738443607156131247662 +B 9 3 13 5 0.0083586622905283031514335111112017736516263403044089 0 47.560129945305985709087486769738443607156131247662 +B 9 3 13 6 0.0079938428868672352364715893278465000545834823061459 0 67.645666868493653450016016424320161504144039086217 +B 9 3 13 8 0.00086384836566946833346981889603300587084713174056983 0 271.61119081430170616620385934206623250649206587918 +B 9 3 13 9 0.00086384836566946833346981889603300587084713174056983 0 291.69672773748937390713238899664795040347997371773 +B 9 4 9 4 0.43044827215892337346995982993387168699614972392585 0 2.7182818284590452353602874713526624977572470937000 +B 9 4 10 5 0.26466650806515282310939906404939768598692095455018 0 7.3890560989306502272304274605750078131803155705521 +B 9 4 10 8 0.021353789796192323403420074557504559224221256143955 0 7.3890560989306502272304274605750078131803155705521 +B 9 4 11 7 0.039594257231674030564855204590244853942287415004903 0 27.474593022118317968158957115156725710168223409107 +B 9 4 11 10 0.0011631584427049402455021382305238495213099758982087 0 47.560129945305985709087486769738443607156131247662 +B 9 4 12 7 0.011278493696003603565266851231527473798857070507868 0 27.474593022118317968158957115156725710168223409107 +B 9 4 12 10 0.00033132772479455815582745080614122911258518134476522 0 122.24381690163789252812627762718103990693477612483 +B 9 4 13 5 0.010706845605471663453060304769501209069205261376786 0 7.3890560989306502272304274605750078131803155705521 +B 9 4 13 6 0.010342026201810595538098382986145935472162403378522 0 27.474593022118317968158957115156725710168223409107 +B 9 4 13 8 0.00086384836566946833346981889603300587084713174056983 0 176.84196693478213160623653883004191830972551316345 +B 9 4 13 9 0.00086384836566946833346981889603300587084713174056983 0 196.92750385796979934716506848462363620671342100200 +B 9 7 9 7 0.47616341697589792546332481973311156465209040199147 0 2.7182818284590452353602874713526624977572470937000 +B 9 7 10 8 0.27157247857277435785067987946200653680342392291523 0 7.3890560989306502272304274605750078131803155705521 +B 9 7 11 10 0.010648535817975621974303485726341466001409624204608 0 27.474593022118317968158957115156725710168223409107 +B 9 7 12 10 0.0030332541255157388008814258063889137784112073166622 0 27.474593022118317968158957115156725710168223409107 +B 9 7 13 8 0.010986220432765045369900837095941294735248532026603 0 7.3890560989306502272304274605750078131803155705521 +B 9 7 13 9 0.0086380371178216850682740434376418593176696109542266 0 27.474593022118317968158957115156725710168223409107 +B 9 7 13 11 0.00086384836566946833346981889603300587084713174056983 0 176.84196693478213160623653883004191830972551316345 +B 9 10 9 10 0.21655224757262596961054568858755596758904527270584 0 2.7182818284590452353602874713526624977572470937000 +B 9 10 13 11 0.0050361286989181682099062214711088092736403428042625 0 7.3890560989306502272304274605750078131803155705521 +B 10 2 10 2 0.60300885188457322999987349067880702005615598535459 0 2.7182818284590452353602874713526624977572470937000 +B 10 2 11 3 0.25773571039378780858112985230263368932260713696953 0 7.3890560989306502272304274605750078131803155705521 +B 10 2 11 4 0.12280730744776970308628656949707275295192986570530 0 7.3890560989306502272304274605750078131803155705521 +B 10 2 11 7 0.029801477673300786226516751271714741729754484674866 0 7.3890560989306502272304274605750078131803155705521 +B 10 2 12 3 0.11760391316702858923534424414438346237327243282251 0 7.3890560989306502272304274605750078131803155705521 +B 10 2 12 4 0.056036549608502374179378228084593018269658116007404 0 27.474593022118317968158957115156725710168223409107 +B 10 2 12 7 0.013598311181578826226744882637554828721243622591192 0 47.560129945305985709087486769738443607156131247662 +B 10 2 13 5 0.0039314818428865115969818709348622797551196587481863 0 142.32935382482556026905480728176275780392268396339 +B 10 2 13 6 0.0034452830506793697648359155034897127832482737626705 0 142.32935382482556026905480728176275780392268396339 +B 10 2 13 8 0.00066506133218253537525645739213926158568069928128216 0 291.69672773748937390713238899664795040347997371773 +B 10 5 10 5 0.66204849467374585727175787986835068115159091735074 0 2.7182818284590452353602874713526624977572470937000 +B 10 5 11 7 0.16052123312680337235519656310802052174150293131345 0 7.3890560989306502272304274605750078131803155705521 +B 10 5 11 10 0.013874177903184214645720059633484602942139493506475 0 7.3890560989306502272304274605750078131803155705521 +B 10 5 12 7 0.073245283446619939567965741290472201168251347979744 0 7.3890560989306502272304274605750078131803155705521 +B 10 5 12 10 0.0063307393876347797283608458738285412304850115169428 0 27.474593022118317968158957115156725710168223409107 +B 10 5 13 6 0.022335852823858939878547630214542877527206236597551 0 7.3890560989306502272304274605750078131803155705521 +B 10 5 13 8 0.0052531071847619204901234627520950300370730782730271 0 47.560129945305985709087486769738443607156131247662 +B 10 5 13 9 0.0021236577088039608716943236862569625012948542378297 0 47.560129945305985709087486769738443607156131247662 +B 10 5 13 11 0.00066506133218253537525645739213926158568069928128216 0 142.32935382482556026905480728176275780392268396339 +B 10 8 10 8 0.55600892891044751110322935419632449580282248849947 0 2.7182818284590452353602874713526624977572470937000 +B 10 8 11 10 0.085093381768736033817376575886124984162356800097146 0 7.3890560989306502272304274605750078131803155705521 +B 10 8 12 10 0.038827815770384808790790714878713835371064884035062 0 7.3890560989306502272304274605750078131803155705521 +B 10 8 13 9 0.018257103880800900795985974446819867152057359399332 0 7.3890560989306502272304274605750078131803155705521 +B 10 8 13 11 0.0034452830506793697648359155034897127832482737626705 0 47.560129945305985709087486769738443607156131247662 +B 11 1 11 1 0.30994660269094874800905949373720638030142612409410 0 2.7182818284590452353602874713526624977572470937000 +B 11 1 12 3 0.099440243643822040705605745931037703936859783037202 0 7.3890560989306502272304274605750078131803155705521 +B 11 1 12 4 0.018797929886450164634042809999994748571387464594424 0 7.3890560989306502272304274605750078131803155705521 +B 11 1 12 7 0.0047902159707681407422136065796312277643391046884581 0 7.3890560989306502272304274605750078131803155705521 +B 11 1 13 2 0.037460200724813900325650236784022019918742598174163 0 7.3890560989306502272304274605750078131803155705521 +B 11 1 13 5 0.0050950039710649130927241388595033562509932561935448 0 47.560129945305985709087486769738443607156131247662 +B 11 1 13 6 0.0039285331378638804671978133818274398623307901259791 0 47.560129945305985709087486769738443607156131247662 +B 11 3 11 3 0.44265635486749619908348237011683427207407487571736 0 2.7182818284590452353602874713526624977572470937000 +B 11 3 12 4 0.12531618962900854035698338699316810650781637458520 0 7.3890560989306502272304274605750078131803155705521 +B 11 3 12 7 0.021313301477421988713804455791338621676209564432415 0 7.3890560989306502272304274605750078131803155705521 +B 11 3 13 5 0.026725924302910365101734622481318593537770325722877 0 27.474593022118317968158957115156725710168223409107 +B 11 3 13 6 0.025559453469709332476208297003642677149107859655312 0 27.474593022118317968158957115156725710168223409107 +B 11 3 13 8 0.0027620623046628478416714879041515234736683240584135 0 47.560129945305985709087486769738443607156131247662 +B 11 3 13 9 0.0027620623046628478416714879041515234736683240584135 0 47.560129945305985709087486769738443607156131247662 +B 11 4 11 4 0.29089127463273068746599867706768353844031487350698 0 2.7182818284590452353602874713526624977572470937000 +B 11 4 12 7 0.043853687053968166738114251649480768894664213990854 0 7.3890560989306502272304274605750078131803155705521 +B 11 4 12 10 0.0012882874918476347692563057245403475625770147119667 0 7.3890560989306502272304274605750078131803155705521 +B 11 4 13 5 0.034233988074747095597202984223610301260376428184248 0 7.3890560989306502272304274605750078131803155705521 +B 11 4 13 6 0.033067517241546062971676658745934384871713962116683 0 7.3890560989306502272304274605750078131803155705521 +B 11 4 13 8 0.0027620623046628478416714879041515234736683240584135 0 27.474593022118317968158957115156725710168223409107 +B 11 4 13 9 0.0027620623046628478416714879041515234736683240584135 0 27.474593022118317968158957115156725710168223409107 +B 11 7 11 7 0.32178496757086814004684513241048172953218382843049 0 2.7182818284590452353602874713526624977572470937000 +B 11 7 12 10 0.011794072928609152688128208289812988167863284641441 0 7.3890560989306502272304274605750078131803155705521 +B 11 7 13 8 0.035127259058411835074597585828670187141417666039031 0 7.3890560989306502272304274605750078131803155705521 +B 11 7 13 9 0.027619195286575104579129224086378479418811563577659 0 7.3890560989306502272304274605750078131803155705521 +B 11 7 13 11 0.0027620623046628478416714879041515234736683240584135 0 27.474593022118317968158957115156725710168223409107 +B 11 10 11 10 0.14634315757626384435379016201478029743690841754733 0 2.7182818284590452353602874713526624977572470937000 +B 11 10 13 11 0.016102480242504741464771477034822813139586756857614 0 7.3890560989306502272304274605750078131803155705521 +B 12 1 12 1 0.30994660269094874800905949373720638030142612409410 0 2.7182818284590452353602874713526624977572470937000 +B 12 1 13 2 0.058733436378199013100464558527733921246250742517231 0 7.3890560989306502272304274605750078131803155705521 +B 12 1 13 5 0.0079884006436460181924220389629409248114277119074589 0 7.3890560989306502272304274605750078131803155705521 +B 12 1 13 6 0.0061595038640445255507279061545807441453130452790289 0 7.3890560989306502272304274605750078131803155705521 +B 12 3 12 3 0.44265635486749619908348237011683427207407487571736 0 2.7182818284590452353602874713526624977572470937000 +B 12 3 13 5 0.041903282532433545181737870621552948367482622391830 0 7.3890560989306502272304274605750078131803155705521 +B 12 3 13 6 0.040074385752832052540043737813192767701367955763400 0 7.3890560989306502272304274605750078131803155705521 +B 12 3 13 8 0.0043306070844430329090337733462205634791983786505986 0 7.3890560989306502272304274605750078131803155705521 +B 12 3 13 9 0.0043306070844430329090337733462205634791983786505986 0 7.3890560989306502272304274605750078131803155705521 +B 12 4 12 4 0.29089127463273068746599867706768353844031487350698 0 2.7182818284590452353602874713526624977572470937000 +B 12 4 13 5 0.053675093076271047587901434108571107143131046730058 0 7.3890560989306502272304274605750078131803155705521 +B 12 4 13 6 0.051846196296669554946207301300210926477016380101627 0 7.3890560989306502272304274605750078131803155705521 +B 12 4 13 8 0.0043306070844430329090337733462205634791983786505986 0 7.3890560989306502272304274605750078131803155705521 +B 12 4 13 9 0.0043306070844430329090337733462205634791983786505986 0 7.3890560989306502272304274605750078131803155705521 +B 12 7 12 7 0.32178496757086814004684513241048172953218382843049 0 2.7182818284590452353602874713526624977572470937000 +B 12 7 13 8 0.055075642818996027817076292911013559914021409260370 0 7.3890560989306502272304274605750078131803155705521 +B 12 7 13 9 0.043303832275158525410912729423995401138372984922141 0 7.3890560989306502272304274605750078131803155705521 +B 12 7 13 11 0.0043306070844430329090337733462205634791983786505986 0 7.3890560989306502272304274605750078131803155705521 +B 12 10 12 10 0.14634315757626384435379016201478029743690841754733 0 2.7182818284590452353602874713526624977572470937000 +B 12 10 13 11 0.025246901526287998523668000875039625585420136130977 0 7.3890560989306502272304274605750078131803155705521 +B 13 0 13 0 0.10115161711882714405573291827774201598858485465872 0 2.7182818284590452353602874713526624977572470937000 +B 13 2 13 2 0.14572305684656193022178480569403127958960418281678 0 2.7182818284590452353602874713526624977572470937000 +B 13 5 13 5 0.15999057082331225157707155011831295869410769484598 0 2.7182818284590452353602874713526624977572470937000 +B 13 6 13 6 0.18795528895224455870899817213636362611967657856689 0 2.7182818284590452353602874713526624977572470937000 +B 13 8 13 8 0.13436506031643210212398344907421920833948574353304 0 2.7182818284590452353602874713526624977572470937000 +B 13 9 13 9 0.19625864975164579822606080483548292420740180078546 0 2.7182818284590452353602874713526624977572470937000 +B 13 11 13 11 0.17659729242211473061119681551655155486955813928314 0 2.7182818284590452353602874713526624977572470937000 +P 0 11 0 0E+0 +P 0 10 1 0E+0 +P 0 9 0 0E+0 +P 0 8 0 0E+0 +P 0 7 1 0E+0 +P 0 6 0 0E+0 +P 0 5 0 0E+0 +P 0 4 1 0E+0 +P 0 3 1 0E+0 +P 0 2 0 0E+0 +P 0 1 1 0E+0 +P 0 0 0 0E+0 +P 1 11 0 0E+0 +P 1 10 1 0E+0 +P 1 9 0 0E+0 +P 1 8 0 0E+0 +P 1 7 1 0E+0 +P 1 6 0 0E+0 +P 1 5 0 0E+0 +P 1 4 1 0E+0 +P 1 3 0 0E+0 +P 1 2 0 0E+0 +P 1 1 0 0E+0 +P 1 0 0 0E+0 +P 2 11 0 0E+0 +P 2 10 0 0E+0 +P 2 9 0 0E+0 +P 2 8 1 0E+0 +P 2 7 0 0E+0 +P 2 6 0 0E+0 +P 2 5 1 0E+0 +P 2 4 0 0E+0 +P 2 3 0 0E+0 +P 2 2 1 0E+0 +P 2 1 0 0E+0 +P 2 0 0 0E+0 +P 3 11 1 0E+0 +P 3 10 0 0E+0 +P 3 9 1 0E+0 +P 3 8 1 0E+0 +P 3 7 0 0E+0 +P 3 6 1 0E+0 +P 3 5 1 0E+0 +P 3 4 0 0E+0 +P 3 3 0 0E+0 +P 3 2 1 0E+0 +P 3 1 0 0E+0 +P 3 0 1 0E+0 +P 4 11 0 0E+0 +P 4 10 1 0E+0 +P 4 9 0 0E+0 +P 4 8 0 0E+0 +P 4 7 1 0E+0 +P 4 6 0 0E+0 +P 4 5 0 0E+0 +P 4 4 1 0E+0 +P 4 3 0 0E+0 +P 4 2 0 0E+0 +P 4 1 0 0E+0 +P 4 0 0 0E+0 +P 5 11 0 0E+0 +P 5 10 1 0E+0 +P 5 9 0 0E+0 +P 5 8 0 0E+0 +P 5 7 1 0E+0 +P 5 6 0 0E+0 +P 5 5 0 0E+0 +P 5 4 1 0E+0 +P 5 3 0 0E+0 +P 5 2 0 0E+0 +P 5 1 0 0E+0 +P 5 0 0 0E+0 +P 6 11 0 0E+0 +P 6 10 1 0E+0 +P 6 9 0 0E+0 +P 6 8 0 0E+0 +P 6 7 1 0E+0 +P 6 6 0 0E+0 +P 6 5 0 0E+0 +P 6 4 1 0E+0 +P 6 3 1 0E+0 +P 6 2 0 0E+0 +P 6 1 1 0E+0 +P 6 0 0 0E+0 +P 7 11 1 0E+0 +P 7 10 0 0E+0 +P 7 9 1 0E+0 +P 7 8 1 0E+0 +P 7 7 0 0E+0 +P 7 6 1 0E+0 +P 7 5 1 0E+0 +P 7 4 0 0E+0 +P 7 3 0 0E+0 +P 7 2 1 0E+0 +P 7 1 0 0E+0 +P 7 0 1 0E+0 +P 8 11 1 0E+0 +P 8 10 0 0E+0 +P 8 9 1 0E+0 +P 8 8 1 0E+0 +P 8 7 0 0E+0 +P 8 6 1 0E+0 +P 8 5 1 0E+0 +P 8 4 0 0E+0 +P 8 3 0 0E+0 +P 8 2 1 0E+0 +P 8 1 0 0E+0 +P 8 0 1 1.1005735584612756575783984806581962556404642459653E-1 +P 9 11 0 0E+0 +P 9 10 1 0E+0 +P 9 9 0 0E+0 +P 9 8 0 0E+0 +P 9 7 1 0E+0 +P 9 6 0 0E+0 +P 9 5 0 0E+0 +P 9 4 1 0E+0 +P 9 3 1 0E+0 +P 9 2 0 0E+0 +P 9 1 1 1.1005735584612756575783984806581962556404642459653E-1 +P 9 0 0 0E+0 +P 10 11 0 0E+0 +P 10 10 0 0E+0 +P 10 9 0 0E+0 +P 10 8 1 0E+0 +P 10 7 0 0E+0 +P 10 6 0 0E+0 +P 10 5 1 0E+0 +P 10 4 0 0E+0 +P 10 3 0 0E+0 +P 10 2 1 1.1005735584612756575783984806581962556404642459653E-1 +P 10 1 0 0E+0 +P 10 0 0 0E+0 +P 11 11 0 0E+0 +P 11 10 1 0E+0 +P 11 9 0 0E+0 +P 11 8 0 0E+0 +P 11 7 1 0E+0 +P 11 6 0 0E+0 +P 11 5 0 0E+0 +P 11 4 1 0E+0 +P 11 3 1 1.1005735584612756575783984806581962556404642459653E-1 +P 11 2 0 0E+0 +P 11 1 1 0E+0 +P 11 0 0 0E+0 +P 12 11 0 0E+0 +P 12 10 1 0E+0 +P 12 9 0 0E+0 +P 12 8 0 0E+0 +P 12 7 1 0E+0 +P 12 6 0 0E+0 +P 12 5 0 0E+0 +P 12 4 1 1.1005735584612756575783984806581962556404642459653E-1 +P 12 3 1 0E+0 +P 12 2 0 0E+0 +P 12 1 1 0E+0 +P 12 0 0 0E+0 +P 13 11 1 0E+0 +P 13 10 0 0E+0 +P 13 9 1 0E+0 +P 13 8 1 0E+0 +P 13 7 0 0E+0 +P 13 6 1 0E+0 +P 13 5 1 1.1005735584612756575783984806581962556404642459653E-1 +P 13 4 0 0E+0 +P 13 3 0 0E+0 +P 13 2 1 0E+0 +P 13 1 0 0E+0 +P 13 0 1 0E+0 +END +CASE random08 10 14 7 +Z 2.6189396722694609712858318187062440939281069588821E+0 +S 3 7 4 +S 5 3 4 +B 0 4 0 4 0.33048882165305291504344256279255451441825454156388 0 2.7182818284590452353602874713526624977572470937000 +B 0 4 1 7 0.016991409939943731326339904309512221901110099213043 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 1 9 0.0045696939403287305353706025612845839731925716873829 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 2 7 0.014890114977677886489757365674819381277454305356583 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 2 9 0.0040045686864593439619620997921710435612203524565393 0 27.474593022118317968158957115156725710168223409107 +B 0 4 3 6 0.015888007152973324950997356389453225866949813297540 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 3 7 0.0049756131409864156517276328886368033609317078513118 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 3 9 0.0013381484703241125519710583883646625255923393692360 0 47.560129945305985709087486769738443607156131247662 +B 0 4 4 5 0.0091782030655181053248927101580224846082432955642313 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 4 8 0.0028743181787205708151450942539439627372759139948521 0 87.731203791681321190944546078901879401131946924772 +B 0 4 4 10 0.00077302321645472597856255561925112211362012013839238 0 311.78226466067704164806091865122966830046788155628 +B 0 4 5 6 0.0024683989780628856987880639265917433495367778309232 0 27.474593022118317968158957115156725710168223409107 +B 0 4 5 7 0.00077302321645472597856255561925112211362012013839238 0 47.560129945305985709087486769738443607156131247662 +B 0 4 5 9 0.00020789796258533940515405285013758170164790090754877 0 346.29487777063361298524265019950882880627071075635 +B 0 4 6 5 0.0024683989780628856987880639265917433495367778309232 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 6 8 0.00077302321645472597856255561925112211362012013839238 0 311.78226466067704164806091865122966830046788155628 +B 0 4 6 10 0.00020789796258533940515405285013758170164790090754877 148.41315910257660342111558004055227962348766759389 1567.2253770152202986314837026829865158921500050328 +B 0 5 0 5 0.16476506760985839961885916240174236090806541568812 0 2.7182818284590452353602874713526624977572470937000 +B 0 5 1 7 0.041834841939173732908278507805967497756945154264362 0 7.3890560989306502272304274605750078131803155705521 +B 0 5 1 9 0.016991409939943731326339904309512221901110099213043 0 7.3890560989306502272304274605750078131803155705521 +B 0 5 2 7 0.036661207560114971545347897440116056709922211156669 0 7.3890560989306502272304274605750078131803155705521 +B 0 5 2 9 0.014890114977677886489757365674819381277454305356583 0 27.474593022118317968158957115156725710168223409107 +B 0 5 3 6 0.042938244726144139283621055726026493791105440179865 0 7.3890560989306502272304274605750078131803155705521 +B 0 5 3 7 0.012250542482311021851240781889181085031610444815464 0 7.3890560989306502272304274605750078131803155705521 +B 0 5 3 9 0.0049756131409864156517276328886368033609317078513118 0 47.560129945305985709087486769738443607156131247662 +B 0 5 4 8 0.0070769081032522604883101715233296439845875017077715 0 87.731203791681321190944546078901879401131946924772 +B 0 5 4 10 0.0028743181787205708151450942539439627372759139948521 0 311.78226466067704164806091865122966830046788155628 +B 0 5 4 11 0.0028743181787205708151450942539439627372759139948521 0 311.78226466067704164806091865122966830046788155628 +B 0 5 5 6 0.0066709889025945753719531411959774245968483655438427 0 7.3890560989306502272304274605750078131803155705521 +B 0 5 5 7 0.0019032737241934991253795611574782029375645586000796 0 27.474593022118317968158957115156725710168223409107 +B 0 5 5 9 0.00077302321645472597856255561925112211362012013839238 0 326.20934084744594524431412054492711090928280291780 +B 0 5 6 8 0.0019032737241934991253795611574782029375645586000796 0 182.50042767120089575091186659092619359789849964050 +B 0 5 6 10 0.00077302321645472597856255561925112211362012013839238 148.41315910257660342111558004055227962348766759389 1383.3453899925999136562243894198221627867898860783 +B 0 5 6 11 0.00077302321645472597856255561925112211362012013839238 0 2379.2706135581036686283870676566391479972636235627 +B 1 7 1 7 0.28148331799486344659849767489800235296208560547856 0 2.7182818284590452353602874713526624977572470937000 +B 1 7 2 9 0.061071872637918921239455012991051028388233977497875 0 7.3890560989306502272304274605750078131803155705521 +B 1 7 3 9 0.022597811240428544577102002620883967125656331030847 0 7.3890560989306502272304274605750078131803155705521 +B 1 7 3 13 0.0091782030655181053248927101580224846082432955642313 0 27.474593022118317968158957115156725710168223409107 +B 1 7 4 8 0.061071872637918921239455012991051028388233977497875 0 7.3890560989306502272304274605750078131803155705521 +B 1 7 4 10 0.017424176861369783214171392255032526078633387923156 0 47.560129945305985709087486769738443607156131247662 +B 1 7 4 11 0.017424176861369783214171392255032526078633387923156 0 47.560129945305985709087486769738443607156131247662 +B 1 7 4 12 0.017424176861369783214171392255032526078633387923156 0 47.560129945305985709087486769738443607156131247662 +B 1 7 5 9 0.0070769081032522604883101715233296439845875017077715 0 27.474593022118317968158957115156725710168223409107 +B 1 7 5 13 0.0028743181787205708151450942539439627372759139948521 0 455.49117783692209114146317260523058561185218483358 +B 1 7 6 8 0.024804616814369357327787098461001959193976902861854 0 7.3890560989306502272304274605750078131803155705521 +B 1 7 6 10 0.0070769081032522604883101715233296439845875017077715 0 142.32935382482556026905480728176275780392268396339 +B 1 7 6 11 0.0070769081032522604883101715233296439845875017077715 0 271.61119081430170616620385934206623250649206587918 +B 1 7 6 12 0.0070769081032522604883101715233296439845875017077715 0 400.89302780377785206335291140236970720906144779496 +B 1 9 1 9 0.60557780596085256576292347083901110332094601401879 0 2.7182818284590452353602874713526624977572470937000 +B 1 9 3 13 0.034127145676423074820933870859902911908743128590097 0 7.3890560989306502272304274605750078131803155705521 +B 1 9 4 10 0.13138885423635105608068448708721147630956337812699 0 7.3890560989306502272304274605750078131803155705521 +B 1 9 4 11 0.084025030898233013813016192263663766509742794641828 0 7.3890560989306502272304274605750078131803155705521 +B 1 9 4 12 0.036661207560114971545347897440116056709922211156669 0 7.3890560989306502272304274605750078131803155705521 +B 1 9 5 13 0.010687525053146196816592288405433700030142717643663 0 67.645666868493653450016016424320161504144039086217 +B 1 9 6 10 0.053364176375168263152110376044986442540031951823610 0 7.3890560989306502272304274605750078131803155705521 +B 1 9 6 11 0.034127145676423074820933870859902911908743128590097 0 27.474593022118317968158957115156725710168223409107 +B 1 9 6 12 0.014890114977677886489757365674819381277454305356583 0 47.560129945305985709087486769738443607156131247662 +B 2 7 2 7 0.28148331799486344659849767489800235296208560547856 0 2.7182818284590452353602874713526624977572470937000 +B 2 7 3 9 0.041834841939173732908278507805967497756945154264362 0 7.3890560989306502272304274605750078131803155705521 +B 2 7 3 13 0.016991409939943731326339904309512221901110099213043 0 7.3890560989306502272304274605750078131803155705521 +B 2 7 4 8 0.12849781178630883570719124787169329171380834105210 0 7.3890560989306502272304274605750078131803155705521 +B 2 7 4 10 0.036661207560114971545347897440116056709922211156669 0 27.474593022118317968158957115156725710168223409107 +B 2 7 4 11 0.036661207560114971545347897440116056709922211156669 0 27.474593022118317968158957115156725710168223409107 +B 2 7 4 12 0.036661207560114971545347897440116056709922211156669 0 27.474593022118317968158957115156725710168223409107 +B 2 7 5 9 0.026313938801997448819486676708413174615876324941286 0 27.474593022118317968158957115156725710168223409107 +B 2 7 5 13 0.010687525053146196816592288405433700030142717643663 0 271.61119081430170616620385934206623250649206587918 +B 2 7 6 8 0.024804616814369357327787098461001959193976902861854 0 7.3890560989306502272304274605750078131803155705521 +B 2 7 6 10 0.0070769081032522604883101715233296439845875017077715 0 122.24381690163789252812627762718103990693477612483 +B 2 7 6 11 0.0070769081032522604883101715233296439845875017077715 0 196.92750385796979934716506848462363620671342100200 +B 2 7 6 12 0.0070769081032522604883101715233296439845875017077715 0 271.61119081430170616620385934206623250649206587918 +B 2 7 8 9 0.0019032737241934991253795611574782029375645586000796 0 47.560129945305985709087486769738443607156131247662 +B 2 7 8 13 0.00077302321645472597856255561925112211362012013839238 0 1972.2937804765747734129733834954799189686371921373 +B 2 9 2 9 0.60557780596085256576292347083901110332094601401879 0 2.7182818284590452353602874713526624977572470937000 +B 2 9 3 13 0.063178850819591173308228602100773567214147197503087 0 7.3890560989306502272304274605750078131803155705521 +B 2 9 4 10 0.27644772516765442715333512983077384635176901904036 0 7.3890560989306502272304274605750078131803155705521 +B 2 9 4 11 0.17679223084762852975785353477267717585275865934736 0 7.3890560989306502272304274605750078131803155705521 +B 2 9 4 12 0.077136736527602632362371939714580505353748299654365 0 7.3890560989306502272304274605750078131803155705521 +B 2 9 5 13 0.039739230196314295303887019646304355335546786556655 0 67.645666868493653450016016424320161504144039086217 +B 2 9 6 10 0.053364176375168263152110376044986442540031951823610 0 7.3890560989306502272304274605750078131803155705521 +B 2 9 6 11 0.034127145676423074820933870859902911908743128590097 0 27.474593022118317968158957115156725710168223409107 +B 2 9 6 12 0.014890114977677886489757365674819381277454305356583 0 47.560129945305985709087486769738443607156131247662 +B 2 9 8 13 0.0028743181787205708151450942539439627372759139948521 0 291.69672773748937390713238899664795040347997371773 +B 3 1 3 1 0.39820156837986849357813618739426234501610579526901 0 2.7182818284590452353602874713526624977572470937000 +B 3 1 4 4 0.19592375093469875017492748275233555503938270460633 0 7.3890560989306502272304274605750078131803155705521 +B 3 1 4 5 0.072495696462238483569184324024644821726655997082579 0 7.3890560989306502272304274605750078131803155705521 +B 3 1 5 2 0.29700198656029549201637452354475457183687181906066 0 7.3890560989306502272304274605750078131803155705521 +B 3 1 5 3 0.29700198656029549201637452354475457183687181906066 0 7.3890560989306502272304274605750078131803155705521 +B 3 1 5 6 0.059076088287328044316975031561783339209242961615963 0 47.560129945305985709087486769738443607156131247662 +B 3 1 5 7 0.018500731927571822818039482556923437323009521292474 0 47.560129945305985709087486769738443607156131247662 +B 3 1 6 4 0.024804616814369357327787098461001959193976902861854 0 47.560129945305985709087486769738443607156131247662 +B 3 1 6 5 0.0091782030655181053248927101580224846082432955642313 0 67.645666868493653450016016424320161504144039086217 +B 3 1 7 4 0.024804616814369357327787098461001959193976902861854 0 47.560129945305985709087486769738443607156131247662 +B 3 1 7 5 0.0091782030655181053248927101580224846082432955642313 0 196.92750385796979934716506848462363620671342100200 +B 3 1 8 2 0.012409748535522723308292254330942406055843527882378 0 7.3890560989306502272304274605750078131803155705521 +B 3 1 8 3 0.012409748535522723308292254330942406055843527882378 0 27.474593022118317968158957115156725710168223409107 +B 3 1 8 6 0.0024683989780628856987880639265917433495367778309232 148.41315910257660342111558004055227962348766759389 917.06616095159522543498711796925069304326935329767 +B 3 1 8 7 0.00077302321645472597856255561925112211362012013839238 0 1194.7611570436479747532517500701064473693264028074 +B 3 1 9 4 0.0066709889025945753719531411959774245968483655438427 0 142.32935382482556026905480728176275780392268396339 +B 3 1 9 5 0.0024683989780628856987880639265917433495367778309232 0 420.97856472696551980428144105695142510604935563351 +B 3 2 3 2 0.61350444123810380558157925512175779452701763753189 0 2.7182818284590452353602874713526624977572470937000 +B 3 2 4 4 0.39298748526948431230843403600938131850850123157665 0 7.3890560989306502272304274605750078131803155705521 +B 3 2 4 5 0.072495696462238483569184324024644821726655997082579 0 7.3890560989306502272304274605750078131803155705521 +B 3 2 4 8 0.022703321852103512491204559826309118570321109005395 0 7.3890560989306502272304274605750078131803155705521 +B 3 2 5 3 0.45758744384818155441000804786090096322240371544586 0 7.3890560989306502272304274605750078131803155705521 +B 3 2 5 6 0.059076088287328044316975031561783339209242961615963 0 47.560129945305985709087486769738443607156131247662 +B 3 2 5 7 0.018500731927571822818039482556923437323009521292474 0 47.560129945305985709087486769738443607156131247662 +B 3 2 6 4 0.049753559425274326823828259162882386494476735887720 0 27.474593022118317968158957115156725710168223409107 +B 3 2 6 5 0.0091782030655181053248927101580224846082432955642313 0 47.560129945305985709087486769738443607156131247662 +B 3 2 6 8 0.0028743181787205708151450942539439627372759139948521 0 326.20934084744594524431412054492711090928280291780 +B 3 2 7 4 0.049753559425274326823828259162882386494476735887720 0 27.474593022118317968158957115156725710168223409107 +B 3 2 7 5 0.0091782030655181053248927101580224846082432955642313 0 122.24381690163789252812627762718103990693477612483 +B 3 2 8 3 0.019119552622977942934396900562373147314550045615686 0 7.3890560989306502272304274605750078131803155705521 +B 3 2 8 6 0.0024683989780628856987880639265917433495367778309232 148.41315910257660342111558004055227962348766759389 530.17486479325399796050196346267318191163082971075 +B 3 2 8 7 0.00077302321645472597856255561925112211362012013839238 0 807.86986088530674727876659556352893623768787922043 +B 3 2 9 4 0.013380792990049794998057787427408165855554883277151 0 47.560129945305985709087486769738443607156131247662 +B 3 2 9 5 0.0024683989780628856987880639265917433495367778309232 0 217.01304078115746708809359813920535410370132884056 +B 3 3 3 3 0.61350444123810380558157925512175779452701763753189 0 2.7182818284590452353602874713526624977572470937000 +B 3 3 4 4 0.39298748526948431230843403600938131850850123157665 0 7.3890560989306502272304274605750078131803155705521 +B 3 3 4 5 0.072495696462238483569184324024644821726655997082579 0 7.3890560989306502272304274605750078131803155705521 +B 3 3 4 8 0.022703321852103512491204559826309118570321109005395 0 7.3890560989306502272304274605750078131803155705521 +B 3 3 5 6 0.059076088287328044316975031561783339209242961615963 0 47.560129945305985709087486769738443607156131247662 +B 3 3 5 7 0.018500731927571822818039482556923437323009521292474 0 47.560129945305985709087486769738443607156131247662 +B 3 3 5 9 0.0049756131409864156517276328886368033609317078513118 0 67.645666868493653450016016424320161504144039086217 +B 3 3 6 4 0.049753559425274326823828259162882386494476735887720 0 7.3890560989306502272304274605750078131803155705521 +B 3 3 6 5 0.0091782030655181053248927101580224846082432955642313 0 27.474593022118317968158957115156725710168223409107 +B 3 3 6 8 0.0028743181787205708151450942539439627372759139948521 0 306.12380392425827750338559089034539301229489507924 +B 3 3 7 4 0.049753559425274326823828259162882386494476735887720 0 7.3890560989306502272304274605750078131803155705521 +B 3 3 7 5 0.0091782030655181053248927101580224846082432955642313 0 47.560129945305985709087486769738443607156131247662 +B 3 3 8 6 0.0024683989780628856987880639265917433495367778309232 0 291.69672773748937390713238899664795040347997371773 +B 3 3 8 7 0.00077302321645472597856255561925112211362012013839238 0 420.97856472696551980428144105695142510604935563351 +B 3 3 8 9 0.00020789796258533940515405285013758170164790090754877 0 1402.4767121057003711801909174000709677077081717564 +B 3 3 9 4 0.013380792990049794998057787427408165855554883277151 0 7.3890560989306502272304274605750078131803155705521 +B 3 3 9 5 0.0024683989780628856987880639265917433495367778309232 0 67.645666868493653450016016424320161504144039086217 +B 3 6 3 6 0.61350444123810380558157925512175779452701763753189 0 2.7182818284590452353602874713526624977572470937000 +B 3 6 4 8 0.19592375093469875017492748275233555503938270460633 0 7.3890560989306502272304274605750078131803155705521 +B 3 6 4 10 0.055898238258860159876524402625199587341211034390185 0 7.3890560989306502272304274605750078131803155705521 +B 3 6 4 11 0.055898238258860159876524402625199587341211034390185 0 7.3890560989306502272304274605750078131803155705521 +B 3 6 4 12 0.055898238258860159876524402625199587341211034390185 0 7.3890560989306502272304274605750078131803155705521 +B 3 6 5 7 0.15965649511114918626325956822228648584512562997031 0 7.3890560989306502272304274605750078131803155705521 +B 3 6 5 9 0.045550969500742637150663181893496705247165148174799 0 27.474593022118317968158957115156725710168223409107 +B 3 6 6 8 0.024804616814369357327787098461001959193976902861854 0 27.474593022118317968158957115156725710168223409107 +B 3 6 6 10 0.0070769081032522604883101715233296439845875017077715 0 122.24381690163789252812627762718103990693477612483 +B 3 6 6 11 0.0070769081032522604883101715233296439845875017077715 0 142.32935382482556026905480728176275780392268396339 +B 3 6 6 12 0.0070769081032522604883101715233296439845875017077715 0 162.41489074801322800998333693634447570091059180195 +B 3 6 8 7 0.0066709889025945753719531411959774245968483655438427 0 7.3890560989306502272304274605750078131803155705521 +B 3 6 8 9 0.0019032737241934991253795611574782029375645586000796 0 122.24381690163789252812627762718103990693477612483 +B 3 7 3 7 0.21405737884647353213076144001736008963651124192434 0 2.7182818284590452353602874713526624977572470937000 +B 3 7 4 8 0.19592375093469875017492748275233555503938270460633 0 7.3890560989306502272304274605750078131803155705521 +B 3 7 4 10 0.055898238258860159876524402625199587341211034390185 0 7.3890560989306502272304274605750078131803155705521 +B 3 7 4 11 0.055898238258860159876524402625199587341211034390185 0 7.3890560989306502272304274605750078131803155705521 +B 3 7 4 12 0.055898238258860159876524402625199587341211034390185 0 7.3890560989306502272304274605750078131803155705521 +B 3 7 5 9 0.045550969500742637150663181893496705247165148174799 0 27.474593022118317968158957115156725710168223409107 +B 3 7 5 13 0.018500731927571822818039482556923437323009521292474 0 87.731203791681321190944546078901879401131946924772 +B 3 7 6 8 0.024804616814369357327787098461001959193976902861854 0 7.3890560989306502272304274605750078131803155705521 +B 3 7 6 10 0.0070769081032522604883101715233296439845875017077715 54.598150033144239078110261202860878402790737038617 47.560129945305985709087486769738443607156131247662 +B 3 7 6 11 0.0070769081032522604883101715233296439845875017077715 0 122.24381690163789252812627762718103990693477612483 +B 3 7 6 12 0.0070769081032522604883101715233296439845875017077715 0 142.32935382482556026905480728176275780392268396339 +B 3 7 8 9 0.0019032737241934991253795611574782029375645586000796 0 47.560129945305985709087486769738443607156131247662 +B 3 7 8 13 0.00077302321645472597856255561925112211362012013839238 148.41315910257660342111558004055227962348766759389 1030.9667069442152575189209664615238121609541916915 +B 3 9 3 9 0.46051893502954919469027282809544873327874037310540 0 2.7182818284590452353602874713526624977572470937000 +B 3 9 4 10 0.42150659609895779822598577257433621639397465995371 0 7.3890560989306502272304274605750078131803155705521 +B 3 9 4 11 0.26955943079702404570269087728169058519577452405289 0 7.3890560989306502272304274605750078131803155705521 +B 3 9 4 12 0.11761226549509029317939598198904495399757438815206 0 7.3890560989306502272304274605750078131803155705521 +B 3 9 5 13 0.068790935339482393791181750887175010640950855469644 0 67.645666868493653450016016424320161504144039086217 +B 3 9 6 10 0.053364176375168263152110376044986442540031951823610 0 7.3890560989306502272304274605750078131803155705521 +B 3 9 6 11 0.034127145676423074820933870859902911908743128590097 0 27.474593022118317968158957115156725710168223409107 +B 3 9 6 12 0.014890114977677886489757365674819381277454305356583 0 47.560129945305985709087486769738443607156131247662 +B 3 9 8 13 0.0028743181787205708151450942539439627372759139948521 0 291.69672773748937390713238899664795040347997371773 +B 3 13 3 13 0.33077562923147857911039995251362008169053143171477 0 2.7182818284590452353602874713526624977572470937000 +B 4 0 4 0 0.62942334578478712888362208362083253458728556112915 0 2.7182818284590452353602874713526624977572470937000 +B 4 0 5 1 0.41461830172832741677534152002525295523798016496626 0 7.3890560989306502272304274605750078131803155705521 +B 4 0 5 2 0.41461830172832741677534152002525295523798016496626 0 7.3890560989306502272304274605750078131803155705521 +B 4 0 5 3 0.41461830172832741677534152002525295523798016496626 0 7.3890560989306502272304274605750078131803155705521 +B 4 0 5 6 0.049188434171404940250419756393768846082504516656876 0 7.3890560989306502272304274605750078131803155705521 +B 4 0 6 4 0.091665430708889885222114830572530682107579047185235 0 67.645666868493653450016016424320161504144039086217 +B 4 0 6 5 0.022138196598234125917796057057195578158348889774551 0 67.645666868493653450016016424320161504144039086217 +B 4 0 7 4 0.035663315384819533084107906725482212120426703215713 0 67.645666868493653450016016424320161504144039086217 +B 4 0 7 5 0.0086130778116487187514842073889089441962710763333876 0 251.52565389111403842527532968748451460950415804062 +B 4 0 8 1 0.041940352550848700822381065011392649201609932238908 0 7.3890560989306502272304274605750078131803155705521 +B 4 0 8 2 0.041940352550848700822381065011392649201609932238908 0 27.474593022118317968158957115156725710168223409107 +B 4 0 8 3 0.041940352550848700822381065011392649201609932238908 0 47.560129945305985709087486769738443607156131247662 +B 4 0 8 6 0.0049756131409864156517276328886368033609317078513118 148.41315910257660342111558004055227962348766759389 1154.5900831972726392713946907609430115753505871302 +B 4 0 9 4 0.0055407383948558022251361356577503437729039270821554 0 291.69672773748937390713238899664795040347997371773 +B 4 0 9 5 0.0013381484703241125519710583883646625255923393692360 0 659.45670178273014385765101552297665661420021162654 +B 4 4 4 4 0.56460444819158930505073692443263078451551347942110 0 2.7182818284590452353602874713526624977572470937000 +B 4 4 5 6 0.090734834985688233439120838495094507768449312375136 0 7.3890560989306502272304274605750078131803155705521 +B 4 4 5 7 0.028415233764263293656069215343106015239532118797745 0 7.3890560989306502272304274605750078131803155705521 +B 4 4 5 9 0.0076420333571216470617186742924431843965597209386152 0 7.3890560989306502272304274605750078131803155705521 +B 4 4 6 5 0.040836949763878294447038517091333653167449646323406 0 7.3890560989306502272304274605750078131803155705521 +B 4 4 6 8 0.012788820015412041653174827040126540653798511500123 0 47.560129945305985709087486769738443607156131247662 +B 4 4 6 10 0.0034394434325899573885535970230575031492481332256957 0 67.645666868493653450016016424320161504144039086217 +B 4 4 7 5 0.015888007152973324950997356389453225866949813297540 0 7.3890560989306502272304274605750078131803155705521 +B 4 4 8 6 0.0091782030655181053248927101580224846082432955642313 0 47.560129945305985709087486769738443607156131247662 +B 4 4 8 7 0.0028743181787205708151450942539439627372759139948521 0 67.645666868493653450016016424320161504144039086217 +B 4 4 8 9 0.00077302321645472597856255561925112211362012013839238 0 217.01304078115746708809359813920535410370132884056 +B 4 4 9 5 0.0024683989780628856987880639265917433495367778309232 0 7.3890560989306502272304274605750078131803155705521 +B 4 5 4 5 0.28148331799486344659849767489800235296208560547856 0 2.7182818284590452353602874713526624977572470937000 +B 4 5 5 6 0.24521606217131388268682976036795328376782853084255 0 7.3890560989306502272304274605750078131803155705521 +B 4 5 5 7 0.069961634578546586844770297444431676925476914516007 0 7.3890560989306502272304274605750078131803155705521 +B 4 5 5 9 0.028415233764263293656069215343106015239532118797745 0 7.3890560989306502272304274605750078131803155705521 +B 4 5 6 8 0.031487573181056210182417287074264615662899268048979 0 47.560129945305985709087486769738443607156131247662 +B 4 5 6 10 0.012788820015412041653174827040126540653798511500123 0 67.645666868493653450016016424320161504144039086217 +B 4 5 6 11 0.012788820015412041653174827040126540653798511500123 0 67.645666868493653450016016424320161504144039086217 +B 4 5 8 6 0.024804616814369357327787098461001959193976902861854 0 7.3890560989306502272304274605750078131803155705521 +B 4 5 8 7 0.0070769081032522604883101715233296439845875017077715 0 27.474593022118317968158957115156725710168223409107 +B 4 5 8 9 0.0028743181787205708151450942539439627372759139948521 0 176.84196693478213160623653883004191830972551316345 +B 4 8 4 8 0.80675222061905190279078962756087889726350881876597 0 2.7182818284590452353602874713526624977572470937000 +B 4 8 5 9 0.52755312809966977283434935979678606955141458771542 0 7.3890560989306502272304274605750078131803155705521 +B 4 8 5 13 0.10565584735707611827992367627953540323922172803145 0 7.3890560989306502272304274605750078131803155705521 +B 4 8 6 10 0.23743538623706303068904807430966132946700330588868 0 27.474593022118317968158957115156725710168223409107 +B 4 8 6 11 0.15184328823672356026181237407079674855225882632150 0 27.474593022118317968158957115156725710168223409107 +B 4 8 6 12 0.066251190236384089834576673831932167637514346754320 0 27.474593022118317968158957115156725710168223409107 +B 4 8 8 9 0.053364176375168263152110376044986442540031951823610 0 7.3890560989306502272304274605750078131803155705521 +B 4 8 8 13 0.010687525053146196816592288405433700030142717643663 0 251.52565389111403842527532968748451460950415804062 +B 4 10 4 10 0.80675222061905190279078962756087889726350881876597 0 2.7182818284590452353602874713526624977572470937000 +B 4 10 5 13 0.22444286176417223609247921931729045292485613298340 0 7.3890560989306502272304274605750078131803155705521 +B 4 10 6 11 0.23071989893020140383075237760320089000603936200662 0 7.3890560989306502272304274605750078131803155705521 +B 4 10 6 12 0.14512780092986193340351667736433630909129488243943 0 7.3890560989306502272304274605750078131803155705521 +B 4 10 8 13 0.022703321852103512491204559826309118570321109005395 0 47.560129945305985709087486769738443607156131247662 +B 4 11 4 11 0.58844998801552386817143553721445221578185302653146 0 2.7182818284590452353602874713526624977572470937000 +B 4 11 5 13 0.22444286176417223609247921931729045292485613298340 0 7.3890560989306502272304274605750078131803155705521 +B 4 11 6 12 0.14512780092986193340351667736433630909129488243943 0 7.3890560989306502272304274605750078131803155705521 +B 4 11 8 13 0.022703321852103512491204559826309118570321109005395 0 27.474593022118317968158957115156725710168223409107 +B 4 12 4 12 0.58844998801552386817143553721445221578185302653146 0 2.7182818284590452353602874713526624977572470937000 +B 4 12 5 13 0.30168347535698506071633368025371984092454574221711 0 7.3890560989306502272304274605750078131803155705521 +B 4 12 8 13 0.030516528726529138492651753977798855863187912654204 0 7.3890560989306502272304274605750078131803155705521 +B 5 1 5 1 0.58159422458506826072445679275856673761790011023893 0 2.7182818284590452353602874713526624977572470937000 +B 5 1 6 4 0.17779012302292396821909352548731102044225416728832 0 7.3890560989306502272304274605750078131803155705521 +B 5 1 6 5 0.065785892374783263943079677793214080467949479349271 0 7.3890560989306502272304274605750078131803155705521 +B 5 1 7 4 0.11036418387453405375135729060666875711667980373409 0 7.3890560989306502272304274605750078131803155705521 +B 5 1 7 5 0.040836949763878294447038517091333653167449646323406 0 27.474593022118317968158957115156725710168223409107 +B 5 1 8 2 0.046142942475380390495546142280778330448921519951829 0 7.3890560989306502272304274605750078131803155705521 +B 5 1 8 3 0.046142942475380390495546142280778330448921519951829 0 7.3890560989306502272304274605750078131803155705521 +B 5 1 8 6 0.0091782030655181053248927101580224846082432955642313 0 142.32935382482556026905480728176275780392268396339 +B 5 1 8 7 0.0028743181787205708151450942539439627372759139948521 0 142.32935382482556026905480728176275780392268396339 +B 5 1 9 4 0.0066709889025945753719531411959774245968483655438427 0 47.560129945305985709087486769738443607156131247662 +B 5 1 9 5 0.0024683989780628856987880639265917433495367778309232 0 87.731203791681321190944546078901879401131946924772 +B 5 2 5 2 0.89605533507338516588561919515942877913025738527603 0 2.7182818284590452353602874713526624977572470937000 +B 5 2 6 4 0.35661471883425978048266356427390709786957937896608 0 7.3890560989306502272304274605750078131803155705521 +B 5 2 6 5 0.065785892374783263943079677793214080467949479349271 0 7.3890560989306502272304274605750078131803155705521 +B 5 2 6 8 0.020602026889837667654622021191616277946665315148934 0 7.3890560989306502272304274605750078131803155705521 +B 5 2 7 4 0.22137052234737931956613114758613185250148898373217 0 7.3890560989306502272304274605750078131803155705521 +B 5 2 7 5 0.040836949763878294447038517091333653167449646323406 0 27.474593022118317968158957115156725710168223409107 +B 5 2 8 3 0.071091885086285359991587302982658757749421352977695 0 7.3890560989306502272304274605750078131803155705521 +B 5 2 8 6 0.0091782030655181053248927101580224846082432955642313 0 142.32935382482556026905480728176275780392268396339 +B 5 2 8 7 0.0028743181787205708151450942539439627372759139948521 0 142.32935382482556026905480728176275780392268396339 +B 5 2 9 4 0.013380792990049794998057787427408165855554883277151 0 27.474593022118317968158957115156725710168223409107 +B 5 2 9 5 0.0024683989780628856987880639265917433495367778309232 0 67.645666868493653450016016424320161504144039086217 +B 5 3 5 3 0.89605533507338516588561919515942877913025738527603 0 2.7182818284590452353602874713526624977572470937000 +B 5 3 6 4 0.35661471883425978048266356427390709786957937896608 0 7.3890560989306502272304274605750078131803155705521 +B 5 3 6 5 0.065785892374783263943079677793214080467949479349271 0 7.3890560989306502272304274605750078131803155705521 +B 5 3 6 8 0.020602026889837667654622021191616277946665315148934 0 7.3890560989306502272304274605750078131803155705521 +B 5 3 7 4 0.22137052234737931956613114758613185250148898373217 0 7.3890560989306502272304274605750078131803155705521 +B 5 3 7 5 0.040836949763878294447038517091333653167449646323406 0 27.474593022118317968158957115156725710168223409107 +B 5 3 8 6 0.0091782030655181053248927101580224846082432955642313 54.598150033144239078110261202860878402790737038617 87.731203791681321190944546078901879401131946924772 +B 5 3 8 7 0.0028743181787205708151450942539439627372759139948521 0 142.32935382482556026905480728176275780392268396339 +B 5 3 8 9 0.00077302321645472597856255561925112211362012013839238 0 162.41489074801322800998333693634447570091059180195 +B 5 3 9 4 0.013380792990049794998057787427408165855554883277151 0 7.3890560989306502272304274605750078131803155705521 +B 5 3 9 5 0.0024683989780628856987880639265917433495367778309232 0 47.560129945305985709087486769738443607156131247662 +B 5 6 5 6 0.89605533507338516588561919515942877913025738527603 0 2.7182818284590452353602874713526624977572470937000 +B 5 6 6 8 0.17779012302292396821909352548731102044225416728832 0 7.3890560989306502272304274605750078131803155705521 +B 5 6 6 10 0.050724603879801398513593792259348146294188091282492 0 7.3890560989306502272304274605750078131803155705521 +B 5 6 6 11 0.050724603879801398513593792259348146294188091282492 0 7.3890560989306502272304274605750078131803155705521 +B 5 6 6 12 0.050724603879801398513593792259348146294188091282492 0 7.3890560989306502272304274605750078131803155705521 +B 5 6 8 7 0.024804616814369357327787098461001959193976902861854 0 7.3890560989306502272304274605750078131803155705521 +B 5 6 8 9 0.0070769081032522604883101715233296439845875017077715 0 27.474593022118317968158957115156725710168223409107 +B 5 7 5 7 0.31264200131970379715456599524859554709340289439677 0 2.7182818284590452353602874713526624977572470937000 +B 5 7 6 8 0.17779012302292396821909352548731102044225416728832 0 7.3890560989306502272304274605750078131803155705521 +B 5 7 6 10 0.050724603879801398513593792259348146294188091282492 0 7.3890560989306502272304274605750078131803155705521 +B 5 7 6 11 0.050724603879801398513593792259348146294188091282492 0 7.3890560989306502272304274605750078131803155705521 +B 5 7 6 12 0.050724603879801398513593792259348146294188091282492 0 7.3890560989306502272304274605750078131803155705521 +B 5 7 8 9 0.0070769081032522604883101715233296439845875017077715 0 27.474593022118317968158957115156725710168223409107 +B 5 7 8 13 0.0028743181787205708151450942539439627372759139948521 0 87.731203791681321190944546078901879401131946924772 +B 5 9 5 9 0.67261199903097314390700000254034843959362022862879 0 2.7182818284590452353602874713526624977572470937000 +B 5 9 6 10 0.38249425716836640176169871705322369950920894680203 0 7.3890560989306502272304274605750078131803155705521 +B 5 9 6 11 0.24461048818611907620664971657981015789527469102702 0 7.3890560989306502272304274605750078131803155705521 +B 5 9 6 12 0.10672671920387175065160071610639661628134043525201 0 7.3890560989306502272304274605750078131803155705521 +B 5 9 8 13 0.010687525053146196816592288405433700030142717643663 0 67.645666868493653450016016424320161504144039086217 +B 5 13 5 13 0.48311511272351296361475479473275643160567323574107 0 2.7182818284590452353602874713526624977572470937000 +B 6 0 6 0 0.47865256294132397664610678536047326787586891042343 0 2.7182818284590452353602874713526624977572470937000 +B 6 0 7 4 0.12178800769885361608108660164026255045510182331879 0 7.3890560989306502272304274605750078131803155705521 +B 6 0 7 5 0.029413125939558732117309206057739859829027626738701 0 7.3890560989306502272304274605750078131803155705521 +B 6 0 8 1 0.10326206159697820214419269744874729714103161787534 0 7.3890560989306502272304274605750078131803155705521 +B 6 0 8 2 0.10326206159697820214419269744874729714103161787534 0 7.3890560989306502272304274605750078131803155705521 +B 6 0 8 3 0.10326206159697820214419269744874729714103161787534 0 7.3890560989306502272304274605750078131803155705521 +B 6 0 8 6 0.012250542482311021851240781889181085031610444815464 0 47.560129945305985709087486769738443607156131247662 +B 6 0 9 4 0.020602026889837667654622021191616277946665315148934 0 67.645666868493653450016016424320161504144039086217 +B 6 0 9 5 0.0049756131409864156517276328886368033609317078513118 0 87.731203791681321190944546078901879401131946924772 +B 6 4 6 4 0.42936025170470884413420450774485553914742308418722 0 2.7182818284590452353602874713526624977572470937000 +B 6 4 7 5 0.054256557938788733699247809554195135684862681790020 0 7.3890560989306502272304274605750078131803155705521 +B 6 4 8 6 0.022597811240428544577102002620883967125656331030847 0 27.474593022118317968158957115156725710168223409107 +B 6 4 8 7 0.0070769081032522604883101715233296439845875017077715 0 27.474593022118317968158957115156725710168223409107 +B 6 4 8 9 0.0019032737241934991253795611574782029375645586000796 0 27.474593022118317968158957115156725710168223409107 +B 6 4 9 5 0.0091782030655181053248927101580224846082432955642313 0 7.3890560989306502272304274605750078131803155705521 +B 6 5 6 5 0.21405737884647353213076144001736008963651124192434 0 2.7182818284590452353602874713526624977572470937000 +B 6 5 8 6 0.061071872637918921239455012991051028388233977497875 0 7.3890560989306502272304274605750078131803155705521 +B 6 5 8 7 0.017424176861369783214171392255032526078633387923156 0 7.3890560989306502272304274605750078131803155705521 +B 6 5 8 9 0.0070769081032522604883101715233296439845875017077715 0 7.3890560989306502272304274605750078131803155705521 +B 6 8 6 8 0.61350444123810380558157925512175779452701763753189 0 2.7182818284590452353602874713526624977572470937000 +B 6 8 8 9 0.13138885423635105608068448708721147630956337812699 0 7.3890560989306502272304274605750078131803155705521 +B 6 8 8 13 0.026313938801997448819486676708413174615876324941286 0 7.3890560989306502272304274605750078131803155705521 +B 6 10 6 10 0.61350444123810380558157925512175779452701763753189 0 2.7182818284590452353602874713526624977572470937000 +B 6 10 8 13 0.055898238258860159876524402625199587341211034390185 0 7.3890560989306502272304274605750078131803155705521 +B 6 11 6 11 0.44749387961648362609003846500988007374455162150522 0 2.7182818284590452353602874713526624977572470937000 +B 6 11 8 13 0.055898238258860159876524402625199587341211034390185 0 7.3890560989306502272304274605750078131803155705521 +B 6 12 6 12 0.44749387961648362609003846500988007374455162150522 0 2.7182818284590452353602874713526624977572470937000 +B 6 12 8 13 0.075135268957605348207700907810283117972499857623698 0 7.3890560989306502272304274605750078131803155705521 +B 7 4 7 4 0.56460444819158930505073692443263078451551347942110 0 2.7182818284590452353602874713526624977572470937000 +B 7 4 8 6 0.036017419415338983829311295083745449643069366497463 0 7.3890560989306502272304274605750078131803155705521 +B 7 4 8 7 0.011279498027783950161475248792715325231899089420691 0 7.3890560989306502272304274605750078131803155705521 +B 7 4 8 9 0.0030335242319322722721965666957052837615089970617668 0 7.3890560989306502272304274605750078131803155705521 +B 7 4 9 5 0.022597811240428544577102002620883967125656331030847 0 7.3890560989306502272304274605750078131803155705521 +B 7 5 7 5 0.28148331799486344659849767489800235296208560547856 0 2.7182818284590452353602874713526624977572470937000 +B 7 5 8 6 0.097339128461468485151122927521100097582491052133898 0 7.3890560989306502272304274605750078131803155705521 +B 7 5 8 7 0.027771445619487305940032612986735408172679274138539 0 7.3890560989306502272304274605750078131803155705521 +B 7 5 8 9 0.011279498027783950161475248792715325231899089420691 0 7.3890560989306502272304274605750078131803155705521 +B 8 1 8 1 0.21480891217466872643181558202995795241431148029907 0 2.7182818284590452353602874713526624977572470937000 +B 8 1 9 4 0.079205500549693703195288970256075562985362514815886 0 7.3890560989306502272304274605750078131803155705521 +B 8 1 9 5 0.029307615327883764203206648852314708384362848764155 0 7.3890560989306502272304274605750078131803155705521 +B 8 2 8 2 0.33095354740282244527753931508408680992377788978774 0 2.7182818284590452353602874713526624977572470937000 +B 8 2 9 4 0.15887185873094792230113967436930504841124229371942 0 7.3890560989306502272304274605750078131803155705521 +B 8 2 9 5 0.029307615327883764203206648852314708384362848764155 0 7.3890560989306502272304274605750078131803155705521 +B 8 3 8 3 0.33095354740282244527753931508408680992377788978774 0 2.7182818284590452353602874713526624977572470937000 +B 8 3 9 4 0.15887185873094792230113967436930504841124229371942 0 7.3890560989306502272304274605750078131803155705521 +B 8 3 9 5 0.029307615327883764203206648852314708384362848764155 0 7.3890560989306502272304274605750078131803155705521 +B 8 6 8 6 0.33095354740282244527753931508408680992377788978774 0 2.7182818284590452353602874713526624977572470937000 +B 8 7 8 7 0.11547275637324326710695688478612463217961958945191 0 2.7182818284590452353602874713526624977572470937000 +B 8 9 8 9 0.24842587102812524547354565365054902696386051758204 0 2.7182818284590452353602874713526624977572470937000 +B 8 13 8 13 0.17843614573944419460604511029448373177538962768851 0 2.7182818284590452353602874713526624977572470937000 +B 9 4 9 4 0.52823168175636477322496645269715656387659162681053 0 2.7182818284590452353602874713526624977572470937000 +B 9 5 9 5 0.26334969008308866464266371763297781836495706816056 0 2.7182818284590452353602874713526624977572470937000 +P 0 13 0 0E+0 +P 0 12 0 0E+0 +P 0 11 0 0E+0 +P 0 10 0 0E+0 +P 0 9 0 0E+0 +P 0 8 0 0E+0 +P 0 7 0 0E+0 +P 0 6 0 0E+0 +P 0 5 1 1.1472681761368075886742677292520335343101852290935E-1 +P 0 4 1 3.0854793398279495066268150027989757421959708991976E-2 +P 0 3 0 0E+0 +P 0 2 0 0E+0 +P 0 1 0 0E+0 +P 0 0 0 0E+0 +P 1 13 0 0E+0 +P 1 12 0 0E+0 +P 1 11 0 0E+0 +P 1 10 0 0E+0 +P 1 9 1 0E+0 +P 1 8 0 0E+0 +P 1 7 1 0E+0 +P 1 6 0 0E+0 +P 1 5 0 0E+0 +P 1 4 0 0E+0 +P 1 3 0 0E+0 +P 1 2 0 0E+0 +P 1 1 0 0E+0 +P 1 0 0 0E+0 +P 2 13 0 0E+0 +P 2 12 0 0E+0 +P 2 11 0 0E+0 +P 2 10 0 0E+0 +P 2 9 1 0E+0 +P 2 8 0 0E+0 +P 2 7 1 0E+0 +P 2 6 0 0E+0 +P 2 5 0 0E+0 +P 2 4 0 0E+0 +P 2 3 0 0E+0 +P 2 2 0 0E+0 +P 2 1 0 0E+0 +P 2 0 0 0E+0 +P 3 13 1 0E+0 +P 3 12 0 0E+0 +P 3 11 0 0E+0 +P 3 10 0 0E+0 +P 3 9 1 0E+0 +P 3 8 0 0E+0 +P 3 7 1 6.4669451901778215288896242660336270688481085283579E-1 +P 3 6 1 0E+0 +P 3 5 0 0E+0 +P 3 4 0 0E+0 +P 3 3 1 0E+0 +P 3 2 1 3.6634289025988455027090264161684414145819496466147E-1 +P 3 1 1 3.6634289025988455027090264161684414145819496466147E-1 +P 3 0 0 0E+0 +P 4 13 0 0E+0 +P 4 12 1 0E+0 +P 4 11 1 0E+0 +P 4 10 1 0E+0 +P 4 9 0 0E+0 +P 4 8 1 6.4669451901778215288896242660336270688481085283579E-1 +P 4 7 0 0E+0 +P 4 6 0 0E+0 +P 4 5 1 0E+0 +P 4 4 1 0E+0 +P 4 3 0 0E+0 +P 4 2 0 0E+0 +P 4 1 0 0E+0 +P 4 0 1 7.3844646472608781889979660521902350809507355578890E-1 +P 5 13 1 0E+0 +P 5 12 0 0E+0 +P 5 11 0 0E+0 +P 5 10 0 0E+0 +P 5 9 1 6.4669451901778215288896242660336270688481085283579E-1 +P 5 8 0 0E+0 +P 5 7 1 0E+0 +P 5 6 1 0E+0 +P 5 5 0 0E+0 +P 5 4 0 0E+0 +P 5 3 1 1.9722451532516788183968693921028813870432961060463E+0 +P 5 2 1 0E+0 +P 5 1 1 0E+0 +P 5 0 0 0E+0 +P 6 13 0 0E+0 +P 6 12 1 0E+0 +P 6 11 1 0E+0 +P 6 10 1 6.4669451901778215288896242660336270688481085283579E-1 +P 6 9 0 0E+0 +P 6 8 1 0E+0 +P 6 7 0 0E+0 +P 6 6 0 0E+0 +P 6 5 1 0E+0 +P 6 4 1 1.9722451532516788183968693921028813870432961060463E+0 +P 6 3 0 0E+0 +P 6 2 0 0E+0 +P 6 1 0 0E+0 +P 6 0 1 0E+0 +P 7 13 0 0E+0 +P 7 12 0 0E+0 +P 7 11 0 0E+0 +P 7 10 0 0E+0 +P 7 9 0 0E+0 +P 7 8 0 0E+0 +P 7 7 0 0E+0 +P 7 6 0 0E+0 +P 7 5 1 1.9722451532516788183968693921028813870432961060463E+0 +P 7 4 1 0E+0 +P 7 3 0 0E+0 +P 7 2 0 0E+0 +P 7 1 0 0E+0 +P 7 0 0 0E+0 +P 8 13 1 1.1472681761368075886742677292520335343101852290935E-1 +P 8 12 0 0E+0 +P 8 11 0 0E+0 +P 8 10 0 0E+0 +P 8 9 1 0E+0 +P 8 8 0 0E+0 +P 8 7 1 0E+0 +P 8 6 1 1.9722451532516788183968693921028813870432961060463E+0 +P 8 5 0 0E+0 +P 8 4 0 0E+0 +P 8 3 1 0E+0 +P 8 2 1 0E+0 +P 8 1 1 0E+0 +P 8 0 0 0E+0 +P 9 13 0 0E+0 +P 9 12 0 0E+0 +P 9 11 0 0E+0 +P 9 10 0 0E+0 +P 9 9 0 0E+0 +P 9 8 0 0E+0 +P 9 7 0 0E+0 +P 9 6 0 0E+0 +P 9 5 1 0E+0 +P 9 4 1 0E+0 +P 9 3 0 0E+0 +P 9 2 0 0E+0 +P 9 1 0 0E+0 +P 9 0 0 0E+0 +END +CASE random09 15 13 8 +Z 3.6482022900263229041784731414666952674058608368036E+0 +S 0 3 5 +S 5 1 5 +B 0 1 0 1 0.26303194965333685193754815100891447200911099316975 0 2.7182818284590452353602874713526624977572470937000 +B 0 1 1 2 0.017795003478060391654466047877489316650040178579053 0 7.3890560989306502272304274605750078131803155705521 +B 0 1 1 4 0.0052738901346756608512443098440777250952052020160477 0 7.3890560989306502272304274605750078131803155705521 +B 0 1 1 8 0.00080449380401872740606934972862833154024160527482372 0 7.3890560989306502272304274605750078131803155705521 +B 0 1 2 3 0.0062745315303705722091862046597250441606997161318407 0 27.474593022118317968158957115156725710168223409107 +B 0 1 2 5 0.0019759219050722008056791647292801125900536820514734 0 47.560129945305985709087486769738443607156131247662 +B 0 1 3 3 0.0052362313802415305135958115095096608029383318752137 0 27.474593022118317968158957115156725710168223409107 +B 0 1 3 5 0.0016489492855627788481810075048971379530021141142556 0 122.24381690163789252812627762718103990693477612483 +B 0 1 3 6 0.00068678600552261761483244084027971864043997968375863 0 251.52565389111403842527532968748451460950415804062 +B 0 1 3 7 0.00048286362126894186461110262053395635496090395183745 0 251.52565389111403842527532968748451460950415804062 +B 0 1 4 3 0.0047170813051770096658006149344019691240576397469002 0 27.474593022118317968158957115156725710168223409107 +B 0 1 4 5 0.0014854629758080678694319288927056506344763301456467 0 196.92750385796979934716506848462363620671342100200 +B 0 1 4 6 0.00061869409352924747277594158520403717415715240507798 0 658.50248697264293364068901384864374363813058946609 +B 0 1 4 7 0.00043498974652505410829073316923541237215472255481294 0 1342.2201013361373679574053284363258140167444482408 +B 0 1 5 3 0.0041979312301124888180054183592942774451769476185867 0 27.474593022118317968158957115156725710168223409107 +B 0 1 5 5 0.0013219766660533568906828502805141633159505461770378 0 271.61119081430170616620385934206623250649206587918 +B 0 1 6 2 0.0025074572626607261706327763073264810710965741447187 0 7.3890560989306502272304274605750078131803155705521 +B 0 1 6 4 0.00074313298881741089696464122633435486307285542161379 0 326.20934084744594524431412054492711090928280291780 +B 0 1 6 8 0.00011335956377526856683248606114103718687402123182666 0 8887.4531648571570383219333334698031028139792844189 +B 0 1 7 3 0.0012292847896278899581356880376320405908531454203273 0 47.560129945305985709087486769738443607156131247662 +B 0 1 7 5 0.00038711587178116635197036371793686838934854115778840 0 1253.1093381930365575421133356851857751081508820021 +B 0 1 7 6 0.00016123343851915632315285551243958116968020262885119 0 2988.3045409652661961260645913868786220760988374603 +B 0 1 7 7 0.00011335956377526856683248606114103718687402123182666 0 5462.0174996615850792085672436735619177387585968197 +B 0 3 0 3 0.31064420004183214319394715133935057236560782329739 0 2.7182818284590452353602874713526624977572470937000 +B 0 3 1 4 0.035304740997488137692718829706964666157514270077992 0 7.3890560989306502272304274605750078131803155705521 +B 0 3 1 8 0.0092916782267734413132461449864638426149519565654467 0 7.3890560989306502272304274605750078131803155705521 +B 0 3 1 9 0.0071048373382014421860305850064678808225519818366749 0 7.3890560989306502272304274605750078131803155705521 +B 0 3 2 5 0.022910599872165301212860451613445751512085567606515 0 27.474593022118317968158957115156725710168223409107 +B 0 3 3 5 0.019119387863479974243270157162120831322586769813170 0 27.474593022118317968158957115156725710168223409107 +B 0 3 3 6 0.017602906071907003277015700272377517268420652416019 0 102.15827997845022478719774797259932200994686828628 +B 0 3 3 7 0.0068894990603450911403897831971627789762272338348387 0 102.15827997845022478719774797259932200994686828628 +B 0 3 3 10 0.0012411045170554273477383310654056133820439626504133 0 142.32935382482556026905480728176275780392268396339 +B 0 3 4 5 0.017223781859137310758475009936458371227837370916498 0 27.474593022118317968158957115156725710168223409107 +B 0 3 4 6 0.015857652788588056694133452153392393911203875135891 0 176.84196693478213160623653883004191830972551316345 +B 0 3 4 7 0.0062064345250704641082190043056297903179104859445352 148.41315910257660342111558004055227962348766759389 306.12380392425827750338559089034539301229489507924 +B 0 3 4 10 0.0011180542817996811404615120607684010304714704451166 0 772.40303296526296572462286234091686275581542785991 +B 0 3 5 5 0.015328175854794647273679862710795911133087972019826 0 27.474593022118317968158957115156725710168223409107 +B 0 3 6 4 0.0049747182870546157402138127651140863616277848361281 0 7.3890560989306502272304274605750078131803155705521 +B 0 3 6 8 0.0013092712277777580194731744792338223958676556183544 403.42879349273512260838718054338827960589989735717 2194.4364117253960734361657527191418819158338824479 +B 0 3 6 9 0.0010011279854854012307992664221348799049495227515535 403.42879349273512260838718054338827960589989735717 2214.5219486485837411770942823737235998128217902865 +B 0 3 7 5 0.0044885664862441366790427659538164006338474948374145 0 47.560129945305985709087486769738443607156131247662 +B 0 3 7 6 0.0041325493692078921340484884454189141601231805735893 0 346.29487777063361298524265019950882880627071075635 +B 0 3 7 7 0.0016174144700701148081470825363327648867857884851552 0 1104.6961790904599541209977556446334954846632144082 +B 0 3 7 10 0.00029136812229339083932962481533978042373617836373937 2596.6951103496523211358276571196311444903381670246 14239.484415932135018992565653757188023452825810906 +B 0 5 0 5 0.65886868730819787335632356284003753555788276274060 0 2.7182818284590452353602874713526624977572470937000 +B 0 5 1 8 0.042696509872740983075359487579986059294945177525294 0 7.3890560989306502272304274605750078131803155705521 +B 0 5 1 9 0.021196718753578671722353153540121292009844190595842 0 7.3890560989306502272304274605750078131803155705521 +B 0 5 1 11 0.0011442466605327087644555269130441746449169294599854 0 7.3890560989306502272304274605750078131803155705521 +B 0 5 3 6 0.052812447153875609290596984382300737320845858234201 0 7.3890560989306502272304274605750078131803155705521 +B 0 5 3 7 0.042099040142313697153971067307085999028652439653019 0 7.3890560989306502272304274605750078131803155705521 +B 0 5 3 10 0.0027575863086283983139927879551489274362100800475649 0 47.560129945305985709087486769738443607156131247662 +B 0 5 3 12 0.000075018852761590364168426181042431784002752487995140 0 67.645666868493653450016016424320161504144039086217 +B 0 5 4 6 0.047576317595557489683950341720223590444913784528985 0 7.3890560989306502272304274605750078131803155705521 +B 0 5 4 7 0.037925099332039897098035893872460986851620395337627 0 27.474593022118317968158957115156725710168223409107 +B 0 5 4 10 0.0024841833523489352048030698438343783471049662257240 0 87.731203791681321190944546078901879401131946924772 +B 0 5 4 12 0.000067581052516667379320316337298162768149862854282859 0 237.09857770434513482902212779378707200068923667911 +B 0 5 6 8 0.0060162772040289028816143872441957686070532323116258 0 142.32935382482556026905480728176275780392268396339 +B 0 5 6 9 0.0029867859508297691362470828886245464001710117239228 0 162.41489074801322800998333693634447570091059180195 +B 0 5 6 11 0.00016123343851915632315285551243958116968020262885119 0 550.26040171644166570143049311725489980861873754931 +B 0 5 7 6 0.012398523532451580162010595008548565356306880970629 0 7.3890560989306502272304274605750078131803155705521 +B 0 5 7 7 0.0098833886333138028361091890994624160829694888821946 0 47.560129945305985709087486769738443607156131247662 +B 0 5 7 10 0.00064738523932963538432390232373726689746049262756474 0 1010.8811700210275897779924368069420942639662838529 +B 0 5 7 12 0.000017611814287493054191747158543949221261658437777614 0 2894.4895318958338317830592725491872208554019069050 +B 1 0 1 0 0.054074036095181836797037867708640490838115103823296 0 2.7182818284590452353602874713526624977572470937000 +B 1 0 2 1 0.022393917148027496362659157711021751142983412324178 0 7.3890560989306502272304274605750078131803155705521 +B 1 0 2 3 0.0046069856512570654056492617527347034513250487733121 0 7.3890560989306502272304274605750078131803155705521 +B 1 0 2 5 0.00064274950602286832018031129841123167242843822157473 0 7.3890560989306502272304274605750078131803155705521 +B 1 0 3 1 0.017847607538406590532578408959278874145047290767947 0 7.3890560989306502272304274605750078131803155705521 +B 1 0 3 3 0.0036716967065294796613102714859235988638127719606816 0 27.474593022118317968158957115156725710168223409107 +B 1 0 3 5 0.00051226147052219912805538245002975030500305638256579 0 47.560129945305985709087486769738443607156131247662 +B 1 0 3 6 0.00013776832799532409018501531982951379851471315244423 0 67.645666868493653450016016424320161504144039086217 +B 1 0 3 7 0.00013776832799532409018501531982951379851471315244423 0 67.645666868493653450016016424320161504144039086217 +B 1 0 4 1 0.016884055598334012082317961658168349495141945526211 0 7.3890560989306502272304274605750078131803155705521 +B 1 0 4 3 0.0034734701107618750030770029279477181434739689471128 0 47.560129945305985709087486769738443607156131247662 +B 1 0 4 5 0.00048460563302779375747114280250834380567352086719736 0 142.32935382482556026905480728176275780392268396339 +B 1 0 4 6 0.00013033052775040110533690547608524478266182351873195 0 291.69672773748937390713238899664795040347997371773 +B 1 0 4 7 0.00013033052775040110533690547608524478266182351873195 0 475.57671476010975888239170225981230350884009267213 +B 1 0 5 1 0.015920503658261433632057514357057824845236600284475 0 7.3890560989306502272304274605750078131803155705521 +B 1 0 5 3 0.0032752435149942703448437343699718374231351659335440 0 67.645666868493653450016016424320161504144039086217 +B 1 0 5 5 0.00045694979553338838688690315498693730634398535182899 0 291.69672773748937390713238899664795040347997371773 +B 1 0 6 2 0.0013708110503742666582885966640720029751896665919202 0 87.731203791681321190944546078901879401131946924772 +B 1 0 6 4 0.00020910731326304407947322496373812515248638402587572 0 495.66225168329742662332023191439402140582800051069 +B 1 0 7 1 0.0042086787095438730423361627040502431512389260992538 0 7.3890560989306502272304274605750078131803155705521 +B 1 0 7 3 0.00086582987234672242829330068549028510127594152278967 0 326.20934084744594524431412054492711090928280291780 +B 1 0 7 5 0.00012079736402019155168059590488530620272691086553894 0 2081.4900805428632515691939059012016757742186662145 +B 1 0 7 6 0.000032487414777339023887966846032487252967437705202176 0 3410.6626650436512051546934791160682066896098124077 +B 1 0 7 7 0.000032487414777339023887966846032487252967437705202176 0 4387.4565664960545026028896293726363869791652642141 +B 1 0 8 2 0.00042929395803898301630266350746553080701444983646059 0 107.81674071486898893187307573348359729811985476333 +B 1 0 8 4 0.000065485689031380810512116609842493204067839834802139 0 1640.9548491614649952335604918660961992158590277495 +B 1 2 1 2 0.072435462537959366942098020926719933154760003823015 0 2.7182818284590452353602874713526624977572470937000 +B 1 2 2 3 0.024610978990788702842675106181841508211797367560072 0 7.3890560989306502272304274605750078131803155705521 +B 1 2 2 5 0.011595682861149027827461269686749562291655670036687 0 7.3890560989306502272304274605750078131803155705521 +B 1 2 3 3 0.019614571727673668318141037042325916677696320172066 0 7.3890560989306502272304274605750078131803155705521 +B 1 2 3 5 0.0092415808934902906520793152973108229684555166566699 0 27.474593022118317968158957115156725710168223409107 +B 1 2 3 6 0.0074746167042232128665166872142637804358064872525513 0 47.560129945305985709087486769738443607156131247662 +B 1 2 3 7 0.0071001235616963378286463200840635439293181440224299 0 47.560129945305985709087486769738443607156131247662 +B 1 2 4 3 0.018555625389839749031188010384099586175548018240401 0 7.3890560989306502272304274605750078131803155705521 +B 1 2 4 5 0.0087426488556752521900202485259802687730514704100126 0 47.560129945305985709087486769738443607156131247662 +B 1 2 4 6 0.0070710790641695152411501998000490320926453976958224 0 142.32935382482556026905480728176275780392268396339 +B 1 2 4 7 0.0067168039588921225890159624736259330696337003473570 0 271.61119081430170616620385934206623250649206587918 +B 1 2 5 3 0.017496679052005829744234983725873255673399716308737 0 7.3890560989306502272304274605750078131803155705521 +B 1 2 5 5 0.0082437168178602137279611817546497145776474241633554 0 67.645666868493653450016016424320161504144039086217 +B 1 2 6 4 0.0028359975495977574747535278507467649476446140135316 0 87.731203791681321190944546078901879401131946924772 +B 1 2 6 8 0.0011058812026457090749107094875135461259112471109099 0 1879.4329862172296192869300663321214307240098837425 +B 1 2 6 9 0.00053746859280488325388326282461420512688116277433270 0 1879.4329862172296192869300663321214307240098837425 +B 1 2 7 3 0.0046253499383285647445388296237791420753931780080476 0 7.3890560989306502272304274605750078131803155705521 +B 1 2 7 5 0.0021792749905140791259334521289946049988550565166176 0 326.20934084744594524431412054492711090928280291780 +B 1 2 7 6 0.0017626037617293874237307852092657060747008046078238 0 734.14038873906205067668980638041925291397885650372 +B 1 2 7 7 0.0016742938124865348959381561504128871249413314474870 0 1250.3135218868794240483240129473002387481867620064 +B 1 2 8 4 0.00088814327308149138283763021672309214883461042392651 0 107.81674071486898893187307573348359729811985476333 +B 1 2 8 8 0.00034632644555576690454994456490131130902584329035538 0 8419.0305883643841164986248712479521622004107222291 +B 1 2 8 9 0.00016831788703764463205280581070256807216368615844268 0 13527.859122605198608611621278280910852200752748244 +B 1 4 1 4 0.14980923130854855290248981052400747617756435534403 0 2.7182818284590452353602874713526624977572470937000 +B 1 4 2 5 0.10872227272446246175324446218430521262111424577591 0 7.3890560989306502272304274605750078131803155705521 +B 1 4 3 5 0.086649979163682441114652805984967722383294492142116 0 7.3890560989306502272304274605750078131803155705521 +B 1 4 3 6 0.083865037070202035619268284079274110330973119794121 0 27.474593022118317968158957115156725710168223409107 +B 1 4 3 7 0.064190407070102090716173629263967136893367853956219 0 27.474593022118317968158957115156725710168223409107 +B 1 4 3 10 0.0046896746107428073711321653085701683834851149045570 0 27.474593022118317968158957115156725710168223409107 +B 1 4 4 5 0.081971942886229158310329369345267760461240796086189 0 7.3890560989306502272304274605750078131803155705521 +B 1 4 4 6 0.079337353513772469716857746546251485146452045354738 0 47.560129945305985709087486769738443607156131247662 +B 1 4 4 7 0.060724912261716844364474560958396646407746808906662 0 122.24381690163789252812627762718103990693477612483 +B 1 4 4 10 0.0044364896917128266476785770010327567778566469643721 0 196.92750385796979934716506848462363620671342100200 +B 1 4 5 5 0.077293906608775875506005932705567798539187100030267 0 7.3890560989306502272304274605750078131803155705521 +B 1 4 6 8 0.0080034443947067647860581926306107114851426632870400 0 698.67356081901826912254607315780717943210640514320 +B 1 4 6 9 0.0024151309307785430514611936564994012043891999291855 0 698.67356081901826912254607315780717943210640514320 +B 1 4 6 11 0.00020910731326304407947322496373812515248638402587572 0 1308.6617030362680068371855985623795664870112412012 +B 1 4 7 5 0.020433098481342379198877837386955251669835231240734 0 7.3890560989306502272304274605750078131803155705521 +B 1 4 7 6 0.019776375922258700850057761665203091721045673743820 0 87.731203791681321190944546078901879401131946924772 +B 1 4 7 7 0.015136863527032284422733417301212673049908222875737 0 291.69672773748937390713238899664795040347997371773 +B 1 4 7 10 0.0011058812026457090749107094875135461259112471109099 0 4497.0568496172441229665597933672531436113611544670 +B 1 4 8 8 0.0025064215241119552542316219369022111615534826655664 0 1750.1511492277534733897810142718179560214405018267 +B 1 4 8 9 0.00075634137627736550347916489060103299160688346293889 0 3649.3427936268664003117878743765409381110678764886 +B 1 4 8 11 0.000065485689031380810512116609842493204067839834802139 0 18382.790496105065039809371927228796299493648450117 +B 1 8 1 8 0.11396144880131430127441044753858061858048921602142 0 2.7182818284590452353602874713526624977572470937000 +B 1 8 3 10 0.019240078585146793280270669912125680171207976941944 0 7.3890560989306502272304274605750078131803155705521 +B 1 8 3 12 0.0016357408981028242416664838406304598244680860729305 0 7.3890560989306502272304274605750078131803155705521 +B 1 8 4 10 0.018201350284562356379053773057676487152536320891936 0 7.3890560989306502272304274605750078131803155705521 +B 1 8 4 12 0.0015474309488599717138738547817776408747086129125937 0 27.474593022118317968158957115156725710168223409107 +B 1 8 6 9 0.0090924378251037988373675831445823876661128447310091 0 7.3890560989306502272304274605750078131803155705521 +B 1 8 6 11 0.00089070838977629336505377906002548092591905541567976 0 47.560129945305985709087486769738443607156131247662 +B 1 8 7 10 0.0045370399890857122167462005649263231256337048477108 0 27.474593022118317968158957115156725710168223409107 +B 1 8 7 12 0.00038572721174874913505848308144376305200533034654924 0 196.92750385796979934716506848462363620671342100200 +B 1 8 8 9 0.0028474592622349106049347435134319299345289090029058 0 7.3890560989306502272304274605750078131803155705521 +B 1 8 8 11 0.00027894123701526611438976440078819406948182821991629 0 142.32935382482556026905480728176275780392268396339 +B 1 9 1 9 0.11396144880131430127441044753858061858048921602142 0 2.7182818284590452353602874713526624977572470937000 +B 1 9 3 10 0.030613256068859004416418653862428461913053123984878 0 7.3890560989306502272304274605750078131803155705521 +B 1 9 3 12 0.0034027050873699020272291119236775023571171154770494 0 7.3890560989306502272304274605750078131803155705521 +B 1 9 4 10 0.028960515654570332636372854303781257378780486341103 0 7.3890560989306502272304274605750078131803155705521 +B 1 9 4 12 0.0032190007403657086627439035077088775551146856267842 0 27.474593022118317968158957115156725710168223409107 +B 1 9 6 11 0.0026800607785071006348390808330578580536676194101958 0 47.560129945305985709087486769738443607156131247662 +B 1 9 7 10 0.0072189708771646617608793195872156564077059697517086 0 7.3890560989306502272304274605750078131803155705521 +B 1 9 7 12 0.00080239844053344083726115000117266197615958225534299 0 176.84196693478213160623653883004191830972551316345 +B 1 9 8 11 0.00083930888876058161523188383316525248959549000904411 0 67.645666868493653450016016424320161504144039086217 +B 1 11 1 11 0.079295214616343071727661091549779105571604002529179 0 2.7182818284590452353602874713526624977572470937000 +B 1 11 3 12 0.022738424454311960371924662843502002262370036917505 0 7.3890560989306502272304274605750078131803155705521 +B 1 11 4 12 0.021510828377358885819893361139339788892078345523356 0 7.3890560989306502272304274605750078131803155705521 +B 1 11 7 12 0.0053619916665860501789721998553471913357398843141937 0 7.3890560989306502272304274605750078131803155705521 +B 2 1 2 1 0.23734293543041795099691912174282437594321621670250 0 2.7182818284590452353602874713526624977572470937000 +B 2 1 3 3 0.035310113931060871840467111419583798631135625669772 0 7.3890560989306502272304274605750078131803155705521 +B 2 1 3 5 0.011119559643500214501297228082671517298177925873343 0 7.3890560989306502272304274605750078131803155705521 +B 2 1 3 6 0.0046312873401219393584885370802719943452069570989597 0 7.3890560989306502272304274605750078131803155705521 +B 2 1 3 7 0.0032561528019001529626762751344244387732240997530450 0 7.3890560989306502272304274605750078131803155705521 +B 2 1 4 3 0.030557375210123242043219493055458621499209756101504 0 7.3890560989306502272304274605750078131803155705521 +B 2 1 4 5 0.0096228677387213307151523972924715310665781825644664 0 27.474593022118317968158957115156725710168223409107 +B 2 1 4 6 0.0040079164070187374722407706678111224608872078357665 0 47.560129945305985709087486769738443607156131247662 +B 2 1 4 7 0.0028178748758335616578255977744252970282499911513562 0 67.645666868493653450016016424320161504144039086217 +B 2 1 5 3 0.025804636489185612245971874691333444367283886533233 0 7.3890560989306502272304274605750078131803155705521 +B 2 1 5 5 0.0081261758339424469290075665022715448349784392555895 0 47.560129945305985709087486769738443607156131247662 +B 2 1 6 2 0.031128630077462452120653100334577638796914094270774 0 7.3890560989306502272304274605750078131803155705521 +B 2 1 6 4 0.0092255657760282305413870049950187853581635372510319 0 67.645666868493653450016016424320161504144039086217 +B 2 1 6 8 0.0014072933481460122306328267918307838277153025522400 0 645.02962559596124026139781362927921400538529026504 +B 2 1 7 3 0.0090969239609526448421544858524033677960631677584782 0 27.474593022118317968158957115156725710168223409107 +B 2 1 7 5 0.0028647256350883160106096661812857785321029882783186 0 271.61119081430170616620385934206623250649206587918 +B 2 1 7 6 0.0011931558435825790617396174553545418516969155641283 0 495.66225168329742662332023191439402140582800051069 +B 2 1 7 7 0.00083888073830518640960538012893144282868521821566282 0 645.02962559596124026139781362927921400538529026504 +B 2 1 8 2 0.012500271788890795219700914586357664139298668920731 0 7.3890560989306502272304274605750078131803155705521 +B 2 1 8 4 0.0037046949807835214479344212497336048149131740902815 0 162.41489074801322800998333693634447570091059180195 +B 2 1 8 8 0.00056512443029928862446750247213561162621069828970109 0 4762.7166027737839599749109047234019918619529864351 +B 2 1 9 3 0.0041979312301124888180054183592942774451769476185867 0 47.560129945305985709087486769738443607156131247662 +B 2 1 9 5 0.0013219766660533568906828502805141633159505461770378 0 807.86986088530674727876659556352893623768787922043 +B 2 3 2 3 0.28030513559107121563044832323076619395467836757252 0 2.7182818284590452353602874713526624977572470937000 +B 2 3 3 5 0.12893008630196930813095627363294131604519240874631 0 7.3890560989306502272304274605750078131803155705521 +B 2 3 3 6 0.11870381077165633063696341551983738128321618588937 0 7.3890560989306502272304274605750078131803155705521 +B 2 3 3 7 0.046458794328049875514925304877930951262516671014545 0 7.3890560989306502272304274605750078131803155705521 +B 2 3 3 10 0.0083692905670566417096727041909764061542122111815137 0 7.3890560989306502272304274605750078131803155705521 +B 2 3 4 5 0.11157610623105908422540616116730246530546616837246 0 7.3890560989306502272304274605750078131803155705521 +B 2 3 4 6 0.10272628663002424936841325370475329895935865228388 0 27.474593022118317968158957115156725710168223409107 +B 2 3 4 7 0.040205444051069724968588107376902750210626805429746 0 47.560129945305985709087486769738443607156131247662 +B 2 3 4 10 0.0072427846763509790863220515056998802013037491956456 0 67.645666868493653450016016424320161504144039086217 +B 2 3 5 5 0.094222126160148860319856048701663614565739927998603 0 7.3890560989306502272304274605750078131803155705521 +B 2 3 6 4 0.061758247130796165953664769136909914284295875346586 0 7.3890560989306502272304274605750078131803155705521 +B 2 3 6 8 0.016253844214003425421819345921668342162534563280913 0 311.78226466067704164806091865122966830046788155628 +B 2 3 6 9 0.012428424278426831578403734752584514586745413667084 0 311.78226466067704164806091865122966830046788155628 +B 2 3 7 5 0.033216182583210341493363761773430011942070128591303 0 27.474593022118317968158957115156725710168223409107 +B 2 3 7 6 0.030581593210753652899892138974413736627281377859852 0 87.731203791681321190944546078901879401131946924772 +B 2 3 7 7 0.011969151958698027547508953386558897888576141411777 0 182.50042767120089575091186659092619359789849964050 +B 2 3 7 10 0.0021561754245335307063411915284395804860795935813878 0 2026.8919305097190124910836446983407973714279291759 +B 2 3 8 4 0.024800155754344355433076999297458027569655842878829 0 7.3890560989306502272304274605750078131803155705521 +B 2 3 8 8 0.0065270289692714787332760970432998955936480957883692 0 1141.1172218205909458921034905415784819426052879292 +B 2 3 8 9 0.0049908614995706521869443835778049300715279997340379 0 1988.6292862835180974431505887378431875295913578198 +B 2 3 9 5 0.015328175854794647273679862710795911133087972019826 0 47.560129945305985709087486769738443607156131247662 +B 2 5 2 5 0.59452027981776402060269981496248550803586628473468 0 2.7182818284590452353602874713526624977572470937000 +B 2 5 3 6 0.35613657811574044546677393748159093573204947885602 0 7.3890560989306502272304274605750078131803155705521 +B 2 5 3 7 0.28389156167213399034473582683968450571134996398118 0 7.3890560989306502272304274605750078131803155705521 +B 2 5 3 10 0.018595566097369619203665562304080340916188434038452 0 7.3890560989306502272304274605750078131803155705521 +B 2 5 3 12 0.00050588372545658017105175124272932762925838506121587 0 7.3890560989306502272304274605750078131803155705521 +B 2 5 4 6 0.30820062106792203257406776662941447610148157893834 0 7.3890560989306502272304274605750078131803155705521 +B 2 5 4 7 0.24567977848896750817424262030156392735274973208419 0 27.474593022118317968158957115156725710168223409107 +B 2 5 4 10 0.016092604277385813943314958968249046547411265284224 0 47.560129945305985709087486769738443607156131247662 +B 2 5 4 12 0.00043779181346321002899525198765364616297555778253521 0 67.645666868493653450016016424320161504144039086217 +B 2 5 6 8 0.074688598013814163510865630785963940398401309610792 0 142.32935382482556026905480728176275780392268396339 +B 2 5 6 9 0.037079218205810692012210634303211345285740509376240 0 142.32935382482556026905480728176275780392268396339 +B 2 5 6 11 0.0020016197837223915293844729202771438753623054888257 0 291.69672773748937390713238899664795040347997371773 +B 2 5 7 6 0.091751257930178710694596621833187906242467223119617 0 7.3890560989306502272304274605750078131803155705521 +B 2 5 7 7 0.073138816678123085342213436245333067503761986671541 0 47.560129945305985709087486769738443607156131247662 +B 2 5 7 10 0.0047907647969902192998128143274558558008683443128377 0 916.11194614150801521802511629491778006719973113721 +B 2 5 7 12 0.00013033052775040110533690547608524478266182351873195 0 1858.3932344839547413290395350032067998509523537434 +B 2 5 8 8 0.029992575078973532001134677445199283631908213493662 0 291.69672773748937390713238899664795040347997371773 +B 2 5 8 9 0.014889839486633940621202579951684736531485333489587 0 678.58802389583060138161754350322546153511849730464 +B 2 5 8 11 0.00080378710056585805417303063766576731350279306658214 0 3705.0971499975484207105849580481822294032354437755 +B 3 1 3 1 0.23734293543041795099691912174282437594321621670250 0 2.7182818284590452353602874713526624977572470937000 +B 3 1 4 3 0.051968499354703215885516585389745418362347817380291 0 7.3890560989306502272304274605750078131803155705521 +B 3 1 4 5 0.016365476171672696320989238157245334203739039041368 0 7.3890560989306502272304274605750078131803155705521 +B 3 1 4 6 0.0068162072095398944631333431957493647847410537920160 0 7.3890560989306502272304274605750078131803155705521 +B 3 1 4 7 0.0047923202716009795090079885999194042953441958073766 0 7.3890560989306502272304274605750078131803155705521 +B 3 1 5 3 0.047215760633765586088268967025620241230421947812020 0 7.3890560989306502272304274605750078131803155705521 +B 3 1 5 5 0.014868784266893812534844407367045347972139295732491 0 27.474593022118317968158957115156725710168223409107 +B 3 1 6 2 0.074802381832179050387071374972073906569467651974957 0 7.3890560989306502272304274605750078131803155705521 +B 3 1 6 4 0.022169118656332535097692019128575440008419132168779 0 47.560129945305985709087486769738443607156131247662 +B 3 1 6 8 0.0033817387439134300818152176173248910948095072082604 0 182.50042767120089575091186659092619359789849964050 +B 3 1 7 3 0.030508048105532618684451578186690164659201229037264 0 27.474593022118317968158957115156725710168223409107 +B 3 1 7 5 0.0096073340680396816164465070460595816692638447552203 0 196.92750385796979934716506848462363620671342100200 +B 3 1 7 6 0.0040014466461037360526321899832927841755507615203776 0 291.69672773748937390713238899664795040347997371773 +B 3 1 7 7 0.0028133261340726042607877709544255500957794228716831 0 311.78226466067704164806091865122966830046788155628 +B 3 1 8 2 0.022194761889066302358537988713772786230860301426427 0 7.3890560989306502272304274605750078131803155705521 +B 3 1 8 4 0.0065778428148405478710792026904883594623816241675175 0 142.32935382482556026905480728176275780392268396339 +B 3 1 8 8 0.0010034023563658799293181798321347533711848068913901 0 2582.2819226938245111276129089000523060235420281953 +B 3 1 9 3 0.0089506699510501186152530367234194545771028171868563 0 47.560129945305985709087486769738443607156131247662 +B 3 1 9 5 0.0028186685708322406768276810707141495475502894859145 0 678.58802389583060138161754350322546153511849730464 +B 3 1 10 3 0.0070203236606945614509736995519726010805403992452239 0 47.560129945305985709087486769738443607156131247662 +B 3 1 10 5 0.0022107803960694720956133517325198292579998524038830 0 807.86986088530674727876659556352893623768787922043 +B 3 3 3 3 0.28030513559107121563044832323076619395467836757252 0 2.7182818284590452353602874713526624977572470937000 +B 3 3 4 5 0.18975591865456252898239810198721578712288656563452 0 7.3890560989306502272304274605750078131803155705521 +B 3 3 4 6 0.17470515460617475517493702125588376926368431110510 0 7.3890560989306502272304274605750078131803155705521 +B 3 3 4 7 0.068376834687403975858835948842441889200443517031811 0 7.3890560989306502272304274605750078131803155705521 +B 3 3 4 10 0.012317702295794866412738528965585413224945323072089 0 7.3890560989306502272304274605750078131803155705521 +B 3 3 5 5 0.17240193858365230507684798952157693638316032526067 0 7.3890560989306502272304274605750078131803155705521 +B 3 3 6 4 0.14840563081857527999664878815755337831459873896969 0 7.3890560989306502272304274605750078131803155705521 +B 3 3 6 8 0.039058135809738476501309195820868764696016177742363 0 87.731203791681321190944546078901879401131946924772 +B 3 3 6 9 0.029865616833562682847135593085446220663891930987916 0 87.731203791681321190944546078901879401131946924772 +B 3 3 7 5 0.11139599500671378625035570259334333375949052585337 0 27.474593022118317968158957115156725710168223409107 +B 3 3 7 6 0.10256046118690415870641590652554420693160703668107 0 67.645666868493653450016016424320161504144039086217 +B 3 3 7 7 0.040140542595032278437756794852098036878392853013842 0 87.731203791681321190944546078901879401131946924772 +B 3 3 7 10 0.0072310930439774180327576689883251135097211674578310 0 584.77301482639823703861222466553406031442156674937 +B 3 3 8 4 0.044033726712135182712729948686467300793839502743718 0 7.3890560989306502272304274605750078131803155705521 +B 3 3 8 8 0.011589016324010097224010432946235058369014895266313 0 604.85855174958590477954075432011577821140947458793 +B 3 3 8 9 0.0088614859320677386220758578826470545703717331051274 0 843.33668880535052883291032878614100971956033058095 +B 3 3 9 5 0.032682155925704871179229975176434761872814212393681 0 47.560129945305985709087486769738443607156131247662 +B 3 3 10 5 0.025633758565839687554183172870780171563072533004613 0 47.560129945305985709087486769738443607156131247662 +B 3 5 3 5 0.59452027981776402060269981496248550803586628473468 0 2.7182818284590452353602874713526624977572470937000 +B 3 5 4 6 0.52415247274842225857882454068577055962143444151647 0 7.3890560989306502272304274605750078131803155705521 +B 3 5 4 7 0.41782415282965147926272346827232867955819364744318 0 7.3890560989306502272304274605750078131803155705521 +B 3 5 4 10 0.027368466344182640220199609696917431084147577601512 0 7.3890560989306502272304274605750078131803155705521 +B 3 5 4 12 0.00074454639572314960075727940825948331655047983809691 0 7.3890560989306502272304274605750078131803155705521 +B 3 5 6 8 0.17947738185833102173377062262340825964451041020331 0 47.560129945305985709087486769738443607156131247662 +B 3 5 6 9 0.089101699347761217688758090147669165353122933129555 0 47.560129945305985709087486769738443607156131247662 +B 3 5 6 11 0.0048099105862435485202770454482153861992161514450752 0 67.645666868493653450016016424320161504144039086217 +B 3 5 7 6 0.30770310961067893669935339588954398976242008569777 0 7.3890560989306502272304274605750078131803155705521 +B 3 5 7 7 0.24528319101880705643069428421609781970920590203055 0 27.474593022118317968158957115156725710168223409107 +B 3 5 7 10 0.016066626863787045576697465056124240337604656630127 0 306.12380392425827750338559089034539301229489507924 +B 3 5 7 12 0.00043708511001034067709893289669108193623674557429363 0 510.08932787006633021957343380809146401464292187220 +B 3 5 8 8 0.053253087097623024606190302611917780506153721235081 0 142.32935382482556026905480728176275780392268396339 +B 3 5 8 9 0.026437540523395466747485251957838466250097959031828 0 271.61119081430170616620385934206623250649206587918 +B 3 5 8 11 0.0014271580336690599404207970501266391978225423297753 0 1253.1093381930365575421133356851857751081508820021 +B 3 6 3 6 0.59452027981776402060269981496248550803586628473468 0 2.7182818284590452353602874713526624977572470937000 +B 3 6 4 7 0.43837641196429422501978973477349674585760017125269 0 7.3890560989306502272304274605750078131803155705521 +B 3 6 4 10 0.047920725478825385977265876198085497383554101411012 0 7.3890560989306502272304274605750078131803155705521 +B 3 6 4 12 0.0027684333336620645548826340040894438059473378227366 0 7.3890560989306502272304274605750078131803155705521 +B 3 6 6 8 0.19398024624375977143426194064198732324490010245339 0 27.474593022118317968158957115156725710168223409107 +B 3 6 6 9 0.10360456373318996738924940816624822895351262537963 0 27.474593022118317968158957115156725710168223409107 +B 3 6 6 11 0.0062380824285736669587388732791058813036227956818897 0 47.560129945305985709087486769738443607156131247662 +B 3 6 7 7 0.25734837123649036595475955928892927587125979714030 0 7.3890560989306502272304274605750078131803155705521 +B 3 6 7 10 0.028131807081470355100762740128955696499658551739875 0 176.84196693478213160623653883004191830972551316345 +B 3 6 7 12 0.0016252056220414724689433519255583160160080842229883 0 326.20934084744594524431412054492711090928280291780 +B 3 6 8 8 0.057556260524188152514643473816295729117437332196052 0 47.560129945305985709087486769738443607156131247662 +B 3 6 8 9 0.030740713949960594655938423162216414861381569992800 0 122.24381690163789252812627762718103990693477612483 +B 3 6 8 11 0.0018509137109722399515234142681185250244602777681606 0 697.71934600893105890558407148347426645603678298274 +B 3 7 3 7 0.50690426609972209238226295370217793799331474794400 0 2.7182818284590452353602874713526624977572470937000 +B 3 7 4 10 0.073974479699723103683937328469089612123164894500579 0 7.3890560989306502272304274605750078131803155705521 +B 3 7 4 12 0.0047923202716009795090079885999194042953441958073766 0 7.3890560989306502272304274605750078131803155705521 +B 3 7 6 8 0.21236528419611135874260914611283241130914859596227 0 7.3890560989306502272304274605750078131803155705521 +B 3 7 6 9 0.12198960168554155469759661363709331701776111888852 0 7.3890560989306502272304274605750078131803155705521 +B 3 7 6 11 0.0076662542709037853972007011099963764080294399187051 0 27.474593022118317968158957115156725710168223409107 +B 3 7 7 10 0.043426633697027346604953494206819481995882852787078 0 47.560129945305985709087486769738443607156131247662 +B 3 7 7 12 0.0028133261340726042607877709544255500957794228716831 0 142.32935382482556026905480728176275780392268396339 +B 3 7 8 8 0.063011321308072869718512623943471736714723656518424 0 7.3890560989306502272304274605750078131803155705521 +B 3 7 8 9 0.036195774733845311859807573289392422458667894315172 0 27.474593022118317968158957115156725710168223409107 +B 3 7 8 11 0.0022746693882754199626260314861104108510980132065458 0 196.92750385796979934716506848462363620671342100200 +B 3 10 3 10 0.26998748890009174921041063742988672295671963861768 0 2.7182818284590452353602874713526624977572470937000 +B 3 10 4 12 0.033440127157999385082575673484407312552338151555432 0 7.3890560989306502272304274605750078131803155705521 +B 3 10 6 11 0.086715546579784025985632231473954904265915579806050 0 7.3890560989306502272304274605750078131803155705521 +B 3 10 7 12 0.019630988399880440952230722142725942576918672576211 0 27.474593022118317968158957115156725710168223409107 +B 3 10 8 11 0.025729540440791045303007192906469715954748298894003 0 7.3890560989306502272304274605750078131803155705521 +B 3 12 3 12 0.21763743190211025398341644733044533439721003564361 0 2.7182818284590452353602874713526624977572470937000 +B 4 1 4 1 0.36110699553122032001883406374639079973686122170682 0 2.7182818284590452353602874713526624977572470937000 +B 4 1 5 3 0.081546168078884004194574350681774635630603451957561 0 7.3890560989306502272304274605750078131803155705521 +B 4 1 5 5 0.025679823107407373582373639617369981721655921101135 0 7.3890560989306502272304274605750078131803155705521 +B 4 1 6 2 0.14482848986237883880940778380284895287185109638195 0 7.3890560989306502272304274605750078131803155705521 +B 4 1 6 4 0.042922697084430518919456939131335893668341050657344 0 27.474593022118317968158957115156725710168223409107 +B 4 1 6 8 0.0065475470619223799886004700409120366384267779711348 0 47.560129945305985709087486769738443607156131247662 +B 4 1 7 3 0.064838455550651036790756961842844559059382733182807 0 27.474593022118317968158957115156725710168223409107 +B 4 1 7 5 0.020418372908553242663975739296384215418780470123865 0 122.24381690163789252812627762718103990693477612483 +B 4 1 7 6 0.0085042353284688858362305103821397188445163863061572 0 142.32935382482556026905480728176275780392268396339 +B 4 1 7 7 0.0059791344520815541675730233780126956393966936345578 0 142.32935382482556026905480728176275780392268396339 +B 4 1 8 2 0.031889251989241809497375062841187908322421933932122 0 7.3890560989306502272304274605750078131803155705521 +B 4 1 8 4 0.0094509906488975742942239841312431141098500742447529 0 122.24381690163789252812627762718103990693477612483 +B 4 1 8 8 0.0014416802824324712341688571921338951161589154930791 0 1323.0887792230369104334388004560770090958261625627 +B 4 1 9 3 0.013703408671987748412500655087544631709028686755126 0 47.560129945305985709087486769738443607156131247662 +B 4 1 9 5 0.0043153604756111244629725118609141357791500327947912 0 549.30618690635445548446849144292198683254911538885 +B 4 1 10 3 0.011773062381632191248221317916097778212466268813494 0 47.560129945305985709087486769738443607156131247662 +B 4 1 10 5 0.0037074723008483558817581825227198154895995957127598 0 678.58802389583060138161754350322546153511849730464 +B 4 1 11 2 0.0035664036004946454575858029655528115732448760763832 0 7.3890560989306502272304274605750078131803155705521 +B 4 1 11 4 0.0010569720195958387776266189452031789191312610067670 0 400.89302780377785206335291140236970720906144779496 +B 4 1 11 8 0.00016123343851915632315285551243958116968020262885119 0 5271.7936567440137881324921040547410788507078238012 +B 4 3 4 3 0.42647212212869029522610826022843533923795146782307 0 2.7182818284590452353602874713526624977572470937000 +B 4 3 5 5 0.29775475968535142476179671139447123295505961557087 0 7.3890560989306502272304274605750078131803155705521 +B 4 3 6 4 0.28733528093729483396613797368384161562675761493688 0 7.3890560989306502272304274605750078131803155705521 +B 4 3 6 8 0.075622335647748985090633765493378230437329450252536 0 27.474593022118317968158957115156725710168223409107 +B 4 3 6 9 0.057824257448344968539037542980779655620148264401076 0 27.474593022118317968158957115156725710168223409107 +B 4 3 7 5 0.23674881610841290593530442446623763033138981616358 0 27.474593022118317968158957115156725710168223409107 +B 4 3 7 6 0.21797074270101885561712894064600268359310103387136 0 47.560129945305985709087486769738443607156131247662 +B 4 3 7 7 0.085310301656271009924503984301783533404763064621034 0 47.560129945305985709087486769738443607156131247662 +B 4 3 7 10 0.015368171155778579326660765288130169008541084780666 0 196.92750385796979934716506848462363620671342100200 +B 4 3 8 4 0.063267297669926009992382898075476574018023162608607 0 7.3890560989306502272304274605750078131803155705521 +B 4 3 8 8 0.016651003678748715714744768849170221144381694744258 0 380.80749088059018432242438174778798931207353995641 +B 4 3 8 9 0.012732110364564825057207332187489179069215466476217 0 455.49117783692209114146317260523058561185218483358 +B 4 3 9 5 0.050036135996615095084780087642073612612540452767535 0 47.560129945305985709087486769738443607156131247662 +B 4 3 10 5 0.042987738636749911459733285336419022302798773378468 0 47.560129945305985709087486769738443607156131247662 +B 4 3 11 4 0.0070756353356833721921421788470154140791994702759607 0 7.3890560989306502272304274605750078131803155705521 +B 4 3 11 8 0.0018622010792781505354671840678666118001284277737699 0 659.45670178273014385765101552297665661420021162654 +B 4 3 11 9 0.0014239231532115592306165067078674700551543191720809 0 1769.2824713408539309137475422520667609423587875048 +B 4 5 4 5 0.90453685355346375612046857720291086502220387709400 0 2.7182818284590452353602874713526624977572470937000 +B 4 5 6 8 0.34749479284379602002062045305380890177180217103609 0 7.3890560989306502272304274605750078131803155705521 +B 4 5 6 9 0.17251408637841827694421739690380837130564345274497 0 7.3890560989306502272304274605750078131803155705521 +B 4 5 6 11 0.0093126992686086983038753658470623208681817762308545 0 7.3890560989306502272304274605750078131803155705521 +B 4 5 7 6 0.65395840226405725419939070225212228812352341180883 0 7.3890560989306502272304274605750078131803155705521 +B 4 5 7 7 0.52129796121930940850676574590790313793518544255851 0 7.3890560989306502272304274605750078131803155705521 +B 4 5 7 10 0.034146244563172629644836249108365115746829867072884 0 47.560129945305985709087486769738443607156131247662 +B 4 5 7 12 0.00092893269930689083025804936975864922915730829135953 0 67.645666868493653450016016424320161504144039086217 +B 4 5 8 8 0.076513599116272517211245927778636277380399228976501 0 47.560129945305985709087486769738443607156131247662 +B 4 5 8 9 0.037985241560156992873767923963992195968710584574068 0 67.645666868493653450016016424320161504144039086217 +B 4 5 8 11 0.0020505289667722618266685634625875110821422915929686 0 217.01304078115746708809359813920535410370132884056 +B 4 5 11 8 0.0085570641627823930964593492711531237396606251179525 0 47.560129945305985709087486769738443607156131247662 +B 4 5 11 9 0.0042481618042187153564771976063118574958427831451736 0 196.92750385796979934716506848462363620671342100200 +B 4 5 11 11 0.00022932535051252646520935476751526263596302990753184 0 530.17486479325399796050196346267318191163082971075 +B 4 6 4 6 0.90453685355346375612046857720291086502220387709400 0 2.7182818284590452353602874713526624977572470937000 +B 4 6 6 8 0.37557448624624520400565223472578190611245144894314 0 7.3890560989306502272304274605750078131803155705521 +B 4 6 6 9 0.20059377978086746092924917857578137564629273065202 0 7.3890560989306502272304274605750078131803155705521 +B 4 6 6 11 0.012077851475295016619150261653212605097936774490574 0 7.3890560989306502272304274605750078131803155705521 +B 4 6 7 7 0.54693997045401315231537148463412853483749892332523 0 7.3890560989306502272304274605750078131803155705521 +B 4 6 7 10 0.059788253797876373453441987834590512649143347839608 0 47.560129945305985709087486769738443607156131247662 +B 4 6 7 12 0.0034540335756942224989155363738856724342770009629586 0 67.645666868493653450016016424320161504144039086217 +B 4 6 8 8 0.082696363429718248493801935906384648476140259428507 0 27.474593022118317968158957115156725710168223409107 +B 4 6 8 9 0.044168005873602724156323932091740567064451615026076 0 47.560129945305985709087486769738443607156131247662 +B 4 6 8 11 0.0026593776511120524191682697330411270481256676928580 0 196.92750385796979934716506848462363620671342100200 +B 4 6 11 8 0.0092485270078789651247636149386896770902632016598264 0 27.474593022118317968158957115156725710168223409107 +B 4 6 11 9 0.0049396246493152873847814632738484108464453596870476 0 122.24381690163789252812627762718103990693477612483 +B 4 6 11 11 0.00029741726250589660726585402259094410224585718621247 0 400.89302780377785206335291140236970720906144779496 +B 4 7 4 7 0.77123288384917117488191835194405218113356396872123 0 2.7182818284590452353602874713526624977572470937000 +B 4 7 6 8 0.41117064264505323710884467975097905574681382064607 0 7.3890560989306502272304274605750078131803155705521 +B 4 7 6 9 0.23618993617967549403244162360097852528065510235495 0 7.3890560989306502272304274605750078131803155705521 +B 4 7 6 11 0.014843003681981334934425157459362889327691772750293 0 7.3890560989306502272304274605750078131803155705521 +B 4 7 7 10 0.092294198859889810752477981466806359715481527080846 0 47.560129945305985709087486769738443607156131247662 +B 4 7 7 12 0.0059791344520815541675730233780126956393966936345578 0 67.645666868493653450016016424320161504144039086217 +B 4 7 8 8 0.090534150058086029808876809229746732626472715964591 0 7.3890560989306502272304274605750078131803155705521 +B 4 7 8 9 0.052005792501970505471398805415102651214784071562155 0 27.474593022118317968158957115156725710168223409107 +B 4 7 8 11 0.0032682263354518430116679760034947430141090437927474 0 176.84196693478213160623653883004191830972551316345 +B 4 7 11 8 0.010125082860012147734464969658687960580211418863205 0 7.3890560989306502272304274605750078131803155705521 +B 4 7 11 9 0.0058161805014484699944828179938466943363935768904256 0 47.560129945305985709087486769738443607156131247662 +B 4 7 11 11 0.00036550917449926674932235327766662556852868446489313 0 271.61119081430170616620385934206623250649206587918 +B 4 10 4 10 0.41077426960666095913029016918161660558429376032906 0 2.7182818284590452353602874713526624977572470937000 +B 4 10 6 11 0.16789414121754899475807235221373903887730433105683 0 7.3890560989306502272304274605750078131803155705521 +B 4 10 7 12 0.041721547192334624650808710120746185362188945087680 0 27.474593022118317968158957115156725710168223409107 +B 4 10 8 11 0.036967992843751582735803147373813460029919994526568 0 7.3890560989306502272304274605750078131803155705521 +B 4 10 11 11 0.0041343955896329756269408981511849779654481929200446 0 7.3890560989306502272304274605750078131803155705521 +B 4 12 4 12 0.33112592547479473881510234643923868704022612011515 0 2.7182818284590452353602874713526624977572470937000 +B 5 1 5 1 0.36110699553122032001883406374639079973686122170682 0 2.7182818284590452353602874713526624977572470937000 +B 5 1 6 2 0.15452297996255434594824485793026407496341272888765 0 7.3890560989306502272304274605750078131803155705521 +B 5 1 6 4 0.045795844918487545342601720572090648315809500734580 0 7.3890560989306502272304274605750078131803155705521 +B 5 1 6 8 0.0069858249879889712934511474009111783834008865728241 0 7.3890560989306502272304274605750078131803155705521 +B 5 1 7 3 0.069591194271588666588004580206969736191308602751075 0 27.474593022118317968158957115156725710168223409107 +B 5 1 7 5 0.021915064813332126450120570086584201650380213432741 0 47.560129945305985709087486769738443607156131247662 +B 5 1 7 6 0.0091276062615720877224782767946005907288361355693504 0 47.560129945305985709087486769738443607156131247662 +B 5 1 7 7 0.0064174123781481454724237007380118373843708022362468 0 47.560129945305985709087486769738443607156131247662 +B 5 1 8 2 0.041583742089417316636212136968603030413983566437820 0 7.3890560989306502272304274605750078131803155705521 +B 5 1 8 4 0.012324138482954600717368765571997868757318524321989 0 102.15827997845022478719774797259932200994686828628 +B 5 1 8 8 0.0018799582084990625390195345521330368611330240947681 0 510.08932787006633021957343380809146401464292187220 +B 5 1 9 3 0.018456147392925378209748273451669808840954556323396 0 47.560129945305985709087486769738443607156131247662 +B 5 1 9 5 0.0058120523803900082491173426511141220107497761036684 148.41315910257660342111558004055227962348766759389 271.61119081430170616620385934206623250649206587918 +B 5 1 10 3 0.016525801102569821045468936280222955344392138381764 0 47.560129945305985709087486769738443607156131247662 +B 5 1 10 5 0.0052041642056272396679030133129198017211993390216365 0 549.30618690635445548446849144292198683254911538885 +B 5 1 11 2 0.0035664036004946454575858029655528115732448760763832 0 7.3890560989306502272304274605750078131803155705521 +B 5 1 11 4 0.0010569720195958387776266189452031789191312610067670 0 380.80749088059018432242438174778798931207353995641 +B 5 1 11 8 0.00016123343851915632315285551243958116968020262885119 403.42879349273512260838718054338827960589989735717 3297.9183253885689543914464530925755004613018042622 +B 5 1 12 3 0.0012292847896278899581356880376320405908531454203273 0 67.645666868493653450016016424320161504144039086217 +B 5 1 12 5 0.00038711587178116635197036371793686838934854115778840 0 1733.8156434208101493596038090294546874604863361443 +B 5 1 12 6 0.00016123343851915632315285551243958116968020262885119 403.42879349273512260838718054338827960589989735717 4094.5822709345962105751346144981977769815308792703 +B 5 1 12 7 0.00011335956377526856683248606114103718687402123182666 403.42879349273512260838718054338827960589989735717 4223.8641079240723564722836665585012516841002611862 +B 5 3 5 3 0.42647212212869029522610826022843533923795146782307 0 2.7182818284590452353602874713526624977572470937000 +B 5 3 6 4 0.30656885189508566124579092307285088885094127480176 0 7.3890560989306502272304274605750078131803155705521 +B 5 3 6 8 0.080684323002487603581368101396313393212696249730483 0 7.3890560989306502272304274605750078131803155705521 +B 5 3 6 9 0.061694881880842054974169017285621780118991997772166 0 7.3890560989306502272304274605750078131803155705521 +B 5 3 7 5 0.25410279617932312984085453693187648107111605653743 0 27.474593022118317968158957115156725710168223409107 +B 5 3 7 6 0.23394826684265093688567910246108676591695856747686 0 27.474593022118317968158957115156725710168223409107 +B 5 3 7 7 0.091563651933251160470841181802811734456652930205833 0 27.474593022118317968158957115156725710168223409107 +B 5 3 7 10 0.016494677046484241950011417973406694961449546766535 0 67.645666868493653450016016424320161504144039086217 +B 5 3 8 4 0.082500868627716837272035847464485847242206822473496 0 7.3890560989306502272304274605750078131803155705521 +B 5 3 8 8 0.021712991033487334205479104752105383919748494222202 0 251.52565389111403842527532968748451460950415804062 +B 5 3 8 9 0.016602734797061911492338806492331303568059199847307 0 271.61119081430170616620385934206623250649206587918 +B 5 3 9 5 0.067390116067525318990330200107712463352266693141388 0 47.560129945305985709087486769738443607156131247662 +B 5 3 10 5 0.060341718707660135365283397802057873042525013752322 0 47.560129945305985709087486769738443607156131247662 +B 5 3 11 4 0.0070756353356833721921421788470154140791994702759607 0 7.3890560989306502272304274605750078131803155705521 +B 5 3 11 8 0.0018622010792781505354671840678666118001284277737699 0 530.17486479325399796050196346267318191163082971075 +B 5 3 11 9 0.0014239231532115592306165067078674700551543191720809 0 1233.9780160799361000181468077049369701872325963240 +B 5 3 12 5 0.0044885664862441366790427659538164006338474948374145 0 67.645666868493653450016016424320161504144039086217 +B 5 3 12 6 0.0041325493692078921340484884454189141601231805735893 0 400.89302780377785206335291140236970720906144779496 +B 5 3 12 7 0.0016174144700701148081470825363327648867857884851552 0 475.57671476010975888239170225981230350884009267213 +B 5 3 12 10 0.00029136812229339083932962481533978042373617836373937 0 6807.9295730242174990316936637196867170417183248709 +B 5 5 5 5 0.90453685355346375612046857720291086502220387709400 0 2.7182818284590452353602874713526624977572470937000 +B 5 5 6 8 0.37075530486244551262567607822052739864604767877750 0 7.3890560989306502272304274605750078131803155705521 +B 5 5 6 9 0.18406178741517980307050006890996210102425607828721 0 7.3890560989306502272304274605750078131803155705521 +B 5 5 6 11 0.0099360702017119001901231322595231927525015254940480 0 7.3890560989306502272304274605750078131803155705521 +B 5 5 7 6 0.70189435931187566709209687310429874775409131172654 0 7.3890560989306502272304274605750078131803155705521 +B 5 5 7 7 0.55950974440247589067725895244602371629378567445551 0 7.3890560989306502272304274605750078131803155705521 +B 5 5 7 10 0.036649206383156434905186852444196410115607035827112 0 47.560129945305985709087486769738443607156131247662 +B 5 5 7 12 0.00099702461130026097231454862483433069544013557004016 0 67.645666868493653450016016424320161504144039086217 +B 5 5 8 8 0.099774111134922009816301552945354774254644736717926 0 47.560129945305985709087486769738443607156131247662 +B 5 5 8 9 0.049532942596918519000050595970145925687323210116309 0 67.645666868493653450016016424320161504144039086217 +B 5 5 8 11 0.0026738998998754637129163298750483829664620408561618 0 217.01304078115746708809359813920535410370132884056 +B 5 5 11 8 0.0085570641627823930964593492711531237396606251179525 0 47.560129945305985709087486769738443607156131247662 +B 5 5 11 9 0.0042481618042187153564771976063118574958427831451736 0 196.92750385796979934716506848462363620671342100200 +B 5 5 11 11 0.00022932535051252646520935476751526263596302990753184 0 530.17486479325399796050196346267318191163082971075 +B 5 5 12 6 0.012398523532451580162010595008548565356306880970629 0 7.3890560989306502272304274605750078131803155705521 +B 5 5 12 7 0.0098833886333138028361091890994624160829694888821946 0 27.474593022118317968158957115156725710168223409107 +B 5 5 12 10 0.00064738523932963538432390232373726689746049262756474 0 1065.4793200541718288561026980098029726667570208916 +B 5 5 12 12 0.000017611814287493054191747158543949221261658437777614 0 3245.9140001341312777034006938331526585051679791314 +B 6 0 6 0 0.27334631866906308391110033206027309692255495465841 0 2.7182818284590452353602874713526624977572470937000 +B 6 0 7 1 0.13798368585167142937007748443747841916478421345389 0 7.3890560989306502272304274605750078131803155705521 +B 6 0 7 3 0.028386675570165072369449763219355462699371106666871 0 7.3890560989306502272304274605750078131803155705521 +B 6 0 7 5 0.0039604034137541839458227129889604956455339368433284 0 7.3890560989306502272304274605750078131803155705521 +B 6 0 7 6 0.0010651165232936311143710478799100121617229628487208 0 7.3890560989306502272304274605750078131803155705521 +B 6 0 7 7 0.0010651165232936311143710478799100121617229628487208 0 7.3890560989306502272304274605750078131803155705521 +B 6 0 8 2 0.015197286317011627140513547012752623404786974399224 0 27.474593022118317968158957115156725710168223409107 +B 6 0 8 4 0.0023182361345656538438702119121321786061071326964572 0 47.560129945305985709087486769738443607156131247662 +B 6 0 9 1 0.043076112893091501377916503153386626476396256253801 0 7.3890560989306502272304274605750078131803155705521 +B 6 0 9 3 0.0088618276426856392818015344365411496118206768020428 0 102.15827997845022478719774797259932200994686828628 +B 6 0 9 5 0.0012363692381463782670356383358950274933366289499188 0 251.52565389111403842527532968748451460950415804062 +B 6 0 10 1 0.039493355223543173998096201702754274128365479939305 0 7.3890560989306502272304274605750078131803155705521 +B 6 0 10 3 0.0081247652937256581956958127277059257446472030029810 0 122.24381690163789252812627762718103990693477612483 +B 6 0 10 5 0.0011335370401401144454949491350349526252407826262783 0 549.30618690635445548446849144292198683254911538885 +B 6 0 11 2 0.0010569720195958387776266189452031789191312610067670 0 67.645666868493653450016016424320161504144039086217 +B 6 0 11 4 0.00016123343851915632315285551243958116968020262885119 0 772.40303296526296572462286234091686275581542785991 +B 6 0 12 1 0.0022815748293987161418152681018291938514282356157815 0 7.3890560989306502272304274605750078131803155705521 +B 6 0 12 3 0.00046937668081151311182676356953852366059833549565204 0 326.20934084744594524431412054492711090928280291780 +B 6 0 12 5 0.000065485689031380810512116609842493204067839834802139 0 3185.1739857334867036281994270690827942329937961166 +B 6 0 12 6 0.000017611814287493054191747158543949221261658437777614 0 5382.1461631478400476093994489292432485456661281268 +B 6 0 12 7 0.000017611814287493054191747158543949221261658437777614 0 5402.2317000710277153503279785838249664426540359653 +B 6 0 13 1 0.0013180228893261376915548208007186692015228903740454 0 7.3890560989306502272304274605750078131803155705521 +B 6 0 13 3 0.00027115008504390845359349501156264294025953248208323 0 346.29487777063361298524265019950882880627071075635 +B 6 0 13 5 0.000037829851536975439927876962321086704738304319433736 0 4091.9884461558896481850701125547597405348739673624 +B 6 2 6 2 0.36616403094065064985104776387942946481557957079699 0 2.7182818284590452353602874713526624977572470937000 +B 6 2 7 3 0.15164446537510714999761684210720114443360828536297 0 7.3890560989306502272304274605750078131803155705521 +B 6 2 7 5 0.071448646102065743553800533462044429839423498324737 0 7.3890560989306502272304274605750078131803155705521 +B 6 2 7 6 0.057787866578630022926261175792321704570599426415665 0 7.3890560989306502272304274605750078131803155705521 +B 6 2 7 7 0.054892579688169470094809510683271221086788452421057 0 7.3890560989306502272304274605750078131803155705521 +B 6 2 8 4 0.031440851562885519940018388845108958097655204315049 0 27.474593022118317968158957115156725710168223409107 +B 6 2 8 8 0.012260182221772591874631893886621394670763002130531 0 87.731203791681321190944546078901879401131946924772 +B 6 2 8 9 0.0059585630631056371058887340287542760425506416487809 0 87.731203791681321190944546078901879401131946924772 +B 6 2 9 3 0.047340771264311708537468168614728891473592453487175 0 7.3890560989306502272304274605750078131803155705521 +B 6 2 9 5 0.022305027775961854702658456993756578096972079277040 0 102.15827997845022478719774797259932200994686828628 +B 6 2 10 3 0.043403310339030593299887126133439630441639708030833 0 7.3890560989306502272304274605750078131803155705521 +B 6 2 10 5 0.020449857846118155989335569375648392969175972143680 0 122.24381690163789252812627762718103990693477612483 +B 6 2 11 4 0.0021867127907590021107815619727388740147079461503299 0 67.645666868493653450016016424320161504144039086217 +B 6 2 11 8 0.00085269628361572835145712117997613452028277917072505 0 812.57410681163830120647992165008029854979124353703 +B 6 2 11 9 0.00041441835754913704660644381997699277530867056903603 0 1051.0522438674029252598494961161055300579420995300 +B 6 2 12 3 0.0025074572626607261706327763073264810710965741447187 0 7.3890560989306502272304274605750078131803155705521 +B 6 2 12 5 0.0011814109148840022018153185863334966080469640233028 0 326.20934084744594524431412054492711090928280291780 +B 6 2 12 6 0.00095552848162199217299781038083620938837862549436560 0 956.28301998788335069988217560408121586117554681432 +B 6 2 12 7 0.00090765460687810441667744092953766540557244409734106 0 976.36855691107101844081070525866293375816345465288 +B 6 2 13 3 0.0014485109248268068836797496491001505689482722130543 0 7.3890560989306502272304274605750078131803155705521 +B 6 2 13 5 0.00068247887706896373975625181500294241264291777664542 0 346.29487777063361298524265019950882880627071075635 +B 6 4 6 4 0.75729138858348782772229056239372307503353778021541 0 2.7182818284590452353602874713526624977572470937000 +B 6 4 7 5 0.66990959310633033406495053855555899822707052118256 0 7.3890560989306502272304274605750078131803155705521 +B 6 4 7 6 0.64837860784037999847277515343421451465704432535363 0 7.3890560989306502272304274605750078131803155705521 +B 6 4 7 7 0.49626981906632829133572426846188360192477102006192 0 7.3890560989306502272304274605750078131803155705521 +B 6 4 7 10 0.036256881312679687334085790670977221000573230586732 0 7.3890560989306502272304274605750078131803155705521 +B 6 4 8 8 0.088728957908117409991237350790814162418069702500940 0 67.645666868493653450016016424320161504144039086217 +B 6 4 8 9 0.026774978388225952696213440655040546695115293700146 0 67.645666868493653450016016424320161504144039086217 +B 6 4 8 11 0.0023182361345656538438702119121321786061071326964572 0 87.731203791681321190944546078901879401131946924772 +B 6 4 9 5 0.20913415294496370860977719854464342439836441130564 0 7.3890560989306502272304274605750078131803155705521 +B 6 4 10 5 0.19173989566163697077550897898500589608259835372777 0 7.3890560989306502272304274605750078131803155705521 +B 6 4 11 8 0.0061711034378418282754493357327078780439462697465487 0 107.81674071486898893187307573348359729811985476333 +B 6 4 11 9 0.0018622010792781505354671840678666118001284277737699 0 291.69672773748937390713238899664795040347997371773 +B 6 4 11 11 0.00016123343851915632315285551243958116968020262885119 0 495.66225168329742662332023191439402140582800051069 +B 6 4 12 5 0.011077025926435813590230964107555327825727839128886 0 7.3890560989306502272304274605750078131803155705521 +B 6 4 12 6 0.010721008809399569045236686599157841352003524865061 0 67.645666868493653450016016424320161504144039086217 +B 6 4 12 7 0.0082058739102617917193352806900716920786661327766265 0 87.731203791681321190944546078901879401131946924772 +B 6 4 12 10 0.00059951136458574762800353287243872291465431123054020 0 1561.5669162788015344868083749221022406039770185557 +B 6 4 13 5 0.0063989896489825307859075274678553659036741430729618 0 7.3890560989306502272304274605750078131803155705521 +B 6 8 6 8 0.57607947823979466441425335394039632232511759415940 0 2.7182818284590452353602874713526624977572470937000 +B 6 8 7 10 0.14874917848464659716616517699815066094979731136836 0 7.3890560989306502272304274605750078131803155705521 +B 6 8 7 12 0.012646264085135842440177708316111946096966858827151 0 7.3890560989306502272304274605750078131803155705521 +B 6 8 8 9 0.10080191643480122502288745417618728194313756915516 0 7.3890560989306502272304274605750078131803155705521 +B 6 8 8 11 0.0098747018567576841270642715302625810212492713403719 0 27.474593022118317968158957115156725710168223409107 +B 6 8 11 9 0.0070107783041475027598899699341989017555848661549748 0 7.3890560989306502272304274605750078131803155705521 +B 6 8 11 11 0.00068678600552261761483244084027971864043997968375863 0 47.560129945305985709087486769738443607156131247662 +B 6 8 12 10 0.0024595833879168384143124068560279370882903927476942 0 47.560129945305985709087486769738443607156131247662 +B 6 8 12 12 0.00020910731326304407947322496373812515248638402587572 0 271.61119081430170616620385934206623250649206587918 +B 6 9 6 9 0.57607947823979466441425335394039632232511759415940 0 2.7182818284590452353602874713526624977572470937000 +B 6 9 7 10 0.23667765549036378831263561147280888112688617403816 0 7.3890560989306502272304274605750078131803155705521 +B 6 9 7 12 0.026307043608571563067717065985834671365790930736226 0 7.3890560989306502272304274605750078131803155705521 +B 6 9 8 11 0.029712082483464987962095093781171775429139265968841 0 27.474593022118317968158957115156725710168223409107 +B 6 9 11 11 0.0020664768152582609616366818330936561989769096098119 0 27.474593022118317968158957115156725710168223409107 +B 6 9 12 10 0.0039134900485873182007877204699212473391606944641618 0 7.3890560989306502272304274605750078131803155705521 +B 6 9 12 12 0.00043498974652505410829073316923541237215472255481294 0 176.84196693478213160623653883004191830972551316345 +B 6 11 6 11 0.40084033981295463697999652886903224821914345096682 0 2.7182818284590452353602874713526624977572470937000 +B 6 11 7 12 0.17579564151184037789728008909335560605084935860993 0 7.3890560989306502272304274605750078131803155705521 +B 6 11 12 12 0.0029067995126799010749095964470227645951565015258954 0 7.3890560989306502272304274605750078131803155705521 +B 7 1 7 1 0.35520202124700576579148899596145203581012439279854 0 2.7182818284590452353602874713526624977572470937000 +B 7 1 8 2 0.064149561303270088774745365198112266103551737244206 0 7.3890560989306502272304274605750078131803155705521 +B 7 1 8 4 0.019011951243403937205644261610113850220430641231919 0 7.3890560989306502272304274605750078131803155705521 +B 7 1 8 8 0.0029001356848639084176819976260269522994997854892197 0 7.3890560989306502272304274605750078131803155705521 +B 7 1 9 3 0.029519075059994200347629099905243238141448371844874 0 27.474593022118317968158957115156725710168223409107 +B 7 1 9 5 0.0092958951192119087576542400680885564295266146272487 0 47.560129945305985709087486769738443607156131247662 +B 7 1 10 3 0.027588728769638643183349762733796384644885953903243 0 27.474593022118317968158957115156725710168223409107 +B 7 1 10 5 0.0086880069444491401764399107298942361399761775452173 0 122.24381690163789252812627762718103990693477612483 +B 7 1 11 2 0.016437732714171910457281957067646925171251414377073 0 7.3890560989306502272304274605750078131803155705521 +B 7 1 11 4 0.0048716369459881488427573335425644057347749278394622 0 176.84196693478213160623653883004191830972551316345 +B 7 1 11 8 0.00074313298881741089696464122633435486307285542161379 0 658.50248697264293364068901384864374363813058946609 +B 7 1 12 3 0.0041979312301124888180054183592942774451769476185867 0 47.560129945305985709087486769738443607156131247662 +B 7 1 12 5 0.0013219766660533568906828502805141633159505461770378 0 697.71934600893105890558407148347426645603678298274 +B 7 1 12 6 0.00055060218153587733071944233012835570787432512639732 0 1159.2943291236041931991080168474943738874539514468 +B 7 1 12 7 0.00038711587178116635197036371793686838934854115778840 0 1159.2943291236041931991080168474943738874539514468 +B 7 1 13 3 0.0017484348646924108059308846127397322697338375486408 0 47.560129945305985709087486769738443607156131247662 +B 7 1 13 5 0.00055060218153587733071944233012835570787432512639732 0 827.00118299840720480273312354377774115860616489853 +B 7 1 14 3 0.00071013471456336911034049146252434891197245329201382 0 47.560129945305985709087486769738443607156131247662 +B 7 1 14 5 0.00022362956202645537322128510574538107082275718917949 0 956.28301998788335069988217560408121586117554681432 +B 7 3 7 3 0.41949826965485584960523736582332182730334743949532 0 2.7182818284590452353602874713526624977572470937000 +B 7 3 8 4 0.12727076168918476118712684448820837684328919852277 0 7.3890560989306502272304274605750078131803155705521 +B 7 3 8 8 0.033495755297465748734929805323874077683264409644338 0 7.3890560989306502272304274605750078131803155705521 +B 7 3 8 9 0.025612369165234558362053475959213323016361055851068 0 7.3890560989306502272304274605750078131803155705521 +B 7 3 9 5 0.10778489422237375725581586671597754511596737057911 0 27.474593022118317968158957115156725710168223409107 +B 7 3 10 5 0.10073649686250857363076906441032295480622569119005 0 27.474593022118317968158957115156725710168223409107 +B 7 3 11 4 0.032611957439360468827580226481728670456098186460348 0 7.3890560989306502272304274605750078131803155705521 +B 7 3 11 8 0.0085829779885179465741835487367001427882775437179611 0 176.84196693478213160623653883004191830972551316345 +B 7 3 11 9 0.0065629330888871196651997018699073650046124418047529 0 196.92750385796979934716506848462363620671342100200 +B 7 3 12 5 0.015328175854794647273679862710795911133087972019826 0 47.560129945305985709087486769738443607156131247662 +B 7 3 12 6 0.014112399505269110111251204034407270553987097855762 0 196.92750385796979934716506848462363620671342100200 +B 7 3 12 7 0.0055233699897958370760482254140968016595937380542314 0 196.92750385796979934716506848462363620671342100200 +B 7 3 12 10 0.00099500404654393493318469305613118867889897823981997 0 1253.1093381930365575421133356851857751081508820021 +B 7 3 13 5 0.0063841724905868001638379131794788607285968937340870 0 47.560129945305985709087486769738443607156131247662 +B 7 3 14 5 0.0025929604819014731942476187281539405390980959407423 0 47.560129945305985709087486769738443607156131247662 +B 7 5 7 5 0.88974548444276548822279219511716724248344689070726 0 2.7182818284590452353602874713526624977572470937000 +B 7 5 8 8 0.15391749604848146567094768935966383340095793061975 0 7.3890560989306502272304274605750078131803155705521 +B 7 5 8 9 0.076412472230608409913306284135515318411563775464545 0 7.3890560989306502272304274605750078131803155705521 +B 7 5 8 11 0.0041249175020619779115813604651971711339500212185902 0 7.3890560989306502272304274605750078131803155705521 +B 7 5 11 8 0.039439937057692356346049860518743686011728311278354 0 7.3890560989306502272304274605750078131803155705521 +B 7 5 11 9 0.019579990401147080143450213765527520501470722951168 0 27.474593022118317968158957115156725710168223409107 +B 7 5 11 11 0.0010569720195958387776266189452031789191312610067670 0 47.560129945305985709087486769738443607156131247662 +B 7 5 12 6 0.042340188037239370077303699058146443568981710823769 0 7.3890560989306502272304274605750078131803155705521 +B 7 5 12 7 0.033751158521766097042100720437835974674588351022236 0 7.3890560989306502272304274605750078131803155705521 +B 7 5 12 10 0.0022107803960694720956133517325198292579998524038830 0 142.32935382482556026905480728176275780392268396339 +B 7 5 12 12 0.000060143252271744394472206493553893752296973220570579 0 291.69672773748937390713238899664795040347997371773 +B 7 6 7 6 0.88974548444276548822279219511716724248344689070726 0 2.7182818284590452353602874713526624977572470937000 +B 7 6 8 8 0.16635496615542728597721186482624007481853807917433 0 7.3890560989306502272304274605750078131803155705521 +B 7 6 8 9 0.088849942337554230219570459602091559829143924019133 0 7.3890560989306502272304274605750078131803155705521 +B 7 6 8 11 0.0053496993192600474054807233043673899684002569479603 0 7.3890560989306502272304274605750078131803155705521 +B 7 6 11 8 0.042626923922527810649856619678367264715255166940739 0 7.3890560989306502272304274605750078131803155705521 +B 7 6 11 9 0.022766977265982534447256972925151099204997578613557 0 27.474593022118317968158957115156725710168223409107 +B 7 6 11 11 0.0013708110503742666582885966640720029751896665919202 0 47.560129945305985709087486769738443607156131247662 +B 7 6 12 7 0.035411336736299691806994629840227448224713878299722 0 7.3890560989306502272304274605750078131803155705521 +B 7 6 12 10 0.0038709586106030668605072611349113028081253796813687 0 142.32935382482556026905480728176275780392268396339 +B 7 6 12 12 0.00022362956202645537322128510574538107082275718917949 0 291.69672773748937390713238899664795040347997371773 +B 7 7 7 7 0.75862135761836391234845840669038124810418480163011 0 2.7182818284590452353602874713526624977572470937000 +B 7 7 8 8 0.18212173841988966672296452355556158415234478676087 0 7.3890560989306502272304274605750078131803155705521 +B 7 7 8 9 0.10461671460201661096532311833141306916295063160567 0 7.3890560989306502272304274605750078131803155705521 +B 7 7 8 11 0.0065744811364581168993800861435376088028504926773308 0 7.3890560989306502272304274605750078131803155705521 +B 7 7 11 8 0.046667013721789464467824313411952820282585370767157 0 7.3890560989306502272304274605750078131803155705521 +B 7 7 11 9 0.026807067065244188265224666658736654772327782439973 0 27.474593022118317968158957115156725710168223409107 +B 7 7 11 11 0.0016846500811526945389505743829408270312480721770734 0 47.560129945305985709087486769738443607156131247662 +B 7 7 12 10 0.0059755386901447192278664212633056093292755600722770 0 142.32935382482556026905480728176275780392268396339 +B 7 7 12 12 0.00038711587178116635197036371793686838934854115778840 0 291.69672773748937390713238899664795040347997371773 +B 7 10 7 10 0.40405711505506868071350953553361598227824567674202 0 2.7182818284590452353602874713526624977572470937000 +B 7 10 8 11 0.074366138283492418690284915888331332366310155606715 0 7.3890560989306502272304274605750078131803155705521 +B 7 10 11 11 0.019055636223452736715830757731015362151494962735058 0 7.3890560989306502272304274605750078131803155705521 +B 7 10 12 12 0.0027012393253336050318605875690942912135772043097098 0 47.560129945305985709087486769738443607156131247662 +B 7 12 7 12 0.32571121432557149183680462876927723979043175945964 0 2.7182818284590452353602874713526624977572470937000 +B 8 0 8 0 0.11333347705456518598364298664576205580820476717089 0 2.7182818284590452353602874713526624977572470937000 +B 8 0 9 1 0.058370695511357389347458156257026560518424706753514 0 7.3890560989306502272304274605750078131803155705521 +B 8 0 9 3 0.012008303634293168284457689829857925800853375011859 0 7.3890560989306502272304274605750078131803155705521 +B 8 0 9 5 0.0016753538676658389237826347868567334650495497598494 0 7.3890560989306502272304274605750078131803155705521 +B 8 0 10 1 0.054787937841809061967637854806394208170393930439021 0 7.3890560989306502272304274605750078131803155705521 +B 8 0 10 3 0.011271241285333187198351968121022701933679901212797 0 27.474593022118317968158957115156725710168223409107 +B 8 0 10 5 0.0015725216696595751022419455859966585969537034362089 0 47.560129945305985709087486769738443607156131247662 +B 8 0 11 2 0.0051854759767665767234193112614332297908333334246153 0 47.560129945305985709087486769738443607156131247662 +B 8 0 11 4 0.00079100686356129865328501067763289884587903681863831 0 142.32935382482556026905480728176275780392268396339 +B 8 0 12 1 0.0087549883191647788724169114557931201491750476554847 0 7.3890560989306502272304274605750078131803155705521 +B 8 0 12 3 0.0018011188170743081726322909523013896887882183354203 0 176.84196693478213160623653883004191830972551316345 +B 8 0 12 5 0.00025128539952086074380552475326678757015229270454790 0 658.50248697264293364068901384864374363813058946609 +B 8 0 12 6 0.000067581052516667379320316337298162768149862854282859 0 807.86986088530674727876659556352893623768787922043 +B 8 0 12 7 0.000067581052516667379320316337298162768149862854282859 0 807.86986088530674727876659556352893623768787922043 +B 8 0 13 1 0.0042086787095438730423361627040502431512389260992538 0 7.3890560989306502272304274605750078131803155705521 +B 8 0 13 3 0.00086582987234672242829330068549028510127594152278967 0 196.92750385796979934716506848462363620671342100200 +B 8 0 13 5 0.00012079736402019155168059590488530620272691086553894 0 1159.2943291236041931991080168474943738874539514468 +B 8 0 14 1 0.0022815748293987161418152681018291938514282356157815 0 7.3890560989306502272304274605750078131803155705521 +B 8 0 14 3 0.00046937668081151311182676356953852366059833549565204 0 217.01304078115746708809359813920535410370132884056 +B 8 0 14 5 0.000065485689031380810512116609842493204067839834802139 0 1714.6843213077096918356372810492058825395680504662 +B 8 2 8 2 0.15181709049852325605268699720439615358662826140858 0 2.7182818284590452353602874713526624977572470937000 +B 8 2 9 3 0.064149561303270088774745365198112266103551737244206 0 7.3890560989306502272304274605750078131803155705521 +B 8 2 9 5 0.030224639533151688018009074237519872803560554057138 0 7.3890560989306502272304274605750078131803155705521 +B 8 2 10 3 0.060212100377988973537164322716823005071598991787861 0 7.3890560989306502272304274605750078131803155705521 +B 8 2 10 5 0.028369469603307989304686186619411687675764446923778 0 27.474593022118317968158957115156725710168223409107 +B 8 2 11 4 0.010727953469293185419519905446988653154903553278261 0 47.560129945305985709087486769738443607156131247662 +B 8 2 11 8 0.0041833047726828459242249886934953451722281790241877 0 142.32935382482556026905480728176275780392268396339 +B 8 2 11 9 0.0020331251892777844990643725238023681345071013760911 0 142.32935382482556026905480728176275780392268396339 +B 8 2 12 3 0.0096217572014435992690728987632947336094942253960536 0 7.3890560989306502272304274605750078131803155705521 +B 8 2 12 5 0.0045333769581728163013154065184333443220552098966351 0 176.84196693478213160623653883004191830972551316345 +B 8 2 12 6 0.0036666080758939959046594192109317308617360321560665 0 271.61119081430170616620385934206623250649206587918 +B 8 2 12 7 0.0034829037288898025401742107949631060597336023058013 0 271.61119081430170616620385934206623250649206587918 +B 8 2 13 3 0.0046253499383285647445388296237791420753931780080476 0 7.3890560989306502272304274605750078131803155705521 +B 8 2 13 5 0.0021792749905140791259334521289946049988550565166176 0 196.92750385796979934716506848462363620671342100200 +B 8 2 14 3 0.0025074572626607261706327763073264810710965741447187 0 7.3890560989306502272304274605750078131803155705521 +B 8 2 14 5 0.0011814109148840022018153185863334966080469640233028 0 217.01304078115746708809359813920535410370132884056 +B 8 4 8 4 0.31398435007114743066116233332772332189352920799795 0 2.7182818284590452353602874713526624977572470937000 +B 8 4 9 5 0.28338921835572394275117351342289349958348233767305 0 7.3890560989306502272304274605750078131803155705521 +B 8 4 10 5 0.26599496107239720491690529386325597126771628009517 0 7.3890560989306502272304274605750078131803155705521 +B 8 4 11 8 0.030275265601928159287392052387819141739731525585639 0 47.560129945305985709087486769738443607156131247662 +B 8 4 11 9 0.0091359078400183390901775583253329321925383158733763 0 47.560129945305985709087486769738443607156131247662 +B 8 4 11 11 0.00079100686356129865328501067763289884587903681863831 0 47.560129945305985709087486769738443607156131247662 +B 8 4 12 5 0.042505392042122399837469493586292741907654984874526 0 7.3890560989306502272304274605750078131803155705521 +B 8 4 12 6 0.041139262971573145773127935803226764591021489093919 0 47.560129945305985709087486769738443607156131247662 +B 8 4 12 7 0.031488044708055553187213487955464160997728099902565 0 47.560129945305985709087486769738443607156131247662 +B 8 4 12 10 0.0023004790053447418403178614278657535451025363754590 0 306.12380392425827750338559089034539301229489507924 +B 8 4 13 5 0.020433098481342379198877837386955251669835231240734 0 7.3890560989306502272304274605750078131803155705521 +B 8 4 14 5 0.011077025926435813590230964107555327825727839128886 0 7.3890560989306502272304274605750078131803155705521 +B 8 8 8 8 0.23885117841202875442235705924240144113561086780796 0 2.7182818284590452353602874713526624977572470937000 +B 8 8 11 9 0.034394687655491765230275362793824326768336941813993 0 7.3890560989306502272304274605750078131803155705521 +B 8 8 11 11 0.0033693534613894255646568026143862142926473072433285 0 7.3890560989306502272304274605750078131803155705521 +B 8 8 12 10 0.0094380528544394059045876903473261088074917955457884 0 27.474593022118317968158957115156725710168223409107 +B 8 8 12 12 0.00080239844053344083726115000117266197615958225534299 0 47.560129945305985709087486769738443607156131247662 +B 8 9 8 9 0.23885117841202875442235705924240144113561086780796 0 2.7182818284590452353602874713526624977572470937000 +B 8 9 11 11 0.010138079044102069889371880893270816811143470273804 0 7.3890560989306502272304274605750078131803155705521 +B 8 9 12 10 0.015017065941062775979392431012286591576155021162765 0 7.3890560989306502272304274605750078131803155705521 +B 8 9 12 12 0.0016691673228122612339171373086742754364787599959117 0 27.474593022118317968158957115156725710168223409107 +B 8 11 8 11 0.16619440743131233097160134989194018895196820034562 0 2.7182818284590452353602874713526624977572470937000 +B 8 11 12 12 0.011154135929161353576623020851398794977949935181964 0 7.3890560989306502272304274605750078131803155705521 +B 9 1 9 1 0.32900422694262355938002127667798825156389178127436 0 2.7182818284590452353602874713526624977572470937000 +B 9 1 10 3 0.066202051965220793597875483047736721338121162552980 0 7.3890560989306502272304274605750078131803155705521 +B 9 1 10 5 0.020847785050668523130070785404639318199881100063376 0 7.3890560989306502272304274605750078131803155705521 +B 9 1 11 2 0.060212100377988973537164322716823005071598991787861 0 7.3890560989306502272304274605750078131803155705521 +B 9 1 11 4 0.017845009278199309810821349317283049300568887482739 0 27.474593022118317968158957115156725710168223409107 +B 9 1 11 8 0.0027221271263457861451848588718282090626376283573071 0 47.560129945305985709087486769738443607156131247662 +B 9 1 12 3 0.022835990048701013386102144369671207512960084334974 0 27.474593022118317968158957115156725710168223409107 +B 9 1 12 5 0.0071913150396702563902950799396942499083764342363401 0 122.24381690163789252812627762718103990693477612483 +B 9 1 12 6 0.0029951767308988145784264174376614760383733360750272 0 142.32935382482556026905480728176275780392268396339 +B 9 1 12 7 0.0021058406417610725678370427576303240808013626237054 0 142.32935382482556026905480728176275780392268396339 +B 9 1 13 3 0.011400166316470196627327570469973999752545927256802 0 27.474593022118317968158957115156725710168223409107 +B 9 1 13 5 0.0035900430553497202367910890210999571556265105365551 0 196.92750385796979934716506848462363620671342100200 +B 9 1 14 3 0.0041979312301124888180054183592942774451769476185867 0 27.474593022118317968158957115156725710168223409107 +B 9 1 14 5 0.0013219766660533568906828502805141633159505461770378 0 271.61119081430170616620385934206623250649206587918 +B 9 3 9 3 0.38855832922073362970233468840835803381036270081448 0 2.7182818284590452353602874713526624977572470937000 +B 9 3 10 5 0.24172780325512055171152321009715277356907746549653 0 7.3890560989306502272304274605750078131803155705521 +B 9 3 11 4 0.11945896000416864779262361730393773395684685494125 0 7.3890560989306502272304274605750078131803155705521 +B 9 3 11 8 0.031439806278219280894022353630473830488634961714744 0 27.474593022118317968158957115156725710168223409107 +B 9 3 11 9 0.024040297575918090883798157667110888083276613780353 0 27.474593022118317968158957115156725710168223409107 +B 9 3 12 5 0.083382516791598349725218951944684104066499450816193 0 27.474593022118317968158957115156725710168223409107 +B 9 3 12 6 0.076768912352330950122660376300680860241637201396211 0 47.560129945305985709087486769738443607156131247662 +B 9 3 12 7 0.030046138254363852154349766998110512385928990275870 0 47.560129945305985709087486769738443607156131247662 +B 9 3 12 10 0.0054126428613947723691163305796319459932324873336965 0 196.92750385796979934716506848462363620671342100200 +B 9 3 13 5 0.041626159289912718289071924707751812277305290679419 0 27.474593022118317968158957115156725710168223409107 +B 9 3 14 5 0.015328175854794647273679862710795911133087972019826 0 27.474593022118317968158957115156725710168223409107 +B 9 5 9 5 0.82412263381018069705636688675414927113569014613263 0 2.7182818284590452353602874713526624977572470937000 +B 9 5 11 8 0.14447013406976264132603250628611943102113783283506 0 7.3890560989306502272304274605750078131803155705521 +B 9 5 11 9 0.071722321316095270391058650321672534441578386002963 0 7.3890560989306502272304274605750078131803155705521 +B 9 5 11 11 0.0038717325830319971881277721576597595283215532784053 0 7.3890560989306502272304274605750078131803155705521 +B 9 5 12 6 0.23032299951531582976606849172764013825823884916749 0 7.3890560989306502272304274605750078131803155705521 +B 9 5 12 7 0.18360022541734873179775788242506979040253063804715 0 7.3890560989306502272304274605750078131803155705521 +B 9 5 12 10 0.012026247300662171971674906223635189818094736753678 0 47.560129945305985709087486769738443607156131247662 +B 9 5 12 12 0.00032716846348558854665829339756802016565741572106159 0 67.645666868493653450016016424320161504144039086217 +B 10 1 10 1 0.32900422694262355938002127667798825156389178127436 0 2.7182818284590452353602874713526624977572470937000 +B 10 1 11 2 0.067028075890717284725373381021175196633356180768881 0 7.3890560989306502272304274605750078131803155705521 +B 10 1 11 4 0.019865054177830136719805196184075827084233989395947 0 7.3890560989306502272304274605750078131803155705521 +B 10 1 11 8 0.0030302703686381429338587669289271515535557612241080 0 7.3890560989306502272304274605750078131803155705521 +B 10 1 12 3 0.026177532554347606866865622137457222827204228089925 0 27.474593022118317968158957115156725710168223409107 +B 10 1 12 5 0.0082436050794410825739746600038914031689515244317942 0 47.560129945305985709087486769738443607156131247662 +B 10 1 12 6 0.0034334546569654058832770947976606177833474446767162 0 47.560129945305985709087486769738443607156131247662 +B 10 1 12 7 0.0024139838840534293565109508147292665717194954905062 0 47.560129945305985709087486769738443607156131247662 +B 10 1 13 3 0.014741708822116790108091048237760015066790071011753 0 27.474593022118317968158957115156725710168223409107 +B 10 1 13 5 0.0046423330951205464204706690852971104162016007320092 0 122.24381690163789252812627762718103990693477612483 +B 10 1 14 3 0.0075394737357590822987688961270802927594210913735377 0 27.474593022118317968158957115156725710168223409107 +B 10 1 14 5 0.0023742667058241830743624303447113165765256363724920 0 196.92750385796979934716506848462363620671342100200 +B 10 3 10 3 0.38855832922073362970233468840835803381036270081448 0 2.7182818284590452353602874713526624977572470937000 +B 10 3 11 4 0.13298164632557211812970170559057769201215985666446 0 7.3890560989306502272304274605750078131803155705521 +B 10 3 11 8 0.034998774465211824059843247428641535473633085418515 0 7.3890560989306502272304274605750078131803155705521 +B 10 3 11 9 0.026761645586824867840491553965583167799240701501256 0 7.3890560989306502272304274605750078131803155705521 +B 10 3 12 5 0.095583705506986053490517409330330824591233410697652 0 27.474593022118317968158957115156725710168223409107 +B 10 3 12 6 0.088002346207858653162654566883731956243281149559919 0 27.474593022118317968158957115156725710168223409107 +B 10 3 12 7 0.034442726617442161529298158295973642639961149962503 0 27.474593022118317968158957115156725710168223409107 +B 10 3 12 10 0.0062046635336171295204423720380287007456956260593744 0 67.645666868493653450016016424320161504144039086217 +B 10 3 13 5 0.053827348005300422054370382093398532802039250560878 0 27.474593022118317968158957115156725710168223409107 +B 10 3 14 5 0.027529364570182351038978320096442631657821931901286 0 27.474593022118317968158957115156725710168223409107 +B 10 5 10 5 0.82412263381018069705636688675414927113569014613263 0 2.7182818284590452353602874713526624977572470937000 +B 10 5 11 8 0.16082407106844679980101791040625088064817063559811 0 7.3890560989306502272304274605750078131803155705521 +B 10 5 11 9 0.079841247291732603215323803231670791285877393504874 0 7.3890560989306502272304274605750078131803155705521 +B 10 5 11 11 0.0043100105090985884929784495176589012732956618800943 0 7.3890560989306502272304274605750078131803155705521 +B 10 5 12 6 0.26402568073330081156342148651645016030392814034770 0 7.3890560989306502272304274605750078131803155705521 +B 10 5 12 7 0.21046606114288431993006507792869184670060814075028 0 7.3890560989306502272304274605750078131803155705521 +B 10 5 12 10 0.013786022832744529848305214484627569093647887197110 0 47.560129945305985709087486769738443607156131247662 +B 10 5 12 12 0.00037504233822947630297866284886656414846359711808613 0 67.645666868493653450016016424320161504144039086217 +B 11 0 11 0 0.12291627437099350686299609995898727225241104981265 0 2.7182818284590452353602874713526624977572470937000 +B 11 0 12 1 0.054787937841809061967637854806394208170393930439021 0 7.3890560989306502272304274605750078131803155705521 +B 11 0 12 3 0.011271241285333187198351968121022701933679901212797 0 7.3890560989306502272304274605750078131803155705521 +B 11 0 12 5 0.0015725216696595751022419455859966585969537034362089 0 7.3890560989306502272304274605750078131803155705521 +B 11 0 12 6 0.00042291621297336405929903230016510813126977851511065 0 7.3890560989306502272304274605750078131803155705521 +B 11 0 12 7 0.00042291621297336405929903230016510813126977851511065 0 7.3890560989306502272304274605750078131803155705521 +B 11 0 13 1 0.033562841915261084109937533856409840333799877204499 0 7.3890560989306502272304274605750078131803155705521 +B 11 0 13 3 0.0069047112256837382285449903910796577448207966736398 0 27.474593022118317968158957115156725710168223409107 +B 11 0 13 5 0.00096331963359334983379407977006176051760092123219867 0 47.560129945305985709087486769738443607156131247662 +B 11 0 14 1 0.020195363177140353040916775354990955591582117188256 0 7.3890560989306502272304274605750078131803155705521 +B 11 0 14 3 0.0041546884256114185423553721137146429964657044909613 0 47.560129945305985709087486769738443607156131247662 +B 11 0 14 5 0.00057964667906269991821556261414286754454707145300487 0 142.32935382482556026905480728176275780392268396339 +B 11 2 11 2 0.16465383075592103332373817580272523595432569818791 0 2.7182818284590452353602874713526624977572470937000 +B 11 2 12 3 0.060212100377988973537164322716823005071598991787861 0 7.3890560989306502272304274605750078131803155705521 +B 11 2 12 5 0.028369469603307989304686186619411687675764446923778 0 7.3890560989306502272304274605750078131803155705521 +B 11 2 12 6 0.022945307067128077735159718708982890774559385574935 0 7.3890560989306502272304274605750078131803155705521 +B 11 2 12 7 0.021795701610441866692216805423151340308875460653836 0 7.3890560989306502272304274605750078131803155705521 +B 11 2 13 3 0.036885659252356844021909131980703499856522981320129 0 7.3890560989306502272304274605750078131803155705521 +B 11 2 13 5 0.017379008245662252159662240377976608562807881976887 0 27.474593022118317968158957115156725710168223409107 +B 11 2 14 3 0.022194761889066302358537988713772786230860301426427 0 7.3890560989306502272304274605750078131803155705521 +B 11 2 14 5 0.010457260564102495768429756676874422247027499690103 0 47.560129945305985709087486769738443607156131247662 +B 11 4 11 4 0.34053297864462401432569831121235282458871068634045 0 2.7182818284590452353602874713526624977572470937000 +B 11 4 12 5 0.26599496107239720491690529386325597126771628009517 0 7.3890560989306502272304274605750078131803155705521 +B 11 4 12 6 0.25744584691340980386373818461406147839667400723968 0 7.3890560989306502272304274605750078131803155705521 +B 11 4 12 7 0.19704938183054391856533597674111519904574221916520 0 7.3890560989306502272304274605750078131803155705521 +B 11 4 12 10 0.014396192908140676681992609459788397903517112719444 0 7.3890560989306502272304274605750078131803155705521 +B 11 4 13 5 0.16294730519892317129432150350459312074556866127379 0 7.3890560989306502272304274605750078131803155705521 +B 11 4 14 5 0.098048312343069502761572061905742969404558127018234 0 7.3890560989306502272304274605750078131803155705521 +B 11 8 11 8 0.25904699778506839562725352375669638773563903809154 0 2.7182818284590452353602874713526624977572470937000 +B 11 8 12 10 0.059062494921302762494221409430991454605915066866763 0 7.3890560989306502272304274605750078131803155705521 +B 11 8 12 12 0.0050213380397182082310706854434913099940054781995033 0 7.3890560989306502272304274605750078131803155705521 +B 11 9 11 9 0.25904699778506839562725352375669638773563903809154 0 2.7182818284590452353602874713526624977572470937000 +B 11 9 12 10 0.093975462370895038316035712539464914814620126521820 0 7.3890560989306502272304274605750078131803155705521 +B 11 9 12 12 0.010445500575898119800597153353920106895210539548347 0 7.3890560989306502272304274605750078131803155705521 +B 11 11 11 11 0.18024680715404741470982797636843384618550945143191 0 2.7182818284590452353602874713526624977572470937000 +B 11 11 12 12 0.069801590097870189844665396596441942094391796133096 0 7.3890560989306502272304274605750078131803155705521 +B 12 1 12 1 0.31335842117604058072923483144950700014262875538385 0 2.7182818284590452353602874713526624977572470937000 +B 12 1 13 3 0.053971108998075364238545499387023499817857795297188 0 7.3890560989306502272304274605750078131803155705521 +B 12 1 13 5 0.016996120904669066587926717236393359381870668201934 0 7.3890560989306502272304274605750078131803155705521 +B 12 1 14 3 0.037288060022137708514112067982477651666641340054551 0 7.3890560989306502272304274605750078131803155705521 +B 12 1 14 5 0.011742437541155760218881762038613567777652386129287 0 27.474593022118317968158957115156725710168223409107 +B 12 3 12 3 0.37008042635465343791973725568114782867906395824517 0 2.7182818284590452353602874713526624977572470937000 +B 12 3 13 5 0.19706817583541523595900300302892693018292069744257 0 7.3890560989306502272304274605750078131803155705521 +B 12 3 14 5 0.13615228787064936612003594538767289333223871929482 0 7.3890560989306502272304274605750078131803155705521 +B 12 5 12 5 0.78493145752572667452625596003149594088640771943101 0 2.7182818284590452353602874713526624977572470937000 +B 12 6 12 6 0.78493145752572667452625596003149594088640771943101 0 2.7182818284590452353602874713526624977572470937000 +B 12 7 12 7 0.66925404889068852361719392466513055095337609717505 0 2.7182818284590452353602874713526624977572470937000 +B 12 10 12 10 0.35645827462945333275412594634900855475999546166319 0 2.7182818284590452353602874713526624977572470937000 +B 12 12 12 12 0.28734169789370933166067490019358875711362296917740 0 2.7182818284590452353602874713526624977572470937000 +B 13 1 13 1 0.28756620539937377598638706047176323856161783818539 0 2.7182818284590452353602874713526624977572470937000 +B 13 1 14 3 0.050629566492428770757782021619237484503613651542236 0 7.3890560989306502272304274605750078131803155705521 +B 13 1 14 5 0.015943830864898240404247137172196206121295578006480 0 7.3890560989306502272304274605750078131803155705521 +B 13 3 13 3 0.33961947950842935899612393144901248276857486049927 0 2.7182818284590452353602874713526624977572470937000 +B 13 3 14 5 0.18486698712002753219370454564328020965818673756111 0 7.3890560989306502272304274605750078131803155705521 +B 13 5 13 5 0.72032454048032939036177057017020543623262541363551 0 2.7182818284590452353602874713526624977572470937000 +B 14 1 14 1 0.28756620539937377598638706047176323856161783818539 0 2.7182818284590452353602874713526624977572470937000 +B 14 3 14 3 0.33961947950842935899612393144901248276857486049927 0 2.7182818284590452353602874713526624977572470937000 +B 14 5 14 5 0.72032454048032939036177057017020543623262541363551 0 2.7182818284590452353602874713526624977572470937000 +P 0 12 0 0E+0 +P 0 11 0 0E+0 +P 0 10 0 0E+0 +P 0 9 0 0E+0 +P 0 8 0 0E+0 +P 0 7 0 0E+0 +P 0 6 0 0E+0 +P 0 5 1 0E+0 +P 0 4 0 0E+0 +P 0 3 1 2.6097923001933355342308171557443294970222716928515E+0 +P 0 2 0 0E+0 +P 0 1 1 0E+0 +P 0 0 0 0E+0 +P 1 12 0 0E+0 +P 1 11 1 0E+0 +P 1 10 0 0E+0 +P 1 9 1 0E+0 +P 1 8 1 0E+0 +P 1 7 0 0E+0 +P 1 6 0 0E+0 +P 1 5 0 0E+0 +P 1 4 1 2.6097923001933355342308171557443294970222716928515E+0 +P 1 3 0 0E+0 +P 1 2 1 0E+0 +P 1 1 0 0E+0 +P 1 0 1 0E+0 +P 2 12 0 0E+0 +P 2 11 0 0E+0 +P 2 10 0 0E+0 +P 2 9 0 0E+0 +P 2 8 0 0E+0 +P 2 7 0 0E+0 +P 2 6 0 0E+0 +P 2 5 1 2.6097923001933355342308171557443294970222716928515E+0 +P 2 4 0 0E+0 +P 2 3 1 0E+0 +P 2 2 0 0E+0 +P 2 1 1 0E+0 +P 2 0 0 0E+0 +P 3 12 1 0E+0 +P 3 11 0 0E+0 +P 3 10 1 0E+0 +P 3 9 0 0E+0 +P 3 8 0 0E+0 +P 3 7 1 0E+0 +P 3 6 1 2.6097923001933355342308171557443294970222716928515E+0 +P 3 5 1 0E+0 +P 3 4 0 0E+0 +P 3 3 1 0E+0 +P 3 2 0 0E+0 +P 3 1 1 0E+0 +P 3 0 0 0E+0 +P 4 12 1 0E+0 +P 4 11 0 0E+0 +P 4 10 1 0E+0 +P 4 9 0 0E+0 +P 4 8 0 0E+0 +P 4 7 1 2.6097923001933355342308171557443294970222716928515E+0 +P 4 6 1 0E+0 +P 4 5 1 0E+0 +P 4 4 0 0E+0 +P 4 3 1 0E+0 +P 4 2 0 0E+0 +P 4 1 1 0E+0 +P 4 0 0 0E+0 +P 5 12 0 0E+0 +P 5 11 0 0E+0 +P 5 10 0 0E+0 +P 5 9 0 0E+0 +P 5 8 0 0E+0 +P 5 7 0 0E+0 +P 5 6 0 0E+0 +P 5 5 1 0E+0 +P 5 4 0 0E+0 +P 5 3 1 0E+0 +P 5 2 0 0E+0 +P 5 1 1 1.0384099898329873699476559857223657703835891439521E+0 +P 5 0 0 0E+0 +P 6 12 0 0E+0 +P 6 11 1 0E+0 +P 6 10 0 0E+0 +P 6 9 1 7.2340779953215843454714295591728611637030091838721E-1 +P 6 8 1 8.4772165599310348519908413430219898030584970855325E-1 +P 6 7 0 0E+0 +P 6 6 0 0E+0 +P 6 5 0 0E+0 +P 6 4 1 0E+0 +P 6 3 0 0E+0 +P 6 2 1 1.0384099898329873699476559857223657703835891439521E+0 +P 6 1 0 0E+0 +P 6 0 1 0E+0 +P 7 12 1 0E+0 +P 7 11 0 0E+0 +P 7 10 1 7.5659417847100751807090423546965966176157846611893E-1 +P 7 9 0 0E+0 +P 7 8 0 0E+0 +P 7 7 1 0E+0 +P 7 6 1 0E+0 +P 7 5 1 0E+0 +P 7 4 0 0E+0 +P 7 3 1 1.0384099898329873699476559857223657703835891439521E+0 +P 7 2 0 0E+0 +P 7 1 1 0E+0 +P 7 0 0 0E+0 +P 8 12 0 0E+0 +P 8 11 1 0E+0 +P 8 10 0 0E+0 +P 8 9 1 0E+0 +P 8 8 1 0E+0 +P 8 7 0 0E+0 +P 8 6 0 0E+0 +P 8 5 0 0E+0 +P 8 4 1 1.0384099898329873699476559857223657703835891439521E+0 +P 8 3 0 0E+0 +P 8 2 1 0E+0 +P 8 1 0 0E+0 +P 8 0 1 0E+0 +P 9 12 0 0E+0 +P 9 11 0 0E+0 +P 9 10 0 0E+0 +P 9 9 0 0E+0 +P 9 8 0 0E+0 +P 9 7 0 0E+0 +P 9 6 0 0E+0 +P 9 5 1 1.0384099898329873699476559857223657703835891439521E+0 +P 9 4 0 0E+0 +P 9 3 1 0E+0 +P 9 2 0 0E+0 +P 9 1 1 0E+0 +P 9 0 0 0E+0 +P 10 12 0 0E+0 +P 10 11 0 0E+0 +P 10 10 0 0E+0 +P 10 9 0 0E+0 +P 10 8 0 0E+0 +P 10 7 0 0E+0 +P 10 6 0 0E+0 +P 10 5 1 0E+0 +P 10 4 0 0E+0 +P 10 3 1 0E+0 +P 10 2 0 0E+0 +P 10 1 1 0E+0 +P 10 0 0 0E+0 +P 11 12 0 0E+0 +P 11 11 1 0E+0 +P 11 10 0 0E+0 +P 11 9 1 0E+0 +P 11 8 1 6.5046211572468320925182801182675654473904348804001E-2 +P 11 7 0 0E+0 +P 11 6 0 0E+0 +P 11 5 0 0E+0 +P 11 4 1 0E+0 +P 11 3 0 0E+0 +P 11 2 1 0E+0 +P 11 1 0 0E+0 +P 11 0 1 0E+0 +P 12 12 1 0E+0 +P 12 11 0 0E+0 +P 12 10 1 0E+0 +P 12 9 0 0E+0 +P 12 8 0 0E+0 +P 12 7 1 4.5732512044719359723709928089287063422906450569799E-2 +P 12 6 1 6.5046211572468320925182801182675654473904348804001E-2 +P 12 5 1 0E+0 +P 12 4 0 0E+0 +P 12 3 1 0E+0 +P 12 2 0 0E+0 +P 12 1 1 0E+0 +P 12 0 0 0E+0 +P 13 12 0 0E+0 +P 13 11 0 0E+0 +P 13 10 0 0E+0 +P 13 9 0 0E+0 +P 13 8 0 0E+0 +P 13 7 0 0E+0 +P 13 6 0 0E+0 +P 13 5 1 0E+0 +P 13 4 0 0E+0 +P 13 3 1 0E+0 +P 13 2 0 0E+0 +P 13 1 1 0E+0 +P 13 0 0 0E+0 +P 14 12 0 0E+0 +P 14 11 0 0E+0 +P 14 10 0 0E+0 +P 14 9 0 0E+0 +P 14 8 0 0E+0 +P 14 7 0 0E+0 +P 14 6 0 0E+0 +P 14 5 1 0E+0 +P 14 4 0 0E+0 +P 14 3 1 0E+0 +P 14 2 0 0E+0 +P 14 1 1 0E+0 +P 14 0 0 0E+0 +END +CASE random10 16 14 8 +Z 2.4872742576227010784009272144678128689224276522040E+0 +S 5 5 6 +S 6 6 6 +B 0 0 0 0 0.18695701887732585566966717258355074202859428818460 0 2.7182818284590452353602874713526624977572470937000 +B 0 0 1 1 0.10810263967833063034038466277261899794436994794191 0 7.3890560989306502272304274605750078131803155705521 +B 0 0 1 7 0.00084366938800814223885214277849601985149128113407602 0 7.3890560989306502272304274605750078131803155705521 +B 0 0 2 2 0.010198122445049959442260801152984413697992452148758 0 27.474593022118317968158957115156725710168223409107 +B 0 0 2 3 0.0024759985669741631588701797818898496927801491478335 0 27.474593022118317968158957115156725710168223409107 +B 0 0 2 4 0.00043136961404410694838946967667317105767607666697290 0 27.474593022118317968158957115156725710168223409107 +B 0 0 3 2 0.0020661684347113953097237306593792175409352464274304 0 27.474593022118317968158957115156725710168223409107 +B 0 0 3 3 0.00050164430864975780450907731307716655372359273381672 0 102.15827997845022478719774797259932200994686828628 +B 0 0 3 4 0.000087396703171002659021794763021193252372662835440460 0 176.84196693478213160623653883004191830972551316345 +B 0 0 4 1 0.0021661055965175932334617288453756591511740012328712 0 7.3890560989306502272304274605750078131803155705521 +B 0 0 4 5 0.000021924501266791685029830987460271843261098374391826 0 1084.6106421672722863800692259900517775876753065696 +B 0 0 4 6 0.000016905017198588637520863234194963832875166442250409 0 1084.6106421672722863800692259900517775876753065696 +B 0 0 4 7 0.000016905017198588637520863234194963832875166442250409 0 1084.6106421672722863800692259900517775876753065696 +B 0 0 5 1 0.0010797081370714666242825323031740306795857120984367 0 7.3890560989306502272304274605750078131803155705521 +B 0 0 5 5 0.000010928397238364456836990703517659397807969407178369 0 1104.6961790904599541209977556446334954846632144082 +B 0 0 5 6 0.0000084264057375565686722312745762433461235108247281393 0 4052.9735786470520940238998757143767176302749819336 +B 0 0 5 7 0.0000084264057375565686722312745762433461235108247281393 0 7001.2509782036442339268019957841199397758867494590 +B 0 0 6 1 0.00088492328579400467601082016503342355633546403352934 0 7.3890560989306502272304274605750078131803155705521 +B 0 0 6 5 0.0000089568586737394248482983871351924621415900851422989 0 1124.7817160136476218619262852992152133816511222468 +B 0 0 6 6 0.0000069062391925073049428792888441443644243167059377131 0 7075.9346651599761407458407866415625360756653943361 +B 0 0 6 7 0.0000069062391925073049428792888441443644243167059377131 0 21041.336494777477023922319949225495508316640557337 +B 0 0 7 1 0.00078753086015527370187496409596311999471034000107564 0 7.3890560989306502272304274605750078131803155705521 +B 0 0 7 7 0.0000061461559199826730782032959780948735747196465424997 0 43353.280350991347259787738666354730762833424397797 +B 0 2 0 2 0.089621224404813964947468875754355239943792910939322 0 2.7182818284590452353602874713526624977572470937000 +B 0 2 1 7 0.0045694566193547638442059426302208150062118804022927 0 7.3890560989306502272304274605750078131803155705521 +B 0 2 2 3 0.0053407965788647467284937033720438431871976241584945 0 7.3890560989306502272304274605750078131803155705521 +B 0 2 2 4 0.0032961676259346905180129932668271645520935516776338 0 7.3890560989306502272304274605750078131803155705521 +B 0 2 2 8 0.00066416754183434352152902086702199396418316176500262 0 27.474593022118317968158957115156725710168223409107 +B 0 2 2 9 0.00034454412086717754000933277489237541033685452582345 0 27.474593022118317968158957115156725710168223409107 +B 0 2 3 3 0.0010820604838708513608109306748952719657975186673401 0 7.3890560989306502272304274605750078131803155705521 +B 0 2 3 4 0.00066781287839209621532364812483929866444658876896386 0 27.474593022118317968158957115156725710168223409107 +B 0 2 3 8 0.00013456222139831917480933123974354131434306620430250 0 67.645666868493653450016016424320161504144039086217 +B 0 2 3 9 0.000069805612821082632327193732202928900704269199702389 0 142.32935382482556026905480728176275780392268396339 +B 0 2 4 5 0.00015617690025449513780125528925059226039438529401481 0 142.32935382482556026905480728176275780392268396339 +B 0 2 4 6 0.00013751304385545606338896434405231170435799995450891 0 142.32935382482556026905480728176275780392268396339 +B 0 2 4 7 0.000091560442794744935170027014988086057020707800274028 0 142.32935382482556026905480728176275780392268396339 +B 0 2 5 5 0.000077847298995244353618224820918548997942462371413522 0 142.32935382482556026905480728176275780392268396339 +B 0 2 5 6 0.000068544189462831408458785770390406778543978782465291 0 529.22064998316678774353996178834026893556120755030 +B 0 2 5 7 0.000045638843867208349309987476688812223717445180521062 0 916.11194614150801521802511629491778006719973113721 +B 0 2 6 5 0.000063803249463239109905109100093095477769780794094719 0 142.32935382482556026905480728176275780392268396339 +B 0 2 6 6 0.000056178468309089604308475599114214564172279438273949 0 916.11194614150801521802511629491778006719973113721 +B 0 2 6 7 0.000037405363809105327329413292759668018814322129220802 0 2741.5741183943762455379551872165310788331180830824 +B 0 2 7 7 0.000033288623780053816339126200795095916362760603570673 0 5618.7158705834302512288450200466026541016777397989 +B 0 3 0 3 0.11823281764338185076434882439006190423855855985949 0 2.7182818284590452353602874713526624977572470937000 +B 0 3 1 7 0.0060019126840516888728642598418880403679876171290261 0 7.3890560989306502272304274605750078131803155705521 +B 0 3 2 4 0.013744388311960099785610887436624181249497810501482 0 7.3890560989306502272304274605750078131803155705521 +B 0 3 2 8 0.00086739199890639121647893336397720106477592645516690 0 27.474593022118317968158957115156725710168223409107 +B 0 3 2 9 0.00054776857793922523495924527184758251092961921598776 0 27.474593022118317968158957115156725710168223409107 +B 0 3 2 10 0.00029588664266274181842286134536969965728090020686336 0 27.474593022118317968158957115156725710168223409107 +B 0 3 3 4 0.0027846519236854560602083131220997499335387734174479 0 7.3890560989306502272304274605750078131803155705521 +B 0 3 3 8 0.00017573607086189745939770050892297969699666152447159 0 47.560129945305985709087486769738443607156131247662 +B 0 3 3 9 0.00011097946228466091691556300138236728335786451987148 0 122.24381690163789252812627762718103990693477612483 +B 0 3 3 10 0.000059947470195283802629548583568234330603599288661066 0 196.92750385796979934716506848462363620671342100200 +B 0 3 4 5 0.00084849913792544544746595490150682888395979992348451 0 47.560129945305985709087486769738443607156131247662 +B 0 3 4 6 0.00041510295624552030899931914683303982175158775247678 0 47.560129945305985709087486769738443607156131247662 +B 0 3 4 7 0.00012026326733019010460025346671698263382895700406276 0 47.560129945305985709087486769738443607156131247662 +B 0 3 5 5 0.00042293941024346882356073938699186331139028569144102 0 47.560129945305985709087486769738443607156131247662 +B 0 3 5 6 0.00020691052195297212479155304474749373370639690400088 0 176.84196693478213160623653883004191830972551316345 +B 0 3 5 7 0.000059945936401237070798945385099786546484845934369755 0 306.12380392425827750338559089034539301229489507924 +B 0 3 6 5 0.00034663898488305625545981407918428310184416025248523 0 47.560129945305985709087486769738443607156131247662 +B 0 3 6 6 0.00016958280915489397596697115435093262163362622498907 0 306.12380392425827750338559089034539301229489507924 +B 0 3 6 7 0.000049131383925719072736884990320645127846370243450747 0 916.11194614150801521802511629491778006719973113721 +B 0 3 7 7 0.000043724107687960073705854792931074418527132397991245 0 1877.5245565970551988530060629834556047718706394216 +B 0 4 0 4 0.14325534343380362119321309043088424525182362686084 0 2.7182818284590452353602874713526624977572470937000 +B 0 4 1 7 0.0094771952869681756645581260692448222361604229424031 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 1 11 0.0017751161958447976401905927414272186401714309511302 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 2 8 0.0016230378047358414660880851434108496257220834825401 0 27.474593022118317968158957115156725710168223409107 +B 0 4 2 9 0.0013034143837686754845683970512812310718757762433609 0 27.474593022118317968158957115156725710168223409107 +B 0 4 2 10 0.0010515324484921920680320131248033482182270572342366 0 27.474593022118317968158957115156725710168223409107 +B 0 4 3 8 0.00032883204713002880225574376236537855525945721810282 0 27.474593022118317968158957115156725710168223409107 +B 0 4 3 9 0.00026407543855279225977360625482476614162066021350272 0 102.15827997845022478719774797259932200994686828628 +B 0 4 3 10 0.00021304344646341514548759183701063318886639498229231 0 176.84196693478213160623653883004191830972551316345 +B 0 4 4 5 0.0013972453987635977755541166859400256228537011982191 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 4 6 0.00081164835198824167611658766477553214070945419725318 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 4 7 0.00018989920885814335474044949424479684758856642994496 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 4 11 0.000035568873597627711933154179393244388911551781756313 0 1084.6106421672722863800692259900517775876753065696 +B 0 4 5 5 0.00069646522725212376056191584152709918269131261120923 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 5 6 0.00040457091819126036002147119509934104683106099946213 0 27.474593022118317968158957115156725710168223409107 +B 0 4 5 7 0.000094656383030080963271942158270939372394321707712446 0 47.560129945305985709087486769738443607156131247662 +B 0 4 5 11 0.000017729515269969513831670325104385565521994413676370 0 1144.8672529368352896028548149537969312786390300853 +B 0 4 6 5 0.00057081935032265390484634319918135964177798828571331 0 7.3890560989306502272304274605750078131803155705521 +B 0 4 6 6 0.00033158426242258686339952911085711335926394823564314 0 47.560129945305985709087486769738443607156131247662 +B 0 4 6 7 0.000077579889061084975217999895945120684519102287529251 0 142.32935382482556026905480728176275780392268396339 +B 0 4 6 11 0.000014531020346656810539512789823025278021818061758485 0 1368.9183138058310100599711875261247201779749647168 +B 0 4 7 7 0.000069041642076586981191028764782211340581492577437657 0 291.69672773748937390713238899664795040347997371773 +B 0 4 7 11 0.000012931772885000458893434022182345134271729885799543 0 1905.1769838768360511725339237475874239091707780581 +B 0 8 0 8 0.19479532583719339018116743755310861189517210127073 0 2.7182818284590452353602874713526624977572470937000 +B 0 8 1 11 0.0066828548634582094605427761804512258701199734912405 0 7.3890560989306502272304274605750078131803155705521 +B 0 8 2 9 0.022275396200071186948300195397806843545248802558374 0 7.3890560989306502272304274605750078131803155705521 +B 0 8 2 10 0.0044200943309357424707283045679131074199419702631465 0 7.3890560989306502272304274605750078131803155705521 +B 0 8 3 9 0.0045130582366773865041649038341681254217683292506606 0 7.3890560989306502272304274605750078131803155705521 +B 0 8 3 10 0.00089552360586326293036147403445700450644885137823657 0 27.474593022118317968158957115156725710168223409107 +B 0 8 4 11 0.00013390763966102613150357665864995517947941041142725 0 142.32935382482556026905480728176275780392268396339 +B 0 8 4 12 0.000064271698133072881363380631122140965719800985545052 0 162.41489074801322800998333693634447570091059180195 +B 0 8 4 13 0.000035568873597627711933154179393244388911551781756313 0 162.41489074801322800998333693634447570091059180195 +B 0 8 5 11 0.000066747054432842127793625006686512714198870940867752 0 142.32935382482556026905480728176275780392268396339 +B 0 8 5 12 0.000032036607803998235320628233515359888289395167525061 0 549.30618690635445548446849144292198683254911538885 +B 0 8 5 13 0.000017729515269969513831670325104385565521994413676370 0 990.79563309783992203706390715236037636697837601438 +B 0 8 6 11 0.000054705545598636458428099393008477943726598220066934 0 142.32935382482556026905480728176275780392268396339 +B 0 8 6 12 0.000026257040463270555946984487384002387053866175988430 0 936.19748306469568295895364594949949796418763897576 +B 0 8 6 13 0.000014531020346656810539512789823025278021818061758485 0 2870.8559553838523914351042392768345535356874649981 +B 0 8 7 11 0.000048684791181533623745336586169460558490461859666526 0 142.32935382482556026905480728176275780392268396339 +B 0 9 0 9 0.16018957515550531402873683448537832579596402703660 0 2.7182818284590452353602874713526624977572470937000 +B 0 9 1 11 0.022520537517976034132642220819768978071381573013531 0 7.3890560989306502272304274605750078131803155705521 +B 0 9 2 10 0.010388699359754971204713165834106699655104268383082 0 7.3890560989306502272304274605750078131803155705521 +B 0 9 3 10 0.0021047798563402177162928130502803634496536427489987 0 7.3890560989306502272304274605750078131803155705521 +B 0 9 4 11 0.00045125505260026253093792829619928163272822851881906 0 47.560129945305985709087486769738443607156131247662 +B 0 9 4 12 0.00020691052195297212479155304474749373370639690400088 0 67.645666868493653450016016424320161504144039086217 +B 0 9 4 13 0.000081521474658338840152091508457470036248843935991194 0 67.645666868493653450016016424320161504144039086217 +B 0 9 5 11 0.00022493074805328812100063743514813727228288458400344 0 47.560129945305985709087486769738443607156131247662 +B 0 9 5 12 0.00010313577258536658754197758897967851733458331284919 0 196.92750385796979934716506848462363620671342100200 +B 0 9 5 13 0.000040634860865592572980468618805980120348528015620604 0 380.80749088059018432242438174778798931207353995641 +B 0 9 6 11 0.00018435209461632882270168628093867901386443212303277 0 47.560129945305985709087486769738443607156131247662 +B 0 9 6 12 0.000084529553520540697223099487923394078537616134952728 0 326.20934084744594524431412054492711090928280291780 +B 0 9 6 13 0.000033304124846641087518575096177571823379775370811631 0 1045.3937831309841611151741683552212547697691130530 +B 0 9 7 11 0.00016406276789784917355221070383394988465520589254743 0 47.560129945305985709087486769738443607156131247662 +B 0 10 0 10 0.13305617930024038417011650022664961913314310836226 0 2.7182818284590452353602874713526624977572470937000 +B 0 10 1 11 0.045762191182542034809568885494192217354996812651511 0 7.3890560989306502272304274605750078131803155705521 +B 0 10 4 11 0.00091695946301006277072017818800432379662327943669721 0 7.3890560989306502272304274605750078131803155705521 +B 0 10 4 12 0.00052041406726734140360290967006183147766541299192081 0 27.474593022118317968158957115156725710168223409107 +B 0 10 4 13 0.00013249355978725301587999659078700369397206802236749 0 27.474593022118317968158957115156725710168223409107 +B 0 10 5 11 0.00045706386390780282192394244950737523707928196688978 0 7.3890560989306502272304274605750078131803155705521 +B 0 10 5 12 0.00025940346766951458669402429915552792395461787142854 0 47.560129945305985709087486769738443607156131247662 +B 0 10 5 13 0.000066042197962023520294026341448990726859520200015063 0 122.24381690163789252812627762718103990693477612483 +B 0 10 6 11 0.00037460721317155799348237710943874322355269548296587 0 7.3890560989306502272304274605750078131803155705521 +B 0 10 6 12 0.00021260575990386510604981915293256248592237347231182 0 67.645666868493653450016016424320161504144039086217 +B 0 10 6 13 0.000054127848827857484403056500823166466455006059069362 0 271.61119081430170616620385934206623250649206587918 +B 0 10 7 11 0.00033337888780343557926159443940442721678940224100393 0 7.3890560989306502272304274605750078131803155705521 +B 1 1 1 1 0.37468295951964957947169640048431411849078975162643 0 2.7182818284590452353602874713526624977572470937000 +B 1 1 2 2 0.046487639293086189215242169816935870491274833815265 0 7.3890560989306502272304274605750078131803155705521 +B 1 1 2 3 0.014864428834327943201796394681987820556505449836253 0 7.3890560989306502272304274605750078131803155705521 +B 1 1 2 4 0.0066863906346234282621769448823095067420485292324084 0 7.3890560989306502272304274605750078131803155705521 +B 1 1 2 8 0.00064157721587190052866194196337412805374283502155311 0 7.3890560989306502272304274605750078131803155705521 +B 1 1 3 2 0.016086850117435717065449398639669779168863279927769 0 7.3890560989306502272304274605750078131803155705521 +B 1 1 3 3 0.0051437724602781970375009814598235920229977285002393 0 27.474593022118317968158957115156725710168223409107 +B 1 1 3 4 0.0023137970781366420318243827541763381578869218299322 0 47.560129945305985709087486769738443607156131247662 +B 1 1 3 8 0.00022201507040233668321383372697906347516280042150742 0 67.645666868493653450016016424320161504144039086217 +B 1 1 4 5 0.00070936489281991235245917349703257163166101229801365 0 291.69672773748937390713238899664795040347997371773 +B 1 1 4 6 0.00055637970882229074114601268961620698086855259564066 0 291.69672773748937390713238899664795040347997371773 +B 1 1 4 7 0.00017971226249516708399223981239766420112814639497165 0 291.69672773748937390713238899664795040347997371773 +B 1 1 5 5 0.00035667920089716993615391611113815659966261201251755 0 291.69672773748937390713238899664795040347997371773 +B 1 1 5 6 0.00027975597882952370420407328469673997400506527271010 0 1084.6106421672722863800692259900517775876753065696 +B 1 1 5 7 0.000090361993985050113520934785597058798128965236453677 0 1877.5245565970551988530060629834556047718706394216 +B 1 1 6 5 0.00018933104519766835000491193475703721978183847263424 0 291.69672773748937390713238899664795040347997371773 +B 1 1 6 6 0.00014849896416404908475315218638767325656596610854523 0 1877.5245565970551988530060629834556047718706394216 +B 1 1 6 7 0.000047965596884544058442362141434388417317280660429573 0 5618.7158705834302512288450200466026541016777397989 +B 1 1 7 7 0.000019952962702166653041138671077804907594719052355756 0 11515.270669696614531034649260186089098392901274850 +B 1 1 8 2 0.00063978559525069764384928924114225295634934239728048 0 7.3890560989306502272304274605750078131803155705521 +B 1 1 8 3 0.00020457152900096834333939297134438633581034925137709 0 47.560129945305985709087486769738443607156131247662 +B 1 1 8 4 0.000092021373365101341964951198636820780210446642442513 0 142.32935382482556026905480728176275780392268396339 +B 1 1 8 8 0.0000088296989736997913737426140829819520738315052871819 0 63986.829730314909457536377517736762165008857647291 +B 1 7 1 7 0.36565210678136423112531683212347416874259007145303 0 2.7182818284590452353602874713526624977572470937000 +B 1 7 2 8 0.11697626338399314502473687087642353299590346284394 0 7.3890560989306502272304274605750078131803155705521 +B 1 7 2 9 0.078387249526134608872353375767675519823630024787805 0 7.3890560989306502272304274605750078131803155705521 +B 1 7 2 10 0.012447381756102137976229726007842202717684066616282 0 7.3890560989306502272304274605750078131803155705521 +B 1 7 3 8 0.040479139078069868854213195645941582314614394431335 0 7.3890560989306502272304274605750078131803155705521 +B 1 7 3 9 0.027125574742456377663928694755771422670766775068022 0 27.474593022118317968158957115156725710168223409107 +B 1 7 3 10 0.0043073635854574180803620021571475928866566752784145 0 47.560129945305985709087486769738443607156131247662 +B 1 7 4 11 0.00063866781448803191793172223464675815350552550209064 0 291.69672773748937390713238899664795040347997371773 +B 1 7 4 12 0.00017971226249516708399223981239766420112814639497165 0 291.69672773748937390713238899664795040347997371773 +B 1 7 4 13 0.000056280103996555318813675494851837442172687035296697 0 291.69672773748937390713238899664795040347997371773 +B 1 7 5 11 0.00032113166018798880937046326492130867510160545587604 0 291.69672773748937390713238899664795040347997371773 +B 1 7 5 12 0.000090361993985050113520934785597058798128965236453677 0 1084.6106421672722863800692259900517775876753065696 +B 1 7 5 13 0.000028298471947352455771349815260205746484154961704793 0 1877.5245565970551988530060629834556047718706394216 +B 1 7 6 11 0.00017046183998540185419764138654248030696489775269661 0 291.69672773748937390713238899664795040347997371773 +B 1 7 6 12 0.000047965596884544058442362141434388417317280660429573 0 1877.5245565970551988530060629834556047718706394216 +B 1 7 6 13 0.000015021283152514904275628341202177841718883194202508 0 5618.7158705834302512288450200466026541016777397989 +B 1 7 7 11 0.000070909546764493557589594858024862658300928371491096 0 291.69672773748937390713238899664795040347997371773 +B 1 7 8 8 0.0016098844647175034753079298238051801324399977102466 0 7.3890560989306502272304274605750078131803155705521 +B 1 7 8 9 0.0010788036101803440379520344735574070794427501632730 0 47.560129945305985709087486769738443607156131247662 +B 1 7 8 10 0.00017130694669034020662290920370122009765984999757845 0 142.32935382482556026905480728176275780392268396339 +B 1 11 1 11 0.21221908494237961908020309000633765844638044132569 0 2.7182818284590452353602874713526624977572470937000 +B 1 11 4 12 0.0055076093511965108345586398683177478573176327298475 0 7.3890560989306502272304274605750078131803155705521 +B 1 11 4 13 0.0016568290223046518664727348314012974282527708549496 0 7.3890560989306502272304274605750078131803155705521 +B 1 11 5 12 0.0027693077598319630642055010159664556120951121631986 0 7.3890560989306502272304274605750078131803155705521 +B 1 11 5 13 0.00083307823333299590205323092589121992762062891642082 0 27.474593022118317968158957115156725710168223409107 +B 1 11 6 12 0.0014699930114348286938894237233747670235310633512379 0 7.3890560989306502272304274605750078131803155705521 +B 1 11 6 13 0.00044221129870097405260049637311037438669454755503026 0 47.560129945305985709087486769738443607156131247662 +B 2 0 2 0 0.27908238530859269933904006387055946400397923613911 0 2.7182818284590452353602874713526624977572470937000 +B 2 0 3 2 0.026329848661673625676418660231028676883236454177893 0 7.3890560989306502272304274605750078131803155705521 +B 2 0 3 3 0.0063926147098375139595778271784152481427130625595134 0 7.3890560989306502272304274605750078131803155705521 +B 2 0 3 4 0.0011137242876053991852025775882178671192025092951287 0 7.3890560989306502272304274605750078131803155705521 +B 2 0 4 1 0.030199320903274085646568347775321624306331266985473 0 7.3890560989306502272304274605750078131803155705521 +B 2 0 4 5 0.00030566609978042390858048419018543539952333417986752 0 67.645666868493653450016016424320161504144039086217 +B 2 0 4 6 0.00023568566559095693320826278317780445023600654389240 0 67.645666868493653450016016424320161504144039086217 +B 2 0 4 7 0.00023568566559095693320826278317780445023600654389240 0 67.645666868493653450016016424320161504144039086217 +B 2 0 5 1 0.014820332580613513066197076123056175398881617568933 0 7.3890560989306502272304274605750078131803155705521 +B 2 0 5 5 0.00015000579886793896784876189710934347858758778652942 0 87.731203791681321190944546078901879401131946924772 +B 2 0 5 6 0.00011566286406667343645058674618079405998312633980244 0 271.61119081430170616620385934206623250649206587918 +B 2 0 5 7 0.00011566286406667343645058674618079405998312633980244 0 455.49117783692209114146317260523058561185218483358 +B 2 0 6 1 0.0089276202227677293703654132902041978797721507300529 0 7.3890560989306502272304274605750078131803155705521 +B 2 0 6 5 0.000090361993985050113520934785597058798128965236453677 0 107.81674071486898893187307573348359729811985476333 +B 2 0 6 6 0.000069674153305817560937739795484774447580695144870716 0 530.17486479325399796050196346267318191163082971075 +B 2 0 6 7 0.000069674153305817560937739795484774447580695144870716 0 1452.3706162125130563305878525163804837983955444785 +B 2 0 7 1 0.0061600168489315738871553333124137082235879448294632 0 7.3890560989306502272304274605750078131803155705521 +B 2 0 7 7 0.000048074844985489261009133502590654406638852629976812 0 3206.6971410978431524385056361983221356872617856148 +B 2 0 8 2 0.0020226209891923883410021039989483668101797272483782 0 87.731203791681321190944546078901879401131946924772 +B 2 0 8 3 0.00049107143964554391337573445286057800023116354922206 0 107.81674071486898893187307573348359729811985476333 +B 2 0 8 4 0.000085554693049300420047114629676651597656147069654008 0 127.90227763805665667280160538806531519510776260188 +B 2 0 9 2 0.00093079696408657784741569930806313524607248793154359 0 87.731203791681321190944546078901879401131946924772 +B 2 0 9 3 0.00022598786802573815664808080627135269849924492183075 0 346.29487777063361298524265019950882880627071075635 +B 2 0 9 4 0.000039371710755085621406904493531675696086788719688418 0 659.45670178273014385765101552297665661420021162654 +B 2 2 2 2 0.13378318306189873451022511561079915874738766392247 0 2.7182818284590452353602874713526624977572470937000 +B 2 2 3 3 0.013789044641501569780160409765022856928082862903121 0 7.3890560989306502272304274605750078131803155705521 +B 2 2 3 4 0.0085101542192694550057851601748254759045723096387366 0 7.3890560989306502272304274605750078131803155705521 +B 2 2 3 8 0.0017147696506607675495913926967316508788776155761293 0 7.3890560989306502272304274605750078131803155705521 +B 2 2 3 9 0.00088955536752802037837440651609896002400890354500248 0 7.3890560989306502272304274605750078131803155705521 +B 2 2 4 5 0.0021773806115669761697900069258171911150819873108205 0 47.560129945305985709087486769738443607156131247662 +B 2 2 4 6 0.0019171736347726070213742335562353600446544078059607 0 47.560129945305985709087486769738443607156131247662 +B 2 2 4 7 0.0012765135727684335268713562615051287319463245633316 0 47.560129945305985709087486769738443607156131247662 +B 2 2 5 5 0.0010685506777241373927695007591655762739769135338471 0 47.560129945305985709087486769738443607156131247662 +B 2 2 5 6 0.00094085396731663801538009271981034114257657477290975 0 176.84196693478213160623653883004191830972551316345 +B 2 2 5 7 0.00062644970569667094600821890360173458558448138355174 0 306.12380392425827750338559089034539301229489507924 +B 2 2 6 5 0.00064368424848852231137009242679153875174452888016440 0 47.560129945305985709087486769738443607156131247662 +B 2 2 6 6 0.00056676102642087607942024960035012212608698214035697 0 306.12380392425827750338559089034539301229489507924 +B 2 2 6 7 0.00037736704157640248873711110125044095021088210410052 0 916.11194614150801521802511629491778006719973113721 +B 2 2 7 7 0.00026038152120469966719940739747494205734716255836436 0 1877.5245565970551988530060629834556047718706394216 +B 2 2 8 3 0.0010592545164685770502928046960055714042401485022425 0 7.3890560989306502272304274605750078131803155705521 +B 2 2 8 4 0.00065373776987233355696418487282164500166513202267442 0 27.474593022118317968158957115156725710168223409107 +B 2 2 8 8 0.00013172613073561462765698349583794228311679467278540 0 10432.828507766716528037259091141570110720490883034 +B 2 2 8 9 0.000068334360008302341864523949131726253785291225701752 0 10452.914044689904195778187620796151828617478790873 +B 2 2 9 3 0.00048746200765850229627912289252740258664244594496790 0 7.3890560989306502272304274605750078131803155705521 +B 2 2 9 4 0.00030084585038784976103794657978772558422998974282558 0 47.560129945305985709087486769738443607156131247662 +B 2 2 9 8 0.000060619504709351783059736533420561217886070812668135 0 10527.597731646236102597226411653594424917257435750 +B 2 2 9 9 0.000031447026001605996007855256561830135428880749891259 0 38907.051420661186389550377951596591154505140050490 +B 2 3 2 3 0.17649349014985128003173425048092769271967744116851 0 2.7182818284590452353602874713526624977572470937000 +B 2 3 3 4 0.035485714762803322075764950268558668627718612586566 0 7.3890560989306502272304274605750078131803155705521 +B 2 3 3 8 0.0022394612522658305386139713231074498539087744667558 0 7.3890560989306502272304274605750078131803155705521 +B 2 3 3 9 0.0014142469691330833673969851424747589990400624356290 0 7.3890560989306502272304274605750078131803155705521 +B 2 3 3 10 0.00076392988653535719252085850396733446918173670137771 0 7.3890560989306502272304274605750078131803155705521 +B 2 3 4 5 0.011829569986595907770440839298752920059877637932850 0 27.474593022118317968158957115156725710168223409107 +B 2 3 4 6 0.0057872651285836761021068941754004927733599976403368 0 27.474593022118317968158957115156725710168223409107 +B 2 3 4 7 0.0016766814179417366260315724451022217009485593401416 0 27.474593022118317968158957115156725710168223409107 +B 2 3 5 5 0.0058053676785820644062797963506800008871255143903869 0 27.474593022118317968158957115156725710168223409107 +B 2 3 5 6 0.0028401033987654459207884727788524423291813025836490 0 102.15827997845022478719774797259932200994686828628 +B 2 3 5 7 0.00082283228570670138619397724481406855419374303794303 0 176.84196693478213160623653883004191830972551316345 +B 2 3 6 5 0.0034970954670550228630463460159791352818072638940593 0 27.474593022118317968158957115156725710168223409107 +B 2 3 6 6 0.0017108499016234713177022012508405582928797768705628 0 176.84196693478213160623653883004191830972551316345 +B 2 3 6 7 0.00049566594500251382585334390791642627696496902707388 0 529.22064998316678774353996178834026893556120755030 +B 2 3 7 7 0.00034200721989386916296813149649565573355934203726731 0 1084.6106421672722863800692259900517775876753065696 +B 2 3 8 4 0.0027259614142870639077186964418968461290621388070525 0 7.3890560989306502272304274605750078131803155705521 +B 2 3 8 8 0.00017203218261976980964450860946351296971797431830334 0 6026.8489100024969277649455266765422960196810014726 +B 2 3 8 9 0.00010864041189245752385204906275729694038647087121970 0 6046.9344469256845955058740563311240139166689093112 +B 2 3 8 10 0.000058683991793196965388764553926271139922027305975378 0 6067.0199838488722632468025859857057318136568171498 +B 2 3 9 4 0.0012544696323203278346708291107757376583056084083398 0 7.3890560989306502272304274605750078131803155705521 +B 2 3 9 8 0.000079168086439964489285201790334849539443619828955153 0 6046.9344469256845955058740563311240139166689093112 +B 2 3 9 9 0.000049995607732218702233320513476118456986429766178276 0 22449.693858776863372989070873362427145009509111382 +B 2 3 9 10 0.000027005989601343817256594322255483481715089375497072 0 38907.051420661186389550377951596591154505140050490 +B 2 4 2 4 0.21384617273952658395968066170324944420872169756194 0 2.7182818284590452353602874713526624977572470937000 +B 2 4 3 8 0.0041904125000590090632423512386297234434837516695100 0 7.3890560989306502272304274605750078131803155705521 +B 2 4 3 9 0.0033651982169262618920253650579970325886150396383830 0 7.3890560989306502272304274605750078131803155705521 +B 2 4 3 10 0.0027148811343285357171492384194896080587567139041317 0 7.3890560989306502272304274605750078131803155705521 +B 2 4 4 5 0.019480057780065080203460826871626861841279758926586 0 7.3890560989306502272304274605750078131803155705521 +B 2 4 4 6 0.011315805232077654169824706392646078219515664772871 0 7.3890560989306502272304274605750078131803155705521 +B 2 4 4 7 0.0026475288909297462443224445164219150333715497236057 0 7.3890560989306502272304274605750078131803155705521 +B 2 4 4 11 0.00049589264238532608162403615275963552066358604875219 0 67.645666868493653450016016424320161504144039086217 +B 2 4 5 5 0.0095598485778808519374950887534766912987130015391682 0 7.3890560989306502272304274605750078131803155705521 +B 2 4 5 6 0.0055532373557001256551157042554332622450162601571874 0 27.474593022118317968158957115156725710168223409107 +B 2 4 5 7 0.0012992761925354333643534342513064596611906366349654 0 47.560129945305985709087486769738443607156131247662 +B 2 4 5 11 0.00024335957447417281383999478553602919138346510073976 0 127.90227763805665667280160538806531519510776260188 +B 2 4 6 5 0.0057587572361316968086441171928400024883090496363636 0 7.3890560989306502272304274605750078131803155705521 +B 2 4 6 6 0.0033452146805011375304380371691578482512596067846352 0 47.560129945305985709087486769738443607156131247662 +B 2 4 6 7 0.00078267099259386620106952022356980842904688589472074 0 142.32935382482556026905480728176275780392268396339 +B 2 4 6 11 0.00014659737537346379288758262192619107323824188467817 0 351.95333850705237712991797796039310409444369723340 +B 2 4 7 7 0.00054003938129589612204782757873012250250010096725182 0 291.69672773748937390713238899664795040347997371773 +B 2 4 7 11 0.00010115151404029186255670197631172631931593011207370 0 888.21200857805741824248071418185580782563951057465 +B 2 4 8 8 0.00032190144291755148503436213595659037111130501403634 0 1620.8693122382773274926319622115144813188711199110 +B 2 4 8 9 0.00025850967219023919924190258925037434177980156695269 0 1640.9548491614649952335604918660961992158590277495 +B 2 4 8 10 0.00020855325209097864077861808041934854131535800170836 0 1661.0403860846526629744890215206779171128469355881 +B 2 4 9 8 0.00014813694083258914421538036399675446525764100099876 0 1620.8693122382773274926319622115144813188711199110 +B 2 4 9 9 0.00011896446212484335716349908713802338280045093822189 0 6046.9344469256845955058740563311240139166689093112 +B 2 4 9 10 0.000095974843993968472186772895917388407529110547540684 0 10527.597731646236102597226411653594424917257435750 +B 2 8 2 8 0.29078311425836351286750726492347014903804357205180 0 2.7182818284590452353602874713526624977572470937000 +B 2 8 3 9 0.057511352112797746814357773644687617910890375579641 0 7.3890560989306502272304274605750078131803155705521 +B 2 8 3 10 0.011411945231188043887484074283112065903843165716242 0 7.3890560989306502272304274605750078131803155705521 +B 2 8 4 11 0.0018669079605466387990751244076764218220888112090263 0 47.560129945305985709087486769738443607156131247662 +B 2 8 4 12 0.00089606048755862918078425233635672848966582082556218 0 47.560129945305985709087486769738443607156131247662 +B 2 8 4 13 0.00049589264238532608162403615275963552066358604875219 0 47.560129945305985709087486769738443607156131247662 +B 2 8 5 11 0.00091618606131293523218521013324075426698962035215339 0 47.560129945305985709087486769738443607156131247662 +B 2 8 5 12 0.00043974215448420325402575312674836315999272675513106 0 176.84196693478213160623653883004191830972551316345 +B 2 8 5 13 0.00024335957447417281383999478553602919138346510073976 0 306.12380392425827750338559089034539301229489507924 +B 2 8 6 11 0.00055190132639092750521999174424555855207424567529839 0 47.560129945305985709087486769738443607156131247662 +B 2 8 6 12 0.00026489627879957513000381542859217639999232880765154 0 306.12380392425827750338559089034539301229489507924 +B 2 8 6 13 0.00014659737537346379288758262192619107323824188467817 0 916.11194614150801521802511629491778006719973113721 +B 2 8 7 11 0.00038080937413148831740512215756690676446886852096115 0 47.560129945305985709087486769738443607156131247662 +B 2 8 8 9 0.0044179391000261357189942632323856252852720031403615 0 7.3890560989306502272304274605750078131803155705521 +B 2 8 8 10 0.00087664916911253289462225734122639354625323008521748 0 27.474593022118317968158957115156725710168223409107 +B 2 8 9 9 0.0020331067084721966555556780281107690728365997046666 0 7.3890560989306502272304274605750078131803155705521 +B 2 8 9 10 0.00040342821988848238177126736461470824621499235204026 0 47.560129945305985709087486769738443607156131247662 +B 2 9 2 9 0.23912495505345510227533714091429221748692386814484 0 2.7182818284590452353602874713526624977572470937000 +B 2 9 3 10 0.026821886421528847804477740249885459393536626456083 0 7.3890560989306502272304274605750078131803155705521 +B 2 9 4 11 0.0062912889217441579939730355726438723377400185358859 0 27.474593022118317968158957115156725710168223409107 +B 2 9 4 12 0.0028846965082253742915573987110266432268308052645548 0 27.474593022118317968158957115156725710168223409107 +B 2 9 4 13 0.0011365527043894995761269134474898668333716692913814 0 27.474593022118317968158957115156725710168223409107 +B 2 9 5 11 0.0030874533397494119291713582849358158593101847238907 0 27.474593022118317968158957115156725710168223409107 +B 2 9 5 12 0.0014156663251788399917321877345708664392277567255946 0 102.15827997845022478719774797259932200994686828628 +B 2 9 5 13 0.00055776383609413988321186860174463574837555849009778 0 176.84196693478213160623653883004191830972551316345 +B 2 9 6 11 0.0018598510339001833688646381727464438780430549087487 0 27.474593022118317968158957115156725710168223409107 +B 2 9 6 12 0.00085278324522152488899073751297273116778518082290841 0 176.84196693478213160623653883004191830972551316345 +B 2 9 6 13 0.00033599136021793738357072112102587224911434192093460 0 529.22064998316678774353996178834026893556120755030 +B 2 9 7 11 0.0012832886502172626774005988873679623347957496346742 0 27.474593022118317968158957115156725710168223409107 +B 2 9 8 10 0.0020604186200616846903973697587186036394299551400230 0 7.3890560989306502272304274605750078131803155705521 +B 2 9 9 10 0.00094819118685534973554820618521293040869623069641801 0 7.3890560989306502272304274605750078131803155705521 +B 2 10 2 10 0.19862124525811237035918377185933719907923541407546 0 2.7182818284590452353602874713526624977572470937000 +B 2 10 4 11 0.012784027299155660983766306028152330815825490202143 0 7.3890560989306502272304274605750078131803155705521 +B 2 10 4 12 0.0072554871956616829160484938109067453696698230696097 0 7.3890560989306502272304274605750078131803155705521 +B 2 10 4 13 0.0018471932005831400460020121492277290953670801699857 0 7.3890560989306502272304274605750078131803155705521 +B 2 10 5 11 0.0062737681055797636380433227845452952614506126057762 0 7.3890560989306502272304274605750078131803155705521 +B 2 10 5 12 0.0035606341486450839037160913079644753456156550322378 0 27.474593022118317968158957115156725710168223409107 +B 2 10 5 13 0.00090651103251537248398191756888179172397211332618277 0 47.560129945305985709087486769738443607156131247662 +B 2 10 6 11 0.0037792552027877948255252736006555697677373653202771 0 7.3890560989306502272304274605750078131803155705521 +B 2 10 6 12 0.0021448904239101286127894376823382798093575354062048 0 47.560129945305985709087486769738443607156131247662 +B 2 10 6 13 0.00054607318574164352683705461023783777553871204877399 0 142.32935382482556026905480728176275780392268396339 +B 2 10 7 11 0.0026076686893797781794572409996411225615104405441075 0 7.3890560989306502272304274605750078131803155705521 +B 3 0 3 0 0.30644695820795267822020262493342462380356203651641 0 2.7182818284590452353602874713526624977572470937000 +B 3 0 4 1 0.12917682643862982325455947832153979177951523271345 0 7.3890560989306502272304274605750078131803155705521 +B 3 0 4 5 0.0013074789610659068385515587146454264203581307817331 0 7.3890560989306502272304274605750078131803155705521 +B 3 0 4 6 0.0010081394351756849579317461401961007082991061884588 0 7.3890560989306502272304274605750078131803155705521 +B 3 0 4 7 0.0010081394351756849579317461401961007082991061884588 0 7.3890560989306502272304274605750078131803155705521 +B 3 0 5 1 0.079152063123575977428170754467322615699077881368595 0 7.3890560989306502272304274605750078131803155705521 +B 3 0 5 5 0.00080114723447090367401348642098004174282305314006555 0 27.474593022118317968158957115156725710168223409107 +B 3 0 5 6 0.00061772934364742430752138483569849766591395382732732 0 47.560129945305985709087486769738443607156131247662 +B 3 0 5 7 0.00061772934364742430752138483569849766591395382732732 0 67.645666868493653450016016424320161504144039086217 +B 3 0 6 1 0.033101663063015518802410198192493893768578364840065 0 7.3890560989306502272304274605750078131803155705521 +B 3 0 6 5 0.00033504250897313112121430237646204557082218569339105 0 47.560129945305985709087486769738443607156131247662 +B 3 0 6 6 0.00025833652075032557594716923780512357753411659065156 0 142.32935382482556026905480728176275780392268396339 +B 3 0 6 7 0.00025833652075032557594716923780512357753411659065156 0 291.69672773748937390713238899664795040347997371773 +B 3 0 7 1 0.012340279607384981031746335049013718477117742425260 0 7.3890560989306502272304274605750078131803155705521 +B 3 0 7 7 0.000096307695863774284822098810253028526524935962397334 0 827.95539780849441501969512521811065413467578705899 +B 3 0 8 2 0.0040862807006073910864142883834347081753501353619075 0 87.731203791681321190944546078901879401131946924772 +B 3 0 8 3 0.00099210665624720440185767635006689663965904953991309 0 87.731203791681321190944546078901879401131946924772 +B 3 0 8 4 0.00017284527992233358369701517904273511486094034750512 0 87.731203791681321190944546078901879401131946924772 +B 3 0 9 2 0.0029021007797528212056824594817914398016700830952519 0 87.731203791681321190944546078901879401131946924772 +B 3 0 9 3 0.00070460002913285136362327324644777944373900882295158 0 326.20934084744594524431412054492711090928280291780 +B 3 0 9 4 0.00012275574254226788701673922087589518080659830627127 0 564.68747790321056929768369501095234241743365891082 +B 3 0 10 2 0.0022460378993094401159096260638515532889869562996708 0 87.731203791681321190944546078901879401131946924772 +B 3 0 10 3 0.00054531475279149679510270726633356774284986282990670 0 564.68747790321056929768369501095234241743365891082 +B 3 0 10 4 0.000095004988121497646015284822219906720495571565870640 0 1689.8945384581904701669954253080728023304767783111 +B 3 2 3 2 0.14690088542623004796335753970662207409121655494170 0 2.7182818284590452353602874713526624977572470937000 +B 3 2 4 5 0.0093136901406525045943845069160253020903536113452416 0 7.3890560989306502272304274605750078131803155705521 +B 3 2 4 6 0.0082006614209953466696729586754343204895820420523251 0 7.3890560989306502272304274605750078131803155705521 +B 3 2 4 7 0.0054602543138043166567779391025600271113853833601245 0 7.3890560989306502272304274605750078131803155705521 +B 3 2 5 5 0.0057068888457062927187202618849514543336707394447269 0 7.3890560989306502272304274605750078131803155705521 +B 3 2 5 6 0.0050248894352430643256973768574744487309738664143673 0 27.474593022118317968158957115156725710168223409107 +B 3 2 5 7 0.0033457269855003378796129249456065200767014459487656 0 47.560129945305985709087486769738443607156131247662 +B 3 2 6 5 0.0023866404014475256259064530848552264973282476271530 0 7.3890560989306502272304274605750078131803155705521 +B 3 2 6 6 0.0021014259193046742333447593193097331340319639719054 0 47.560129945305985709087486769738443607156131247662 +B 3 2 6 7 0.0013991944493217311461939442999870970307192512116418 0 142.32935382482556026905480728176275780392268396339 +B 3 2 7 7 0.00052161882914647327635039702442048990528718572949391 0 291.69672773748937390713238899664795040347997371773 +B 3 2 8 3 0.0021400011721449851094025091529391263582471398335793 0 7.3890560989306502272304274605750078131803155705521 +B 3 2 8 4 0.0013207397958201142912418479819149648334490306411713 0 7.3890560989306502272304274605750078131803155705521 +B 3 2 8 8 0.00026612496788414806280772951077847054298694148024517 0 1620.8693122382773274926319622115144813188711199110 +B 3 2 8 9 0.00013805521547651811034304399590779874026976317648105 0 1620.8693122382773274926319622115144813188711199110 +B 3 2 9 3 0.0015198415198032710913926285661609692409298923359894 0 7.3890560989306502272304274605750078131803155705521 +B 3 2 9 4 0.00093799723321268761478609454058908497799748181930912 0 27.474593022118317968158957115156725710168223409107 +B 3 2 9 8 0.00018900352995658901617158478390618123031454238804562 0 1661.0403860846526629744890215206779171128469355881 +B 3 2 9 9 0.000098047632514279721402091338447856509700718783818009 0 6067.0199838488722632468025859857057318136568171498 +B 3 2 10 3 0.0011762588254130003265296922947187727966549363650382 0 7.3890560989306502272304274605750078131803155705521 +B 3 2 10 4 0.00072594906074300117744226985060511177430064510100213 0 47.560129945305985709087486769738443607156131247662 +B 3 2 10 8 0.00014627648162581124204476406590635128666353092285230 0 1755.8096099641722375344563420327022313096134883038 +B 3 2 10 9 0.000075882512454785712736172238136643267076206364562765 0 10676.965105558899916235303993368479617516814725504 +B 3 3 3 3 0.19379902153309396327203314081582211359763023828427 0 2.7182818284590452353602874713526624977572470937000 +B 3 3 4 5 0.050600684495407084732138560384211820294490573932433 0 7.3890560989306502272304274605750078131803155705521 +B 3 3 4 6 0.024754879272412335598308644462091571450537949050785 0 7.3890560989306502272304274605750078131803155705521 +B 3 3 4 7 0.0071719620852419183427291124920496601362750018395894 0 7.3890560989306502272304274605750078131803155705521 +B 3 3 5 5 0.031005163106243410974880661066017465144398255006665 0 7.3890560989306502272304274605750078131803155705521 +B 3 3 5 6 0.015168353495023879429226598319053234130808569174815 0 27.474593022118317968158957115156725710168223409107 +B 3 3 5 7 0.0043945621776105250056200131436466138332165176046016 0 47.560129945305985709087486769738443607156131247662 +B 3 3 6 5 0.012966465078166887816070720624826322787500729312678 0 7.3890560989306502272304274605750078131803155705521 +B 3 3 6 6 0.0063434572239651589619450314111564030830957966844457 0 47.560129945305985709087486769738443607156131247662 +B 3 3 6 7 0.0018378209079101936292899043428464343805916730723683 0 142.32935382482556026905480728176275780392268396339 +B 3 3 7 7 0.00068513850282191427703829457907904596671531259254000 0 291.69672773748937390713238899664795040347997371773 +B 3 3 8 4 0.0055072322384281017153334079053910588733666529467978 0 7.3890560989306502272304274605750078131803155705521 +B 3 3 8 8 0.00034755487631087077571705785978127463164111921763926 0 1620.8693122382773274926319622115144813188711199110 +B 3 3 8 9 0.00021948512390324082325237234491060282892394091387515 0 1620.8693122382773274926319622115144813188711199110 +B 3 3 8 10 0.00011855867430451844175746294637419905575815518924240 0 1620.8693122382773274926319622115144813188711199110 +B 3 3 9 4 0.0039112689862559855514689770534122665055364417883218 0 7.3890560989306502272304274605750078131803155705521 +B 3 3 9 8 0.00024683553369173774636365544784936292617439395138605 0 1640.9548491614649952335604918660961992158590277495 +B 3 3 9 9 0.00015587963624942845159416200239103820556057034715844 0 6046.9344469256845955058740563311240139166689093112 +B 3 3 9 10 0.000084201073385502066888692111580440716900030597377642 0 10452.914044689904195778187620796151828617478790873 +B 3 3 10 4 0.0030270686803208758240899607774707223469316207021245 0 7.3890560989306502272304274605750078131803155705521 +B 3 3 10 8 0.00019103470404467997333861627183283702316687580265102 0 1661.0403860846526629744890215206779171128469355881 +B 3 3 10 9 0.00012064073487365444403002444406312900357955124436148 0 10527.597731646236102597226411653594424917257435750 +B 3 3 10 10 0.000065166173175585158486050018268916229493341646004836 1096.6331584284585992637202382881214324422191348337 30274.216195943132452426198286410083098774491213748 +B 3 4 3 4 0.23481420759672231623457748694722637886507154362267 0 2.7182818284590452353602874713526624977572470937000 +B 3 4 4 5 0.083325451288447111111022417325870675256878834255897 0 7.3890560989306502272304274605750078131803155705521 +B 3 4 4 6 0.048403068835861094054850381785530432994523987004153 0 7.3890560989306502272304274605750078131803155705521 +B 3 4 4 7 0.011324737437980328160955492879964260827302254417981 0 7.3890560989306502272304274605750078131803155705521 +B 3 4 4 11 0.0021211681548328428826432943807870823090706754813752 0 7.3890560989306502272304274605750078131803155705521 +B 3 4 5 5 0.051057001182150872742501481090244321162219036994231 0 7.3890560989306502272304274605750078131803155705521 +B 3 4 5 6 0.029658591757485415048269157329527017906843943183122 0 27.474593022118317968158957115156725710168223409107 +B 3 4 5 7 0.0069391419286399592112194516682730921670949104133011 0 47.560129945305985709087486769738443607156131247662 +B 3 4 5 11 0.0012997287541106527005442698631755032686108268576868 0 67.645666868493653450016016424320161504144039086217 +B 3 4 6 5 0.021352212228516680939497292880780546082484332879309 0 7.3890560989306502272304274605750078131803155705521 +B 3 4 6 6 0.012403324342248142716606480894862104006170376682414 0 47.560129945305985709087486769738443607156131247662 +B 3 4 6 7 0.0029019728482587936542695462663714858404887385906190 0 142.32935382482556026905480728176275780392268396339 +B 3 4 6 11 0.00054355100289317696850886300335061694083040024589911 0 291.69672773748937390713238899664795040347997371773 +B 3 4 7 7 0.0010818536909272301421636812926881619871087801490006 0 291.69672773748937390713238899664795040347997371773 +B 3 4 7 11 0.00020263547918444903270417336379489387121549840417147 0 827.95539780849441501969512521811065413467578705899 +B 3 4 8 8 0.00065033422510703792020178605539048595113847639153751 0 1620.8693122382773274926319622115144813188711199110 +B 3 4 8 9 0.00052226447269940796773710054051981414842129808777341 0 1620.8693122382773274926319622115144813188711199110 +B 3 4 8 10 0.00042133802310068558624219114198341037525551236314065 0 1620.8693122382773274926319622115144813188711199110 +B 3 4 9 8 0.00046187122228351690048006512028115539215601320072847 0 1620.8693122382773274926319622115144813188711199110 +B 3 4 9 9 0.00037091532484120760571057167482283067154218959650083 0 6026.8489100024969277649455266765422960196810014726 +B 3 4 9 10 0.00029923676197728122100510178401223318288164984672004 0 10432.828507766716528037259091141570110720490883034 +B 3 4 10 8 0.00035745838913888782997053954921547534542550459772092 0 1620.8693122382773274926319622115144813188711199110 +B 3 4 10 9 0.00028706441996786230066194772144576732583818003943139 0 10432.828507766716528037259091141570110720490883034 +B 3 4 10 10 0.00023158985826979301511797329565155455175197044107475 1096.6331584284585992637202382881214324422191348337 30124.848822030468638788120704695197906174933923994 +B 3 8 3 8 0.31929496648159630847269423805983622021490218537856 0 2.7182818284590452353602874713526624977572470937000 +B 3 8 4 11 0.0079856512790088543868208481581913160249875465392319 0 7.3890560989306502272304274605750078131803155705521 +B 3 8 4 12 0.0038328759262704445685944677702767153339602939608404 0 7.3890560989306502272304274605750078131803155705521 +B 3 8 4 13 0.0021211681548328428826432943807870823090706754813752 0 7.3890560989306502272304274605750078131803155705521 +B 3 8 5 11 0.0048931436972502740321507965858420753590042913222225 0 7.3890560989306502272304274605750078131803155705521 +B 3 8 5 12 0.0023485639462208398265513580612155970251258985135229 0 27.474593022118317968158957115156725710168223409107 +B 3 8 5 13 0.0012997287541106527005442698631755032686108268576868 0 47.560129945305985709087486769738443607156131247662 +B 3 8 6 11 0.0020463294018302394765844649697350057505998876248764 0 7.3890560989306502272304274605750078131803155705521 +B 3 8 6 12 0.00098217746148163945160482304620995429070282210662561 0 47.560129945305985709087486769738443607156131247662 +B 3 8 6 13 0.00054355100289317696850886300335061694083040024589911 0 142.32935382482556026905480728176275780392268396339 +B 3 8 7 11 0.00076287034096520589851745763206256595303709282367819 0 7.3890560989306502272304274605750078131803155705521 +B 3 8 8 9 0.0089255176216202210022529139182471004477221066538376 0 7.3890560989306502272304274605750078131803155705521 +B 3 8 8 10 0.0017710854381959110567768427419284476401751741060723 0 7.3890560989306502272304274605750078131803155705521 +B 3 8 9 9 0.0063389555312613165471412283419858713430242508011131 0 7.3890560989306502272304274605750078131803155705521 +B 3 8 9 10 0.0012578353783755537181853968853466179573936128593195 0 27.474593022118317968158957115156725710168223409107 +B 3 8 10 9 0.0049059407118393620644698203797409792178804524034400 0 7.3890560989306502272304274605750078131803155705521 +B 3 8 10 10 0.00097348305428743511763290717562518515372946317291950 0 47.560129945305985709087486769738443607156131247662 +B 3 9 3 9 0.26257162388345302456289951548450307450551163981008 0 2.7182818284590452353602874713526624977572470937000 +B 3 9 4 11 0.026910828217707084436031497827317501355404834385214 0 7.3890560989306502272304274605750078131803155705521 +B 3 9 4 12 0.012339215883849593901831880122098633229821018801940 0 7.3890560989306502272304274605750078131803155705521 +B 3 9 4 13 0.0048615752620238728955383139536613756872673341735758 0 7.3890560989306502272304274605750078131803155705521 +B 3 9 5 11 0.016489393899203877572043980219589856615182508133529 0 7.3890560989306502272304274605750078131803155705521 +B 3 9 5 12 0.0075607554501882681015796822228691450809325421044796 0 27.474593022118317968158957115156725710168223409107 +B 3 9 5 13 0.0029788912038533791466287217750434319228832473232889 0 47.560129945305985709087486769738443607156131247662 +B 3 9 6 11 0.0068959208316859698013911540537285791724634785793461 0 7.3890560989306502272304274605750078131803155705521 +B 3 9 6 12 0.0031619337454697954154948273422714006212979221500405 0 47.560129945305985709087486769738443607156131247662 +B 3 9 6 13 0.0012457824728761200556596780226732530441431130061628 0 142.32935382482556026905480728176275780392268396339 +B 3 9 7 11 0.0025707950398563258925552903186202158116479627633265 0 7.3890560989306502272304274605750078131803155705521 +B 3 9 8 10 0.0041626428714615355490800870258276662294820658109519 0 7.3890560989306502272304274605750078131803155705521 +B 3 9 9 10 0.0029563336462190163063591296838307383857301992054493 0 7.3890560989306502272304274605750078131803155705521 +B 3 9 10 10 0.0022880106227658725938029392778434498901899739059094 0 7.3890560989306502272304274605750078131803155705521 +B 3 10 3 10 0.21809644624300207825448233935808044985500538039557 0 2.7182818284590452353602874713526624977572470937000 +B 3 10 4 11 0.054683351354125927538664697656170387688841573259421 0 7.3890560989306502272304274605750078131803155705521 +B 3 10 4 12 0.031035161790677169082122960332731526144855535306052 0 7.3890560989306502272304274605750078131803155705521 +B 3 10 4 13 0.0079013218951051247890531461009849947775230174590510 0 7.3890560989306502272304274605750078131803155705521 +B 3 10 5 11 0.033506784440526386537251711436226554757256840713362 0 7.3890560989306502272304274605750078131803155705521 +B 3 10 5 12 0.019016546178064850918209152425752770981221466705053 0 27.474593022118317968158957115156725710168223409107 +B 3 10 5 13 0.0048414715444195849592052752721929046540647671016292 0 47.560129945305985709087486769738443607156131247662 +B 3 10 6 11 0.014012651661950595895373097659832563610172909415334 0 7.3890560989306502272304274605750078131803155705521 +B 3 10 6 12 0.0079527845436676121407116481761268626870983294173657 0 47.560129945305985709087486769738443607156131247662 +B 3 10 6 13 0.0020247199310818686880776261806528111407438948691660 0 142.32935382482556026905480728176275780392268396339 +B 3 10 7 11 0.0052239079112179631054208769293289776369249661320498 0 7.3890560989306502272304274605750078131803155705521 +B 4 1 4 1 0.34476291934747108076490012391292607585550537944089 0 2.7182818284590452353602874713526624977572470937000 +B 4 1 5 5 0.0068433375399628741422211696405919068523474129308165 0 7.3890560989306502272304274605750078131803155705521 +B 4 1 5 6 0.0053674691070788729158042258244315114822960244000990 0 7.3890560989306502272304274605750078131803155705521 +B 4 1 5 7 0.0017337081166167303106186624249417206022407541408100 0 7.3890560989306502272304274605750078131803155705521 +B 4 1 6 5 0.0033517616700353187586618974919739109238358799192483 0 7.3890560989306502272304274605750078131803155705521 +B 4 1 6 6 0.0026289039687355922190664484996830602151822924524501 0 27.474593022118317968158957115156725710168223409107 +B 4 1 6 7 0.00084914362010800425017377072921197641824445992705573 0 47.560129945305985709087486769738443607156131247662 +B 4 1 7 7 0.00027955444791593490187905988059629444836196463607138 0 142.32935382482556026905480728176275780392268396339 +B 4 1 8 2 0.010626561204608650728488348972739870708887545240757 0 7.3890560989306502272304274605750078131803155705521 +B 4 1 8 3 0.0033978443556506334153846332881134674171187616143746 0 7.3890560989306502272304274605750078131803155705521 +B 4 1 8 4 0.0015284350936554278738211842937347819704078030671477 0 7.3890560989306502272304274605750078131803155705521 +B 4 1 8 8 0.00014665746971924921184927283660758369875156685642355 0 678.58802389583060138161754350322546153511849730464 +B 4 1 9 2 0.0091717198195462197027522768311299506864879947964223 0 7.3890560989306502272304274605750078131803155705521 +B 4 1 9 3 0.0029326586296739691613194972249610777581662951155000 0 27.474593022118317968158957115156725710168223409107 +B 4 1 9 4 0.0013191829578217473447768590110426974350241736423027 0 47.560129945305985709087486769738443607156131247662 +B 4 1 9 8 0.00012657916289280660335887174096282962627227008242326 0 738.84463466539360460440313246697061522608222082031 +B 4 1 10 2 0.0083187624682520597783390764271178194588720814363035 0 7.3890560989306502272304274605750078131803155705521 +B 4 1 10 3 0.0026599254033835447843104769055128877692464589604263 0 47.560129945305985709087486769738443607156131247662 +B 4 1 10 4 0.0011965007538606036787536339080607585483855951381751 0 142.32935382482556026905480728176275780392268396339 +B 4 1 10 8 0.00011480747452526747212190656877169178295252928857364 0 962.89569553438932506151950503929840412541815545183 +B 4 1 11 7 0.000081474643166997140946524917942383548777966947514815 0 962.89569553438932506151950503929840412541815545183 +B 4 5 4 5 0.27155836587049741866090736613985466050706796675445 0 2.7182818284590452353602874713526624977572470937000 +B 4 5 5 6 0.075858407099605611668429696407855557817090684648437 0 7.3890560989306502272304274605750078131803155705521 +B 4 5 5 7 0.026692794489896865633607864497080181443769014406247 0 7.3890560989306502272304274605750078131803155705521 +B 4 5 5 11 0.0057643912611738034528368598489272090973454720665303 0 7.3890560989306502272304274605750078131803155705521 +B 4 5 5 12 0.0013367859625217997735860284004460229871913064743786 0 7.3890560989306502272304274605750078131803155705521 +B 4 5 6 6 0.037154283239954370381007872047551398533576471659214 0 7.3890560989306502272304274605750078131803155705521 +B 4 5 6 7 0.013073720960701237886841762619371072504510362307319 0 27.474593022118317968158957115156725710168223409107 +B 4 5 6 11 0.0028233103463713880440132831028837943796937573899502 0 47.560129945305985709087486769738443607156131247662 +B 4 5 6 12 0.00065473724247220842522693612601124225373299498955569 0 67.645666868493653450016016424320161504144039086217 +B 4 5 7 7 0.0043041209506007443818264142926557003894737383824905 0 47.560129945305985709087486769738443607156131247662 +B 4 5 7 11 0.00092948818843485116393746711263471805205472908004333 0 142.32935382482556026905480728176275780392268396339 +B 4 5 8 8 0.0031375665503321605159144387175872637428172399727572 0 271.61119081430170616620385934206623250649206587918 +B 4 5 8 9 0.0028453340733096889920063006031851147442960432037347 0 271.61119081430170616620385934206623250649206587918 +B 4 5 8 10 0.0026150378026536592150109820269972483656866705019473 0 271.61119081430170616620385934206623250649206587918 +B 4 5 9 8 0.0027080144517820539658141997856974485023192701296308 0 271.61119081430170616620385934206623250649206587918 +B 4 5 9 9 0.0024557903926706572585558675402725087211304693753745 0 1009.9269552109403795610304351326091812878966616925 +B 4 5 9 10 0.0022570230935158338016528696619258640863384854487279 0 1748.2427196075790529558570109231521300693012575058 +B 4 5 10 8 0.0024561728256198836440385824231781575358678920504008 0 271.61119081430170616620385934206623250649206587918 +B 4 5 10 9 0.0022274052577255248611957655950066965909346316573124 0 1748.2427196075790529558570109231521300693012575058 +B 4 5 10 10 0.0020471230445029688267571443717918521300291206823787 0 5231.8245744250890237543598655400251429700392162120 +B 4 5 11 7 0.0012544129460721173160430494184157469358429057183738 0 47.560129945305985709087486769738443607156131247662 +B 4 5 11 11 0.00027089434292757472730585467146219050590016917083293 1096.6331584284585992637202382881214324422191348337 29337.829448025312797789782328112773352117917755962 +B 4 6 4 6 0.30754725187697977753927236561919577021288605416436 0 2.7182818284590452353602874713526624977572470937000 +B 4 6 5 7 0.12181402102286795517061308510044164954767330809730 0 7.3890560989306502272304274605750078131803155705521 +B 4 6 5 11 0.0057643912611738034528368598489272090973454720665303 0 7.3890560989306502272304274605750078131803155705521 +B 4 6 5 12 0.0013367859625217997735860284004460229871913064743786 0 7.3890560989306502272304274605750078131803155705521 +B 4 6 5 13 0.00014601950023700816248812632695893014204296347508442 0 7.3890560989306502272304274605750078131803155705521 +B 4 6 6 7 0.059662637441604312888334914830137508205052605654699 0 7.3890560989306502272304274605750078131803155705521 +B 4 6 6 11 0.0028233103463713880440132831028837943796937573899502 0 27.474593022118317968158957115156725710168223409107 +B 4 6 6 12 0.00065473724247220842522693612601124225373299498955569 0 47.560129945305985709087486769738443607156131247662 +B 4 6 6 13 0.000071518109564820950386432316409039760198600177055515 0 67.645666868493653450016016424320161504144039086217 +B 4 6 7 7 0.019642090308674581123981504369793524158714311501501 0 7.3890560989306502272304274605750078131803155705521 +B 4 6 7 11 0.00092948818843485116393746711263471805205472908004333 0 47.560129945305985709087486769738443607156131247662 +B 4 6 8 8 0.017980396197392157634042189778065131663473597604599 0 67.645666868493653450016016424320161504144039086217 +B 4 6 8 9 0.0099537438129966016574705958429806818855941610040431 0 67.645666868493653450016016424320161504144039086217 +B 4 6 8 10 0.0026150378026536592150109820269972483656866705019473 0 67.645666868493653450016016424320161504144039086217 +B 4 6 9 8 0.015518769712199516209839678705714622748017149183373 0 67.645666868493653450016016424320161504144039086217 +B 4 6 9 9 0.0085910152541871686090335995531861571531142369256798 0 251.52565389111403842527532968748451460950415804062 +B 4 6 9 10 0.0022570230935158338016528696619258640863384854487279 0 435.40564091373442340053464295064886771486427699503 +B 4 6 10 8 0.014075545434801491790364369007564389568249147158721 0 67.645666868493653450016016424320161504144039086217 +B 4 6 10 9 0.0077920626302177023947955248785491102772090074143041 0 435.40564091373442340053464295064886771486427699503 +B 4 6 10 10 0.0020471230445029688267571443717918521300291206823787 0 1303.0032422998492426925102708014952911988382547241 +B 4 6 11 7 0.0057245817796268144265717643860625404565826169937969 0 7.3890560989306502272304274605750078131803155705521 +B 4 6 11 11 0.00027089434292757472730585467146219050590016917083293 0 7579.8037357207255335467399693841759133528561277238 +B 4 7 4 7 0.33645321890568977313963690909545922969473126611154 0 2.7182818284590452353602874713526624977572470937000 +B 4 7 5 11 0.0061613134152687339898694938734229067123949197329617 0 7.3890560989306502272304274605750078131803155705521 +B 4 7 5 12 0.0017337081166167303106186624249417206022407541408100 0 7.3890560989306502272304274605750078131803155705521 +B 4 7 5 13 0.00054294165433193869952076035145462775709241114151578 0 7.3890560989306502272304274605750078131803155705521 +B 4 7 6 11 0.0030177167240071838689601177060845285442052223274503 0 7.3890560989306502272304274605750078131803155705521 +B 4 7 6 12 0.00084914362010800425017377072921197641824445992705573 0 27.474593022118317968158957115156725710168223409107 +B 4 7 6 13 0.00026592448720061677533326691960977392471006511455557 0 47.560129945305985709087486769738443607156131247662 +B 4 7 7 11 0.00099349051534911230193515464452252467670084129372408 0 7.3890560989306502272304274605750078131803155705521 +B 4 7 8 8 0.026739482607397031680982623793795616218198880803696 0 7.3890560989306502272304274605750078131803155705521 +B 4 7 8 9 0.017918459991025715887129370239850849043561773537363 0 7.3890560989306502272304274605750078131803155705521 +B 4 7 8 10 0.0028453340733096889920063006031851147442960432037347 0 7.3890560989306502272304274605750078131803155705521 +B 4 7 9 8 0.023078683486837980309908101896623020066648755665626 0 7.3890560989306502272304274605750078131803155705521 +B 4 7 9 9 0.015465312952242942959484344338636327601620332355763 0 27.474593022118317968158957115156725710168223409107 +B 4 7 9 10 0.0024557903926706572585558675402725087211304693753745 0 47.560129945305985709087486769738443607156131247662 +B 4 7 10 8 0.020932397607461484802689711167182685011971802636098 0 7.3890560989306502272304274605750078131803155705521 +B 4 7 10 9 0.014027060080129689041960173402607773084221397740566 0 47.560129945305985709087486769738443607156131247662 +B 4 7 10 10 0.0022274052577255248611957655950066965909346316573124 0 142.32935382482556026905480728176275780392268396339 +B 4 7 11 11 0.00028954747753541684980648864777717853953081656255929 0 827.95539780849441501969512521811065413467578705899 +B 4 11 4 11 0.19527248145947965626921523603870786498135978055203 0 2.7182818284590452353602874713526624977572470937000 +B 4 11 5 12 0.053132640492912276141750116002109953922362076598565 0 7.3890560989306502272304274605750078131803155705521 +B 4 11 5 13 0.015983650107866091116041874280227581597558789646543 0 7.3890560989306502272304274605750078131803155705521 +B 4 11 6 12 0.026023551635723641278688115168665655581406063425962 0 7.3890560989306502272304274605750078131803155705521 +B 4 11 6 13 0.0078285464462260170609895366284076633908765973743352 0 27.474593022118317968158957115156725710168223409107 +B 4 12 4 12 0.24135778055313884611157718700715417353164493803672 0 2.7182818284590452353602874713526624977572470937000 +B 4 12 5 13 0.067400118656396534846960667535388883211831801130568 0 7.3890560989306502272304274605750078131803155705521 +B 4 12 6 13 0.033011543409791806968382012697007028446166411795924 0 7.3890560989306502272304274605750078131803155705521 +B 4 13 4 13 0.20983821396791219115451520572454598434533135025416 0 2.7182818284590452353602874713526624977572470937000 +B 5 1 5 1 0.42606222272522797970205431876880290478682508555577 0 2.7182818284590452353602874713526624977572470937000 +B 5 1 6 5 0.011281779943155940712027279537179476627073918071259 0 7.3890560989306502272304274605750078131803155705521 +B 5 1 6 6 0.0088486948019343307329618053321236626532727154989293 0 7.3890560989306502272304274605750078131803155705521 +B 5 1 6 7 0.0028581541306582109843576801917732179059348812855298 0 7.3890560989306502272304274605750078131803155705521 +B 5 1 7 7 0.0022858853597389784093263687400345652554011993331590 0 47.560129945305985709087486769738443607156131247662 +B 5 1 8 2 0.060445088426338610404825635206707172202151573117493 0 7.3890560989306502272304274605750078131803155705521 +B 5 1 8 3 0.019327325047275423807824012984660943416305425275548 0 7.3890560989306502272304274605750078131803155705521 +B 5 1 8 4 0.0086939126036232931853529906151552820688929250400583 0 7.3890560989306502272304274605750078131803155705521 +B 5 1 8 8 0.00083420436346976848939046564814369154645744398695726 0 196.92750385796979934716506848462363620671342100200 +B 5 1 9 2 0.033562299784534658242464337367581250823188353658546 0 7.3890560989306502272304274605750078131803155705521 +B 5 1 9 3 0.010731549810871798648682612219954366221607228681873 0 27.474593022118317968158957115156725710168223409107 +B 5 1 9 4 0.0048273186242243023666672369229153635558852763832578 0 47.560129945305985709087486769738443607156131247662 +B 5 1 9 8 0.00046319424219982429562910262365440445044882983862759 0 257.18411462753280256995065744836878989767714451766 +B 5 1 10 2 0.0098860893840899840798633657861424840486381484376369 0 7.3890560989306502272304274605750078131803155705521 +B 5 1 10 3 0.0031610783927560209299870237901690291829416237200748 0 47.560129945305985709087486769738443607156131247662 +B 5 1 10 4 0.0014219318613724559149125118248187841030879109149240 0 142.32935382482556026905480728176275780392268396339 +B 5 1 10 8 0.00013643819732202473305281984154203951171103725005649 0 481.23517549652852302706703002069657879701307914918 +B 5 1 11 7 0.00012137548767743089212380164940263999684509320686737 0 868.12647165486975050155218452727408992865160273609 +B 5 1 12 7 0.000060561867375138598966323689278565100646652651058690 0 868.12647165486975050155218452727408992865160273609 +B 5 5 5 5 0.33559514225427825871505088428593604135291783748908 0 2.7182818284590452353602874713526624977572470937000 +B 5 5 6 6 0.12505854792904628708581068528013979807384120642516 0 7.3890560989306502272304274605750078131803155705521 +B 5 5 6 7 0.044005170246875707655752178242225821882497940867975 0 7.3890560989306502272304274605750078131803155705521 +B 5 5 6 11 0.0095030521781286858272579540695321612403056022507248 0 7.3890560989306502272304274605750078131803155705521 +B 5 5 6 12 0.0022037967544638558900615314543647193189019945337339 0 7.3890560989306502272304274605750078131803155705521 +B 5 5 7 7 0.035194314169820219653692908816641412032884196399691 0 27.474593022118317968158957115156725710168223409107 +B 5 5 7 11 0.0076003206453450985861886265152633145299958573935059 0 47.560129945305985709087486769738443607156131247662 +B 5 5 8 8 0.017846835295702226252562280371108399884293268993245 0 122.24381690163789252812627762718103990693477612483 +B 5 5 8 9 0.016184583738066580155025690127723564865318788600631 0 122.24381690163789252812627762718103990693477612483 +B 5 5 8 10 0.014874632364707659372365269299888299778246208425114 0 122.24381690163789252812627762718103990693477612483 +B 5 5 9 8 0.0099095038487621733828049749244771614757592884025114 0 122.24381690163789252812627762718103990693477612483 +B 5 5 9 9 0.0089865341493685745848155456076866307900905294152011 0 454.53696302683488092450117093089767263578256267313 +B 5 5 9 10 0.0082591800856978282396425232244764709391844549910963 0 786.83010915203186932087606423461430536463034922143 +B 5 5 10 8 0.0029189370641993049794766758911727119467903586770475 0 122.24381690163789252812627762718103990693477612483 +B 5 5 10 9 0.0026470677046622587889726832263250170045454878324798 0 786.83010915203186932087606423461430536463034922143 +B 5 5 10 10 0.0024328187606538535919960678957788929059826755550019 403.42879349273512260838718054338827960589989735717 1951.2540287432998954550828521665652880955796621383 +B 5 5 11 7 0.0018687407168671079739247499643767908157432605598724 0 27.474593022118317968158957115156725710168223409107 +B 5 5 11 11 0.00040356031893871772097393199557133150728489018888365 1096.6331584284585992637202382881214324422191348337 12600.979459111675306890375075842501824820134949322 +B 5 5 12 7 0.00093243231907089086608617741016331208163088404592104 0 27.474593022118317968158957115156725710168223409107 +B 5 5 12 11 0.00020136163389422005058378768915895108683547838978529 1096.6331584284585992637202382881214324422191348337 12675.663146068007213709413866699944421119913594199 +B 5 6 5 6 0.38007064673819514917140414086770509204113833020800 0 2.7182818284590452353602874713526624977572470937000 +B 5 6 6 7 0.20081999041339460519401643282574039950695814607627 0 7.3890560989306502272304274605750078131803155705521 +B 5 6 6 11 0.0095030521781286858272579540695321612403056022507248 0 7.3890560989306502272304274605750078131803155705521 +B 5 6 6 12 0.0022037967544638558900615314543647193189019945337339 0 7.3890560989306502272304274605750078131803155705521 +B 5 6 6 13 0.00024072462588079060717308524213922355780333427834645 0 7.3890560989306502272304274605750078131803155705521 +B 5 6 7 7 0.16061116897260704654542793890935291505982472012157 0 7.3890560989306502272304274605750078131803155705521 +B 5 6 7 11 0.0076003206453450985861886265152633145299958573935059 0 27.474593022118317968158957115156725710168223409107 +B 5 6 8 8 0.10227453803405600711239246500233291246187364850517 0 47.560129945305985709087486769738443607156131247662 +B 5 6 8 9 0.056618026600060208274095063928804577386504916839581 0 47.560129945305985709087486769738443607156131247662 +B 5 6 8 10 0.014874632364707659372365269299888299778246208425114 0 47.560129945305985709087486769738443607156131247662 +B 5 6 9 8 0.056788215472740659503849534277500011241706824850027 0 47.560129945305985709087486769738443607156131247662 +B 5 6 9 9 0.031437313294291801054023204516627661832320782759144 0 176.84196693478213160623653883004191830972551316345 +B 5 6 9 10 0.0082591800856978282396425232244764709391844549910963 0 306.12380392425827750338559089034539301229489507924 +B 5 6 10 8 0.016727500133503143218344418708797946065303507335354 0 47.560129945305985709087486769738443607156131247662 +B 5 6 10 9 0.0092601547336818842668413919302037037609174921190720 0 306.12380392425827750338559089034539301229489507924 +B 5 6 10 10 0.0024328187606538535919960678957788929059826755550019 0 916.11194614150801521802511629491778006719973113721 +B 5 6 11 7 0.0085281000105440351769954211652625864226148653852819 0 7.3890560989306502272304274605750078131803155705521 +B 5 6 11 11 0.00040356031893871772097393199557133150728489018888365 0 5329.1876230833151607043916879954874936134626808356 +B 5 6 12 7 0.0042552056571182135101205302517118854940287493751186 0 7.3890560989306502272304274605750078131803155705521 +B 5 6 12 11 0.00020136163389422005058378768915895108683547838978529 0 5349.2731600065028284453202176500692115104505886741 +B 5 7 5 7 0.41579299351952592258065100458657110749066060526718 0 2.7182818284590452353602874713526624977572470937000 +B 5 7 6 11 0.010157409554323040921554102806940659827338489002521 0 7.3890560989306502272304274605750078131803155705521 +B 5 7 6 12 0.0028581541306582109843576801917732179059348812855298 0 7.3890560989306502272304274605750078131803155705521 +B 5 7 6 13 0.00089508200207514570146923397954772214483622103014229 0 7.3890560989306502272304274605750078131803155705521 +B 5 7 7 11 0.0081236604926385751578838955719094389012464929065417 0 7.3890560989306502272304274605750078131803155705521 +B 5 7 8 8 0.15209721748722380072528938510165986029571928294610 0 7.3890560989306502272304274605750078131803155705521 +B 5 7 8 9 0.10192223784977928179751629558678334252997174828807 0 7.3890560989306502272304274605750078131803155705521 +B 5 7 8 10 0.016184583738066580155025690127723564865318788600631 0 7.3890560989306502272304274605750078131803155705521 +B 5 7 9 8 0.084452393777546592575845314089562566513960601998230 0 7.3890560989306502272304274605750078131803155705521 +B 5 7 9 9 0.056592599837017807051033127343919640406944140286819 0 27.474593022118317968158957115156725710168223409107 +B 5 7 9 10 0.0089865341493685745848155456076866307900905294152011 0 47.560129945305985709087486769738443607156131247662 +B 5 7 10 8 0.024876242657540112662899631559203031386657357780057 0 7.3890560989306502272304274605750078131803155705521 +B 5 7 10 9 0.016669879717974502224817041374496375221621448768264 0 47.560129945305985709087486769738443607156131247662 +B 5 7 10 10 0.0026470677046622587889726832263250170045454878324798 0 142.32935382482556026905480728176275780392268396339 +B 5 7 11 11 0.00043134851440339808859774770123127390056984672954488 0 827.95539780849441501969512521811065413467578705899 +B 5 7 12 11 0.00021522691295945364234898911991792422485824757931118 0 827.95539780849441501969512521811065413467578705899 +B 5 11 5 11 0.24132011541486284730235311741411130130701604758934 0 2.7182818284590452353602874713526624977572470937000 +B 5 11 6 12 0.087593335026859550482352608928654037685722937333041 0 7.3890560989306502272304274605750078131803155705521 +B 5 11 6 13 0.026350303803124145282597152760344678682583675822184 0 7.3890560989306502272304274605750078131803155705521 +B 5 12 5 12 0.29827289039415789908836064295340069377720752640734 0 2.7182818284590452353602874713526624977572470937000 +B 5 12 6 13 0.11111439445791098230571398878721341281806687774297 0 7.3890560989306502272304274605750078131803155705521 +B 5 13 5 13 0.25932062538823739010092672917574477935479293573688 0 2.7182818284590452353602874713526624977572470937000 +B 6 1 6 1 0.65567764014864360191063668487796711359862794589652 0 2.7182818284590452353602874713526624977572470937000 +B 6 1 7 7 0.0053558515781021271367467740737252783594146386326100 0 7.3890560989306502272304274605750078131803155705521 +B 6 1 8 2 0.18092977832526779976140643326526661653096226181700 0 7.3890560989306502272304274605750078131803155705521 +B 6 1 8 3 0.057852320634544538007458476091519083312242732831934 0 7.3890560989306502272304274605750078131803155705521 +B 6 1 8 4 0.026023415981428089707546706591139109385750833945372 0 7.3890560989306502272304274605750078131803155705521 +B 6 1 8 8 0.0024970169535691899763965767724464363825033174644711 0 27.474593022118317968158957115156725710168223409107 +B 6 1 9 2 0.062318572122316998229223729297797417447666876367572 0 7.3890560989306502272304274605750078131803155705521 +B 6 1 9 3 0.019926371707734392936876871495348875736067079313241 0 27.474593022118317968158957115156725710168223409107 +B 6 1 9 4 0.0089633787247126601877851882004209403527167379583174 0 47.560129945305985709087486769738443607156131247662 +B 6 1 9 8 0.00086006036459017762328527537588766151910307268249040 0 87.731203791681321190944546078901879401131946924772 +B 6 1 10 2 0.011558672398144820853394584639485860283577535416108 0 7.3890560989306502272304274605750078131803155705521 +B 6 1 10 3 0.0036958870335041309543806768347497685430301733112625 0 47.560129945305985709087486769738443607156131247662 +B 6 1 10 4 0.0016625021198512456463218122664933797424804731249106 0 142.32935382482556026905480728176275780392268396339 +B 6 1 10 8 0.00015952156248725754941686849853646456928693484304397 0 311.78226466067704164806091865122966830046788155628 +B 6 1 11 7 0.00016395593091502787003767898398586712556340612760638 0 827.95539780849441501969512521811065413467578705899 +B 6 1 12 7 0.00010314231061273557688020102386179222936496557179770 0 827.95539780849441501969512521811065413467578705899 +B 6 1 13 2 0.00063978559525069764384928924114225295634934239728048 0 7.3890560989306502272304274605750078131803155705521 +B 6 1 13 3 0.00020457152900096834333939297134438633581034925137709 0 67.645666868493653450016016424320161504144039086217 +B 6 1 13 4 0.000092021373365101341964951198636820780210446642442513 0 291.69672773748937390713238899664795040347997371773 +B 6 1 13 8 0.0000088296989736997913737426140829819520738315052871819 0 5349.2731600065028284453202176500692115104505886741 +B 6 5 6 5 0.51645562357341658612499291772659397815660390890455 0 2.7182818284590452353602874713526624977572470937000 +B 6 5 7 7 0.082460619594754165641545504406104497156296507064754 0 7.3890560989306502272304274605750078131803155705521 +B 6 5 7 11 0.017807625018912539958620898432558869782776654712507 0 7.3890560989306502272304274605750078131803155705521 +B 6 5 8 8 0.053420783026796595894392311091566542793101475418904 0 27.474593022118317968158957115156725710168223409107 +B 6 5 8 9 0.048445179323108438617485606569769028567000132874717 0 27.474593022118317968158957115156725710168223409107 +B 6 5 8 10 0.044524112818465288662293918266653583066458880127899 0 27.474593022118317968158957115156725710168223409107 +B 6 5 9 8 0.018399994465815050621320607013903238479023403912067 0 27.474593022118317968158957115156725710168223409107 +B 6 5 9 9 0.016686221746197150452226597055629473529706016732079 0 102.15827997845022478719774797259932200994686828628 +B 6 5 9 10 0.015335668686176736691476611584873927057437072519441 0 176.84196693478213160623653883004191830972551316345 +B 6 5 10 8 0.0034127789022603568667477497263581201475630288755895 0 27.474593022118317968158957115156725710168223409107 +B 6 5 10 9 0.0030949131881348691096279674252693290727775062643127 0 176.84196693478213160623653883004191830972551316345 +B 6 5 10 10 0.0028444164285742044268104767972765098772452498840015 0 529.22064998316678774353996178834026893556120755030 +B 6 5 11 7 0.0025243245546170931288503716092068724302207359448286 0 7.3890560989306502272304274605750078131803155705521 +B 6 5 11 11 0.00054513566979691107563552088370024289134032775424642 0 3078.5715104459047878620434066067990738740692339473 +B 6 5 12 7 0.0015880161568208760210117990549933936961083594308772 0 7.3890560989306502272304274605750078131803155705521 +B 6 5 12 11 0.00034293698475241340524537657728786247089091595514806 0 3098.6570473690924556029719362613807917710571417859 +B 6 5 13 8 0.00018890117361506935785633528230050263920087479943638 0 67.645666868493653450016016424320161504144039086217 +B 6 5 13 9 0.00017130694669034020662290920370122009765984999757845 0 291.69672773748937390713238899664795040347997371773 +B 6 5 13 10 0.00015744166762510661485770777294224695963708080805257 0 1124.7817160136476218619262852992152133816511222468 +B 6 6 6 6 0.58490007198733208889115201003143702395719372039041 0 2.7182818284590452353602874713526624977572470937000 +B 6 6 7 7 0.37631352733323022083990210252219506567317771756769 0 7.3890560989306502272304274605750078131803155705521 +B 6 6 7 11 0.017807625018912539958620898432558869782776654712507 0 7.3890560989306502272304274605750078131803155705521 +B 6 6 8 8 0.30613752045993677267365290138899565819440453045383 0 27.474593022118317968158957115156725710168223409107 +B 6 6 8 9 0.16947426612580307748493398418384179492783889004773 0 27.474593022118317968158957115156725710168223409107 +B 6 6 8 10 0.044524112818465288662293918266653583066458880127899 0 27.474593022118317968158957115156725710168223409107 +B 6 6 9 8 0.10544451734104354717598227225023293943612701865914 0 27.474593022118317968158957115156725710168223409107 +B 6 6 9 9 0.058372891263099774238461703452323377128166601037692 0 102.15827997845022478719774797259932200994686828628 +B 6 6 9 10 0.015335668686176736691476611584873927057437072519441 0 176.84196693478213160623653883004191830972551316345 +B 6 6 10 8 0.019557550672589257585348611134396819018426082341924 0 27.474593022118317968158957115156725710168223409107 +B 6 6 10 9 0.010826838678498504761501556491889932636358900998246 0 176.84196693478213160623653883004191830972551316345 +B 6 6 10 10 0.0028444164285742044268104767972765098772452498840015 0 529.22064998316678774353996178834026893556120755030 +B 6 6 11 7 0.011519892549319082811654161400506132789442245578267 0 7.3890560989306502272304274605750078131803155705521 +B 6 6 11 11 0.00054513566979691107563552088370024289134032775424642 403.42879349273512260838718054338827960589989735717 2675.1427169531696652536562260634107942681693365901 +B 6 6 12 7 0.0072469981958932611447792704869554318608561295681036 0 7.3890560989306502272304274605750078131803155705521 +B 6 6 12 11 0.00034293698475241340524537657728786247089091595514806 0 3098.6570473690924556029719362613807917710571417859 +B 6 6 13 8 0.0010825325580398395974202591213977164829610057756051 0 67.645666868493653450016016424320161504144039086217 +B 6 6 13 9 0.00059927777083795628172369426685608706784936759238365 0 291.69672773748937390713238899664795040347997371773 +B 6 6 13 10 0.00015744166762510661485770777294224695963708080805257 0 1124.7817160136476218619262852992152133816511222468 +B 6 7 6 7 0.63987407059330512425093616864073997267072372059134 0 2.7182818284590452353602874713526624977572470937000 +B 6 7 7 11 0.019033815359153642372806746901786939623602378320759 0 7.3890560989306502272304274605750078131803155705521 +B 6 7 8 8 0.45527133072837450221849730952918441219001678470087 0 7.3890560989306502272304274605750078131803155705521 +B 6 7 8 9 0.30508298326089176535193788517031358946884444065647 0 7.3890560989306502272304274605750078131803155705521 +B 6 7 8 10 0.048445179323108438617485606569769028567000132874717 0 7.3890560989306502272304274605750078131803155705521 +B 6 7 9 8 0.15681144100123601003975622998680350502244194069438 0 7.3890560989306502272304274605750078131803155705521 +B 6 7 9 9 0.10508129768144606076763824776271472095907857569179 0 27.474593022118317968158957115156725710168223409107 +B 6 7 9 10 0.016686221746197150452226597055629473529706016732079 0 47.560129945305985709087486769738443607156131247662 +B 6 7 10 8 0.029084942306712658358262256333502072581219251602452 0 7.3890560989306502272304274605750078131803155705521 +B 6 7 10 9 0.019490181718024434511046319461300847139172816110959 0 47.560129945305985709087486769738443607156131247662 +B 6 7 10 10 0.0030949131881348691096279674252693290727775062643127 0 142.32935382482556026905480728176275780392268396339 +B 6 7 11 11 0.00058267240429777352403425092815458632019649195878341 0 827.95539780849441501969512521811065413467578705899 +B 6 7 12 11 0.00036655080285382907778549234684123664448489280854972 0 827.95539780849441501969512521811065413467578705899 +B 6 7 13 8 0.0016098844647175034753079298238051801324399977102466 0 7.3890560989306502272304274605750078131803155705521 +B 6 7 13 9 0.0010788036101803440379520344735574070794427501632730 0 67.645666868493653450016016424320161504144039086217 +B 6 7 13 10 0.00017130694669034020662290920370122009765984999757845 0 291.69672773748937390713238899664795040347997371773 +B 6 11 6 11 0.37137346461636102614365835250711440871782955871827 0 2.7182818284590452353602874713526624977572470937000 +B 6 12 6 12 0.45901949166725863636036873407465948655001442444769 0 2.7182818284590452353602874713526624977572470937000 +B 6 13 6 13 0.39907489241561916637651890932693931860791996869201 0 2.7182818284590452353602874713526624977572470937000 +B 7 1 7 1 0.70657224345076044718162010405539423312191085787967 0 2.7182818284590452353602874713526624977572470937000 +B 7 1 8 2 0.22110050464673322082796490111987900267398089117962 0 7.3890560989306502272304274605750078131803155705521 +B 7 1 8 3 0.070696915707744827930267919685491818502290942710932 0 7.3890560989306502272304274605750078131803155705521 +B 7 1 8 4 0.031801235039274160596110737539082588451542689970311 0 7.3890560989306502272304274605750078131803155705521 +B 7 1 8 8 0.0030514142760572530618104156840191602107466240789245 0 7.3890560989306502272304274605750078131803155705521 +B 7 1 9 2 0.098610233086160733128290785928055091165887097803064 0 7.3890560989306502272304274605750078131803155705521 +B 7 1 9 3 0.031530635117961858058207261508643304640901446566811 0 27.474593022118317968158957115156725710168223409107 +B 7 1 9 4 0.014183265681193642854716176358764121091703973958574 0 47.560129945305985709087486769738443607156131247662 +B 7 1 9 8 0.0013609225971022222651597170652471589182992168089152 0 67.645666868493653450016016424320161504144039086217 +B 7 1 10 2 0.014473745034328124036359778282618530678551754403062 0 7.3890560989306502272304274605750078131803155705521 +B 7 1 10 3 0.0046279818958450498082163204333975753645726977014847 0 47.560129945305985709087486769738443607156131247662 +B 7 1 10 4 0.0020817816244726361701967355437769161106320883334867 0 142.32935382482556026905480728176275780392268396339 +B 7 1 10 8 0.00019975256183303406802279482997898759904794885410517 0 291.69672773748937390713238899664795040347997371773 +B 7 1 11 7 0.00023548794612597307014155935660182474436659332896086 0 827.95539780849441501969512521811065413467578705899 +B 7 1 12 7 0.00017199472709651755024748079335477916751696611176573 0 827.95539780849441501969512521811065413467578705899 +B 7 1 13 2 0.00092774090086837100143961085896710938763109803165767 0 7.3890560989306502272304274605750078131803155705521 +B 7 1 13 3 0.00029664527619289425143312342451091847137454713732079 0 67.645666868493653450016016424320161504144039086217 +B 7 1 13 4 0.00013343844009403046531264120084725981212884182322726 0 291.69672773748937390713238899664795040347997371773 +B 7 1 13 8 0.000012803778236124397710025037612867637440619683841237 0 5329.1876230833151607043916879954874936134626808356 +B 7 1 14 5 0.000039245798347136834284611121108008046565017674043525 0 1824.8348361840853802088198051292605523212191467039 +B 7 1 14 6 0.000030781853003855608906574845354496480067025201659022 0 1824.8348361840853802088198051292605523212191467039 +B 7 1 14 7 0.0000099426279560519408426445453264259299747797461603342 0 1824.8348361840853802088198051292605523212191467039 +B 7 7 7 7 0.68954197901667938713955770521886724298036327344736 0 2.7182818284590452353602874713526624977572470937000 +B 7 7 8 8 0.55635242527225039956455903995077735128241671254829 0 7.3890560989306502272304274605750078131803155705521 +B 7 7 8 9 0.37281868237769086670711384620322931682531711293120 0 7.3890560989306502272304274605750078131803155705521 +B 7 7 8 10 0.059201164646233794165204537882088972842153111052640 0 7.3890560989306502272304274605750078131803155705521 +B 7 7 9 8 0.24813169206377035113709644883157463102090425719423 0 7.3890560989306502272304274605750078131803155705521 +B 7 7 9 9 0.16627613413582775726761375018839454352405587019869 0 27.474593022118317968158957115156725710168223409107 +B 7 7 9 10 0.026403560923864889812528317733887478459078791408881 0 47.560129945305985709087486769738443607156131247662 +B 7 7 10 8 0.036420103000156672668386963461095459741375017068754 0 7.3890560989306502272304274605750078131803155705521 +B 7 7 10 9 0.024405564163639211548823074189016408257922436723199 0 47.560129945305985709087486769738443607156131247662 +B 7 7 10 10 0.0038754437227266106515344258501351857762315642238764 0 142.32935382482556026905480728176275780392268396339 +B 7 7 11 11 0.00083688541784729475686398620334480423025855135802886 0 827.95539780849441501969512521811065413467578705899 +B 7 7 12 11 0.00061124096337695611396998344856223749595933714554222 0 827.95539780849441501969512521811065413467578705899 +B 7 7 13 8 0.0023344627867180529197129786240222173158877299207657 0 7.3890560989306502272304274605750078131803155705521 +B 7 7 13 9 0.0015643525590421957073083881244674573439718630667472 0 67.645666868493653450016016424320161504144039086217 +B 7 7 13 10 0.00024840893922475809052066632020911710546730912517882 0 291.69672773748937390713238899664795040347997371773 +B 7 7 14 11 0.000035334463985895616976753372586960629468757163313837 0 1824.8348361840853802088198051292605523212191467039 +B 7 7 14 12 0.0000099426279560519408426445453264259299747797461603342 0 6326.0670614589061258935163679066373918000060404804 +B 7 7 14 13 0.0000031137114829919287373767544777297058721818036781102 0 6326.0670614589061258935163679066373918000060404804 +B 7 11 7 11 0.40019998545714727499176271912299202968187524483182 0 2.7182818284590452353602874713526624977572470937000 +B 7 11 14 12 0.00030470992878236207190665963826553634701235852992334 0 7.3890560989306502272304274605750078131803155705521 +B 7 11 14 13 0.000091664499277045399825597260533892787948367038252813 0 7.3890560989306502272304274605750078131803155705521 +B 8 2 8 2 0.33352968663649548420330067796563813145861911334906 0 2.7182818284590452353602874713526624977572470937000 +B 8 2 9 3 0.052354349161368488992002767955751240553736894571833 0 7.3890560989306502272304274605750078131803155705521 +B 8 2 9 4 0.032311418013090749630245193978395410825351665934634 0 7.3890560989306502272304274605750078131803155705521 +B 8 2 9 8 0.0065106504008123579839687852950163879578642823892360 0 7.3890560989306502272304274605750078131803155705521 +B 8 2 9 9 0.0033774705587478570942425194897115961589178052857349 0 7.3890560989306502272304274605750078131803155705521 +B 8 2 10 3 0.011595942054565049969683513284615571051053685392189 0 7.3890560989306502272304274605750078131803155705521 +B 8 2 10 4 0.0071566419405916634683854492141921041818665621479545 0 27.474593022118317968158957115156725710168223409107 +B 8 2 10 8 0.0014420411292412560116223087826020559580867015878037 0 47.560129945305985709087486769738443607156131247662 +B 8 2 10 9 0.00074807448698338210031721521304437640864405104118133 0 67.645666868493653450016016424320161504144039086217 +B 8 2 11 7 0.0018069133167142912325911068055718139468870483049731 0 142.32935382482556026905480728176275780392268396339 +B 8 2 12 7 0.0012515531293972508202733028995893974971196520600904 0 142.32935382482556026905480728176275780392268396339 +B 8 2 13 3 0.00094973964134061604556137072720045093571997123400313 0 7.3890560989306502272304274605750078131803155705521 +B 8 2 13 4 0.00058614871632485768482012862810057073801484404078586 0 47.560129945305985709087486769738443607156131247662 +B 8 2 13 8 0.00011810714631372639613591295665347118012574235833821 0 916.11194614150801521802511629491778006719973113721 +B 8 2 13 9 0.000061269364025837379385148928442212296713195420570672 0 1065.4793200541718288561026980098029726667570208916 +B 8 2 14 5 0.00016824271780890682214914972453581982770567802422977 0 291.69672773748937390713238899664795040347997371773 +B 8 2 14 6 0.00014813694083258914421538036399675446525764100099876 0 291.69672773748937390713238899664795040347997371773 +B 8 2 14 7 0.000098634162379154108476132677158699796552005622224754 0 291.69672773748937390713238899664795040347997371773 +B 8 2 15 7 0.000041522103838156838319700384724240121265883654870932 0 1877.5245565970551988530060629834556047718706394216 +B 8 3 8 3 0.44000910365412140895297639118019878161627844461126 0 2.7182818284590452353602874713526624977572470937000 +B 8 3 9 4 0.13473243065302190276415298400610411088344094528869 0 7.3890560989306502272304274605750078131803155705521 +B 8 3 9 8 0.0085028034488771702549402707201385211804077310476743 0 7.3890560989306502272304274605750078131803155705521 +B 8 3 9 9 0.0053696236068126693652140049148337293814612539441729 0 7.3890560989306502272304274605750078131803155705521 +B 8 3 9 10 0.0029004947807697725658115675845696486566959263934845 0 7.3890560989306502272304274605750078131803155705521 +B 8 3 10 4 0.029841827541540346555804142962158640662229655440214 0 7.3890560989306502272304274605750078131803155705521 +B 8 3 10 8 0.0018832822425245535313434037752761727743054160975665 0 27.474593022118317968158957115156725710168223409107 +B 8 3 10 9 0.0011893156002666796200383102057184932248627655509441 0 47.560129945305985709087486769738443607156131247662 +B 8 3 10 10 0.00064242932910323821530691496705218594749301984090933 0 67.645666868493653450016016424320161504144039086217 +B 8 3 11 7 0.0023733535205550949223380969457368015726029184529491 0 47.560129945305985709087486769738443607156131247662 +B 8 3 12 7 0.0016438962502186191321215233935202399469074838884532 0 47.560129945305985709087486769738443607156131247662 +B 8 3 13 4 0.0024441279934728097569220959798540882886162542128424 0 7.3890560989306502272304274605750078131803155705521 +B 8 3 13 8 0.00015424601064251436203586557718512564537639097912493 0 306.12380392425827750338559089034539301229489507924 +B 8 3 13 9 0.000097408228354625345285101548973866761963844041357395 0 400.89302780377785206335291140236970720906144779496 +B 8 3 13 10 0.000052616734176332317167655060939826033634846643852094 0 550.26040171644166570143049311725489980861873754931 +B 8 3 14 5 0.00091405195512569175400010143187090386527017922854326 0 67.645666868493653450016016424320161504144039086217 +B 8 3 14 6 0.00044717272154495822157732595713166073902721402295694 0 67.645666868493653450016016424320161504144039086217 +B 8 3 14 7 0.00012955449183098978447196243247690657763851833637476 0 67.645666868493653450016016424320161504144039086217 +B 8 3 15 7 0.000054538660163478071767915187710215837165608088910249 0 435.40564091373442340053464295064886771486427699503 +B 8 4 8 4 0.53313163396051065050581442520799591984641838654885 0 2.7182818284590452353602874713526624977572470937000 +B 8 4 9 8 0.015910189927005860653147582710930763354703713699740 0 7.3890560989306502272304274605750078131803155705521 +B 8 4 9 9 0.012777010084941359763421316905625971555757236596239 0 7.3890560989306502272304274605750078131803155705521 +B 8 4 9 10 0.010307881258898462964018879575361890830991909045550 0 7.3890560989306502272304274605750078131803155705521 +B 8 4 10 8 0.0035239410560148777455375894912750946064146532276705 0 7.3890560989306502272304274605750078131803155705521 +B 8 4 10 9 0.0028299744137570038342324959217174150569720026810484 0 27.474593022118317968158957115156725710168223409107 +B 8 4 10 10 0.0022830881425935624295011006830511077796022569710136 0 47.560129945305985709087486769738443607156131247662 +B 8 4 11 7 0.0037475944725223803154252840808537295704076910336608 0 7.3890560989306502272304274605750078131803155705521 +B 8 4 11 11 0.00070193928078916640728398533543886607311190986850672 0 291.69672773748937390713238899664795040347997371773 +B 8 4 12 7 0.0025957601542979031676112800865202633778261080630372 0 7.3890560989306502272304274605750078131803155705521 +B 8 4 12 11 0.00048619615307060535933072493961243439324462533424682 0 311.78226466067704164806091865122966830046788155628 +B 8 4 13 8 0.00028862049317739344638820504128724783036338317164083 0 47.560129945305985709087486769738443607156131247662 +B 8 4 13 9 0.00023178271088950442963744101307598894695083623387329 0 87.731203791681321190944546078901879401131946924772 +B 8 4 13 10 0.00018699121671121140151999452504194821862183883636799 0 182.50042767120089575091186659092619359789849964050 +B 8 4 14 5 0.0015051929123379525915026109917319282286611730683931 0 7.3890560989306502272304274605750078131803155705521 +B 8 4 14 6 0.00087435417415189528485968440375870148443513916603119 0 7.3890560989306502272304274605750078131803155705521 +B 8 4 14 7 0.00020457032349850149717600967724359731811142858383928 0 7.3890560989306502272304274605750078131803155705521 +B 8 4 14 11 0.000038316831450201074674824595541503709207894552531743 0 1195.7153718537351849702137517444393603453960249678 +B 8 4 15 7 0.000086118136045582969244971027108030028456711997620851 0 47.560129945305985709087486769738443607156131247662 +B 8 4 15 11 0.000016130267808313162185591557463705421771906237717428 0 1255.9719826232981881929993407081845140363597484835 +B 8 8 8 8 0.72494015135596950525531956328511473980731110149162 0 2.7182818284590452353602874713526624977572470937000 +B 8 8 9 9 0.21835953741084839296566285081984747314906645021461 0 7.3890560989306502272304274605750078131803155705521 +B 8 8 9 10 0.043328960111262025446609723679634392300816004582454 0 7.3890560989306502272304274605750078131803155705521 +B 8 8 10 9 0.048364359092180549471279788391992855037220254293054 0 7.3890560989306502272304274605750078131803155705521 +B 8 8 10 10 0.0095969125542200054788950287457408960245694810249529 0 27.474593022118317968158957115156725710168223409107 +B 8 8 11 11 0.0026426204365972554901181626107207816966325525971943 0 142.32935382482556026905480728176275780392268396339 +B 8 8 12 11 0.0018304031779712577066687021265433002739510813371936 0 142.32935382482556026905480728176275780392268396339 +B 8 8 13 9 0.0039611744213393476323968326033109431228640351529375 0 7.3890560989306502272304274605750078131803155705521 +B 8 8 13 10 0.00078601361099713084814072598791633806949273194778788 0 47.560129945305985709087486769738443607156131247662 +B 8 8 14 11 0.00014425299256954846337470159562640123076731751414627 0 291.69672773748937390713238899664795040347997371773 +B 8 8 14 12 0.000069237160902036750670654350859710490294407266681752 0 1065.4793200541718288561026980098029726667570208916 +B 8 8 14 13 0.000038316831450201074674824595541503709207894552531743 0 1065.4793200541718288561026980098029726667570208916 +B 8 8 15 11 0.000060726300015739293110862199847495328962734580467344 0 291.69672773748937390713238899664795040347997371773 +B 8 9 8 9 0.59615318981492479144448693329764436490789899246774 0 2.7182818284590452353602874713526624977572470937000 +B 8 9 9 10 0.10183754156925940014757311989960938123989253137799 0 7.3890560989306502272304274605750078131803155705521 +B 8 9 10 10 0.022555952846948235434949457027295201549828561694501 0 7.3890560989306502272304274605750078131803155705521 +B 8 9 11 11 0.0089053606436339839053180878811278583065651654916248 0 47.560129945305985709087486769738443607156131247662 +B 8 9 12 11 0.0061682715373520917860001063028463517851922145187170 0 47.560129945305985709087486769738443607156131247662 +B 8 9 13 10 0.0018473947581104904836656069832713470119964435397671 0 7.3890560989306502272304274605750078131803155705521 +B 8 9 14 11 0.00048611783401229470261807409567353816112489070278692 0 67.645666868493653450016016424320161504144039086217 +B 8 9 14 12 0.00022289588601068141355586676228048103370003425648831 0 326.20934084744594524431412054492711090928280291780 +B 8 9 14 13 0.000087819609903636110414072282379558377913529931305753 0 326.20934084744594524431412054492711090928280291780 +B 8 9 15 11 0.00020464142133480847185116185804340814307365835351811 0 67.645666868493653450016016424320161504144039086217 +B 8 10 8 10 0.49517495528296729506776689882708446722628195872735 0 2.7182818284590452353602874713526624977572470937000 +B 8 10 11 11 0.018095874310201162112934121798802064745606443547744 0 7.3890560989306502272304274605750078131803155705521 +B 8 10 12 11 0.012534053467099811596491324016579303042948727059620 0 7.3890560989306502272304274605750078131803155705521 +B 8 10 14 11 0.00098780134530790459187735809410134130294469210937574 0 7.3890560989306502272304274605750078131803155705521 +B 8 10 14 12 0.00056061989270096752859499964747430055753676696630149 0 47.560129945305985709087486769738443607156131247662 +B 8 10 14 13 0.00014272966459483014518435016660718375593840315553926 0 47.560129945305985709087486769738443607156131247662 +B 8 10 15 11 0.00041583553853968040770315977947305923031598872492784 0 7.3890560989306502272304274605750078131803155705521 +B 9 0 9 0 0.40099401689788665071116395948135930071360900942062 0 2.7182818284590452353602874713526624977572470937000 +B 9 0 10 2 0.044196273743080833351018922297101558642600235835478 0 7.3890560989306502272304274605750078131803155705521 +B 9 0 10 3 0.010730397780876016217580287270657520582434977553333 0 7.3890560989306502272304274605750078131803155705521 +B 9 0 10 4 0.0018694548579375367655125261196274534650251811849998 0 7.3890560989306502272304274605750078131803155705521 +B 9 0 11 1 0.070971303999522001942063292717605425100198243448609 0 7.3890560989306502272304274605750078131803155705521 +B 9 0 11 7 0.00055388394575362863177955497610409037405072060005037 0 67.645666868493653450016016424320161504144039086217 +B 9 0 12 1 0.041500562135029119871649163076637424817681124503301 0 7.3890560989306502272304274605750078131803155705521 +B 9 0 12 7 0.00032388435622513543724042367894231734849468941051032 0 87.731203791681321190944546078901879401131946924772 +B 9 0 13 2 0.0053675458005133117659414524214259043331825206978165 0 47.560129945305985709087486769738443607156131247662 +B 9 0 13 3 0.0013031845598882727471522797308174915720895296294478 0 67.645666868493653450016016424320161504144039086217 +B 9 0 13 4 0.00022704141598685732405170901888936471746934832942367 0 87.731203791681321190944546078901879401131946924772 +B 9 0 14 1 0.0032250658398908381491572332920299495334578906156357 0 7.3890560989306502272304274605750078131803155705521 +B 9 0 14 5 0.000032642896175444591976233399952154565865845019937629 0 659.45670178273014385765101552297665661420021162654 +B 9 0 14 6 0.000025169499389866201860335208889059851812319028032582 0 659.45670178273014385765101552297665661420021162654 +B 9 0 14 7 0.000025169499389866201860335208889059851812319028032582 0 659.45670178273014385765101552297665661420021162654 +B 9 0 15 1 0.0010797081370714666242825323031740306795857120984367 0 7.3890560989306502272304274605750078131803155705521 +B 9 0 15 7 0.0000084264057375565686722312745762433461235108247281393 0 4264.7205769289798339102812244624368979725937444500 +B 9 2 9 2 0.19222372601573275865940698807110492269156049553016 0 2.7182818284590452353602874713526624977572470937000 +B 9 2 10 3 0.023145761278850736503905392680436300922228973534959 0 7.3890560989306502272304274605750078131803155705521 +B 9 2 10 4 0.014284818355912257051837631529406233804819177166626 0 7.3890560989306502272304274605750078131803155705521 +B 9 2 10 8 0.0028783465435274970299978342578558201431005299737084 0 7.3890560989306502272304274605750078131803155705521 +B 9 2 10 9 0.0014931735095812834832225908518443520978244588659409 0 7.3890560989306502272304274605750078131803155705521 +B 9 2 11 7 0.0029999294726737520910103495415707424998321949276358 0 47.560129945305985709087486769738443607156131247662 +B 9 2 12 7 0.0017542126530779355701163563128172389565371946329042 0 47.560129945305985709087486769738443607156131247662 +B 9 2 13 3 0.0028110047121660047460244973645830743529404014772963 0 7.3890560989306502272304274605750078131803155705521 +B 9 2 13 4 0.0017348615682645893229239266526549474983202201772721 0 27.474593022118317968158957115156725710168223409107 +B 9 2 13 8 0.00034956921915960733449494566617413379209741489952951 0 306.12380392425827750338559089034539301229489507924 +B 9 2 13 9 0.00018134282648761724368462254049229968213418581843927 0 326.20934084744594524431412054492711090928280291780 +B 9 2 14 5 0.00023252826953615236261906447204240956998491936951225 0 142.32935382482556026905480728176275780392268396339 +B 9 2 14 6 0.00020474007407147199499524876638246717669996282885104 0 142.32935382482556026905480728176275780392268396339 +B 9 2 14 7 0.00013632228124858767235559803152882942495214519067746 0 142.32935382482556026905480728176275780392268396339 +B 9 2 15 7 0.000045638843867208349309987476688812223717445180521062 0 916.11194614150801521802511629491778006719973113721 +B 9 3 9 3 0.25359118775360926547965359737730080599404472639990 0 2.7182818284590452353602874713526624977572470937000 +B 9 3 10 4 0.059564959289289394665532986006343361291334417720385 0 7.3890560989306502272304274605750078131803155705521 +B 9 3 10 8 0.0037590737346787304445304235947531048493389266871215 0 7.3890560989306502272304274605750078131803155705521 +B 9 3 10 9 0.0023739007007325168977551801887416368040628555793541 0 7.3890560989306502272304274605750078131803155705521 +B 9 3 10 10 0.0012823033971700478224907998950292636608662500427243 0 7.3890560989306502272304274605750078131803155705521 +B 9 3 11 7 0.0039403623347765912891735173599502870985665908274725 0 27.474593022118317968158957115156725710168223409107 +B 9 3 12 7 0.0023041319898817937965699283077924559973911161463581 0 27.474593022118317968158957115156725710168223409107 +B 9 3 13 4 0.0072340407915277066439259945218208966366050863980428 0 7.3890560989306502272304274605750078131803155705521 +B 9 3 13 8 0.00045653171024522242008365046821358336474661069556682 0 176.84196693478213160623653883004191830972551316345 +B 9 3 13 9 0.00028830531757323232927332734253174925478338161447658 0 196.92750385796979934716506848462363620671342100200 +B 9 3 13 10 0.00015573308859644726699257248419639833570321779873213 0 217.01304078115746708809359813920535410370132884056 +B 9 3 14 5 0.0012633112574472558098043916385782892282935680216310 0 47.560129945305985709087486769738443607156131247662 +B 9 3 14 6 0.00061803744303942825696051016882064571499963419242107 0 47.560129945305985709087486769738443607156131247662 +B 9 3 14 7 0.00017905727028442482021121011931496124634415371514877 0 47.560129945305985709087486769738443607156131247662 +B 9 3 15 7 0.000059945936401237070798945385099786546484845934369755 0 306.12380392425827750338559089034539301229489507924 +B 9 4 9 4 0.30726065247809787959335783340760058454367026114298 0 2.7182818284590452353602874713526624977572470937000 +B 9 4 10 8 0.0070338656453661376703235644758902242789287432970114 0 7.3890560989306502272304274605750078131803155705521 +B 9 4 10 9 0.0056486926114199241235483210698787562336526721892435 0 7.3890560989306502272304274605750078131803155705521 +B 9 4 10 10 0.0045570953078574550482839407761663830904560666526135 0 7.3890560989306502272304274605750078131803155705521 +B 9 4 11 7 0.0062219471215103105817265773369104984407035514960878 0 7.3890560989306502272304274605750078131803155705521 +B 9 4 11 11 0.0011653953274836594965872536174707534054960891819467 0 67.645666868493653450016016424320161504144039086217 +B 9 4 12 7 0.0036382916554392648328285665234141342860119737648243 0 7.3890560989306502272304274605750078131803155705521 +B 9 4 12 11 0.00068146643043833547045940683741104775050531571610881 0 87.731203791681321190944546078901879401131946924772 +B 9 4 13 8 0.00085424839717557760692591504321963612198710214280019 0 47.560129945305985709087486769738443607156131247662 +B 9 4 13 9 0.00068602200450358751611559191753780201202387306170997 0 67.645666868493653450016016424320161504144039086217 +B 9 4 13 10 0.00055344977552680245383483705920245109294370924596549 0 87.731203791681321190944546078901879401131946924772 +B 9 4 14 5 0.0020803272069199567507792391937991151279102373299070 0 7.3890560989306502272304274605750078131803155705521 +B 9 4 14 6 0.0012084449521802031043328587891926648907464196000032 0 7.3890560989306502272304274605750078131803155705521 +B 9 4 14 7 0.00028273665535756790059057475089163610543045388588861 0 7.3890560989306502272304274605750078131803155705521 +B 9 4 14 11 0.000052957694854546569484150914549002245097275568693800 0 659.45670178273014385765101552297665661420021162654 +B 9 4 15 7 0.000094656383030080963271942158270939372394321707712446 0 47.560129945305985709087486769738443607156131247662 +B 9 4 15 11 0.000017729515269969513831670325104385565521994413676370 0 719.71331255229314708043660448672181030516393514220 +B 9 8 9 8 0.41780597834437472110657941299643301910040619775072 0 2.7182818284590452353602874713526624977572470937000 +B 9 8 10 9 0.096536349068037284898161172505497816806512984225219 0 7.3890560989306502272304274605750078131803155705521 +B 9 8 10 10 0.019155653412957113485137806773369909716643273707499 0 7.3890560989306502272304274605750078131803155705521 +B 9 8 11 11 0.0043874129763202179873034814128105093463674457503987 0 47.560129945305985709087486769738443607156131247662 +B 9 8 12 11 0.0025655454327996647331716170480079430799800948480289 0 47.560129945305985709087486769738443607156131247662 +B 9 8 13 9 0.011724139416123332366956121026435092335576264720779 0 7.3890560989306502272304274605750078131803155705521 +B 9 8 13 10 0.0023264143857581045772685644096387357119549087253028 0 27.474593022118317968158957115156725710168223409107 +B 9 8 14 11 0.00019937206896352679771912763391180892557558426390495 0 142.32935382482556026905480728176275780392268396339 +B 9 8 14 12 0.000095692683890383717339763002335134066489284093165114 0 400.89302780377785206335291140236970720906144779496 +B 9 8 14 13 0.000052957694854546569484150914549002245097275568693800 0 400.89302780377785206335291140236970720906144779496 +B 9 8 15 11 0.000066747054432842127793625006686512714198870940867752 0 142.32935382482556026905480728176275780392268396339 +B 9 9 9 9 0.34358197190189797531666388517931740765268802473003 0 2.7182818284590452353602874713526624977572470937000 +B 9 9 10 10 0.045022189448329379680865758947889839102287540936441 0 7.3890560989306502272304274605750078131803155705521 +B 9 9 11 11 0.014785133084417200630279235396733510460112646687830 0 27.474593022118317968158957115156725710168223409107 +B 9 9 12 11 0.0086456257623315385119800058100598030387871091447065 0 27.474593022118317968158957115156725710168223409107 +B 9 9 13 10 0.0054678515502933790788930108534449321051653515777248 0 7.3890560989306502272304274605750078131803155705521 +B 9 9 14 11 0.00067186348512230981425641380251522426315178217663185 0 47.560129945305985709087486769738443607156131247662 +B 9 9 14 12 0.00030806441631346106048656411699201181127488066974354 0 196.92750385796979934716506848462363620671342100200 +B 9 9 14 13 0.00012137548767743089212380164940263999684509320686737 0 196.92750385796979934716506848462363620671342100200 +B 9 9 15 11 0.00022493074805328812100063743514813727228288458400344 0 47.560129945305985709087486769738443607156131247662 +B 9 10 9 10 0.28538501593084446450277179350152608152782771971219 0 2.7182818284590452353602874713526624977572470937000 +B 9 10 11 11 0.030043691733750178432085727351803934631990769011335 0 7.3890560989306502272304274605750078131803155705521 +B 9 10 12 11 0.017568087738257670126165545431145410789989282990055 0 7.3890560989306502272304274605750078131803155705521 +B 9 10 14 11 0.0013652402936739197122320284925296578489621030952592 0 7.3890560989306502272304274605750078131803155705521 +B 9 10 14 12 0.00077483278453314486485967987215763867321531768767707 0 47.560129945305985709087486769738443607156131247662 +B 9 10 14 13 0.00019726667728589360487935057531937246264643683694599 0 47.560129945305985709087486769738443607156131247662 +B 9 10 15 11 0.00045706386390780282192394244950737523707928196688978 0 7.3890560989306502272304274605750078131803155705521 +B 10 0 10 0 0.31188260614570564732085256587660786038230182759465 0 2.7182818284590452353602874713526624977572470937000 +B 10 0 11 1 0.14773693726660891055490873661127128891783893368924 0 7.3890560989306502272304274605750078131803155705521 +B 10 0 11 7 0.0011529887875152578913739065883218445584926576494450 0 7.3890560989306502272304274605750078131803155705521 +B 10 0 12 1 0.082458461431047148668876117556095777700320924279953 0 7.3890560989306502272304274605750078131803155705521 +B 10 0 12 7 0.00064353358899125490858108974892246288581424504521207 0 27.474593022118317968158957115156725710168223409107 +B 10 0 13 2 0.014821084138343820901324011602090655464765020249171 0 47.560129945305985709087486769738443607156131247662 +B 10 0 13 3 0.0035984058129597232896614158000617697975690125955604 0 47.560129945305985709087486769738443607156131247662 +B 10 0 13 4 0.00062691592289871638669099684916917071553298014059017 0 47.560129945305985709087486769738443607156131247662 +B 10 0 14 1 0.012507627242589561286534355091606987511063590738497 0 7.3890560989306502272304274605750078131803155705521 +B 10 0 14 5 0.00012659747048600812196726475574311109771171517340175 0 435.40564091373442340053464295064886771486427699503 +B 10 0 14 6 0.000097613733139069044042290811060503040409627049447665 0 435.40564091373442340053464295064886771486427699503 +B 10 0 14 7 0.000097613733139069044042290811060503040409627049447665 0 435.40564091373442340053464295064886771486427699503 +B 10 0 15 1 0.0026955857182042156913094810687028043423159459242534 0 7.3890560989306502272304274605750078131803155705521 +B 10 0 15 7 0.000021037258294227419690599221542011842343742735141496 0 2822.6016612456590584578098044296301609155873820236 +B 10 2 10 2 0.14950656146096919927673197257763425614855850565328 0 2.7182818284590452353602874713526624977572470937000 +B 10 2 11 7 0.0062447829944288223423075097138146324723674290306505 0 7.3890560989306502272304274605750078131803155705521 +B 10 2 12 7 0.0034854871585844928820352241217835537237120370437011 0 7.3890560989306502272304274605750078131803155705521 +B 10 2 13 3 0.0077618596842357743526649602877476436182033573219771 0 7.3890560989306502272304274605750078131803155705521 +B 10 2 13 4 0.0047903697941747674496945413368550445361673248670068 0 7.3890560989306502272304274605750078131803155705521 +B 10 2 13 8 0.00096524463915039527549262405758917770723233158062118 0 47.560129945305985709087486769738443607156131247662 +B 10 2 13 9 0.00050073113283933757133128362827319787518128464795605 0 47.560129945305985709087486769738443607156131247662 +B 10 2 14 5 0.00090180388962881769942076667275648813462316380553340 0 47.560129945305985709087486769738443607156131247662 +B 10 2 14 6 0.00079403418573086434801721370387383798352094968003416 0 47.560129945305985709087486769738443607156131247662 +B 10 2 14 7 0.00052869254873088244965650268659110364481848355144463 0 47.560129945305985709087486769738443607156131247662 +B 10 2 15 7 0.00011394136202166630376281252325845774098642649547574 0 306.12380392425827750338559089034539301229489507924 +B 10 3 10 3 0.19723656014628541839014486561157562599216621900887 0 2.7182818284590452353602874713526624977572470937000 +B 10 3 11 7 0.0082024287318226339850531105673194893394595484588754 0 7.3890560989306502272304274605750078131803155705521 +B 10 3 12 7 0.0045781350672197707587568398537489584227329661488041 0 7.3890560989306502272304274605750078131803155705521 +B 10 3 13 4 0.019974925453116787171909785875415139266442848720485 0 7.3890560989306502272304274605750078131803155705521 +B 10 3 13 8 0.0012605937873356135352531508826951540434337027932709 0 47.560129945305985709087486769738443607156131247662 +B 10 3 13 9 0.00079608028102455583109181045337917421138265586060567 0 47.560129945305985709087486769738443607156131247662 +B 10 3 13 10 0.00043001649077523754685064563243185315806539933215710 0 47.560129945305985709087486769738443607156131247662 +B 10 3 14 5 0.0048994430141780311135019975687294999889118527551382 0 27.474593022118317968158957115156725710168223409107 +B 10 3 14 6 0.0023969067123795518760415088444806694306124390247486 0 27.474593022118317968158957115156725710168223409107 +B 10 3 14 7 0.00069442972732271395691000354483896991052487392485200 0 27.474593022118317968158957115156725710168223409107 +B 10 3 15 7 0.00014966026880730746240573179301597194008655535960577 0 176.84196693478213160623653883004191830972551316345 +B 10 4 10 4 0.23897925909777878165508431466072031957756621327436 0 2.7182818284590452353602874713526624977572470937000 +B 10 4 11 7 0.012951874345903488170980613656746447309022606548619 0 7.3890560989306502272304274605750078131803155705521 +B 10 4 11 11 0.0024259373392436490041073073696950415369613504947464 0 7.3890560989306502272304274605750078131803155705521 +B 10 4 12 7 0.0072290088786945245405319331572349832658575175945520 0 7.3890560989306502272304274605750078131803155705521 +B 10 4 12 11 0.0013540219813895644019446233421377355952886930448343 0 27.474593022118317968158957115156725710168223409107 +B 10 4 13 8 0.0023587851580835683879766453455371172033854723786167 0 47.560129945305985709087486769738443607156131247662 +B 10 4 13 9 0.0018942716517725106838153049162211373713344254459515 0 47.560129945305985709087486769738443607156131247662 +B 10 4 13 10 0.0015282078615231923995741400952738163180171689175029 0 47.560129945305985709087486769738443607156131247662 +B 10 4 14 5 0.0080680390846386641313292710954127727476866049502963 0 7.3890560989306502272304274605750078131803155705521 +B 10 4 14 6 0.0046866574995475293020612199223567690573752165878684 0 7.3890560989306502272304274605750078131803155705521 +B 10 4 14 7 0.0010965248055675882845992414756869624576316423028949 0 7.3890560989306502272304274605750078131803155705521 +B 10 4 14 11 0.00020538343703702239544584377994315319151184117494690 0 435.40564091373442340053464295064886771486427699503 +B 10 4 15 7 0.00023631793210785562766551212256821647650951015791679 0 47.560129945305985709087486769738443607156131247662 +B 10 4 15 11 0.000044263284226087140708652546971123317004413675225058 0 495.66225168329742662332023191439402140582800051069 +B 10 8 10 8 0.32495850785345369780230687544447892466865477815188 0 2.7182818284590452353602874713526624977572470937000 +B 10 8 11 11 0.0091330286907183148327804113126268563736165280127148 0 7.3890560989306502272304274605750078131803155705521 +B 10 8 12 11 0.0050975437014995960604413323775891651374341735956857 0 7.3890560989306502272304274605750078131803155705521 +B 10 8 13 9 0.032373167029039524812271070834444374491132034418215 0 7.3890560989306502272304274605750078131803155705521 +B 10 8 13 10 0.0064237893132978800310600142248543322452860267008167 0 7.3890560989306502272304274605750078131803155705521 +B 10 8 14 11 0.00077321569387372823038858256903901200432499992639719 0 47.560129945305985709087486769738443607156131247662 +B 10 8 14 12 0.00037112061562885390269934463819101945721823154835430 0 87.731203791681321190944546078901879401131946924772 +B 10 8 14 13 0.00020538343703702239544584377994315319151184117494690 0 87.731203791681321190944546078901879401131946924772 +B 10 8 15 11 0.00016663985431227646461135214628088205252749733766610 0 47.560129945305985709087486769738443607156131247662 +B 10 9 10 9 0.26722902663341284079148538634742550790132238215227 0 2.7182818284590452353602874713526624977572470937000 +B 10 9 11 11 0.030777372767248568515647816985291284428914029148030 0 7.3890560989306502272304274605750078131803155705521 +B 10 9 12 11 0.017178201012095339989125516024789694823726894402294 0 7.3890560989306502272304274605750078131803155705521 +B 10 9 13 10 0.015098052423720699990866089883504012139522981809635 0 7.3890560989306502272304274605750078131803155705521 +B 10 9 14 11 0.0026056578212683580642354361180944723400446249472943 0 27.474593022118317968158957115156725710168223409107 +B 10 9 14 12 0.0011947523173930362300232874890255458452938220162128 0 67.645666868493653450016016424320161504144039086217 +B 10 9 14 13 0.00047072507403700429380655479722588753021430730353644 0 67.645666868493653450016016424320161504144039086217 +B 10 9 15 11 0.00056155926886128617259717104935725294794000534772547 0 27.474593022118317968158957115156725710168223409107 +B 10 10 10 10 0.22196496399623608785690697081324594486002884090247 0 2.7182818284590452353602874713526624977572470937000 +B 10 10 11 11 0.062540248675102276891404416164840778809764393626240 0 7.3890560989306502272304274605750078131803155705521 +B 10 10 12 11 0.034906454531121400091228586479073474771561075064961 0 7.3890560989306502272304274605750078131803155705521 +B 10 10 14 11 0.0052947497935158049265780568354259951432463788047284 0 7.3890560989306502272304274605750078131803155705521 +B 10 10 14 12 0.0030049990063478275005583457575498955164836012416087 0 47.560129945305985709087486769738443607156131247662 +B 10 10 14 13 0.00076505044838392527009223975919122992621886155608010 0 47.560129945305985709087486769738443607156131247662 +B 10 10 15 11 0.0011410998783419912414761033402669908227926912659782 0 7.3890560989306502272304274605750078131803155705521 +B 11 1 11 1 0.40561902779981853591404808214248760641272811491075 0 2.7182818284590452353602874713526624977572470937000 +B 11 1 12 7 0.0020165571788247983687472550565692032523274985207841 0 7.3890560989306502272304274605750078131803155705521 +B 11 1 13 2 0.046692958719483115385859921097319801636382145337951 0 7.3890560989306502272304274605750078131803155705521 +B 11 1 13 3 0.014930079748170669588759613993208623015497338785062 0 7.3890560989306502272304274605750078131803155705521 +B 11 1 13 4 0.0067159220522355683581007622594130771361785399355674 0 7.3890560989306502272304274605750078131803155705521 +B 11 1 13 8 0.00064441083504369070817134582763555070746812133665726 0 27.474593022118317968158957115156725710168223409107 +B 11 1 14 5 0.0012783187524225116414875527638746255231810774983151 0 67.645666868493653450016016424320161504144039086217 +B 11 1 14 6 0.0010026301307745607529981619420933149889826696426240 0 67.645666868493653450016016424320161504144039086217 +B 11 1 14 7 0.00032385244535377752461851822521119667953258482646080 0 67.645666868493653450016016424320161504144039086217 +B 11 1 15 7 0.000058022763122000469846422857700853882408096955101372 0 435.40564091373442340053464295064886771486427699503 +B 11 7 11 7 0.39584253379378534169860849238246846642287220108128 0 2.7182818284590452353602874713526624977572470937000 +B 11 7 12 11 0.0071665124477792409045437818153892773071425615019806 0 7.3890560989306502272304274605750078131803155705521 +B 11 7 13 8 0.11749290608010073593539880739815311292955441530774 0 7.3890560989306502272304274605750078131803155705521 +B 11 7 13 9 0.078733458224925908909556020228708663647257793701758 0 7.3890560989306502272304274605750078131803155705521 +B 11 7 13 10 0.012502357429661163933180628660098496377290743957909 0 7.3890560989306502272304274605750078131803155705521 +B 11 7 14 11 0.0011509183102976301900866906905551282821278083935342 0 67.645666868493653450016016424320161504144039086217 +B 11 7 14 12 0.00032385244535377752461851822521119667953258482646080 0 87.731203791681321190944546078901879401131946924772 +B 11 7 14 13 0.00010142017606917336898572510251847673981487670009537 0 87.731203791681321190944546078901879401131946924772 +B 11 7 15 11 0.00020620335417946996936385183474621992056028718278167 0 67.645666868493653450016016424320161504144039086217 +B 11 11 11 11 0.22974116310293746552213979649478445418086079675164 0 2.7182818284590452353602874713526624977572470937000 +B 11 11 14 12 0.0099250475825837929863720990349484436614148803909880 0 7.3890560989306502272304274605750078131803155705521 +B 11 11 14 13 0.0029857068346735637052804953936510793228522243617877 0 7.3890560989306502272304274605750078131803155705521 +B 12 1 12 1 0.40561902779981853591404808214248760641272811491075 0 2.7182818284590452353602874713526624977572470937000 +B 12 1 13 2 0.076291868584756324572722708315779059283537896630374 0 7.3890560989306502272304274605750078131803155705521 +B 12 1 13 3 0.024394335106292822673880985601792706287452698181951 0 7.3890560989306502272304274605750078131803155705521 +B 12 1 13 4 0.010973180040116653575691281418536675121998528880588 0 7.3890560989306502272304274605750078131803155705521 +B 12 1 13 8 0.0010529062216233567514162441800775364497944265915341 0 7.3890560989306502272304274605750078131803155705521 +B 12 1 14 5 0.0027300710665574422017669663826059080284596006791229 0 67.645666868493653450016016424320161504144039086217 +B 12 1 14 6 0.0021412902731020977466554678096063081149628399891404 0 67.645666868493653450016016424320161504144039086217 +B 12 1 14 7 0.00069164297967053209846350325409578661792286517219645 0 67.645666868493653450016016424320161504144039086217 +B 12 1 15 7 0.00021998119927978268084012592469903414500852934375401 0 435.40564091373442340053464295064886771486427699503 +B 12 7 12 7 0.39584253379378534169860849238246846642287220108128 0 2.7182818284590452353602874713526624977572470937000 +B 12 7 13 8 0.19197227154003296814331062390580009225894206579271 0 7.3890560989306502272304274605750078131803155705521 +B 12 7 13 9 0.12864300770071104622887243239280763776512947124004 0 7.3890560989306502272304274605750078131803155705521 +B 12 7 13 10 0.020427666958388027575676416063623217630347703398067 0 7.3890560989306502272304274605750078131803155705521 +B 12 7 14 11 0.0024579853600365654637979989730945863584131472421439 0 67.645666868493653450016016424320161504144039086217 +B 12 7 14 12 0.00069164297967053209846350325409578661792286517219645 0 67.645666868493653450016016424320161504144039086217 +B 12 7 14 13 0.00021660034926883052274970650886336925274740429269121 0 67.645666868493653450016016424320161504144039086217 +B 12 7 15 11 0.00078177699073959011725034398518982161752443072119443 0 67.645666868493653450016016424320161504144039086217 +B 12 11 12 11 0.22974116310293746552213979649478445418086079675164 0 2.7182818284590452353602874713526624977572470937000 +B 12 11 14 12 0.021196657866489675354840617862119781852143896349397 0 7.3890560989306502272304274605750078131803155705521 +B 12 11 14 13 0.0063764939903431518118336596483706900577614646294952 0 7.3890560989306502272304274605750078131803155705521 +B 13 0 13 0 0.36333881723544573891822679728824402769985389053699 0 2.7182818284590452353602874713526624977572470937000 +B 13 0 14 1 0.14278037453292134968285488853574870789925192015487 0 7.3890560989306502272304274605750078131803155705521 +B 13 0 14 5 0.0014451689277534259768641679574926871563503425313696 0 7.3890560989306502272304274605750078131803155705521 +B 13 0 14 6 0.0011143061035345782007150192002710906365746028527197 0 7.3890560989306502272304274605750078131803155705521 +B 13 0 14 7 0.0011143061035345782007150192002710906365746028527197 0 7.3890560989306502272304274605750078131803155705521 +B 13 0 15 1 0.058070905519148303127348058822842619311746629767135 0 7.3890560989306502272304274605750078131803155705521 +B 13 0 15 7 0.00045320489366587745531414534669112124182862304754624 0 67.645666868493653450016016424320161504144039086217 +B 13 2 13 2 0.17417302581083675408094641181321041824613885128500 0 2.7182818284590452353602874713526624977572470937000 +B 13 2 14 5 0.010294510271141530521769538012066846562988787268805 0 7.3890560989306502272304274605750078131803155705521 +B 13 2 14 6 0.0090642690441359495376004359712869779422430792971315 0 7.3890560989306502272304274605750078131803155705521 +B 13 2 14 7 0.0060352710115569021373914273633905651195574347394120 0 7.3890560989306502272304274605750078131803155705521 +B 13 2 15 7 0.0024546346361751949703495337655519953890432362212988 0 47.560129945305985709087486769738443607156131247662 +B 13 3 13 3 0.22977779801435696515859797638391136249480767661303 0 2.7182818284590452353602874713526624977572470937000 +B 13 3 14 5 0.055929417706424365258624154858698773792117809494034 0 7.3890560989306502272304274605750078131803155705521 +B 13 3 14 6 0.027361803440119993544076570240609277087949757543020 0 7.3890560989306502272304274605750078131803155705521 +B 13 3 14 7 0.0079272378870001786738588269186136267798546220683850 0 7.3890560989306502272304274605750078131803155705521 +B 13 3 15 7 0.0032241257516638439478503120840522196089872627986236 0 47.560129945305985709087486769738443607156131247662 +B 13 4 13 4 0.27840745085932923188495968687039395549698852328802 0 2.7182818284590452353602874713526624977572470937000 +B 13 4 14 5 0.092100413604303795374999781652015258105398175564230 0 7.3890560989306502272304274605750078131803155705521 +B 13 4 14 6 0.053500372222028133608102402454273642904187238843824 0 7.3890560989306502272304274605750078131803155705521 +B 13 4 14 7 0.012517339970803654834386086324511504743061714276427 0 7.3890560989306502272304274605750078131803155705521 +B 13 4 14 11 0.0023445473305401591848841212410509592573203108243928 0 7.3890560989306502272304274605750078131803155705521 +B 13 4 15 7 0.0050909886542425016635147348960205909146316893304328 0 47.560129945305985709087486769738443607156131247662 +B 13 4 15 11 0.00095356232929320683407299245140633977863227634098441 0 67.645666868493653450016016424320161504144039086217 +B 13 8 13 8 0.37857205745840499111874998510496395433005431458402 0 2.7182818284590452353602874713526624977572470937000 +B 13 8 14 11 0.0088266162897869118818787802021718988808245903614079 0 7.3890560989306502272304274605750078131803155705521 +B 13 8 14 12 0.0042365142059834357213515207962740209176174981533655 0 7.3890560989306502272304274605750078131803155705521 +B 13 8 14 13 0.0023445473305401591848841212410509592573203108243928 0 7.3890560989306502272304274605750078131803155705521 +B 13 8 15 11 0.0035899163473605135272381935818749353042207294501185 0 7.3890560989306502272304274605750078131803155705521 +B 13 9 13 9 0.31131802978009890949201659224631200150633502695395 0 2.7182818284590452353602874713526624977572470937000 +B 13 9 14 11 0.029744794309068810550895507172629800047864345390010 0 7.3890560989306502272304274605750078131803155705521 +B 13 9 14 12 0.013638652643131960539219469538617552728669748858604 0 7.3890560989306502272304274605750078131803155705521 +B 13 9 14 13 0.0053735453631192065850931298489473720800059553821123 0 7.3890560989306502272304274605750078131803155705521 +B 13 9 15 11 0.012097650994816266080375348622583987710095296989981 0 7.3890560989306502272304274605750078131803155705521 +B 13 10 13 10 0.25858603813392296556047804987951506793024587815134 0 2.7182818284590452353602874713526624977572470937000 +B 13 10 14 11 0.060442028205165496457632147115057437473748073605714 0 7.3890560989306502272304274605750078131803155705521 +B 13 10 14 12 0.034303459423257356393606314901393071657510592304914 0 7.3890560989306502272304274605750078131803155705521 +B 13 10 14 13 0.0087334062199171017614512872140653814224673396184813 0 7.3890560989306502272304274605750078131803155705521 +B 13 10 15 11 0.024582673359485884024971059997311072313163830520651 0 7.3890560989306502272304274605750078131803155705521 +B 14 1 14 1 0.38037225616899763871656351439795089497826574933344 0 2.7182818284590452353602874713526624977572470937000 +B 14 1 15 7 0.0011200624131107872249118326211091770195499726383276 0 7.3890560989306502272304274605750078131803155705521 +B 14 5 14 5 0.29960666449637113690625069425374499410432324687905 0 2.7182818284590452353602874713526624977572470937000 +B 14 5 15 7 0.017244884258469241222658331248636546673504287909130 0 7.3890560989306502272304274605750078131803155705521 +B 14 5 15 11 0.0037240859197825360776159502981817551003842038212243 0 7.3890560989306502272304274605750078131803155705521 +B 14 6 14 6 0.33931271465166019241380311727206097477858031336633 0 2.7182818284590452353602874713526624977572470937000 +B 14 6 15 7 0.078697968262303632765470506399414962214934781245356 0 7.3890560989306502272304274605750078131803155705521 +B 14 6 15 11 0.0037240859197825360776159502981817551003842038212243 0 7.3890560989306502272304274605750078131803155705521 +B 14 7 14 7 0.37120427629717370709861336808831902383752710538402 0 2.7182818284590452353602874713526624977572470937000 +B 14 7 15 11 0.0039805175425405104528010226157937084031816657914871 0 7.3890560989306502272304274605750078131803155705521 +B 14 11 14 11 0.21544148216705797488627929130064909863894582927089 0 2.7182818284590452353602874713526624977572470937000 +B 14 12 14 12 0.26628676803961128630522014456217781655100899821660 0 2.7182818284590452353602874713526624977572470937000 +B 14 13 14 13 0.23151165742683605894591096585462673444471851421142 0 2.7182818284590452353602874713526624977572470937000 +B 15 1 15 1 0.38336020234057910393636554995973418131956513636132 0 2.7182818284590452353602874713526624977572470937000 +B 15 7 15 7 0.37412020504394335461855748901301133339428570942499 0 2.7182818284590452353602874713526624977572470937000 +B 15 11 15 11 0.21713384416612788656112751926238441256696153803466 0 2.7182818284590452353602874713526624977572470937000 +P 0 13 0 0E+0 +P 0 12 0 0E+0 +P 0 11 0 0E+0 +P 0 10 1 0E+0 +P 0 9 1 0E+0 +P 0 8 1 0E+0 +P 0 7 0 0E+0 +P 0 6 0 0E+0 +P 0 5 0 0E+0 +P 0 4 1 0E+0 +P 0 3 1 0E+0 +P 0 2 1 0E+0 +P 0 1 0 0E+0 +P 0 0 1 0E+0 +P 1 13 0 0E+0 +P 1 12 0 0E+0 +P 1 11 1 0E+0 +P 1 10 0 0E+0 +P 1 9 0 0E+0 +P 1 8 0 0E+0 +P 1 7 1 0E+0 +P 1 6 0 0E+0 +P 1 5 0 0E+0 +P 1 4 0 0E+0 +P 1 3 0 0E+0 +P 1 2 0 0E+0 +P 1 1 1 0E+0 +P 1 0 0 0E+0 +P 2 13 0 0E+0 +P 2 12 0 0E+0 +P 2 11 0 0E+0 +P 2 10 1 0E+0 +P 2 9 1 0E+0 +P 2 8 1 0E+0 +P 2 7 0 0E+0 +P 2 6 0 0E+0 +P 2 5 0 0E+0 +P 2 4 1 0E+0 +P 2 3 1 0E+0 +P 2 2 1 0E+0 +P 2 1 0 0E+0 +P 2 0 1 0E+0 +P 3 13 0 0E+0 +P 3 12 0 0E+0 +P 3 11 0 0E+0 +P 3 10 1 0E+0 +P 3 9 1 0E+0 +P 3 8 1 0E+0 +P 3 7 0 0E+0 +P 3 6 0 0E+0 +P 3 5 0 0E+0 +P 3 4 1 2.5396911773440219645312380965548667753274842116074E-1 +P 3 3 1 7.1463386312237848126675767208515554805496384689134E-2 +P 3 2 1 0E+0 +P 3 1 0 0E+0 +P 3 0 1 0E+0 +P 4 13 1 0E+0 +P 4 12 1 0E+0 +P 4 11 1 0E+0 +P 4 10 0 0E+0 +P 4 9 0 0E+0 +P 4 8 0 0E+0 +P 4 7 1 0E+0 +P 4 6 1 0E+0 +P 4 5 1 2.9707171888506824920562278705167207908788723360437E-1 +P 4 4 0 0E+0 +P 4 3 0 0E+0 +P 4 2 0 0E+0 +P 4 1 1 0E+0 +P 4 0 0 0E+0 +P 5 13 1 0E+0 +P 5 12 1 0E+0 +P 5 11 1 0E+0 +P 5 10 0 0E+0 +P 5 9 0 0E+0 +P 5 8 0 0E+0 +P 5 7 1 0E+0 +P 5 6 1 0E+0 +P 5 5 1 1.9702791131816109477277482821408645804312801544386E+0 +P 5 4 0 0E+0 +P 5 3 0 0E+0 +P 5 2 0 0E+0 +P 5 1 1 0E+0 +P 5 0 0 0E+0 +P 6 13 1 0E+0 +P 6 12 1 0E+0 +P 6 11 1 0E+0 +P 6 10 0 0E+0 +P 6 9 0 0E+0 +P 6 8 0 0E+0 +P 6 7 1 0E+0 +P 6 6 1 2.4872742576227010784009272144678128689224276522040E+0 +P 6 5 1 0E+0 +P 6 4 0 0E+0 +P 6 3 0 0E+0 +P 6 2 0 0E+0 +P 6 1 1 0E+0 +P 6 0 0 0E+0 +P 7 13 0 0E+0 +P 7 12 0 0E+0 +P 7 11 1 0E+0 +P 7 10 0 0E+0 +P 7 9 0 0E+0 +P 7 8 0 0E+0 +P 7 7 1 2.4872742576227010784009272144678128689224276522040E+0 +P 7 6 0 0E+0 +P 7 5 0 0E+0 +P 7 4 0 0E+0 +P 7 3 0 0E+0 +P 7 2 0 0E+0 +P 7 1 1 0E+0 +P 7 0 0 0E+0 +P 8 13 0 0E+0 +P 8 12 0 0E+0 +P 8 11 0 0E+0 +P 8 10 1 0E+0 +P 8 9 1 0E+0 +P 8 8 1 2.4872742576227010784009272144678128689224276522040E+0 +P 8 7 0 0E+0 +P 8 6 0 0E+0 +P 8 5 0 0E+0 +P 8 4 1 0E+0 +P 8 3 1 0E+0 +P 8 2 1 0E+0 +P 8 1 0 0E+0 +P 8 0 0 0E+0 +P 9 13 0 0E+0 +P 9 12 0 0E+0 +P 9 11 0 0E+0 +P 9 10 1 0E+0 +P 9 9 1 2.4872742576227010784009272144678128689224276522040E+0 +P 9 8 1 0E+0 +P 9 7 0 0E+0 +P 9 6 0 0E+0 +P 9 5 0 0E+0 +P 9 4 1 0E+0 +P 9 3 1 0E+0 +P 9 2 1 0E+0 +P 9 1 0 0E+0 +P 9 0 1 0E+0 +P 10 13 0 0E+0 +P 10 12 0 0E+0 +P 10 11 0 0E+0 +P 10 10 1 2.4872742576227010784009272144678128689224276522040E+0 +P 10 9 1 0E+0 +P 10 8 1 0E+0 +P 10 7 0 0E+0 +P 10 6 0 0E+0 +P 10 5 0 0E+0 +P 10 4 1 0E+0 +P 10 3 1 0E+0 +P 10 2 1 0E+0 +P 10 1 0 0E+0 +P 10 0 1 0E+0 +P 11 13 0 0E+0 +P 11 12 0 0E+0 +P 11 11 1 9.5955277161525224246628799736669231389316863623286E-1 +P 11 10 0 0E+0 +P 11 9 0 0E+0 +P 11 8 0 0E+0 +P 11 7 1 0E+0 +P 11 6 0 0E+0 +P 11 5 0 0E+0 +P 11 4 0 0E+0 +P 11 3 0 0E+0 +P 11 2 0 0E+0 +P 11 1 1 0E+0 +P 11 0 0 0E+0 +P 12 13 0 0E+0 +P 12 12 0 0E+0 +P 12 11 1 2.2081984456373349562239041230741088069525147735921E-1 +P 12 10 0 0E+0 +P 12 9 0 0E+0 +P 12 8 0 0E+0 +P 12 7 1 0E+0 +P 12 6 0 0E+0 +P 12 5 0 0E+0 +P 12 4 0 0E+0 +P 12 3 0 0E+0 +P 12 2 0 0E+0 +P 12 1 1 0E+0 +P 12 0 0 0E+0 +P 13 13 0 0E+0 +P 13 12 0 0E+0 +P 13 11 0 0E+0 +P 13 10 1 0E+0 +P 13 9 1 0E+0 +P 13 8 1 0E+0 +P 13 7 0 0E+0 +P 13 6 0 0E+0 +P 13 5 0 0E+0 +P 13 4 1 0E+0 +P 13 3 1 0E+0 +P 13 2 1 0E+0 +P 13 1 0 0E+0 +P 13 0 1 0E+0 +P 14 13 1 0E+0 +P 14 12 1 0E+0 +P 14 11 1 0E+0 +P 14 10 0 0E+0 +P 14 9 0 0E+0 +P 14 8 0 0E+0 +P 14 7 1 0E+0 +P 14 6 1 0E+0 +P 14 5 1 0E+0 +P 14 4 0 0E+0 +P 14 3 0 0E+0 +P 14 2 0 0E+0 +P 14 1 1 0E+0 +P 14 0 0 0E+0 +P 15 13 0 0E+0 +P 15 12 0 0E+0 +P 15 11 1 0E+0 +P 15 10 0 0E+0 +P 15 9 0 0E+0 +P 15 8 0 0E+0 +P 15 7 1 0E+0 +P 15 6 0 0E+0 +P 15 5 0 0E+0 +P 15 4 0 0E+0 +P 15 3 0 0E+0 +P 15 2 0 0E+0 +P 15 1 1 0E+0 +P 15 0 0 0E+0 +END diff --git a/tests/tools/export-seeded-theory.py b/tests/tools/export-seeded-theory.py new file mode 100644 index 00000000..960d8507 --- /dev/null +++ b/tests/tools/export-seeded-theory.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +"""Extract numerical gold data from IntaRNA-probabilities tests/examples/*.json. + +Source revision: f62778504c8abbec8fc9894da16a357b60707680. Run with the path +of that checkout as argument; redirect stdout to tests/data/seeded-theory.dat. +Values preserve unrounded accessibility; they are NOT native ED gold values. +""" +import json +from decimal import Decimal, getcontext +from pathlib import Path +import sys +getcontext().prec = 50 +e = Decimal(1).exp() +def poly(cs): + return sum(Decimal(c) * e**i for i, c in enumerate(cs)) +for path in sorted((Path(sys.argv[1]) / 'tests/examples').glob('*.json')): + d = json.loads(path.read_text()) + p = d['input'] + n, m = len(p['rna1']), len(p['rna2']) + def pair(v): + return f'{v[0]-1} {m-v[1]}' # one-based antiparallel -> internal + print('CASE', p['id'], n, m, p['max_interaction_length']) + print('Z', d['ensembles']['seed']['partition_value_at_e']) + for s in d['seeds']['occurrences']: + print('S', pair(s['left_pair']), len(s['pairs'])) + denominator = Decimal(d['common_denominator']['value_at_e']) + for b in d['helpers']['boundaries']: + print('B', pair(b['left_pair']), pair(b['right_pair']), + poly(b['accessibility_product_coefficients'])/denominator, + poly(b['hybrid']['seed']), poly(b['hybrid']['noseed'])) + for a in d['actual_pairs']: + print('P', pair(a['pair']), int(a['allowed']), a['partition_value_at_e']) + print('END') From 62afc24b5a2644f8a406f605ca2f0de05c09b0f6 Mon Sep 17 00:00:00 2001 From: AlexanderMitrofanov Date: Thu, 8 Oct 2026 13:52:37 +0200 Subject: [PATCH 03/21] feat: compile active stack-seed domains (step 2) --- ChangeLog | 8 ++++ src/IntaRNA/Makefile.am | 6 ++- src/IntaRNA/SeedHandler.h | 13 +++++++ src/IntaRNA/SeedHandlerExplicit.cpp | 10 +++++ src/IntaRNA/SeedHandlerExplicit.h | 3 ++ src/IntaRNA/SeedHandlerIdxOffset.h | 13 +++++++ src/IntaRNA/SeedHandlerMfe.h | 13 +++++++ src/IntaRNA/SeedHandlerNoBulge.h | 13 +++++++ src/IntaRNA/StackSeedDomain.cpp | 46 +++++++++++++++++++++++ src/IntaRNA/StackSeedDomain.h | 58 +++++++++++++++++++++++++++++ tests/Makefile.am | 1 + tests/StackSeedDomain_test.cpp | 50 +++++++++++++++++++++++++ 12 files changed, 232 insertions(+), 2 deletions(-) create mode 100644 src/IntaRNA/StackSeedDomain.cpp create mode 100644 src/IntaRNA/StackSeedDomain.h create mode 100644 tests/StackSeedDomain_test.cpp diff --git a/ChangeLog b/ChangeLog index 606c5d2b..555e85fa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -42,6 +42,9 @@ ## Technical changes and Optimizations +- expose geometric stack-seed capability and compile contained occurrences plus + deduplicated eligible-start boxes (issue #257, implementation step 2) + - establish independent weighted-chain fixtures for seeded pair probabilities (issue #257, implementation step 1) @@ -136,6 +139,11 @@ energies, restricted partition sums, and trackers. ################################################################################ ################################################################################ +261008 Alexander Mitrofanov + * SeedHandler*, StackSeedDomain, tests/StackSeedDomain_test.cpp, Makefile.am : + + preserve each handler's admission rules, normalized allowances and retained + explicit patterns; filter complete endpoints and span limits (PR #258, step 2) + 261008 Alexander Mitrofanov * tests/SeededChainOracle.h, tests/SeededPartitionFunction_test.cpp, tests/Makefile.am : + independently enumerate weighted chains, raw boundaries and pair masses; diff --git a/src/IntaRNA/Makefile.am b/src/IntaRNA/Makefile.am index 5f27f746..d6e0f473 100644 --- a/src/IntaRNA/Makefile.am +++ b/src/IntaRNA/Makefile.am @@ -27,6 +27,7 @@ libIntaRNA_adir = $(includedir)/IntaRNA libIntaRNA_a_HEADERS = \ intarna_config.h \ Matrix.h \ + StackSeedDomain.h \ Accessibility.h \ AccessibilityArchive.h \ AccessibilityConstraint.h \ @@ -97,7 +98,8 @@ libIntaRNA_a_HEADERS = \ # the sources to add to the library and to add to the source distribution -libIntaRNA_a_SOURCES = \ +libIntaRNA_a_SOURCES = \ + StackSeedDomain.cpp \ $(libmylib_a_HEADERS) \ Accessibility.cpp \ AccessibilityConstraint.cpp \ @@ -158,7 +160,7 @@ libIntaRNA_a_SOURCES = \ # generated intaRNA sources -nodist_libIntaRNA_a_SOURCES = \ +nodist_libIntaRNA_a_SOURCES = \ ../config.h \ intarna_config.h diff --git a/src/IntaRNA/SeedHandler.h b/src/IntaRNA/SeedHandler.h index 55253d5c..27952062 100644 --- a/src/IntaRNA/SeedHandler.h +++ b/src/IntaRNA/SeedHandler.h @@ -18,6 +18,13 @@ class SeedHandler public: + /** Whether every exposed seed is a consecutive diagonal pair chain. + * This geometric guarantee does not imply existence or a common length. + * @return false for unknown handlers; offsets preserve this capability + */ + virtual bool guaranteesStackOnlySeeds() const; + + /** * Construction * @param energy the energy function to be used for seed prediction @@ -251,6 +258,12 @@ getInteractionEnergy() const ////////////////////////////////////////////////////////////////////////// +inline bool +SeedHandler::guaranteesStackOnlySeeds() const +{ + return false; +} + } // namespace #endif /* SEEDHANDLER_H_ */ diff --git a/src/IntaRNA/SeedHandlerExplicit.cpp b/src/IntaRNA/SeedHandlerExplicit.cpp index 11d0a439..5c38fde3 100644 --- a/src/IntaRNA/SeedHandlerExplicit.cpp +++ b/src/IntaRNA/SeedHandlerExplicit.cpp @@ -447,4 +447,14 @@ updateToNextSeed( size_t & i1_out, size_t & i2_out ////////////////////////////////////////////////////////////////////////// +bool +SeedHandlerExplicit::guaranteesStackOnlySeeds() const +{ + for (const auto & entry : seedForLeftEnd) { + if (entry.second.dotBar1.find('.') != std::string::npos + || entry.second.dotBar2.find('.') != std::string::npos) return false; + } + return true; +} + } /* namespace IntaRNA */ diff --git a/src/IntaRNA/SeedHandlerExplicit.h b/src/IntaRNA/SeedHandlerExplicit.h index ff1bb4f6..33d6087a 100644 --- a/src/IntaRNA/SeedHandlerExplicit.h +++ b/src/IntaRNA/SeedHandlerExplicit.h @@ -20,6 +20,9 @@ class SeedHandlerExplicit : public SeedHandler { public: + /** @return true if all retained accepted patterns contain only paired positions. */ + bool guaranteesStackOnlySeeds() const override; + /** * Construction * @param energy the energy function to be used for seed prediction diff --git a/src/IntaRNA/SeedHandlerIdxOffset.h b/src/IntaRNA/SeedHandlerIdxOffset.h index e798a5ff..11b30f96 100644 --- a/src/IntaRNA/SeedHandlerIdxOffset.h +++ b/src/IntaRNA/SeedHandlerIdxOffset.h @@ -24,6 +24,13 @@ class SeedHandlerIdxOffset : public SeedHandler public: + /** Whether every exposed seed is a consecutive diagonal pair chain. + * This geometric guarantee does not imply existence or a common length. + * @return false for unknown handlers; offsets preserve this capability + */ + virtual bool guaranteesStackOnlySeeds() const override; + + /** * Construction * @param seedHandler the seed handler to be wrapped @@ -516,6 +523,12 @@ isFeasibleSeedBasePair( const size_t i1 ////////////////////////////////////////////////////////////////////////// +inline bool +SeedHandlerIdxOffset::guaranteesStackOnlySeeds() const +{ + return seedHandlerOriginal->guaranteesStackOnlySeeds(); +} + } // namespace #endif /* SEEDHANDLERIDXOFFSET_H_ */ diff --git a/src/IntaRNA/SeedHandlerMfe.h b/src/IntaRNA/SeedHandlerMfe.h index 30fdeef8..94979fdf 100644 --- a/src/IntaRNA/SeedHandlerMfe.h +++ b/src/IntaRNA/SeedHandlerMfe.h @@ -21,6 +21,13 @@ class SeedHandlerMfe : public SeedHandler { public: + /** Whether every exposed seed is a consecutive diagonal pair chain. + * This geometric guarantee does not imply existence or a common length. + * @return false for unknown handlers; offsets preserve this capability + */ + virtual bool guaranteesStackOnlySeeds() const override; + + //! 5D matrix type to hold the mfe energies for seed interactions //! of the ranges i1..(i1+bp+u1-1) with i2..(i2+bp+u2-1), with //! i1,i2 = the start index of the seed in seq1/2 @@ -403,6 +410,12 @@ decodeSeedLength2( const size_t code ) const ////////////////////////////////////////////////////////////////////////// +inline bool +SeedHandlerMfe::guaranteesStackOnlySeeds() const +{ + return getConstraint().getMaxUnpaired1() == 0 && getConstraint().getMaxUnpaired2() == 0; +} + } // namespace #endif /* SEEDHANDLERMFE_H_ */ diff --git a/src/IntaRNA/SeedHandlerNoBulge.h b/src/IntaRNA/SeedHandlerNoBulge.h index 25ac247a..927643c9 100644 --- a/src/IntaRNA/SeedHandlerNoBulge.h +++ b/src/IntaRNA/SeedHandlerNoBulge.h @@ -34,6 +34,13 @@ class SeedHandlerNoBulge : public SeedHandler public: + /** Whether every exposed seed is a consecutive diagonal pair chain. + * This geometric guarantee does not imply existence or a common length. + * @return false for unknown handlers; offsets preserve this capability + */ + virtual bool guaranteesStackOnlySeeds() const override; + + /** * Construction * @param energy the energy function to be used for seed prediction @@ -314,6 +321,12 @@ storeSeed( const size_t j1, const size_t j2, const StackingEnergyList & bpE ) ////////////////////////////////////////////////////////////////////////// +inline bool +SeedHandlerNoBulge::guaranteesStackOnlySeeds() const +{ + return true; +} + } // namespace #endif /* SEEDHANDLERNOBULGE_H_ */ diff --git a/src/IntaRNA/StackSeedDomain.cpp b/src/IntaRNA/StackSeedDomain.cpp new file mode 100644 index 00000000..1e35fc19 --- /dev/null +++ b/src/IntaRNA/StackSeedDomain.cpp @@ -0,0 +1,46 @@ +#include "IntaRNA/StackSeedDomain.h" +#include +#include + +namespace IntaRNA { +StackSeedDomain::StackSeedDomain(const SeedHandler & handler, size_t n, size_t m, size_t w1, size_t w2) { + if (!handler.guaranteesStackOnlySeeds()) throw std::invalid_argument("stack seed domain requires a stack-only handler"); + if (n==0 || m==0) return; + // Use the range end as an invalid initial cursor, avoiding lastPos+offset wrap. + size_t i=n, j=m; + while (handler.updateToNextSeed(i,j,0,n-1,0,m-1)) { + const size_t len=handler.getSeedLength1(i,j); + if (len != handler.getSeedLength2(i,j)) throw std::logic_error("stack seed has unequal strand lengths"); + add({i,j,len},n,m,w1,w2); + } +} +StackSeedDomain::StackSeedDomain(const std::vector & seeds, size_t n, size_t m, size_t w1, size_t w2) { + for (auto s:seeds) add(s,n,m,w1,w2); +} +void StackSeedDomain::add(Occurrence s, size_t n, size_t m, size_t w1, size_t w2) { + w1=std::min(w1,n); w2=std::min(w2,m); + if (s.length==0 || s.i>=n || s.j>=m || s.length>n-s.i || s.length>m-s.j + || s.length>w1 || s.length>w2) return; + auto [p,inserted]=lengths.emplace(std::make_pair(s.i,s.j),s.length); + if (!inserted && p->second!=s.length) throw std::invalid_argument("multiple retained seed lengths at one start"); + maximum=std::max(maximum,s.length); + const size_t end1=s.i+s.length, end2=s.j+s.length; + boxes.push_back({end1>w1?end1-w1:0,s.i,end2>w2?end2-w2:0,s.j}); +} +void StackSeedDomain::forEachStart(const std::function & visit) const { + if (boxes.empty()) return; + size_t first=boxes.front().i0, last=0; + for (auto b:boxes) { first=std::min(first,b.i0); last=std::max(last,b.i1); } + std::vector> intervals; + for (size_t i=first;i<=last;++i) { + intervals.clear(); + for (auto b:boxes) if (b.i0<=i && i<=b.i1) intervals.emplace_back(b.j0,b.j1); + std::sort(intervals.begin(),intervals.end()); + size_t next=0; + for (auto [lo,hi]:intervals) { + for (size_t j=std::max(lo,next);j<=hi;++j) visit(i,j); + next=std::max(next,hi+1); + } + } +} +} diff --git a/src/IntaRNA/StackSeedDomain.h b/src/IntaRNA/StackSeedDomain.h new file mode 100644 index 00000000..ebd88fc8 --- /dev/null +++ b/src/IntaRNA/StackSeedDomain.h @@ -0,0 +1,58 @@ +#ifndef INTARNA_STACKSEEDDOMAIN_H_ +#define INTARNA_STACKSEEDDOMAIN_H_ + +#include "IntaRNA/SeedHandler.h" +#include +#include +#include +#include + +namespace IntaRNA { +/** Admitted stack occurrences and the deduplicated union of eligible-start boxes. + * Coordinates are local, zero-based and increasing on both strands. Seed energies + * have already been filtered by the handler and are never reused as path weights. + */ +class StackSeedDomain { +public: + /** A consecutive diagonal run, including singleton explicit seeds. */ + struct Occurrence { size_t i, j, length; }; + /** Compile a filled handler, requiring both endpoints inside the active range. + * @param handler filled stack-only handler, including any index offset + * @param n first range length + * @param m second range length + * @param span1 inclusive first-strand interaction span limit + * @param span2 inclusive second-strand interaction span limit + */ + StackSeedDomain(const SeedHandler & handler, size_t n, size_t m, size_t span1, size_t span2); + /** Compile already admitted occurrences (also useful for independent weight models). + * @param occurrences retained occurrences; out-of-range/overlong ones are excluded + * @param n first range length + * @param m second range length + * @param span1 inclusive first span limit + * @param span2 inclusive second span limit + */ + StackSeedDomain(const std::vector & occurrences, size_t n, size_t m, size_t span1, size_t span2); + /** @return retained length at this start, or zero if no occurrence starts here */ + size_t seedLength(size_t i, size_t j) const; + /** @return maximum retained occurrence length, zero for an empty family */ + size_t maxSeedLength() const; + /** Enumerate each eligible left boundary once, in row-major order. + * The caller intersects these boxes with accessible complementary vertices. + * @param visit callback receiving local first/second coordinates + */ + void forEachStart(const std::function & visit) const; +private: + //! admitted occurrences keyed by local start + std::map, size_t> lengths; + //! eligible inclusive rectangles [i0,i1] x [j0,j1] + struct Box { size_t i0, i1, j0, j1; }; + std::vector boxes; + size_t maximum = 0; + void add(Occurrence seed, size_t n, size_t m, size_t span1, size_t span2); +}; +inline size_t StackSeedDomain::seedLength(size_t i, size_t j) const { + auto p=lengths.find({i,j}); return p==lengths.end()?0:p->second; +} +inline size_t StackSeedDomain::maxSeedLength() const { return maximum; } +} +#endif diff --git a/tests/Makefile.am b/tests/Makefile.am index 90b8432d..20e8044e 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -26,6 +26,7 @@ runApiTests_SOURCES = \ SeededChainOracle.h \ SeededTheoryFixtures.h \ SeededPartitionFunction_test.cpp \ + StackSeedDomain_test.cpp \ testEasyLoggingSetup.icc \ AccessibilityConstraint_test.cpp \ AccessibilityFromStream_test.cpp \ diff --git a/tests/StackSeedDomain_test.cpp b/tests/StackSeedDomain_test.cpp new file mode 100644 index 00000000..068c638d --- /dev/null +++ b/tests/StackSeedDomain_test.cpp @@ -0,0 +1,50 @@ +#include "catch.hpp" +#include "IntaRNA/StackSeedDomain.h" +#include "IntaRNA/SeedHandlerExplicit.h" +#include "IntaRNA/SeedHandlerNoBulge.h" +#include "IntaRNA/SeedHandlerMfe.h" +#include "IntaRNA/SeedHandlerIdxOffset.h" +#include "IntaRNA/InteractionEnergyBasePair.h" +#include "IntaRNA/AccessibilityDisabled.h" +#include +using namespace IntaRNA; + +TEST_CASE("stack capability and active occurrence domain", "[StackSeedDomain]") { + #include "testEasyLoggingSetup.icc" + RnaSequence t("t","GGGGGG"), q("q","CCCCCC"); + AccessibilityDisabled at(t,0,nullptr), aq(q,0,nullptr); + ReverseAccessibility ar(aq); + InteractionEnergyBasePair energy(at,ar); + SeedConstraint computed(2,0,4,3,E_INF,Accessibility::ED_UPPER_BOUND,E_INF,IndexRangeList(),IndexRangeList(),"",false,false,false); + SeedHandlerMfe mfe(energy,computed); + SeedHandlerNoBulge stack(energy,computed); + REQUIRE(mfe.guaranteesStackOnlySeeds()); + REQUIRE(stack.guaranteesStackOnlySeeds()); + SeedConstraint bulged(2,1,1,0,E_INF,Accessibility::ED_UPPER_BOUND,E_INF,IndexRangeList(),IndexRangeList(),"",false,false,false); + SeedHandlerMfe bulge(energy,bulged); + REQUIRE_FALSE(bulge.guaranteesStackOnlySeeds()); + SeedConstraint explicitC(1,0,0,0,E_INF,Accessibility::ED_UPPER_BOUND,E_INF, + IndexRangeList(),IndexRangeList(),"1|&6|,2|||&3|||,5||&1||",false,false,false); + SeedHandlerIdxOffset explicitH(new SeedHandlerExplicit(energy,explicitC)); + REQUIRE(explicitH.guaranteesStackOnlySeeds()); + explicitH.setOffset1(1); explicitH.setOffset2(1); + explicitH.fillSeed(0,3,0,3); + StackSeedDomain domain(explicitH,4,4,4,4); + REQUIRE(domain.seedLength(0,0)==3); + REQUIRE(domain.seedLength(3,3)==0); // end outside the active range + REQUIRE(domain.maxSeedLength()==3); + StackSeedDomain mixed({{0,0,1},{2,2,2},{4,4,3}},6,6,4,3); + REQUIRE(mixed.maxSeedLength()==2); + std::set> starts; + size_t calls=0; + mixed.forEachStart([&](size_t i,size_t j){ ++calls; starts.emplace(i,j); }); + REQUIRE(calls==starts.size()); + for (size_t i=0;i<6;++i) for(size_t j=0;j<6;++j) { + const bool expected=(i==0 && j==0) || (i<=2 && j>=1 && j<=2); + REQUIRE((starts.count({i,j})!=0)==expected); + } + SeedConstraint explicitB(2,0,0,0,E_INF,Accessibility::ED_UPPER_BOUND,E_INF, + IndexRangeList(),IndexRangeList(),"1|.|&4|.|",false,false,false); + SeedHandlerExplicit eb(energy,explicitB); + REQUIRE_FALSE(eb.guaranteesStackOnlySeeds()); +} From 5c8907cb4b0bde9ae185f031810f6c52a02d7780 Mon Sep 17 00:00:00 2001 From: AlexanderMitrofanov Date: Thu, 8 Oct 2026 14:02:16 +0200 Subject: [PATCH 04/21] feat: validate and select seeded inside-outside kernel (step 3) --- ChangeLog | 9 ++ doc/Makefile.am | 1 + doc/analysis/seeded-kernel-comparison.md | 63 ++++++++++++ src/IntaRNA/Makefile.am | 3 + src/IntaRNA/PartitionArithmetic.h | 53 +++++++++++ src/IntaRNA/SeededPartitionFunction.cpp | 97 +++++++++++++++++++ src/IntaRNA/SeededPartitionFunction.h | 44 +++++++++ src/IntaRNA/StackSeedDomain.cpp | 2 + src/IntaRNA/StackSeedDomain.h | 7 ++ tests/Makefile.am | 1 + tests/SeededPartitionFunction_test.cpp | 107 ++++++++++++++++++++- tests/SeededStackKernel.h | 116 +++++++++++++++++++++++ 12 files changed, 502 insertions(+), 1 deletion(-) create mode 100644 doc/analysis/seeded-kernel-comparison.md create mode 100644 src/IntaRNA/PartitionArithmetic.h create mode 100644 src/IntaRNA/SeededPartitionFunction.cpp create mode 100644 src/IntaRNA/SeededPartitionFunction.h create mode 100644 tests/SeededStackKernel.h diff --git a/ChangeLog b/ChangeLog index 555e85fa..6bee2563 100644 --- a/ChangeLog +++ b/ChangeLog @@ -42,6 +42,9 @@ ## Technical changes and Optimizations +- select the checked suffix inside/outside kernel after independent correctness + and maximal-stack timing comparisons (issue #257, implementation step 3) + - expose geometric stack-seed capability and compile contained occurrences plus deduplicated eligible-start boxes (issue #257, implementation step 2) @@ -139,6 +142,12 @@ energies, restricted partition sums, and trackers. ################################################################################ ################################################################################ +261008 Alexander Mitrofanov + * SeededPartitionFunction, PartitionArithmetic, StackSeedDomain, tests, doc/analysis : + + add checked nonnegative kernels and raw pair differentiation; compare both + against exhaustive and high-precision gold values and record time/storage + tradeoffs before selecting the suffix backend (PR #258, step 3) + 261008 Alexander Mitrofanov * SeedHandler*, StackSeedDomain, tests/StackSeedDomain_test.cpp, Makefile.am : + preserve each handler's admission rules, normalized allowances and retained diff --git a/doc/Makefile.am b/doc/Makefile.am index 5e3ac756..4092731b 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -6,6 +6,7 @@ EXTRA_DIST = \ conda.txt \ analysis/base-pair-probabilities-plan.md \ + analysis/seeded-kernel-comparison.md \ api-documentation.md \ build-api.sh \ check-api.py \ diff --git a/doc/analysis/seeded-kernel-comparison.md b/doc/analysis/seeded-kernel-comparison.md new file mode 100644 index 00000000..05cc407f --- /dev/null +++ b/doc/analysis/seeded-kernel-comparison.md @@ -0,0 +1,63 @@ +# Seeded partition kernel comparison (PR #258, step 3) + +Production uses the specialized stack-seed suffix automaton. Both candidates +passed independent exhaustive comparisons of raw Z, complete boundary partitions +and every pair numerator: all ten unrounded theory fixtures and 100 deterministic +heterogeneous-weight cases with missing edges, forbidden boundaries, mixed and +singleton occurrences, asymmetric spans and noLP. The tolerance is 2e-12 relative; +the oracle accumulates in long double. Mathematical fixture accessibility remains +unrounded, independently of native integer ED tests. + +## Reproduce + +GCC 14.4.0, Linux x86-64, release Autotools configuration, Z_type=double, +`-O3 -DNDEBUG`, Kokkos mdspan. The hidden Catch case contains every input and +uses deterministic weights and identical callback/checked-arithmetic contracts. + +```sh +OMP_NUM_THREADS=1 OPENBLAS_NUM_THREADS=1 /usr/bin/time -v \ + ./tests/runApiTests '[SeededBenchmark]' +``` + +Single-run milliseconds on the development host (these are kernel timings, +not native full-program speedups; rerun to account for shared-host noise): + +| Case | Stack Z | Suffix Z | Stack Z+outside | Suffix Z+outside | +| --- | ---: | ---: | ---: | ---: | +| none | 0.000 | 0.000 | 0.009 | 0.000 | +| sparse | 59.462 | 43.934 | 156.972 | 140.072 | +| overlap | 109.494 | 77.083 | 304.623 | 249.862 | +| dense | 207.217 | 96.059 | 554.614 | 302.839 | +| long-stack | 1.003 | 0.879 | 3.057 | 1.466 | +| mixed | 196.146 | 99.959 | 522.997 | 310.235 | +| asymmetric | 65.849 | 37.285 | 182.743 | 121.412 | + +The outside increment is the difference between each combined and partition-only +time. All corresponding Z values agree within 2e-12; pair masses were checked +before timing. The numerical kernels do not include native seed preprocessing. +Ordinary cases use 45 x 45 positions, spans 30 x 30, seed length four and loop +limits two. The long-stack case uses a 90-position diagonal (L up to 30); mixed +lengths are one through four; asymmetric spans are 12 x 24. No-seed input exits +before DP allocation. Sparse input has one seed. These are synthetic stress cases; +end-to-end native measurements belong to the final integration gate. + +## Memory and decision + +For a per-start dense rectangle of A cells and c=max(2, maximum seed length), +the suffix implementation stores (c+4)A partition values, or 2(c+4)A with the +outside pass, plus A bytes of validity and A size_t ending lengths. For c=4 and +A=900 this is 65,700 bytes partition-only and 123,300 with outside (eight-byte +Z_type/size_t). Maximal stacks use 4A or 8A partition values, A validity bytes +and up to 3L scratch partition values for the outside pass. The output matrix +adds n*m*sizeof(Z_type) for either kernel. Occurrences/eligible-start boxes are +separate O(number of retained seeds) metadata; neither candidate retains run +lists or boundary coefficients globally. These are physical rectangular-cell +counts, not just complementary vertices. Allocator overhead is not included. + +The suffix candidate generally improves throughput, especially partition-only +and long-stack work. The extra bounded-span memory is acceptable for the intended +workload, so only suffix states ship in the library. Maximal stacks remain in a +test-only header for independent comparisons. This is not a claim of universal +speedup or lower memory use. Final integration also accounts for the global pair +matrix, private regional result, and legacy boundary-map storage when trackers +are enabled. diff --git a/src/IntaRNA/Makefile.am b/src/IntaRNA/Makefile.am index d6e0f473..4e37bc30 100644 --- a/src/IntaRNA/Makefile.am +++ b/src/IntaRNA/Makefile.am @@ -28,6 +28,8 @@ libIntaRNA_a_HEADERS = \ intarna_config.h \ Matrix.h \ StackSeedDomain.h \ + PartitionArithmetic.h \ + SeededPartitionFunction.h \ Accessibility.h \ AccessibilityArchive.h \ AccessibilityConstraint.h \ @@ -100,6 +102,7 @@ libIntaRNA_a_HEADERS = \ # the sources to add to the library and to add to the source distribution libIntaRNA_a_SOURCES = \ StackSeedDomain.cpp \ + SeededPartitionFunction.cpp \ $(libmylib_a_HEADERS) \ Accessibility.cpp \ AccessibilityConstraint.cpp \ diff --git a/src/IntaRNA/PartitionArithmetic.h b/src/IntaRNA/PartitionArithmetic.h new file mode 100644 index 00000000..37f28a89 --- /dev/null +++ b/src/IntaRNA/PartitionArithmetic.h @@ -0,0 +1,53 @@ +#ifndef INTARNA_PARTITIONARITHMETIC_H_ +#define INTARNA_PARTITIONARITHMETIC_H_ +#include "IntaRNA/general.h" +#include + +namespace IntaRNA { +/** Checked nonnegative arithmetic for exact seeded partitions only. + * Structural zero is exactly zero. Positive subnormals are rejected because + * their relative precision is not guaranteed. Ordinary sum rounding remains. + */ +class PartitionArithmetic { +public: + /** @return x; throws on negative, NaN, infinite or positive subnormal values */ + static Z_type check(const Z_type x); + /** @return checked sum of two nonnegative values */ + static Z_type add(const Z_type a, const Z_type b); + /** @return checked product; positive underflow is an error */ + static Z_type multiply(const Z_type a, const Z_type b); + /** @return checked quotient; denominator must be positive */ + static Z_type divide(const Z_type a, const Z_type b); + /** @return checked exponential; a finite exponent must yield a positive normal value */ + static Z_type exp(const Z_type exponent); +}; +inline Z_type PartitionArithmetic::check(const Z_type x) { + if (!(x>=0 && x<=std::numeric_limits::max()) + || (x>0 && x::min())) + throw std::range_error("exact seeded partition: numerical range exceeded"); + return x; +} +inline Z_type PartitionArithmetic::add(const Z_type a,const Z_type b) { + return check(check(a)+check(b)); +} +inline Z_type PartitionArithmetic::multiply(const Z_type a,const Z_type b) { + check(a); check(b); + if (a==0 || b==0) return 0; + const Z_type r=check(a*b); + if (r==0) throw std::range_error("exact seeded partition: product underflow"); + return r; +} +inline Z_type PartitionArithmetic::divide(const Z_type a,const Z_type b) { + check(a); check(b); + if (b==0) throw std::range_error("exact seeded partition: zero denominator"); + const Z_type r=check(a/b); + if (a>0 && r==0) throw std::range_error("exact seeded partition: quotient underflow"); + return r; +} +inline Z_type PartitionArithmetic::exp(const Z_type exponent) { + const Z_type r=check(Z_exp(exponent)); + if (r==0) throw std::range_error("exact seeded partition: exponential underflow"); + return r; +} +} +#endif diff --git a/src/IntaRNA/SeededPartitionFunction.cpp b/src/IntaRNA/SeededPartitionFunction.cpp new file mode 100644 index 00000000..2caa278c --- /dev/null +++ b/src/IntaRNA/SeededPartitionFunction.cpp @@ -0,0 +1,97 @@ +#include "IntaRNA/SeededPartitionFunction.h" +#include "IntaRNA/PartitionArithmetic.h" + +// Seed-free suffix lengths plus two absorbing seeded states (singleton/run). +// Nonstack edges operate on aggregate totals, independently of seed length. +namespace IntaRNA { +SeededPartitionFunction::Result SeededPartitionFunction::compute( + const IntaRNA::SeededPartitionFunction::Domain & d, + const IntaRNA::StackSeedDomain & seeds, + const IntaRNA::SeededPartitionFunction::Weights & w, bool pairs) +{ + using namespace IntaRNA; + using A=PartitionArithmetic; + using Pair=SeededPartitionFunction::Pair; + SeededPartitionFunction::Result out; + if (pairs) out.mass=Matrix(d.n,d.m,0); + if (!seeds.maxSeedLength() || !d.span1 || !d.span2) return out; + // At least two length states are necessary for noLP even with singleton seeds. + const size_t cap=std::max(size_t(2),seeds.maxSeedLength()), s1=cap, s2=cap+1, states=cap+2; + seeds.forEachStart([&](size_t p1,size_t p2) { + const Pair p{p1,p2}; if (!w.valid(p)) return; + const size_t n=std::min(d.span1,d.n-p1),m=std::min(d.span2,d.m-p2); + Matrix h(n*m,states),dh; + Matrix> total(n,m),dt; + Matrix valid(n,m); + Matrix ending(n,m); + if (pairs) { dh.resize(n*m,states); dt.resize(n,m); } + for (size_t i=0;i=cap) return stacked || !d.noLP?s2:s1; + const size_t len=stacked?std::min(cap,c+2):1; + return accepts(i,j,len)?(len>=2 || !d.noLP?s2:s1):len-1; + }; + auto nonstack=[&](size_t i,size_t j,const auto & visit) { + for(size_t u=1;u<=i && u-1<=d.loop1;++u) for(size_t v=1;v<=j && v-1<=d.loop2;++v) + if((u!=1 || v!=1) && valid(i-u,j-v)) visit(i-u,j-v); + }; + const size_t initial=accepts(0,0,1)?(d.noLP?s1:s2):0; + const Z_type init=A::check(w.initiation(p)); h(0,initial)=init; + for(size_t i=0;i0) { + const Z_type b=A::check(w.boundary(p,{p1+i,p2+j})); + out.z=A::add(out.z,A::multiply(b,total(i,j)[1])); + if(pairs) { dh(q,s2)=b;if(!d.noLP) dh(q,s1)=b; } + if(w.complete) w.complete(p,{p1+i,p2+j},total(i,j)[1],b); + } + } + if(!pairs) return; + for(size_t ii=n;ii>0;--ii) for(size_t jj=m;jj>0;--jj) { + const size_t i=ii-1,j=jj-1,q=i*m+j; if(!valid(i,j)) continue; + for(size_t c=d.noLP?1:0;c +#include + +namespace IntaRNA { +/** Nonnegative stack-seed suffix inside/outside computation. A path is counted once + * if it contains any admitted seed. Native energy ownership is supplied by the + * adapter: initiation once, one transition per successive pair, one boundary + * factor. All callbacks must be deterministic; zero denotes forbidden weight. + */ +class SeededPartitionFunction { +public: + //! Local zero-based pair, second strand in reversed coordinates. + using Pair = std::array; + /** Active rectangle, inclusive spans, loop limits and structural restriction. */ + struct Domain { size_t n,m,span1,span2,loop1,loop2; bool noLP; }; + /** Energy adapter. Complete boundary callbacks are made once per positive + * seeded hybrid partition and receive the SAME coefficient used outside. + * No callback may alter the forward weights after observing them. + */ + struct Weights { + std::function valid; + std::function initiation; + std::function transition, boundary; + std::function complete; + }; + /** Raw unnormalized result; pair masses remain empty in partition-only mode. */ + struct Result { Z_type z=0; Matrix mass; }; + /** Compute the union of seeded paths, optionally differentiating every pair. + * @param domain active dimensions and structural constraints + * @param seeds active admitted seed occurrences + * @param weights weight/admission contract (no integer energy reconstruction) + * @param pairs request the outside pass and raw local pair masses + * @return successful raw result, including exact zero for an empty ensemble + * @throws std::range_error on numerical failure; no partial result is returned + */ + static Result compute(const Domain & domain, const StackSeedDomain & seeds, + const Weights & weights, bool pairs); +}; +} +#endif diff --git a/src/IntaRNA/StackSeedDomain.cpp b/src/IntaRNA/StackSeedDomain.cpp index 1e35fc19..baf99c5a 100644 --- a/src/IntaRNA/StackSeedDomain.cpp +++ b/src/IntaRNA/StackSeedDomain.cpp @@ -23,6 +23,8 @@ void StackSeedDomain::add(Occurrence s, size_t n, size_t m, size_t w1, size_t w2 || s.length>w1 || s.length>w2) return; auto [p,inserted]=lengths.emplace(std::make_pair(s.i,s.j),s.length); if (!inserted && p->second!=s.length) throw std::invalid_argument("multiple retained seed lengths at one start"); + auto [end, fresh]=endingLengths.emplace(std::make_pair(s.i+s.length-1,s.j+s.length-1),s.length); + if (!fresh) end->second=std::min(end->second,s.length); maximum=std::max(maximum,s.length); const size_t end1=s.i+s.length, end2=s.j+s.length; boxes.push_back({end1>w1?end1-w1:0,s.i,end2>w2?end2-w2:0,s.j}); diff --git a/src/IntaRNA/StackSeedDomain.h b/src/IntaRNA/StackSeedDomain.h index ebd88fc8..a6c82f64 100644 --- a/src/IntaRNA/StackSeedDomain.h +++ b/src/IntaRNA/StackSeedDomain.h @@ -34,6 +34,8 @@ class StackSeedDomain { StackSeedDomain(const std::vector & occurrences, size_t n, size_t m, size_t span1, size_t span2); /** @return retained length at this start, or zero if no occurrence starts here */ size_t seedLength(size_t i, size_t j) const; + /** @return shortest admitted occurrence ending here, or zero */ + size_t seedEndingLength(size_t i, size_t j) const; /** @return maximum retained occurrence length, zero for an empty family */ size_t maxSeedLength() const; /** Enumerate each eligible left boundary once, in row-major order. @@ -44,6 +46,8 @@ class StackSeedDomain { private: //! admitted occurrences keyed by local start std::map, size_t> lengths; + //! shortest retained length per ending vertex for suffix acceptance + std::map, size_t> endingLengths; //! eligible inclusive rectangles [i0,i1] x [j0,j1] struct Box { size_t i0, i1, j0, j1; }; std::vector boxes; @@ -53,6 +57,9 @@ class StackSeedDomain { inline size_t StackSeedDomain::seedLength(size_t i, size_t j) const { auto p=lengths.find({i,j}); return p==lengths.end()?0:p->second; } +inline size_t StackSeedDomain::seedEndingLength(size_t i, size_t j) const { + auto p=endingLengths.find({i,j}); return p==endingLengths.end()?0:p->second; +} inline size_t StackSeedDomain::maxSeedLength() const { return maximum; } } #endif diff --git a/tests/Makefile.am b/tests/Makefile.am index 20e8044e..ebbc88ca 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -25,6 +25,7 @@ runApiTests_SOURCES = \ catch.hpp \ SeededChainOracle.h \ SeededTheoryFixtures.h \ + SeededStackKernel.h \ SeededPartitionFunction_test.cpp \ StackSeedDomain_test.cpp \ testEasyLoggingSetup.icc \ diff --git a/tests/SeededPartitionFunction_test.cpp b/tests/SeededPartitionFunction_test.cpp index 12338b6c..1eca2608 100644 --- a/tests/SeededPartitionFunction_test.cpp +++ b/tests/SeededPartitionFunction_test.cpp @@ -27,7 +27,7 @@ TEST_CASE("unrounded fixed-seed theory gold agrees with exhaustive chains", "[Se auto fixtures=theoryFixtures(); REQUIRE(fixtures.size()==10); for (const auto & f:fixtures) { - INFO(f.name); + CAPTURE(f.name); const auto got=enumerate(f.model); REQUIRE(double(got.z)==Approx(double(f.expected.z)).epsilon(2e-12)); for (const auto & [pair, mass]:f.expected.mass) { @@ -39,3 +39,108 @@ TEST_CASE("unrounded fixed-seed theory gold agrees with exhaustive chains", "[Se } } } + +#include "IntaRNA/SeededPartitionFunction.h" +#include "IntaRNA/PartitionArithmetic.h" +#include "SeededStackKernel.h" +#include +#include +#include + +namespace { +using Kernel=IntaRNA::SeededPartitionFunction; +using IntaRNA::Z_type; +IntaRNA::StackSeedDomain domainFor(const seeded_oracle::Model & m) { + std::vector seeds; + for(const auto & s:m.seeds) seeds.push_back({s[0][0],s[0][1],s.size()}); + return {seeds,m.n,m.m,m.span1,m.span2}; +} +Kernel::Weights weightsFor(const seeded_oracle::Model & m) { + return {m.valid,[&](auto p){return Z_type(m.init(p));}, + [&](auto p,auto q){return Z_type(m.edge(p,q));}, + [&](auto p,auto q){return Z_type(m.boundary(p,q));},{}}; +} +void compareKernels(const seeded_oracle::Model & m) { + const auto oracle=seeded_oracle::enumerate(m); + const auto seeds=domainFor(m); + Kernel::Domain d{m.n,m.m,m.span1,m.span2,m.n,m.m,m.noLP}; + for(bool suffix:{false,true}) { + CAPTURE(suffix); + auto w=weightsFor(m); + std::map boundaries; + w.complete=[&](auto p,auto q,auto h,auto b){boundaries[{p[0],p[1],q[0],q[1]}]+=h*b;}; + auto got=suffix?Kernel::compute(d,seeds,w,true):seededStack(d,seeds,w,true); + REQUIRE(double(got.z)==Approx(double(oracle.z)).epsilon(2e-12)); + for(auto [b,z]:oracle.boundaries) REQUIRE(double(boundaries[b])==Approx(double(z)).epsilon(2e-12)); + Z_type expectedCount=0; + for(size_t i=0;isecond)).epsilon(2e-12)); + expectedCount+=got.mass(i,j); + } + REQUIRE(double(expectedCount)==Approx(double(oracle.pairCount)).epsilon(2e-12)); + auto only=suffix?Kernel::compute(d,seeds,w,false):seededStack(d,seeds,w,false); + REQUIRE(only.z==got.z); + REQUIRE(only.mass.storageSize()==0); + } +} +} +TEST_CASE("both numerical kernels match all theory fixtures", "[SeededPartitionFunction]") { + for(const auto & f:seeded_oracle::theoryFixtures()) { CAPTURE(f.name);compareKernels(f.model); } +} +TEST_CASE("heterogeneous weighted kernels match independent enumeration", "[SeededPartitionFunction]") { + using namespace seeded_oracle; + std::mt19937 rng(257); + for(size_t trial=0;trial<100;++trial) { + CAPTURE(trial); + Model m{6,5,2+rng()%5,2+rng()%4,bool(trial%2),{}, + [trial](Pair p){return (p[0]+3*p[1]+trial)%7!=0;}, + [](Pair p){return .7L+.13L*p[0];}, + [trial](Pair p,Pair q){return (p[0]+q[1]+trial)%11==0?0.L:.1L+.17L*(q[0]-p[0])+.21L*(q[1]-p[1]);}, + [trial](Pair p,Pair q){return (q[0]+p[1]+trial)%5==0?0.L:.2L+.07L*(q[0]+p[1]);}}; + for(size_t i=0;i::quiet_NaN()),std::range_error); + REQUIRE_THROWS_AS(A::add(std::numeric_limits::max(),std::numeric_limits::max()),std::range_error); +} +TEST_CASE("numerical seeded kernel comparison timing", "[.][SeededBenchmark]") { + using namespace seeded_oracle; + for (std::string kind:{"none","sparse","overlap","dense","long-stack","mixed","asymmetric"}) { + const size_t n=kind=="long-stack"?90:45; + Model m{n,n,kind=="asymmetric"?12u:30u,kind=="asymmetric"?24u:30u,false,{}, + [kind](Pair p){return kind=="long-stack"?p[0]==p[1]:(7*p[0]+11*p[1])%17!=0;}, + [](Pair){return .8L;},[](Pair p,Pair q){return q[0]-p[0]<=3 && q[1]-p[1]<=3?.7L:0.L;}, + [](Pair,Pair){return .6L;}}; + if(kind!="none") for(size_t i=0;i+4(std::chrono::steady_clock::now()-start).count(); + if(!suffix && !outside) reference=r.z; else REQUIRE(double(r.z)==Approx(double(reference)).epsilon(2e-12)); + std::cout< +#include + +inline IntaRNA::SeededPartitionFunction::Result seededStack(const IntaRNA::SeededPartitionFunction::Domain & d, const IntaRNA::StackSeedDomain & seeds, + const IntaRNA::SeededPartitionFunction::Weights & w, bool pairs) +{ + using namespace IntaRNA; + using Pair=SeededPartitionFunction::Pair; + using Result=SeededPartitionFunction::Result; + using A=PartitionArithmetic; + using State=std::array; + Result result; + if (pairs) result.mass=Matrix(d.n,d.m,0); + if (!seeds.maxSeedLength() || !d.span1 || !d.span2) return result; + seeds.forEachStart([&](size_t p1,size_t p2) { + const Pair p{p1,p2}; + if (!w.valid(p)) return; + const size_t n=std::min(d.span1,d.n-p1), m=std::min(d.span2,d.m-p2); + Matrix h(n,m), entry(n,m), dh, de; + Matrix valid(n,m); + if (pairs) { dh.resize(n,m); de.resize(n,m); } + for (size_t i=0;i0 && length<=k+1; + if (d.noLP && k==0) continue; + for (size_t c=0;c<2;++c) { + const size_t accepted=c || hit; + h(i,j)[accepted]=A::add(h(i,j)[accepted],A::multiply(entry(a,b)[c],product)); + } + } + if (h(i,j)[1]>0) { + const Z_type b=A::check(w.boundary(p,q)); + result.z=A::add(result.z,A::multiply(b,h(i,j)[1])); + if (pairs) dh(i,j)[1]=b; + if (w.complete) w.complete(p,q,h(i,j)[1],b); + } + } + if (!pairs) return; + // Recompute each diagonal product chain with O(run length) scratch, then + // reverse it once. Each entry marks the first pair, product edges the rest. + std::vector product, edge, g; + for (size_t ii=n;ii>0;--ii) for (size_t jj=m;jj>0;--jj) { + const size_t i=ii-1,j=jj-1; + if (!valid(i,j)) continue; + product.clear(); edge.clear(); g.clear(); + bool hit=false; + for (size_t k=0;k<=std::min(i,j);++k) { + const size_t a=i-k,b=j-k; + if (!valid(a,b)) break; + Z_type t=1; + if (k) { t=A::check(w.transition({p1+a,p2+b},{p1+a+1,p2+b+1})); if (t==0) break; } + edge.push_back(t); + product.push_back(k?A::multiply(product.back(),t):Z_type(1)); + g.push_back(0); + const size_t length=seeds.seedLength(p1+a,p2+b); + hit |= length>0 && length<=k+1; + if (d.noLP && k==0) continue; // retain the empty product node + for (size_t c=0;c<2;++c) { + const Z_type adj=dh(i,j)[c || hit]; + de(a,b)[c]=A::add(de(a,b)[c],A::multiply(adj,product.back())); + g.back()=A::add(g.back(),A::multiply(adj,entry(a,b)[c])); + } + } + for (size_t k=product.size();k>1;) { + --k; + auto & mass=result.mass(p1+i-k+1,p2+j-k+1); + mass=A::add(mass,A::multiply(g[k],product[k])); + g[k-1]=A::add(g[k-1],A::multiply(g[k],edge[k])); + } + for (size_t c=0;c<2;++c) { + auto & mass=result.mass(p1+i,p2+j); + mass=A::add(mass,A::multiply(de(i,j)[c],entry(i,j)[c])); + } + incoming(i,j,[&](size_t u,size_t v) { + if (de(i,j)[0]==0 && de(i,j)[1]==0) return; + const Z_type t=A::check(w.transition({p1+u,p2+v},{p1+i,p2+j})); + for (size_t c=0;c<2;++c) dh(u,v)[c]=A::add(dh(u,v)[c],A::multiply(de(i,j)[c],t)); + }); + } + }); + return result; +} +#endif From 8bd85345d44d4b0c3e9174ce402f8f641aac8c7e Mon Sep 17 00:00:00 2001 From: AlexanderMitrofanov Date: Thu, 8 Oct 2026 14:06:42 +0200 Subject: [PATCH 05/21] fix: integrate unique exact seeded partition accounting (step 4) --- ChangeLog | 11 +++ src/IntaRNA/OutputHandler.h | 18 ++++- src/IntaRNA/OutputHandlerCsv.cpp | 8 +- src/IntaRNA/OutputHandlerEnsemble.cpp | 4 +- src/IntaRNA/OutputHandlerHub.h | 9 +++ src/IntaRNA/OutputHandlerText.cpp | 2 +- src/IntaRNA/PredictorMfeEns.cpp | 26 ++++++ src/IntaRNA/PredictorMfeEns.h | 10 +++ .../PredictorMfeEns2dSeedExtension.cpp | 50 +++++++++++- src/IntaRNA/PredictorMfeEns2dSeedExtension.h | 7 ++ src/bin/IntaRNA.cpp | 1 + tests/PredictorMfeEnsRegression_test.cpp | 4 +- tests/PredictorSeedOracle_test.cpp | 81 +++++++++++++++++++ 13 files changed, 221 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6bee2563..72fef34c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -42,6 +42,9 @@ ## Technical changes and Optimizations +- count each exact stack-seeded interaction once; preserve tiny positive totals + through complete updates and output forwarding (issue #257, step 4) + - select the checked suffix inside/outside kernel after independent correctness and maximal-stack timing comparisons (issue #257, implementation step 3) @@ -142,6 +145,14 @@ energies, restricted partition sums, and trackers. ################################################################################ ################################################################################ +261008 Alexander Mitrofanov + * PredictorMfeEns*, OutputHandler*, IntaRNA.cpp, predictor oracle tests : + + use the suffix kernel on the exact stack-only path, preserving virtual + update hooks and the legacy heuristic/bulged paths; share the boundary + objective with the outside pass and restore update scopes after exceptions + + retain exact-zero status through collectors, hubs and ensemble diagnostics; + test native Nussinov/nearest-neighbor boundary sums (PR #258, step 4) + 261008 Alexander Mitrofanov * SeededPartitionFunction, PartitionArithmetic, StackSeedDomain, tests, doc/analysis : + add checked nonnegative kernels and raw pair differentiation; compare both diff --git a/src/IntaRNA/OutputHandler.h b/src/IntaRNA/OutputHandler.h index 9528d121..9f925ade 100644 --- a/src/IntaRNA/OutputHandler.h +++ b/src/IntaRNA/OutputHandler.h @@ -3,6 +3,7 @@ #define INTARNA_OUTPUTHANDLER_H_ #include "IntaRNA/general.h" +#include "IntaRNA/PartitionArithmetic.h" #include "IntaRNA/Interaction.h" #include "IntaRNA/InteractionRange.h" #include "IntaRNA/OutputConstraint.h" @@ -97,7 +98,18 @@ class OutputHandler { getOutputConstraint() const; + /** Select exact-zero, checked partition accumulation for the seeded backend. + * @param exact whether this sequence pair uses the checked exact backend + */ + virtual void setExactPartition(bool exact); + /** @return whether exact-zero presentation/merging is enabled */ + bool usesExactPartition() const; + /** @return whether the accumulated partition is nonempty under its policy */ + bool hasNonzeroZ() const; + protected: + //! scoped to a supported sequence-pair ensemble, legacy outputs default false + bool exactPartition = false; //! the output constraints to be applied const OutputConstraint outConstraint; @@ -185,11 +197,15 @@ incrementZ( const Z_type subZ ) #if INTARNA_MULITHREADING #pragma omp critical(intarna_omp_outputHandlerIncrementZ) #endif - {Z += subZ;} + {Z = exactPartition ? PartitionArithmetic::add(Z,subZ) : Z+subZ;} } //////////////////////////////////////////////////////////////////////////// +inline void OutputHandler::setExactPartition(bool exact) { exactPartition=exact; } +inline bool OutputHandler::usesExactPartition() const { return exactPartition; } +inline bool OutputHandler::hasNonzeroZ() const { return exactPartition ? getZ()!=0 : !Z_equal(getZ(),Z_type(0)); } + } // namespace #endif /* OUTPUTHANDLER_H_ */ diff --git a/src/IntaRNA/OutputHandlerCsv.cpp b/src/IntaRNA/OutputHandlerCsv.cpp index 79a7d242..34d04a7e 100644 --- a/src/IntaRNA/OutputHandlerCsv.cpp +++ b/src/IntaRNA/OutputHandlerCsv.cpp @@ -424,7 +424,7 @@ add( const Interaction & i ) break; case Eall: - if ( Z_equal(Z,Z_type(0)) ) outTmp << notAvailable; else outTmp <setExactPartition(usesExactPartition()); outList.push_back(handler); } } @@ -304,6 +308,11 @@ operator= ( const OutputHandlerHub & toCopy) ///////////////////////////////////////////////////////////////////////// +inline void OutputHandlerHub::setExactPartition(bool exact) { + OutputHandler::setExactPartition(exact); + for (auto handler:outList) handler->setExactPartition(exact); +} + } // namespace #endif /* OUTPUTHANDLERHUB_H_ */ diff --git a/src/IntaRNA/OutputHandlerText.cpp b/src/IntaRNA/OutputHandlerText.cpp index d66ca12b..fe1154f5 100644 --- a/src/IntaRNA/OutputHandlerText.cpp +++ b/src/IntaRNA/OutputHandlerText.cpp @@ -417,7 +417,7 @@ add( const Interaction & i ) } // detailed // ensemble output if available - if (!Z_equal(Z,Z_type(0)) && Z_isNotINF(Z)) { + if (hasNonzeroZ() && Z_isNotINF(Z)) { outTmp <<"\n" <<"ensemble energy = "< #include @@ -45,6 +46,17 @@ addPartitionContribution( const size_t i1, const size_t j1 , const bool isHybridZ , Z_type & partZ_noED ) { + if (exactContribution) { + // The coefficient was admitted and computed once by the forward adapter. + // Reconstructing it here could disagree with the reverse objective. + if (!isHybridZ || partZ != exactContribution->first) + throw std::logic_error("exact seeded updateZ override changed a boundary weight; override exactBoundaryWeight instead"); + partZ_noED=PartitionArithmetic::check(partZ); + const Z_type weighted=PartitionArithmetic::multiply(partZ,exactContribution->second); + if (weighted==0) return false; + Zall=PartitionArithmetic::add(Zall,weighted); + return true; + } // check if something to be done if (Z_equal(partZ,0) || Z_isINF(Zall)) return false; @@ -150,6 +162,20 @@ updateCompleteZ( const size_t i1, const size_t j1 //////////////////////////////////////////////////////////////////////////// +void +PredictorMfeEns::updateExactCompleteZ(size_t i1,size_t j1,size_t i2,size_t j2, + Z_type hybrid,Z_type coefficient) +{ + const std::pair contribution(hybrid,coefficient); + struct Restore { + const std::pair * & slot; + const std::pair * previous; + ~Restore() { slot=previous; } + } restore{exactContribution,exactContribution}; + exactContribution=&contribution; + updateCompleteZ(i1,j1,i2,j2,hybrid,true); +} + void PredictorMfeEns:: updateOptimaUsingZ() diff --git a/src/IntaRNA/PredictorMfeEns.h b/src/IntaRNA/PredictorMfeEns.h index 2037d52f..c51fd654 100644 --- a/src/IntaRNA/PredictorMfeEns.h +++ b/src/IntaRNA/PredictorMfeEns.h @@ -61,6 +61,16 @@ class PredictorMfeEns : public PredictorMfe { //! map storing the partition of Zall for all considered interaction sites std::unordered_map Z_partition; + /** Checked exact-path update with the forward/outside boundary coefficient. + * Preserves virtual updateZ dispatch. Observing/delegating overrides work; + * reweighting must override the objective coefficient instead of partFunct. + */ + void updateExactCompleteZ(size_t i1, size_t j1, size_t i2, size_t j2, + Z_type hybrid, Z_type coefficient); + + //! scoped coefficient and hybrid expected by the checked complete update + const std::pair * exactContribution = nullptr; + //! whether updateZ() currently receives one complete boundary partition bool updateZisComplete; diff --git a/src/IntaRNA/PredictorMfeEns2dSeedExtension.cpp b/src/IntaRNA/PredictorMfeEns2dSeedExtension.cpp index d5adb5c4..00d67e1c 100644 --- a/src/IntaRNA/PredictorMfeEns2dSeedExtension.cpp +++ b/src/IntaRNA/PredictorMfeEns2dSeedExtension.cpp @@ -1,5 +1,7 @@ #include "IntaRNA/PredictorMfeEns2dSeedExtension.h" +#include "IntaRNA/SeededPartitionFunction.h" +#include "IntaRNA/PartitionArithmetic.h" namespace IntaRNA { @@ -17,7 +19,7 @@ PredictorMfeEns2dSeedExtension( , hybridZ_left( 0,0 ) , hybridZ_right( 0,0 ) { - assert( seedHandler.getConstraint().getBasePairs() > 1 ); + } ////////////////////////////////////////////////////////////////////////// @@ -33,6 +35,9 @@ void PredictorMfeEns2dSeedExtension:: predict( const IndexRange & r1, const IndexRange & r2 ) { + if (seedHandler.guaranteesStackOnlySeeds()) { predictStackSeeds(r1,r2); return; } + if (seedHandler.getConstraint().getBasePairs()<2) + throw std::invalid_argument("legacy bulged seed extension requires at least two seed pairs"); #if INTARNA_MULITHREADING #pragma omp critical(intarna_omp_logOutput) #endif @@ -130,6 +135,49 @@ predict( const IndexRange & r1, const IndexRange & r2 ) ////////////////////////////////////////////////////////////////////////// +Z_type +PredictorMfeEns2dSeedExtension::exactBoundaryWeight(size_t i1,size_t j1,size_t i2,size_t j2) const +{ + if (!isValidOutputSite(i1,j1,i2,j2)) return 0; + const E_type e=energy.getE(i1,j1,i2,j2,E_type(0)); + return E_isINF(e)?Z_type(0):PartitionArithmetic::exp(-E_2_Z(e)/energy.getRT()); +} + +void +PredictorMfeEns2dSeedExtension::predictStackSeeds(const IndexRange & r1,const IndexRange & r2) +{ + const size_t size1=energy.getAccessibility1().getSequence().size(); + const size_t size2=energy.getAccessibility2().getSequence().size(); + if (!r1.isAscending() || !r2.isAscending() || r1.from>=size1 || r2.from>=size2) + throw std::invalid_argument("exact seeded prediction: invalid region"); + energy.setOffset1(r1.from); energy.setOffset2(r2.from); + seedHandler.setOffset1(r1.from); seedHandler.setOffset2(r2.from); + const size_t n=r1.to==RnaSequence::lastPos?energy.size1():std::min(energy.size1(),r1.to-r1.from+1); + const size_t m=r2.to==RnaSequence::lastPos?energy.size2():std::min(energy.size2(),r2.to-r2.from+1); + initOptima(); initZ(); Zall=0; + if (seedHandler.fillSeed(0,n-1,0,m-1)==0) { + output.setExactPartition(true); + reportOptima(); return; + } + const size_t span1=std::min(n,energy.getAccessibility1().getMaxLength()); + const size_t span2=std::min(m,energy.getAccessibility2().getMaxLength()); + StackSeedDomain seeds(seedHandler,n,m,span1,span2); + using K=SeededPartitionFunction; + const K::Domain domain{n,m,span1,span2,energy.getMaxInternalLoopSize1(),energy.getMaxInternalLoopSize2(),output.getOutputConstraint().noLP}; + auto boltzmann=[&](E_type e) { return E_isINF(e)?Z_type(0):PartitionArithmetic::exp(-E_2_Z(e)/energy.getRT()); }; + K::Weights weights{ + [&](K::Pair p){return energy.isAccessible1(p[0]) && energy.isAccessible2(p[1]) && energy.areComplementary(p[0],p[1]);}, + [&](K::Pair){return boltzmann(energy.getE_init());}, + [&](K::Pair p,K::Pair q){return boltzmann(energy.getE_interLeft(p[0],q[0],p[1],q[1]));}, + [&](K::Pair p,K::Pair q){return exactBoundaryWeight(p[0],q[0],p[1],q[1]);}, + [&](K::Pair p,K::Pair q,Z_type h,Z_type b){updateExactCompleteZ(p[0],q[0],p[1],q[1],h,b);} + }; + const auto result=K::compute(domain,seeds,weights,false); + if (result.z!=Zall) throw std::logic_error("exact seeded updateZ override did not preserve the partition objective"); + output.setExactPartition(true); + reportOptima(); +} + E_type PredictorMfeEns2dSeedExtension:: getNonOverlappingEnergy( const size_t si1, const size_t si2, const size_t si1p, const size_t si2p ) { diff --git a/src/IntaRNA/PredictorMfeEns2dSeedExtension.h b/src/IntaRNA/PredictorMfeEns2dSeedExtension.h index 92107dac..d2591a01 100644 --- a/src/IntaRNA/PredictorMfeEns2dSeedExtension.h +++ b/src/IntaRNA/PredictorMfeEns2dSeedExtension.h @@ -73,6 +73,13 @@ class PredictorMfeEns2dSeedExtension: public PredictorMfeEns { protected: + /** Shared forward/outside objective coefficient. Override here for supported + * reweighting; return zero for forbidden boundaries. Coordinates are local. + * @return complete boundary Boltzmann factor (ED, dangles, ends, energyAdd) + */ + virtual Z_type exactBoundaryWeight(size_t i1,size_t j1,size_t i2,size_t j2) const; + /** Run the selected disjoint stack-seed partition backend. */ + void predictStackSeeds(const IndexRange & r1,const IndexRange & r2); //! access to the interaction energy handler of the super class using PredictorMfeEns::energy; diff --git a/src/bin/IntaRNA.cpp b/src/bin/IntaRNA.cpp index 555e0d02..ca60cf3d 100644 --- a/src/bin/IntaRNA.cpp +++ b/src/bin/IntaRNA.cpp @@ -335,6 +335,7 @@ int main(int argc, char **argv){ #endif {// update final output handler // copy partition function information if available + output->setExactPartition(bestInteractions.usesExactPartition()); output->incrementZ( bestInteractions.getZ() ); // Apply the energy window to the sequence pair's best candidate. // Independent per-region output retains each region's local window. diff --git a/tests/PredictorMfeEnsRegression_test.cpp b/tests/PredictorMfeEnsRegression_test.cpp index faf71ec2..e4f55379 100644 --- a/tests/PredictorMfeEnsRegression_test.cpp +++ b/tests/PredictorMfeEnsRegression_test.cpp @@ -231,7 +231,9 @@ TEST_CASE("ensemble predictor regressions", "[PredictorMfeEns]") { InspectableEnsemblePredictor exact( energy, exactOut, new SeedHandlerNoBulge(energy, seedConstraint)); exact.predict(); - REQUIRE(exact.getPartitionCount() > 0); + // The new exact stack backend streams each completed boundary once. + REQUIRE(exact.getPartitionCount() == 0); + REQUIRE(exact.getZall() > 0); exact.predict(IndexRange(0, 0), IndexRange(0, 0)); REQUIRE(exact.getPartitionCount() == 0); REQUIRE(exact.getZall() == 0.0); diff --git a/tests/PredictorSeedOracle_test.cpp b/tests/PredictorSeedOracle_test.cpp index 61e9e3ad..ae0e1df9 100644 --- a/tests/PredictorSeedOracle_test.cpp +++ b/tests/PredictorSeedOracle_test.cpp @@ -17,6 +17,7 @@ #include "IntaRNA/SeedHandlerMfe.h" #include +#include #include #include #include @@ -208,6 +209,8 @@ bool passesOutputConstraint(const InteractionEnergy & energy, } const SeedOraclePair & left = chain.front(); const SeedOraclePair & right = chain.back(); + if (right.i1-left.i1+1>energy.getAccessibility1().getMaxLength() + || right.i2-left.i2+1>energy.getAccessibility2().getMaxLength()) return false; if (constraint.noGUend && (energy.isGU(left.i1, left.i2) || energy.isGU(right.i1, right.i2))) @@ -665,3 +668,81 @@ TEST_CASE("tiny exhaustive seed oracle for exact predictor families", == Approx(seedOnlyExpected.partition).epsilon(1e-12)); } } + +#include "IntaRNA/AccessibilityBasePair.h" +#include "IntaRNA/InteractionEnergyVrna.h" +#include "IntaRNA/SeedHandlerNoBulge.h" +#include "IntaRNA/OutputHandlerHub.h" + +namespace { +class ExactSeedProbe : public PredictorMfeEns2dSeedExtension { +public: + using PredictorMfeEns2dSeedExtension::PredictorMfeEns2dSeedExtension; + std::map,Z_type> boundaries; + bool throwUpdate=false; + size_t calls=0; + bool restored() const { return exactContribution==nullptr && !updateZisComplete; } + size_t retained() const { return Z_partition.size(); } +protected: + void updateZ(size_t i,size_t j,size_t k,size_t l,Z_type z,bool hybrid) override { + ++calls; + if (throwUpdate) throw std::runtime_error("injected update failure"); + if (exactContribution) boundaries[{i,k,j,l}]=z*exactContribution->second; + PredictorMfeEns2dSeedExtension::updateZ(i,j,k,l,z,hybrid); + } +}; +void checkNativeStackPartition(const InteractionEnergy & energy,bool noLP,bool noGU) { + const SeedConstraint sc=makeSeedConstraint(2,0,0,0,false); + OutputConstraint oc(3,OutputConstraint::OVERLAP_BOTH,E_INF,E_INF,false,noLP,noGU,true,false); + IndexRange r1(0,energy.size1()-1), r2(0,energy.size2()-1); + auto oracle=enumerateSeededInteractions(energy,sc,oc,r1,r2); + OutputHandlerInteractionList output(oc,3); + ExactSeedProbe p(energy,output,nullptr,new SeedHandlerMfe(energy,sc)); + p.predict(); + REQUIRE(p.getZall()==Approx(oracle.unionPartition).epsilon(2e-12)); + REQUIRE(output.getZ()==p.getZall()); + REQUIRE(output.usesExactPartition()); + REQUIRE(p.retained()==0); + std::map,Z_type> expected; + for(const auto & i:oracle.interactions) expected[{i.chain.front().i1,i.chain.front().i2,i.chain.back().i1,i.chain.back().i2}]+=energy.getBoltzmannWeight(i.energy); + for(const auto & [b,z]:p.boundaries) REQUIRE(z==Approx(expected[b]).epsilon(2e-12)); + for(const auto & [b,z]:expected) REQUIRE(p.boundaries[b]==Approx(z).epsilon(2e-12)); +} +} + +TEST_CASE("native exact stacked partitions agree beyond the unique-anchor domain", "[PredictorSeedOracle][SeededPartitionFunction]") { + #include "testEasyLoggingSetup.icc" + RnaSequence t("t","GUGGCGC"),q("q","GCGCCAC"); + AccessibilityBasePair at(t,6,nullptr), aq(q,5,nullptr); + ReverseAccessibility ar(aq); + InteractionEnergyBasePair simple(at,ar,2,1); + VrnaHandler vrna; + InteractionEnergyVrna nearest(at,ar,vrna,2,1); + for(bool noLP:{false,true}) for(bool noGU:{false,true}) { + checkNativeStackPartition(simple,noLP,noGU); + checkNativeStackPartition(nearest,noLP,noGU); + } +} +TEST_CASE("exact seeded updates retain tiny weights and restore scopes on exceptions", "[PredictorSeedOracle][SeededPartitionFunction]") { + #include "testEasyLoggingSetup.icc" + RnaSequence t("t","GGGG"),q("q","CCCC"); + AccessibilityDisabled at(t,0,nullptr),aq(q,0,nullptr);ReverseAccessibility ar(aq); + InteractionEnergyBasePair energy(at,ar,2,2,false,1,-100,3,10000); + const auto sc=makeSeedConstraint(2,0,0,0,false); + const auto oc=makeOutputConstraint(false); + OutputHandlerInteractionList output(oc,1); + ExactSeedProbe p(energy,output,nullptr,new SeedHandlerMfe(energy,sc)); + p.throwUpdate=true;REQUIRE_THROWS(p.predict());REQUIRE(p.restored()); + p.throwUpdate=false;p.predict();REQUIRE(p.restored()); + REQUIRE(p.calls>0); + REQUIRE(p.getZall()>0); + REQUIRE(p.getZall()<1e-19); + REQUIRE(output.hasNonzeroZ()); + auto oracle=enumerateSeededInteractions(energy,sc,oc,IndexRange(0,3),IndexRange(0,3)); + REQUIRE(double(p.getZall()/oracle.unionPartition)==Approx(1).epsilon(2e-12)); + OutputHandlerHub hub(oc,false);hub.addOutputHandler(&output);hub.setExactPartition(true); + REQUIRE(output.usesExactPartition()); + p.predict(IndexRange(1,3),IndexRange(1,3)); + auto sub=enumerateSeededInteractions(energy,sc,oc,IndexRange(1,3),IndexRange(1,3)); + REQUIRE(double(p.getZall()/sub.unionPartition)==Approx(1).epsilon(2e-12)); +} From 99919de070e3c4db8f92f172872b6e2d6409ec21 Mon Sep 17 00:00:00 2001 From: AlexanderMitrofanov Date: Thu, 8 Oct 2026 14:08:58 +0200 Subject: [PATCH 06/21] feat: accumulate raw pair probabilities across regions (step 5) --- ChangeLog | 10 +++ src/IntaRNA/BasePairProbabilities.cpp | 63 +++++++++++++++++++ src/IntaRNA/BasePairProbabilities.h | 62 ++++++++++++++++++ src/IntaRNA/Makefile.am | 2 + .../PredictorMfeEns2dSeedExtension.cpp | 33 +++++++--- src/IntaRNA/PredictorMfeEns2dSeedExtension.h | 9 ++- tests/BasePairProbabilities_test.cpp | 33 ++++++++++ tests/Makefile.am | 1 + tests/PredictorSeedOracle_test.cpp | 52 +++++++++++++++ 9 files changed, 255 insertions(+), 10 deletions(-) create mode 100644 src/IntaRNA/BasePairProbabilities.cpp create mode 100644 src/IntaRNA/BasePairProbabilities.h create mode 100644 tests/BasePairProbabilities_test.cpp diff --git a/ChangeLog b/ChangeLog index 72fef34c..7a3e8406 100644 --- a/ChangeLog +++ b/ChangeLog @@ -42,6 +42,9 @@ ## Technical changes and Optimizations +- collect raw actual-pair masses and disjoint regional denominators with explicit + successful-empty/nonempty/failed lifecycle (issue #257, step 5) + - count each exact stack-seeded interaction once; preserve tiny positive totals through complete updates and output forwarding (issue #257, step 4) @@ -145,6 +148,13 @@ energies, restricted partition sums, and trackers. ################################################################################ ################################################################################ +261008 Alexander Mitrofanov + * BasePairProbabilities, PredictorMfeEns2dSeedExtension, API tests, Makefile.am : + + add optional non-owning pair sink, original-coordinate raw regional commits + and explicit success-only finalization; reject overlap and range failures + + verify tracker parity, offsets, region crossings and injected failure after + a successful region; pair-only computation retains no boundary map (PR #258, step 5) + 261008 Alexander Mitrofanov * PredictorMfeEns*, OutputHandler*, IntaRNA.cpp, predictor oracle tests : + use the suffix kernel on the exact stack-only path, preserving virtual diff --git a/src/IntaRNA/BasePairProbabilities.cpp b/src/IntaRNA/BasePairProbabilities.cpp new file mode 100644 index 00000000..49d4e851 --- /dev/null +++ b/src/IntaRNA/BasePairProbabilities.cpp @@ -0,0 +1,63 @@ +#include "IntaRNA/BasePairProbabilities.h" +#include "IntaRNA/PartitionArithmetic.h" +#include +#include + +namespace IntaRNA { +BasePairProbabilities::BasePairProbabilities(size_t n,size_t m):mass(n,m,0) {} +void BasePairProbabilities::addRegion(const IndexRange & t,const IndexRange & q, + Z_type denominator,const Matrix & values) +{ + using A=PartitionArithmetic; + try { + if (state!=Status::pending) throw std::logic_error("pair probabilities: accumulator is not pending"); + if (!t.isAscending() || !q.isAscending() || t.to>=mass.size1() || q.to>=mass.size2() + || values.size1()!=t.to-t.from+1 || values.size2()!=q.to-q.from+1) + throw std::invalid_argument("pair probabilities: invalid region dimensions"); + for (const auto & r:regions) + if (t.from<=r.first.to && r.first.from<=t.to && q.from<=r.second.to && r.second.from<=q.to) + throw std::invalid_argument("pair probabilities: searched regions overlap"); + const Z_type merged=A::add(z,denominator); + for (size_t i=0;i BasePairProbabilities::probabilities() const { + using A=PartitionArithmetic; + if (state!=Status::nonempty) throw std::logic_error("pair probabilities: no successful nonempty result"); + Matrix p(mass.size1(),mass.size2(),0); + // Only roundoff-sized endpoint correction is allowed. Bound scales with + // matrix dimensions, at 512 ulps per row/column element (tested with oracles). + const Z_type tolerance=512*std::numeric_limits::epsilon() + *Z_type(std::max(size_t(1),mass.size1()+mass.size2())); + std::vector columns(mass.size2(),0); + for(size_t i=0;i1+tolerance) throw std::logic_error("pair probabilities: pair mass exceeds denominator"); + value=std::min(Z_type(1),value); + p(i,j)=value;row=A::add(row,value);columns[j]=A::add(columns[j],value); + } + if(row>1+tolerance) throw std::logic_error("pair probabilities: target exclusivity violated"); + } + for(auto c:columns) if(c>1+tolerance) throw std::logic_error("pair probabilities: query exclusivity violated"); + return p; +} +void BasePairProbabilities::finalize() { + try { + if(state!=Status::pending) throw std::logic_error("pair probabilities: completion requires a pending result"); + PartitionArithmetic::check(z); + state=z==0?Status::empty:Status::nonempty; + if(z>0) probabilities(); // validate all entries before a writer can observe success + } catch (...) { fail();throw; } +} +} diff --git a/src/IntaRNA/BasePairProbabilities.h b/src/IntaRNA/BasePairProbabilities.h new file mode 100644 index 00000000..73d30825 --- /dev/null +++ b/src/IntaRNA/BasePairProbabilities.h @@ -0,0 +1,62 @@ +#ifndef INTARNA_BASEPAIRPROBABILITIES_H_ +#define INTARNA_BASEPAIRPROBABILITIES_H_ +#include "IntaRNA/general.h" +#include "IntaRNA/IndexRange.h" +#include "IntaRNA/Matrix.h" +#include +#include + +namespace IntaRNA { +/** Success-only accumulator for one target/query pair. Raw numerators and Z are + * merged over disjoint searched rectangles, then normalized explicitly. All + * stored coordinates follow the original sequences' 5'-to-3' order. This is + * conditional on an allowed interaction, without an unbound-state contribution. + * A destructor never publishes data. Not thread safe: use one owner per pair. + */ +class BasePairProbabilities { +public: + /** Pending accumulation, successful nonempty/empty completion, or failure. */ + enum class Status { pending, nonempty, empty, failed }; + /** Allocate raw masses for the full original target/query sequences. + * @param targetLength number of target positions + * @param queryLength number of query positions + */ + BasePairProbabilities(size_t targetLength,size_t queryLength); + /** Commit one completed region, after validating ALL sums and disjointness. + * @param target inclusive original target region + * @param query inclusive original query region + * @param denominator raw region Z + * @param masses raw region numerators in original orientation (local indices) + * @throws on invalid/overlapping regions or numerical failure, marking failed + */ + void addRegion(const IndexRange & target,const IndexRange & query, + Z_type denominator,const Matrix & masses); + /** Finalize only after all requested regions succeeded; validate normalized + * masses, row/column exclusivity and numerical range before publication. + * @throws on failed computation or inconsistent masses + */ + void finalize(); + /** Mark this pair failed after any error or cancellation. */ + void fail() noexcept; + /** @return explicit lifecycle status */ + Status status() const; + /** @return the raw merged denominator (not usable as a result after failure) */ + Z_type getZ() const; + /** @return raw merged pair numerators (original coordinates) */ + const Matrix & rawMasses() const; + /** @return validated matrix; only available for finalized nonempty results. + * Successful empty output is represented by status()==empty, not zeroes. + */ + Matrix probabilities() const; +private: + Status state=Status::pending; + Z_type z=0; + Matrix mass; + std::vector> regions; +}; +inline BasePairProbabilities::Status BasePairProbabilities::status() const { return state; } +inline Z_type BasePairProbabilities::getZ() const { return z; } +inline const Matrix & BasePairProbabilities::rawMasses() const { return mass; } +inline void BasePairProbabilities::fail() noexcept { state=Status::failed; } +} +#endif diff --git a/src/IntaRNA/Makefile.am b/src/IntaRNA/Makefile.am index 4e37bc30..253db1d5 100644 --- a/src/IntaRNA/Makefile.am +++ b/src/IntaRNA/Makefile.am @@ -28,6 +28,7 @@ libIntaRNA_a_HEADERS = \ intarna_config.h \ Matrix.h \ StackSeedDomain.h \ + BasePairProbabilities.h \ PartitionArithmetic.h \ SeededPartitionFunction.h \ Accessibility.h \ @@ -102,6 +103,7 @@ libIntaRNA_a_HEADERS = \ # the sources to add to the library and to add to the source distribution libIntaRNA_a_SOURCES = \ StackSeedDomain.cpp \ + BasePairProbabilities.cpp \ SeededPartitionFunction.cpp \ $(libmylib_a_HEADERS) \ Accessibility.cpp \ diff --git a/src/IntaRNA/PredictorMfeEns2dSeedExtension.cpp b/src/IntaRNA/PredictorMfeEns2dSeedExtension.cpp index 00d67e1c..4f50a61e 100644 --- a/src/IntaRNA/PredictorMfeEns2dSeedExtension.cpp +++ b/src/IntaRNA/PredictorMfeEns2dSeedExtension.cpp @@ -12,14 +12,17 @@ PredictorMfeEns2dSeedExtension( const InteractionEnergy & energy , OutputHandler & output , PredictionTracker * predTracker - , SeedHandler * seedHandlerInstance ) + , SeedHandler * seedHandlerInstance + , BasePairProbabilities * pairProbabilities ) : PredictorMfeEns(energy,output,predTracker) + , pairProbabilities(pairProbabilities) , seedHandler(seedHandlerInstance) , hybridZ_left( 0,0 ) , hybridZ_right( 0,0 ) { - + if (pairProbabilities && (!seedHandler.guaranteesStackOnlySeeds() || !output.getOutputConstraint().needZall)) + throw std::invalid_argument("pair probabilities require a stack-only exact predictor and needZall"); } ////////////////////////////////////////////////////////////////////////// @@ -35,7 +38,11 @@ void PredictorMfeEns2dSeedExtension:: predict( const IndexRange & r1, const IndexRange & r2 ) { - if (seedHandler.guaranteesStackOnlySeeds()) { predictStackSeeds(r1,r2); return; } + if (seedHandler.guaranteesStackOnlySeeds()) { + try { predictStackSeeds(r1,r2); } + catch (...) { if (pairProbabilities) pairProbabilities->fail(); throw; } + return; + } if (seedHandler.getConstraint().getBasePairs()<2) throw std::invalid_argument("legacy bulged seed extension requires at least two seed pairs"); #if INTARNA_MULITHREADING @@ -155,13 +162,11 @@ PredictorMfeEns2dSeedExtension::predictStackSeeds(const IndexRange & r1,const In const size_t n=r1.to==RnaSequence::lastPos?energy.size1():std::min(energy.size1(),r1.to-r1.from+1); const size_t m=r2.to==RnaSequence::lastPos?energy.size2():std::min(energy.size2(),r2.to-r2.from+1); initOptima(); initZ(); Zall=0; - if (seedHandler.fillSeed(0,n-1,0,m-1)==0) { - output.setExactPartition(true); - reportOptima(); return; - } + const size_t seedCount=seedHandler.fillSeed(0,n-1,0,m-1); const size_t span1=std::min(n,energy.getAccessibility1().getMaxLength()); const size_t span2=std::min(m,energy.getAccessibility2().getMaxLength()); - StackSeedDomain seeds(seedHandler,n,m,span1,span2); + StackSeedDomain seeds=seedCount ? StackSeedDomain(seedHandler,n,m,span1,span2) + : StackSeedDomain(std::vector(),n,m,span1,span2); using K=SeededPartitionFunction; const K::Domain domain{n,m,span1,span2,energy.getMaxInternalLoopSize1(),energy.getMaxInternalLoopSize2(),output.getOutputConstraint().noLP}; auto boltzmann=[&](E_type e) { return E_isINF(e)?Z_type(0):PartitionArithmetic::exp(-E_2_Z(e)/energy.getRT()); }; @@ -172,10 +177,20 @@ PredictorMfeEns2dSeedExtension::predictStackSeeds(const IndexRange & r1,const In [&](K::Pair p,K::Pair q){return exactBoundaryWeight(p[0],q[0],p[1],q[1]);}, [&](K::Pair p,K::Pair q,Z_type h,Z_type b){updateExactCompleteZ(p[0],q[0],p[1],q[1],h,b);} }; - const auto result=K::compute(domain,seeds,weights,false); + const auto result=K::compute(domain,seeds,weights,pairProbabilities!=nullptr); if (result.z!=Zall) throw std::logic_error("exact seeded updateZ override did not preserve the partition objective"); output.setExactPartition(true); reportOptima(); + if (pairProbabilities) { + const auto first=energy.getBasePair(0,0), last=energy.getBasePair(n-1,m-1); + const IndexRange target(first.first,last.first), query(last.second,first.second); + Matrix original(n,m,0); + for(size_t i=0;iaddRegion(target,query,result.z,original); + } } E_type diff --git a/src/IntaRNA/PredictorMfeEns2dSeedExtension.h b/src/IntaRNA/PredictorMfeEns2dSeedExtension.h index d2591a01..e046de5b 100644 --- a/src/IntaRNA/PredictorMfeEns2dSeedExtension.h +++ b/src/IntaRNA/PredictorMfeEns2dSeedExtension.h @@ -3,6 +3,7 @@ #define INTARNA_PREDICTORMFEENS2DSEEDEXTENSION_H_ #include "IntaRNA/PredictorMfeEns.h" +#include "IntaRNA/BasePairProbabilities.h" #include "IntaRNA/Matrix.h" #include "IntaRNA/SeedHandlerIdxOffset.h" @@ -38,13 +39,16 @@ class PredictorMfeEns2dSeedExtension: public PredictorMfeEns { * @param predTracker the prediction tracker to be used or NULL if no * tracking is to be done; if non-NULL, the tracker gets deleted * on this->destruction. + * @param pairProbabilities optional non-owning sink; must outlive predictions + * and remain pending until all disjoint regions have succeeded * @param seedHandler the seed handler to be used */ PredictorMfeEns2dSeedExtension( const InteractionEnergy & energy , OutputHandler & output , PredictionTracker * predTracker - , SeedHandler * seedHandler ); + , SeedHandler * seedHandler + , BasePairProbabilities * pairProbabilities = nullptr ); /** @@ -81,6 +85,9 @@ class PredictorMfeEns2dSeedExtension: public PredictorMfeEns { /** Run the selected disjoint stack-seed partition backend. */ void predictStackSeeds(const IndexRange & r1,const IndexRange & r2); + //! optional sequence-pair owner, never deleted or finalized by the predictor + BasePairProbabilities * pairProbabilities; + //! access to the interaction energy handler of the super class using PredictorMfeEns::energy; diff --git a/tests/BasePairProbabilities_test.cpp b/tests/BasePairProbabilities_test.cpp new file mode 100644 index 00000000..c53671ba --- /dev/null +++ b/tests/BasePairProbabilities_test.cpp @@ -0,0 +1,33 @@ +#include "catch.hpp" +#include "IntaRNA/BasePairProbabilities.h" +using namespace IntaRNA; +TEST_CASE("raw pair regions commit once and finalize only on success", "[BasePairProbabilities]") { + BasePairProbabilities r(4,5); + Matrix m(2,2,0);m(0,1)=2;m(1,0)=2; + r.addRegion({0,1},{1,2},2,m); + REQUIRE_THROWS(r.probabilities()); + r.addRegion({2,3},{3,4},2,m); + r.finalize(); + REQUIRE(r.getZ()==4); + REQUIRE(r.status()==BasePairProbabilities::Status::nonempty); + auto p=r.probabilities(); + REQUIRE(p(0,2)==.5);REQUIRE(p(3,3)==.5);REQUIRE(p(0,4)==0); + BasePairProbabilities empty(1,1);empty.finalize(); + REQUIRE(empty.status()==BasePairProbabilities::Status::empty); + BasePairProbabilities overlap(4,5);overlap.addRegion({0,1},{1,2},2,m); + REQUIRE_THROWS(overlap.addRegion({1,2},{2,3},2,m)); + REQUIRE(overlap.status()==BasePairProbabilities::Status::failed); + REQUIRE(overlap.getZ()==2);REQUIRE_THROWS(overlap.finalize()); + BasePairProbabilities cancelled(4,5);cancelled.addRegion({0,1},{1,2},2,m);cancelled.fail(); + REQUIRE_THROWS(cancelled.finalize());REQUIRE_THROWS(cancelled.probabilities()); +} +TEST_CASE("pair result rejects inconsistent and out-of-range numerical results", "[BasePairProbabilities]") { + Matrix m(1,1,1e-100);BasePairProbabilities tiny(1,1); + tiny.addRegion({0,0},{0,0},1e-100,m);tiny.finalize();REQUIRE(tiny.probabilities()(0,0)==1); + m(0,0)=2;BasePairProbabilities excess(1,1);excess.addRegion({0,0},{0,0},1,m); + REQUIRE_THROWS(excess.finalize());REQUIRE(excess.status()==BasePairProbabilities::Status::failed); + m(0,0)=std::numeric_limits::max();BasePairProbabilities overflow(2,1); + overflow.addRegion({0,0},{0,0},m(0,0),m); + REQUIRE_THROWS(overflow.addRegion({1,1},{0,0},m(0,0),m)); + REQUIRE(overflow.status()==BasePairProbabilities::Status::failed); +} diff --git a/tests/Makefile.am b/tests/Makefile.am index ebbc88ca..023ad135 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -28,6 +28,7 @@ runApiTests_SOURCES = \ SeededStackKernel.h \ SeededPartitionFunction_test.cpp \ StackSeedDomain_test.cpp \ + BasePairProbabilities_test.cpp \ testEasyLoggingSetup.icc \ AccessibilityConstraint_test.cpp \ AccessibilityFromStream_test.cpp \ diff --git a/tests/PredictorSeedOracle_test.cpp b/tests/PredictorSeedOracle_test.cpp index ae0e1df9..530ba836 100644 --- a/tests/PredictorSeedOracle_test.cpp +++ b/tests/PredictorSeedOracle_test.cpp @@ -746,3 +746,55 @@ TEST_CASE("exact seeded updates retain tiny weights and restore scopes on except auto sub=enumerateSeededInteractions(energy,sc,oc,IndexRange(1,3),IndexRange(1,3)); REQUIRE(double(p.getZall()/sub.unionPartition)==Approx(1).epsilon(2e-12)); } + +namespace { +class PairTestTracker : public PredictionTracker { +public: + void updateOptimumCalled(size_t,size_t,size_t,size_t,E_type) override {} +}; +} +TEST_CASE("raw native pair masses share the exact forward denominator", "[BasePairProbabilities][PredictorSeedOracle]") { + #include "testEasyLoggingSetup.icc" + RnaSequence t("target","GGAGGG"),q("query","CCUCCC"); + AccessibilityBasePair at(t,5,nullptr),aq(q,4,nullptr);ReverseAccessibility ar(aq); + InteractionEnergyBasePair energy(at,ar,2,1); + const auto sc=makeSeedConstraint(2,0,0,0,false); + for(bool noLP:{false,true}) for(bool tracker:{false,true}) { + auto oc=makeOutputConstraint(noLP); + BasePairProbabilities result(t.size(),q.size()); + OutputHandlerInteractionList output(oc,1); + ExactSeedProbe p(energy,output,tracker?new PairTestTracker():nullptr,new SeedHandlerMfe(energy,sc),&result); + const IndexRange r1(1,5),r2(1,4); + p.predict(r1,r2);result.finalize(); + auto oracle=enumerateSeededInteractions(energy,sc,oc,r1,r2); + REQUIRE(result.getZ()==p.getZall()); + REQUIRE(result.getZ()==Approx(oracle.unionPartition).epsilon(2e-12)); + REQUIRE((p.retained()>0)==tracker); + Matrix expected(t.size(),q.size(),0); + for(const auto & chain:oracle.interactions) for(const auto & pair:chain.chain) { + const auto bp=energy.getBasePair(pair.i1,pair.i2); + expected(bp.first,bp.second)+=energy.getBoltzmannWeight(chain.energy); + } + for(size_t i=0;i Date: Thu, 8 Oct 2026 14:19:49 +0200 Subject: [PATCH 07/21] feat: expose exact actual-pair probability output (step 6) --- ChangeLog | 12 +++ src/IntaRNA/BasePairProbabilityWriter.cpp | 59 +++++++++++ src/IntaRNA/BasePairProbabilityWriter.h | 39 ++++++++ src/IntaRNA/Makefile.am | 2 + src/IntaRNA/OutputHandler.h | 10 +- src/IntaRNA/PredictorMfe.cpp | 2 + src/IntaRNA/SeedHandlerExplicit.cpp | 9 +- src/bin/CommandLineParsing.cpp | 31 +++++- src/bin/CommandLineParsing.h | 11 +- src/bin/IntaRNA.cpp | 19 +++- tests/BasePairProbabilities_test.cpp | 17 ++++ tests/Makefile.am | 4 +- tests/PredictorSeedOracle_test.cpp | 22 ++++ tests/StackSeedDomain_test.cpp | 22 ++++ tests/runBasePairProbabilities.sh | 4 + tests/testBasePairProbabilities.py | 117 ++++++++++++++++++++++ 16 files changed, 371 insertions(+), 9 deletions(-) create mode 100644 src/IntaRNA/BasePairProbabilityWriter.cpp create mode 100644 src/IntaRNA/BasePairProbabilityWriter.h create mode 100644 tests/runBasePairProbabilities.sh create mode 100644 tests/testBasePairProbabilities.py diff --git a/ChangeLog b/ChangeLog index 7a3e8406..f876d0e8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,6 +14,10 @@ ## Interface and handling +- --out=bpProb:FILE writes actual-pair conditional probabilities for exact + model P/mode M stack-seed ensembles, with disjoint-region merging, original + coordinates and success-only publication (issue #257, implementation step 6) + - deterministic kinetic seed extension with --model=X --mode=K and configurable local scoring; complete-energy downhill steps, atomic noLP loop/stack moves and retained greedy traceback; equilibrium probability output is unsupported @@ -148,6 +152,14 @@ energies, restricted partition sums, and trackers. ################################################################################ ################################################################################ +261008 Alexander Mitrofanov + * BasePairProbabilityWriter, CommandLineParsing, IntaRNA.cpp, CLI/API tests : + + add bpProb matrix output, capability/mode validation, multi-FASTA naming, + gzip and synchronized standard-stream blocks; preserve spot coverage + + guard OpenMP cancellation before publication, propagate write errors, keep + tiny totals, support ranked count zero and mixed explicit seeds in debug + validation (PR #258, step 6) + 261008 Alexander Mitrofanov * BasePairProbabilities, PredictorMfeEns2dSeedExtension, API tests, Makefile.am : + add optional non-owning pair sink, original-coordinate raw regional commits diff --git a/src/IntaRNA/BasePairProbabilityWriter.cpp b/src/IntaRNA/BasePairProbabilityWriter.cpp new file mode 100644 index 00000000..d0aea7af --- /dev/null +++ b/src/IntaRNA/BasePairProbabilityWriter.cpp @@ -0,0 +1,59 @@ +#include "IntaRNA/BasePairProbabilityWriter.h" +#include +#include +#include +#include +#include + +namespace IntaRNA { +std::string BasePairProbabilityWriter::block(const BasePairProbabilities & result, + const RnaSequence & target,const RnaSequence & query,const std::string & sep) +{ + const bool empty=result.status()==BasePairProbabilities::Status::empty; + if (!empty && result.status()!=BasePairProbabilities::Status::nonempty) + throw std::logic_error("bpProb output requires successful explicit finalization"); + if (result.rawMasses().size1()!=target.size() || result.rawMasses().size2()!=query.size()) + throw std::invalid_argument("bpProb output sequence dimensions do not match result"); + // Validate every normalized value before opening a file or writing a header. + const auto p=empty?Matrix():result.probabilities(); + std::ostringstream data; + data<::max_digits10)<<"bpProb"; + for(size_t j=0;j file(out==&std::cout || out==&std::cerr?nullptr:out); + emit(*out,data); + if(auto filtered=dynamic_cast(out)) filtered->reset(); +} +} diff --git a/src/IntaRNA/BasePairProbabilityWriter.h b/src/IntaRNA/BasePairProbabilityWriter.h new file mode 100644 index 00000000..48578daf --- /dev/null +++ b/src/IntaRNA/BasePairProbabilityWriter.h @@ -0,0 +1,39 @@ +#ifndef INTARNA_BASEPAIRPROBABILITYWRITER_H_ +#define INTARNA_BASEPAIRPROBABILITYWRITER_H_ +#include "IntaRNA/BasePairProbabilities.h" +#include "IntaRNA/RnaSequence.h" +#include +#include + +namespace IntaRNA { +/** Explicit writer for a completed actual-pair matrix, independent of trackers. + * Whole blocks are synchronized for shared streams. No destructor emits data. + */ +class BasePairProbabilityWriter { +public: + /** Validate and write one matrix with original 5'-to-3' nucleotide/index labels. + * @param out destination stream; an I/O failure throws + * @param result explicitly finalized raw result + * @param target original target sequence + * @param query original query sequence + * @param separator CSV-style separator, shared with ordinary output + */ + static void write(std::ostream & out,const BasePairProbabilities & result, + const RnaSequence & target,const RnaSequence & query,const std::string & separator=";"); + /** Write to a filename or STDOUT/STDERR, using existing gzip stream support. + * Checks stream flush and explicit close; does not publish pending/failed data. + * @param filename destination (already expanded for multi-FASTA) + * @param result finalized raw result + * @param target original target sequence + * @param query original query sequence + * @param separator CSV-style separator + */ + static void writeFile(const std::string & filename,const BasePairProbabilities & result, + const RnaSequence & target,const RnaSequence & query,const std::string & separator=";"); +private: + static std::string block(const BasePairProbabilities & result,const RnaSequence & target, + const RnaSequence & query,const std::string & separator); + static void emit(std::ostream & out,const std::string & data); +}; +} +#endif diff --git a/src/IntaRNA/Makefile.am b/src/IntaRNA/Makefile.am index 253db1d5..4fc5db3e 100644 --- a/src/IntaRNA/Makefile.am +++ b/src/IntaRNA/Makefile.am @@ -29,6 +29,7 @@ libIntaRNA_a_HEADERS = \ Matrix.h \ StackSeedDomain.h \ BasePairProbabilities.h \ + BasePairProbabilityWriter.h \ PartitionArithmetic.h \ SeededPartitionFunction.h \ Accessibility.h \ @@ -104,6 +105,7 @@ libIntaRNA_a_HEADERS = \ libIntaRNA_a_SOURCES = \ StackSeedDomain.cpp \ BasePairProbabilities.cpp \ + BasePairProbabilityWriter.cpp \ SeededPartitionFunction.cpp \ $(libmylib_a_HEADERS) \ Accessibility.cpp \ diff --git a/src/IntaRNA/OutputHandler.h b/src/IntaRNA/OutputHandler.h index 9f925ade..2e6aefe6 100644 --- a/src/IntaRNA/OutputHandler.h +++ b/src/IntaRNA/OutputHandler.h @@ -8,6 +8,7 @@ #include "IntaRNA/InteractionRange.h" #include "IntaRNA/OutputConstraint.h" #include +#include namespace IntaRNA { @@ -193,11 +194,16 @@ incrementZ( const Z_type subZ ) LOG(WARNING) <<"OutputHandler::incrementZ() : partition function overflow! Recompile with larger partition function data type!"; } #endif - // increment partition function + // Capture range failures within the OpenMP structured block. + std::exception_ptr failure; #if INTARNA_MULITHREADING #pragma omp critical(intarna_omp_outputHandlerIncrementZ) #endif - {Z = exactPartition ? PartitionArithmetic::add(Z,subZ) : Z+subZ;} + { + try { Z = exactPartition ? PartitionArithmetic::add(Z,subZ) : Z+subZ; } + catch (...) { failure=std::current_exception(); } + } + if (failure) std::rethrow_exception(failure); } //////////////////////////////////////////////////////////////////////////// diff --git a/src/IntaRNA/PredictorMfe.cpp b/src/IntaRNA/PredictorMfe.cpp index 91792bea..ac6ec7ca 100644 --- a/src/IntaRNA/PredictorMfe.cpp +++ b/src/IntaRNA/PredictorMfe.cpp @@ -215,6 +215,8 @@ reportOptima() output.incrementZ( getZall() ); } + // A zero ranked-output count still publishes ensemble statistics. + if (mfeInteractions.empty()) return; // temporary access const OutputConstraint & outConstraint = output.getOutputConstraint(); // number of reported interactions diff --git a/src/IntaRNA/SeedHandlerExplicit.cpp b/src/IntaRNA/SeedHandlerExplicit.cpp index 5c38fde3..7deb8b2c 100644 --- a/src/IntaRNA/SeedHandlerExplicit.cpp +++ b/src/IntaRNA/SeedHandlerExplicit.cpp @@ -86,7 +86,14 @@ getSeedMinBP( const std::string & seedEncoding ) size_t minBP = 99999; if (!seedEncoding.empty()) { #if INTARNA_IN_DEBUG_MODE - if (!checkSeedEncoding(seedEncoding).empty()) throw std::runtime_error("SeedHandlerExplicit::getSeedMinBP() : no valid seed encoding : "+checkSeedEncoding(seedEncoding)); + size_t begin=0; + while(begin::getUnescaped( outSep ); + if (hasBasePairProbabilityOutput()) { + if (model.val!='P' || mode.val!='M' || noSeedRequired || !rri.empty() || windowWidth.val!=0) + throw error("bpProb requires --model=P --mode=M with stack-only seeds and no windows"); + outNeedsZall=true; + } // K needs a seed even before the usual --noSeed model normalization. if (mode.val == 'K') { if (model.val != 'X') throw error("--mode=K is available only with --model=X"); @@ -1573,6 +1580,9 @@ parse(int argc, char** argv) if (c1->second.empty()) { continue; } for (auto c2=c1; noDuplicate && (++c2)!=outPrefix2streamName.end();) { if ( ! c2->second.empty() && boost::iequals( c1->second, c2->second ) ) { + // Pair matrices emit synchronized complete blocks on shared standard streams. + if ((c1->first==OP_bpProb || c2->first==OP_bpProb) + && (boost::iequals(c1->second,"STDOUT") || boost::iequals(c1->second,"STDERR"))) continue; noDuplicate = false; throw error("--out argument shows multiple times '"+toString(c1->second)+"' as target file/stream."); } @@ -2478,10 +2488,27 @@ getTemperature() const { //////////////////////////////////////////////////////////////////////////// +bool CommandLineParsing::hasBasePairProbabilityOutput() const { + return !outPrefix2streamName.at(OutPrefixCode::OP_bpProb).empty(); +} +void CommandLineParsing::writeBasePairProbabilities(const BasePairProbabilities & result,const InteractionEnergy & energy) const { + const auto & t=energy.getAccessibility1().getSequence(); + const auto & q=energy.getAccessibility2().getAccessibilityOrigin().getSequence(); + BasePairProbabilityWriter::writeFile(getFullFilename(outPrefix2streamName.at(OutPrefixCode::OP_bpProb),&t,&q),result,t,q,outSep); +} + Predictor* CommandLineParsing:: -getPredictor( const InteractionEnergy & energy, OutputHandler & output ) const +getPredictor( const InteractionEnergy & energy, OutputHandler & output, BasePairProbabilities * pairProbabilities ) const { + std::unique_ptr pairSeeds; + if (pairProbabilities) { + if(model.val!='P' || mode.val!='M' || noSeedRequired || !rri.empty() || windowWidth.val!=0) + throw std::invalid_argument("bpProb requires --model=P --mode=M with stack-only seeds and no windows"); + pairSeeds.reset(getSeedHandler(energy)); + if(!pairSeeds->guaranteesStackOnlySeeds()) + throw std::invalid_argument("bpProb requires a stack-only seed handler; bulged seeds are unsupported"); + } // set up hub for prediction tracking (if needed) PredictionTrackerHub * predTracker = new PredictionTrackerHub(); @@ -2627,7 +2654,7 @@ getPredictor( const InteractionEnergy & energy, OutputHandler & output ) const case 'P' : { switch ( mode.val ) { case 'H' : return new PredictorMfeEns2dHeuristicSeedExtension( energy, output, predTracker, getSeedHandler( energy ) ); - case 'M' : return new PredictorMfeEns2dSeedExtension( energy, output, predTracker, getSeedHandler( energy ) ); + case 'M' : return new PredictorMfeEns2dSeedExtension( energy, output, predTracker, pairSeeds ? pairSeeds.release() : getSeedHandler( energy ), pairProbabilities ); case 'S' : return new PredictorMfeEnsSeedOnly( energy, output, predTracker, getSeedHandler(energy) ); default : INTARNA_NOT_IMPLEMENTED("mode "+toString(mode.val)+" not available for model "+toString(model.val)); } diff --git a/src/bin/CommandLineParsing.h b/src/bin/CommandLineParsing.h index f6658728..efcc3c11 100644 --- a/src/bin/CommandLineParsing.h +++ b/src/bin/CommandLineParsing.h @@ -26,6 +26,7 @@ #include "IntaRNA/Predictor.h" #include "IntaRNA/SeedConstraint.h" #include "IntaRNA/SeedHandler.h" +#include "IntaRNA/BasePairProbabilities.h" #include "IntaRNA/SeedHandlerExplicit.h" #include "IntaRNA/PredictionTrackerSpotProb.h" #include "IntaRNA/VrnaHandler.h" @@ -281,11 +282,17 @@ class CommandLineParsing { * parameters * @param energy the interaction energy handler to be used * @param output the output handler to be used + * @param pairProbabilities optional non-owning raw result sink for exact stack seeds * @return the newly allocated Predictor object to be deleted by the calling * function */ Predictor* getPredictor( const InteractionEnergy & energy - , OutputHandler & output ) const; + , OutputHandler & output, BasePairProbabilities * pairProbabilities = nullptr ) const; + + /** @return whether actual base-pair matrix output was requested */ + bool hasBasePairProbabilityOutput() const; + /** Publish a successful sequence-pair result using ordinary filename rules. */ + void writeBasePairProbabilities(const BasePairProbabilities & result,const InteractionEnergy & energy) const; /** * Provides the seed constraint according to the user settings @@ -404,6 +411,7 @@ class CommandLineParsing { OP_tPu, OP_spotProb, OP_spotProbAll, + OP_bpProb, OP_UNKNOWN }; @@ -430,6 +438,7 @@ class CommandLineParsing { if (prefLC == "tacc") { return OutPrefixCode::OP_tAcc; } else if (prefLC == "qpu") { return OutPrefixCode::OP_qPu; } else if (prefLC == "tpu") { return OutPrefixCode::OP_tPu; } else + if (prefLC == "bpprob") { return OutPrefixCode::OP_bpProb; } else if (prefLC == "spotprob") { return OutPrefixCode::OP_spotProb; } else // not known return OutPrefixCode::OP_UNKNOWN; diff --git a/src/bin/IntaRNA.cpp b/src/bin/IntaRNA.cpp index ca60cf3d..15d02b8c 100644 --- a/src/bin/IntaRNA.cpp +++ b/src/bin/IntaRNA.cpp @@ -243,6 +243,11 @@ int main(int argc, char **argv){ (parameters.reportBestPerRegion() ? std::numeric_limits::max() : 1 ) * parameters.getOutputConstraint(*energy).reportMax ); + // One owner spans all disjoint searched regions for this sequence pair. + std::unique_ptr pairProbabilities; + if (parameters.hasBasePairProbabilityOutput()) + pairProbabilities=std::make_unique(energy->size1(),energy->size2()); + // run prediction for all range combinations for(const IndexRange & tRange : parameters.getTargetRanges(*energy, targetNumber, *targetAcc)) { for(const IndexRange & qRange : parameters.getQueryRanges(*energy, queryNumber, *queryAcc.at(queryNumber).original)) { @@ -289,7 +294,7 @@ int main(int argc, char **argv){ // The prediction collector merges equal-energy structures with // identical boundaries and pair counts, even if inner pairs differ. std::unique_ptr predictor(parameters.getPredictor( *energy, - parameters.isEvaluation() ? *output : bestInteractions )); + parameters.isEvaluation() ? *output : bestInteractions, pairProbabilities.get() )); INTARNA_CHECK_NOT_NULL(predictor.get(),"predictor initialization failed"); // run prediction for this window combination @@ -330,6 +335,15 @@ int main(int argc, char **argv){ }} // window combinations } // target ranges } // query ranges + bool publish=true; +#if INTARNA_MULITHREADING + #pragma omp flush(threadAborted) + publish=!threadAborted; +#endif + if (pairProbabilities) { + if (publish) pairProbabilities->finalize(); else pairProbabilities->fail(); + } + if (publish) { #if INTARNA_MULITHREADING #pragma omp critical(intarna_omp_outputHandlerUpdate) #endif @@ -349,6 +363,9 @@ int main(int argc, char **argv){ } } + if (pairProbabilities) parameters.writeBasePairProbabilities(*pairProbabilities,*energy); + } // successful sequence-pair computation + #if INTARNA_MULITHREADING #pragma omp atomic update #endif diff --git a/tests/BasePairProbabilities_test.cpp b/tests/BasePairProbabilities_test.cpp index c53671ba..500c306c 100644 --- a/tests/BasePairProbabilities_test.cpp +++ b/tests/BasePairProbabilities_test.cpp @@ -31,3 +31,20 @@ TEST_CASE("pair result rejects inconsistent and out-of-range numerical results", REQUIRE_THROWS(overflow.addRegion({1,1},{0,0},m(0,0),m)); REQUIRE(overflow.status()==BasePairProbabilities::Status::failed); } + +#include "IntaRNA/BasePairProbabilityWriter.h" +#include +TEST_CASE("pair writer validates before emitting and checks stream failure", "[BasePairProbabilities]") { + RnaSequence t("target","GA"),q("query","UC"); + BasePairProbabilities r(2,2);std::ostringstream out; + REQUIRE_THROWS(BasePairProbabilityWriter::write(out,r,t,q));REQUIRE(out.str().empty()); + Matrix m(2,2,0);m(0,1)=1e-100; + r.addRegion({0,1},{0,1},1,m);r.finalize(); + BasePairProbabilityWriter::write(out,r,t,q); + REQUIRE(out.str().find("bpProb;U_1;C_2\nG_1;0;1e-100\nA_2;0;0\n")==0); + std::ostringstream broken;broken.setstate(std::ios::badbit); + REQUIRE_THROWS(BasePairProbabilityWriter::write(broken,r,t,q)); + BasePairProbabilities empty(2,2);empty.finalize();std::ostringstream na; + BasePairProbabilityWriter::write(na,empty,t,q); + REQUIRE(na.str()=="bpProb;U_1;C_2\nG_1;NA;NA\nA_2;NA;NA\n"); +} diff --git a/tests/Makefile.am b/tests/Makefile.am index 023ad135..0a0f3e62 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -15,7 +15,7 @@ TEST_EXTENSIONS = $(EXEEXT) .sh SH_LOG_COMPILER = $(SHELL) # the script needed for tests -dist_check_SCRIPTS = runIntaRNA.sh runAccessibilityBinary.sh runIntaRNAeval.sh runKineticSeedExtension.sh runOutputOverlap.sh +dist_check_SCRIPTS = runIntaRNA.sh runAccessibilityBinary.sh runIntaRNAeval.sh runKineticSeedExtension.sh runOutputOverlap.sh runBasePairProbabilities.sh # the program to build check_PROGRAMS = runApiTests @@ -84,4 +84,4 @@ runApiTests_CXXFLAGS = -I$(top_builddir)/src \ -EXTRA_DIST = tools/export-seeded-theory.py +EXTRA_DIST = tools/export-seeded-theory.py testBasePairProbabilities.py diff --git a/tests/PredictorSeedOracle_test.cpp b/tests/PredictorSeedOracle_test.cpp index 530ba836..7801b8a4 100644 --- a/tests/PredictorSeedOracle_test.cpp +++ b/tests/PredictorSeedOracle_test.cpp @@ -798,3 +798,25 @@ TEST_CASE("raw pair owner excludes region crossings and invalidates partial resu REQUIRE(failed.status()==BasePairProbabilities::Status::failed); REQUIRE_THROWS(failed.finalize());REQUIRE(p2.restored()); } + +#include "SeededChainOracle.h" +#include "IntaRNA/SeedHandlerExplicit.h" +TEST_CASE("native singleton and mixed explicit seeds count overlapping witnesses once", "[BasePairProbabilities][PredictorSeedOracle]") { + #include "testEasyLoggingSetup.icc" + using namespace seeded_oracle; + RnaSequence t("t","GGGG"),q("q","CCCC"); + AccessibilityDisabled at(t,0,nullptr),aq(q,0,nullptr);ReverseAccessibility ar(aq); + InteractionEnergyBasePair energy(at,ar,2,2); + SeedConstraint sc(1,0,0,0,-10000,0,-10000,IndexRangeList(),IndexRangeList(),"1|&4|,2||&2||",true,true,true); + for(bool noLP:{false,true}) { + BasePairProbabilities result(4,4);auto oc=makeOutputConstraint(noLP);OutputHandlerInteractionList output(oc,1); + ExactSeedProbe p(energy,output,nullptr,new SeedHandlerExplicit(energy,sc),&result); + p.predict();result.finalize(); + Model model{4,4,4,4,noLP,{{{0,0}},{{1,1},{2,2}}},[](Pair){return true;}, + [](Pair){return std::exp(1.L);},[](Pair,Pair){return std::exp(1.L);},[](Pair,Pair){return 1.L;}}; + auto ref=enumerate(model); + REQUIRE(double(result.getZ())==Approx(double(ref.z)).epsilon(2e-12)); + for(size_t i=0;i<4;++i) for(size_t j=0;j<4;++j) + REQUIRE(double(result.rawMasses()(i,3-j))==Approx(double(ref.mass[{i,j}])).epsilon(2e-12)); + } +} diff --git a/tests/StackSeedDomain_test.cpp b/tests/StackSeedDomain_test.cpp index 068c638d..2e1a57c2 100644 --- a/tests/StackSeedDomain_test.cpp +++ b/tests/StackSeedDomain_test.cpp @@ -48,3 +48,25 @@ TEST_CASE("stack capability and active occurrence domain", "[StackSeedDomain]") SeedHandlerExplicit eb(energy,explicitB); REQUIRE_FALSE(eb.guaranteesStackOnlySeeds()); } + +TEST_CASE("stack-domain admission preserves handler-specific threshold equality", "[StackSeedDomain]") { + #include "testEasyLoggingSetup.icc" + RnaSequence t("t","GGG"),q("q","CCC"); + AccessibilityDisabled at(t,0,nullptr),aq(q,0,nullptr);ReverseAccessibility ar(aq); + InteractionEnergyBasePair e(at,ar); + for(bool hybrid:{false,true}) { + SeedConstraint sc(2,0,0,0,hybrid?E_INF:-200,Accessibility::ED_UPPER_BOUND,hybrid?-200:E_INF,IndexRangeList(),IndexRangeList(),"",false,false,false); + SeedHandlerMfe mfe(e,sc);SeedHandlerNoBulge nb(e,sc); + REQUIRE(mfe.fillSeed(0,2,0,2)==4); + REQUIRE(nb.fillSeed(0,2,0,2)==0); + REQUIRE(StackSeedDomain(mfe,3,3,3,3).maxSeedLength()==2); + REQUIRE(StackSeedDomain(nb,3,3,3,3).maxSeedLength()==0); + } + SeedConstraint exactED(2,0,0,0,E_INF,0,E_INF,IndexRangeList(),IndexRangeList(),"",false,false,false); + SeedHandlerMfe mfe(e,exactED);SeedHandlerNoBulge nb(e,exactED); + REQUIRE(mfe.fillSeed(0,2,0,2)==0);REQUIRE(nb.fillSeed(0,2,0,2)==0); + // Explicit seeds ignore these computed-seed admission thresholds. + SeedConstraint explicitC(1,0,0,0,-10000,0,-10000,IndexRangeList(),IndexRangeList(),"1|&3|,2||&1||",true,true,true); + SeedHandlerExplicit ex(e,explicitC);REQUIRE(ex.fillSeed(0,2,0,2)==2); + REQUIRE(StackSeedDomain(ex,3,3,3,3).maxSeedLength()==2); +} diff --git a/tests/runBasePairProbabilities.sh b/tests/runBasePairProbabilities.sh new file mode 100644 index 00000000..be6d002c --- /dev/null +++ b/tests/runBasePairProbabilities.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -euo pipefail +script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) +python3 "$script_dir/testBasePairProbabilities.py" "$INTARNABINPATH/src/bin/IntaRNA" diff --git a/tests/testBasePairProbabilities.py b/tests/testBasePairProbabilities.py new file mode 100644 index 00000000..6ae33bba --- /dev/null +++ b/tests/testBasePairProbabilities.py @@ -0,0 +1,117 @@ +"""Native CLI checks with an independent exhaustive base-pair-energy oracle.""" +import csv +import gzip +import math +from pathlib import Path +import subprocess +import sys +import tempfile + +BIN = sys.argv[1] +COMMON = ['--energy=B', '--acc=N', '--model=P', '--mode=M', '--seedBP=2', + '--threads=1', '--outOverlap=B', '--outNoLP=false', '--outNoGUend=false', + '--outMode=C', '--outCsvCols=Zall,Eall', '--default-log-file=/dev/null'] + +def run(t='GGAGGG', q='CCCC', options=(), success=True): + keys = {o.split('=')[0] for o in options} + if any(o.startswith('--outMode=') and o!='--outMode=C' for o in options): + keys.add('--outCsvCols') + common = [o for o in COMMON if o.split('=')[0] not in keys] + p = subprocess.run([BIN, f'--target={t}', f'--query={q}', *common, *options], + text=True, capture_output=True) + assert (p.returncode == 0) == success, (p.args, p.returncode, p.stdout, p.stderr) + return p + +def matrix(path): + with (gzip.open(path, 'rt') if str(path).endswith('.gz') else open(path)) as f: + rows = list(csv.reader(f, delimiter=';')) + assert rows[0][0] == 'bpProb', rows + return rows[0][1:], [r[0] for r in rows[1:]], [[None if v=='NA' else float(v) for v in r[1:]] for r in rows[1:]] + +def oracle(t, q, regions=None, no_lp=False, seeds=None): + # Both internal coordinates increase; only printing reverses query labels. + n, m = len(t), len(q) + qr = q[::-1] + valid = {(i,j) for i in range(n) for j in range(m) if t[i]+qr[j] in ('GC','CG','AU','UA','GU','UG')} + z = 0.0 + mass = [[0.0]*m for _ in t] + if regions is None: regions = [(0,n-1,0,m-1)] + def stack(a,b): return b==(a[0]+1,a[1]+1) + def visit(path, end1, end2): + nonlocal z + admitted = any(stack(a,b) for a,b in zip(path,path[1:])) if seeds is None else any( + any(path[k:k+len(s)]==s for k in range(len(path))) for s in seeds) + lp_ok = all((k and stack(path[k-1],p)) or (k+10 for v in covered[3][1:]);assert all(v==0 for v in with_spot[2]) + compressed=d/'pairs.csv.gz';run(options=[f'--out=bpProb:{compressed}']);same(matrix(compressed)[2],values) + # Unsupported requests fail explicitly and never create a probability file. + for opts in (['--mode=H'],['--mode=S'],['--model=X','--mode=K'],['--noSeed'],['--windowWidth=3','--windowOverlap=2'],['--seedMaxUP=1'],['--seedTQ=1|.|&2||']): + fail=d/'unsupported.csv';run(options=[f'--out=bpProb:{fail}',*opts],success=False);assert not fail.exists() + fail=d/'range.csv';run('GGGG','CCCC',[f'--out=bpProb:{fail}',*seedopt,'--energyAdd=900'],success=False);assert not fail.exists() + run(options=['--out=bpProb:/dev/full'],success=False) + # Independent pairs and complete shared-stream blocks at both thread counts. + fasta=d/'targets.fa';fasta.write_text('>a\nGGGG\n>b\nGAGG\n') + for threads in (1,2): + prefix=d/f'multi{threads}.csv' + run(str(fasta),'CCCC',[f'--threads={threads}',f'--out=bpProb:{prefix}','--outNumber=0']) + files=sorted(d.glob(f'multi{threads}*.csv'));assert len(files)==2,files + for file,t in zip(files,('GGGG','GAGG')):same(matrix(file)[2],oracle(t,'CCCC')[1]) + shared=run(str(fasta),'CCCC',[f'--threads={threads}','--out=bpProb:STDOUT','--outNumber=0']) + lines=shared.stdout.splitlines();starts=[i for i,l in enumerate(lines) if l.startswith('bpProb;')] + assert len(starts)==2 and starts[1]-starts[0]==5,lines +print('base-pair probability CLI regressions passed') From 48efc541e23571ce1bab88e2754e1db7445cbc89 Mon Sep 17 00:00:00 2001 From: AlexanderMitrofanov Date: Thu, 8 Oct 2026 14:47:21 +0200 Subject: [PATCH 08/21] test: finish seeded probability validation and documentation (step 7) --- .github/workflows/build.yml | 5 + ChangeLog | 19 +++ IntaRNA.pc.in | 2 +- README.md | 67 +++++++- doc/Makefile.am | 4 +- doc/analysis/base-pair-probabilities-plan.md | 16 +- .../seeded-probabilities-validation.md | 159 ++++++++++++++++++ doc/seeded-probabilities-example.cpp | 29 ++++ src/IntaRNA/OutputHandlerHub.h | 2 + src/IntaRNA/SeededPartitionFunction.cpp | 2 +- src/bin/CommandLineParsing.cpp | 10 ++ src/bin/CommandLineParsing.h | 4 + src/bin/IntaRNA.cpp | 21 +-- tests/Makefile.am | 1 + tests/OutputHandlerHub_test.cpp | 11 ++ tests/PredictorSeedOracle_test.cpp | 5 +- tests/SeededNativeBenchmark_test.cpp | 68 ++++++++ tests/SeededPartitionFunction_test.cpp | 12 +- tests/StackSeedDomain_test.cpp | 15 ++ tests/testBasePairProbabilities.py | 8 + 20 files changed, 433 insertions(+), 27 deletions(-) create mode 100644 doc/analysis/seeded-probabilities-validation.md create mode 100644 doc/seeded-probabilities-example.cpp create mode 100644 tests/SeededNativeBenchmark_test.cpp diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 31f22a56..9459ab05 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -128,3 +128,8 @@ jobs: ${LDFLAGS:-} $(pkg-config --cflags --libs IntaRNA) \ -o "$RUNNER_TEMP/intarna-consumer" "$RUNNER_TEMP/intarna-consumer" + "$CXX" -std=c++23 ${CPPFLAGS:-} ${CXXFLAGS:-} doc/seeded-probabilities-example.cpp \ + ${LDFLAGS:-} $(pkg-config --cflags --libs IntaRNA) \ + -o "$RUNNER_TEMP/intarna-probabilities-consumer" + "$RUNNER_TEMP/intarna-probabilities-consumer" > "$RUNNER_TEMP/intarna-pair-probabilities.csv" + grep -q '^bpProb;' "$RUNNER_TEMP/intarna-pair-probabilities.csv" diff --git a/ChangeLog b/ChangeLog index f876d0e8..bd016930 100644 --- a/ChangeLog +++ b/ChangeLog @@ -46,6 +46,10 @@ ## Technical changes and Optimizations +- validate exact pair probabilities on independent mathematical/native oracles, + release/debug suites and installed consumers; document measured runtime and + storage, and supply the required logging link dependency (issue #257, step 7) + - collect raw actual-pair masses and disjoint regional denominators with explicit successful-empty/nonempty/failed lifecycle (issue #257, step 5) @@ -152,6 +156,21 @@ energies, restricted partition sums, and trackers. ################################################################################ ################################################################################ +261008 Alexander Mitrofanov + * tests, README.md, doc/analysis, doc/seeded-probabilities-example.cpp : + + finish probability regression and native performance gates, document the + selected algorithm, supported ensemble, public API and numerical limits + * CommandLineParsing, IntaRNA.cpp, OutputHandlerHub, SeededPartitionFunction : + + retain copied output policy, check dense-grid dimension products, serialize + seed-constraint initialization and emit empty matrices for too-short pairs + + preserve dynamic OpenMP exceptions and report fatal failures as errors even + with redirected warning logs; reject unsupported empty searches (PR #258) + * IntaRNA.pc.in, .github/workflows/build.yml, Makefile.am : + + link the logging dependency required by installed predictor consumers; + compile/run a real probability consumer in CI and distribute new artifacts + + GCC 14 release/debug: seven suites pass, 91,361 API assertions; all 74 + installed headers, installed consumer and source distribution checks pass + 261008 Alexander Mitrofanov * BasePairProbabilityWriter, CommandLineParsing, IntaRNA.cpp, CLI/API tests : + add bpProb matrix output, capability/mode validation, multi-FASTA naming, diff --git a/IntaRNA.pc.in b/IntaRNA.pc.in index db398781..73479143 100644 --- a/IntaRNA.pc.in +++ b/IntaRNA.pc.in @@ -6,5 +6,5 @@ includedir=${prefix}/include Name: IntaRNA Description: RNA-RNA interaction prediction C++ library Version: @VERSION@ -Libs: -L${libdir} -lIntaRNA @LIBS@ +Libs: -L${libdir} -lIntaRNA -leasylogging @LIBS@ Cflags: -I${includedir} @BOOST_CPPFLAGS@ @VRNA_CFLAGS@ diff --git a/README.md b/README.md index 3e0266d5..32f77132 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,7 @@ The following topics are covered by this documentation: - [Minimal energy profiles](#profileMinE) - [Minimal energy for all intermolecular index pairs](#pairMinE) - [Spot probability profiles](#profileSpotProb) using partition functions + - [Actual base-pair probabilities](#bpProb) - [Interaction probabilities for interaction spots of interest](#spotProb) - [Accessibility and unpaired probabilities](#accessibility) - [Local versus global unpaired probabilities](#accLocalGlobal) @@ -1875,13 +1876,14 @@ targeted file/stream name: - `qSpotProb:`/`tSpotProb:` [query/target's spot probability profile](#profileSpotProb) (CSV format), respectively - `spotProb:` [all spot probabilities](#spotProb) (CSV format) +- `bpProb:` [actual base-pair probabilities](#bpProb) for exact stack-seeded ensembles (CSV matrix) - `qMinE:`/`tMinE:` [the query/target's minimal interaction energy profile](profileMinE) (CSV format), respectively - `pMinE:` [minimal interaction energy for all query-target index pairs](pairMinE) (CSV format) - `qAcc:`/`tAcc:` the [query/target's ED accessibility values](#accessibility) (RNAplfold-like format), respectively - `qPu:`/`tPu:` the [query/target's unpaired probabilities](#accessibility) (RNAplfold format; rounded!!), respectively Note, for *multiple sequences* in FASTA input, the provided file names are suffixed by -- `-t#q#` : for `*spotProb` and `*minE` output, and +- `-t#q#` : for `bpProb`, `*spotProb` and `*minE` output, and - `-s#` : for `*Acc` and `*Pu` output, where `#` denotes the according target/query sequence number within the input where numbering starts with 1. @@ -2005,6 +2007,63 @@ or `STDERR` instead of a file name. [![up](doc/figures/icon-up.28.png) back to overview](#overview)
+ + +## Actual base-pair probabilities + +`--out=bpProb:FILE` writes the probability that each target/query nucleotide pair +actually pairs, conditional on an allowed seeded interaction. It requires +`--model=P --mode=M` and a stack-only seed handler. For example: + +```sh +IntaRNA -t GGAGGG -q CCCC --energy=B --acc=N --seedBP=2 \ + --model=P --mode=M --out=bpProb:pairs.csv +``` + +Every complete ordered interaction is counted once, even when it contains +several overlapping or disjoint seeds. The exact stack-seeded partition backend +is also used without `bpProb`, so requesting the matrix does not change `Zall`. +Computed seeds preserve their handler-specific admission thresholds. Explicit +stacked seeds may have different lengths, including singletons; competing +explicit patterns at the same start still retain only the selected minimum-energy +pattern. Other predictors retain their existing behavior. Heuristic, kinetic, +evaluation, seed-only, unseeded and bulged-seed `bpProb` requests are rejected. + +Rows follow the original target and columns the original query, both 5' to 3'. +The header starts with `bpProb`; labels contain each nucleotide and its display +index (including `tIdxPos0`/`qIdxPos0` shifts). Entries use sufficient significant +digits for the partition type, with scientific notation for small probabilities. +A successful empty ensemble contains `NA`; pairs absent from a nonempty ensemble +have probability zero. The output uses `outSep`, the usual multi-FASTA filename +suffixes and gzip support. `STDOUT`/`STDERR` receive synchronized complete blocks. + +The ensemble is the union of the searched, disjoint target/query region pairs. +Interactions crossing excluded region boundaries are absent. Region selection, +`outMinPu`, accessibility, seed admission, loop/span limits, `outNoLP` and +`outNoGUend` can restrict it. Ranked reporting options (`outNumber`, `outMaxE`, +`outDeltaE`, overlap selection and `outPerRegion`) do not select the probability +ensemble. Raw numerators and denominators are merged before normalization. +Model P continues to reject nonzero `windowWidth`. + +Unlike `spotProb` coverage, this output uses interior pair chains: an unpaired +bulge can have positive site coverage and zero actual-pair probability. There +is no added unbound-state weight. Individual pair events can coexist, so +`1 - sum(pair probabilities)` is not a probability of no interaction. + +The backend checks nonnegative arithmetic and reports numerical range failures +as errors, including underflow, overflow and NaN. Positive subnormals are rejected; +there is currently no scaling fallback. Failed or cancelled regional work never +produces a successful-looking probability matrix. Ordinary floating-point +rounding remains; "exact" describes the enumerated ensemble, not real arithmetic. + +For library use, keep a `BasePairProbabilities` owner alive across predictions, +pass its optional non-owning pointer to `PredictorMfeEns2dSeedExtension`, and call +`finalize()` only after all requested disjoint regions succeed. A writer is called +explicitly after finalization; its destructor publishes nothing. The output +constraint must enable `needZall`. The [standalone API example](doc/seeded-probabilities-example.cpp) +and [implementation validation report](doc/analysis/seeded-probabilities-validation.md) +show the public API and measured limits. + ### Interaction probabilities for interaction spots of interest @@ -2387,8 +2446,10 @@ Doxygen and Graphviz and run `bash doc/build-api.sh`, then open Autotools, and publishing instructions. The [seeded base-pair probability implementation plan](doc/analysis/base-pair-probabilities-plan.md) -records the proposed algorithms, numerical contracts, integration, and validation -for issue #257. It is a design document; the proposed output is not implemented. +records the reviewed algorithms, numerical contracts, integration, and validation +for issue #257. The implementation selects the suffix backend after the +[measured kernel comparison](doc/analysis/seeded-kernel-comparison.md); +[actual base-pair output](#bpProb) is available for exact stack-seeded ensembles. When IntaRNA is build while `pkg-config` is present, according pkg-config information is generated and installed too. diff --git a/doc/Makefile.am b/doc/Makefile.am index 4092731b..9d47b6ab 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -6,7 +6,9 @@ EXTRA_DIST = \ conda.txt \ analysis/base-pair-probabilities-plan.md \ - analysis/seeded-kernel-comparison.md \ + analysis/seeded-kernel-comparison.md \ + analysis/seeded-probabilities-validation.md \ + seeded-probabilities-example.cpp \ api-documentation.md \ build-api.sh \ check-api.py \ diff --git a/doc/analysis/base-pair-probabilities-plan.md b/doc/analysis/base-pair-probabilities-plan.md index 7080047e..c682f943 100644 --- a/doc/analysis/base-pair-probabilities-plan.md +++ b/doc/analysis/base-pair-probabilities-plan.md @@ -1,7 +1,11 @@ # Implementation plan: seeded base-pair probabilities -Status: design only. This document addresses [issue #257](https://github.com/BackofenLab/IntaRNA/issues/257); -it does not implement the recurrences, proposed APIs, or proposed output options. +Status: implemented in the seven milestone commits of [PR #258](https://github.com/BackofenLab/IntaRNA/pull/258). +This document preserves the reviewed design for [issue #257](https://github.com/BackofenLab/IntaRNA/issues/257). +The [kernel comparison](seeded-kernel-comparison.md) selected the suffix automaton +for production; sections 6–7 below describe the retained test-only maximal-stack +candidate. See [implementation validation](seeded-probabilities-validation.md) +for the delivered API, tests, measurements and numerical limits. The code assessment uses IntaRNA revision [`5454030a04bbcde79b2e75a0614dadf6f1115e6f`](https://github.com/BackofenLab/IntaRNA/tree/5454030a04bbcde79b2e75a0614dadf6f1115e6f). @@ -490,7 +494,7 @@ seed-locality and memory cases used in the early algorithm comparison. ## 11. Implementation sequence and affected components -Each milestone has an exit condition; none is implemented by this document. +Each milestone has an exit condition and a separate implementation commit in PR #258. | Order | Work | Main files/components | Exit condition | | --- | --- | --- | --- | @@ -514,6 +518,6 @@ Record toolchain, options, inputs, timings, peak memory, and numerical differenc An intentionally corrected partition can change ensemble rankings; justify those changes against the oracle instead of regenerating expected files blindly. -For this documentation-only plan, validate references, equations, pseudocode -contracts, Markdown structure, distribution registration, and `git diff --check`. -No C++ implementation build or performance result is claimed by this plan. +The original plan was validated as documentation only. Implementation builds, +independent numerical checks and performance measurements are recorded in the +linked validation report. diff --git a/doc/analysis/seeded-probabilities-validation.md b/doc/analysis/seeded-probabilities-validation.md new file mode 100644 index 00000000..a08848d0 --- /dev/null +++ b/doc/analysis/seeded-probabilities-validation.md @@ -0,0 +1,159 @@ +# Exact seeded probabilities: implementation and validation + +PR #258 implements the seven steps of the reviewed plan in separate commits. +The library ships the specialized suffix automaton; maximal stacks remain a +correctness/performance comparison in the tests. See the [kernel decision](seeded-kernel-comparison.md) +for measured tradeoffs and exact cell-storage counts. + +## Delivered contract + +- Stack-only capability is geometric and forwarded through index offsets. Active + occurrences retain each handler's admission and per-start selection policies; + both endpoints and inclusive span limits are checked. +- Seed-free suffix lengths and two seeded run-length states count ordered chains + once. Whole-interaction noLP forbids departure/termination of singleton runs. + End GU and full-span ED filters affect termination, not intermediate states. +- Initiation, successive-pair loop energies and the complete boundary coefficient + own their contributions once. The complete coefficient is shared with outside + initialization and virtual `updateZ` dispatch. Overrides can observe/delegate; + reweighting belongs in `exactBoundaryWeight`, which serves both passes. Changing + the hybrid mass through an old update override is rejected. +- The pair sink is non-owning. Each prediction creates private region state and + converts internal pairs once through `getBasePair`. The accumulator rejects + intersecting rectangles, validates every merge before mutation, and requires + explicit finalization. CLI ownership spans all regions of one sequence pair. + Cancellation/failure guards apply before output, including the OpenMP path. +- `bpProb` is independent of coverage trackers and ranked reporting. Pair-only + output does not retain `Z_partition`. Simultaneous legacy trackers retain their + existing callbacks/map and native energy rounding semantics. + +## Numerical limits + +Arithmetic uses `Z_type`, exact zero and checked nonnegative sums/products, +exponentials, division and region merges. Structural forbidden energies become +zero before exponentiation. NaN, infinity, positive underflow and positive +subnormals are errors. No scaling is implemented. Ordinary rounding loss in a +sum with widely different terms remains possible. Final row/column exclusivity +and pair mass bounds are checked; endpoint correction is limited to +`512 * epsilon(Z_type) * max(1, targetLength + queryLength)` above one. + +Independent tests use a 2e-12 relative tolerance for raw double-precision totals, +boundaries and masses against long-double enumeration and 50-digit theory gold +values. The CLI base-pair-energy oracle also uses a 2e-14 absolute tolerance for +printed zeros/small values. Native integer ED is preserved and is not compared +against unrounded theoretical ED as though they were identical models. + +## Memory + +Beyond the active suffix grids documented in the kernel comparison, pair output +holds one full target-by-query raw matrix, the private regional outside matrix, +and briefly a regional matrix in original coordinates. Explicit finalization and +writing allocate a normalized full matrix; writing also buffers the complete CSV +block. These phases are sequential, not all simultaneous. Native accessibility +and retained seed preprocessing are additional costs. Legacy trackers add their +own coverage matrices and complete-boundary map. No global run tape or global +boundary-weight table is retained. Without pair output, no pair matrix or reverse +state is allocated. + +## Reproducible checks + +Use GCC 14 with C++23, Boost, ViennaRNA and the bundled Kokkos mdspan fallback: + +```sh +bash autotools-init.sh +./configure --disable-debug # dependency prefixes as in AGENTS.md when needed +make -j2 +make tests -j2 +# Repeat in a clean source/build directory with --enable-debug. +``` + +The focused tags are `[SeededPartitionFunction]`, `[StackSeedDomain]`, +`[BasePairProbabilities]`, `[PredictorSeedOracle]` and `[PredictorMfeEns]`. +`tests/runBasePairProbabilities.sh` checks CLI behavior with a separate Python +chain enumerator. `tests/tools/export-seeded-theory.py` reproduces all ten +fixture extractions from the cited theory revision. No legacy CLI golden file +is regenerated for this change. + +Final local verification used GCC 14.4.0, ViennaRNA 2.7.2, Boost 1.85, +Z_type=double and Kokkos mdspan on Linux x86-64. Release and debug each passed all +seven Autotools test suites; the API suite passed 91,361 assertions in 85 cases. +The initial incremental run exposed stale objects after the virtual interface +change; clean release/debug rebuilds passed. No failing golden files were replaced. + +All 74 installed public headers compiled independently. The standalone probability +consumer compiled, linked through installed pkg-config metadata, and produced the +expected matrix. This check exposed a missing `-leasylogging` dependency in the +metadata; it is fixed, and CI now builds/runs this predictor consumer on Linux +and macOS. `make dist` includes every new source, fixture, test, example and report. +Apple Clang execution was not available locally; its existing CI job remains the +platform gate. + +The final integration checks also cover too-short sequences as successful empty +matrices, dynamic OpenMP exception propagation and visible fatal diagnostics even +when a log file is selected. Seed-constraint lazy initialization is synchronized +for concurrent sequence pairs. Pure header/Matrix consumers did not previously +exercise the logging dependency; the new consumer calls a real predictor. + +## Native measurements + +The hidden `[SeededNativeBenchmark]` case uses the production predictor, native +ViennaRNA transition energies, inclusive spans of 30, loop limits three and a +four-pair computed stack seed. OxyS/fhlA accessibility is ViennaRNA-derived; +synthetic cases disable accessibility. Inputs and the timing adapter are committed +in `tests/SeededNativeBenchmark_test.cpp`. Set `INTARNA_BENCH_CASE` and +`INTARNA_BENCH_OUTSIDE=0|1` to measure an individual case in a fresh process. + +```sh +OMP_NUM_THREADS=1 OPENBLAS_NUM_THREADS=1 /usr/bin/time -v \ + ./tests/runApiTests '[SeededNativeBenchmark]' +``` + +Milliseconds from one controlled single-thread run; "predictor" excludes measured +seed filling but includes active-domain construction, merging and finalization. +The added outside cost is the difference between the two predictor columns; it +includes pair-result allocation/normalization, not just differentiation. + +| Input | Accessibility | Seed filling (Z / pairs) | Predictor Z | Predictor Z+pairs | Z | +| --- | ---: | ---: | ---: | ---: | ---: | + +| none | 0.005 | 0.024 / 0.019 | 0.010 | 0.198 | 0 | +| sparse100 | 0.000 | 0.074 / 0.028 | 0.751 | 1.488 | 1.702e+15 | +| sparse400 | 0.000 | 0.308 / 0.288 | 0.712 | 5.621 | 1.702e+15 | +| dense | 0.000 | 0.296 / 0.304 | 413.301 | 972.852 | 2.00398e+68 | +| OxyS-fhlA | 27.627 | 0.180 / 0.178 | 53.376 | 134.278 | 37643.8 | + +Raw Z was bitwise identical with pair output off/on for every measured case. No +representative measured case exceeded the checked numerical range. Increasing +unrelated sparse-sequence length from 100 to 400 leaves partition DP work nearly +constant; seed preprocessing and full-matrix pair output still grow. These costs +are reported separately rather than attributed to the recurrence. + +Fresh-process peak RSS (KiB, includes the executable, native libraries, +accessibility and allocator overhead; small differences include measurement noise): + +| Input | Z only | Z+pairs | +| --- | ---: | ---: | +| sparse100 | 15,436 | 15,376 | +| sparse400 | 15,436 | 18,688 | +| dense | 15,560 | 16,000 | +| OxyS-fhlA | 17,784 | 17,836 | + +Full CLI measurement (including startup, accessibility, computation, normalization +and file output) used the repository's `doc/handson/fhlA.fasta` and `OxyS.fasta`: + +```sh +OMP_NUM_THREADS=1 OPENBLAS_NUM_THREADS=1 /usr/bin/time -v src/bin/IntaRNA \ + --target=doc/handson/fhlA.fasta --query=doc/handson/OxyS.fasta \ + --model=P --mode=M --seedBP=4 --intLenMax=30 \ + --qIntLoopMax=3 --tIntLoopMax=3 --threads=1 \ + --outNoLP=false --outNoGUend=false --outNumber=0 --outMode=E \ + --default-log-file=/dev/null --out=ensemble.txt +# Repeat with --out=bpProb:pairs.csv. +``` + +- Without pair matrix: median 0.09 s over three runs, maximum observed RSS 16,916 KiB. +- With pair matrix: median 0.16 s over three runs, maximum observed RSS 16,788 KiB. + +Both runs report Eall=-6.52 kcal/mol with the native presentation convention. +These measurements quantify added output work; they are not a speedup claim over +the legacy seeded ensemble, whose multi-anchor partition is a different result. diff --git a/doc/seeded-probabilities-example.cpp b/doc/seeded-probabilities-example.cpp new file mode 100644 index 00000000..eb63e832 --- /dev/null +++ b/doc/seeded-probabilities-example.cpp @@ -0,0 +1,29 @@ +// Standalone installed-library example; see README.md#bpProb. +#include +#include +#include +#include +#include +#include +#include + +INITIALIZE_EASYLOGGINGPP + +int main() { + using namespace IntaRNA; + RnaSequence target("target", "GGAGGG"), query("query", "CCCC"); + AccessibilityDisabled targetAcc(target, 0, nullptr), queryAcc(query, 0, nullptr); + ReverseAccessibility reversed(queryAcc); + InteractionEnergyBasePair energy(targetAcc, reversed); + SeedConstraint seeds(2, 0, 0, 0, E_INF, Accessibility::ED_UPPER_BOUND, + E_INF, IndexRangeList(), IndexRangeList(), "", false, false, false); + OutputConstraint constraints(1, OutputConstraint::OVERLAP_BOTH, E_INF, E_INF, + false, false, false, true, false); // needZall=true; needBPs=false + OutputHandlerInteractionList output(constraints, 1); + BasePairProbabilities probabilities(target.size(), query.size()); + PredictorMfeEns2dSeedExtension predictor(energy, output, nullptr, + new SeedHandlerNoBulge(energy, seeds), &probabilities); + predictor.predict(); + probabilities.finalize(); + BasePairProbabilityWriter::write(std::cout, probabilities, target, query); +} diff --git a/src/IntaRNA/OutputHandlerHub.h b/src/IntaRNA/OutputHandlerHub.h index e711627e..ac5e4cb2 100644 --- a/src/IntaRNA/OutputHandlerHub.h +++ b/src/IntaRNA/OutputHandlerHub.h @@ -160,6 +160,7 @@ ::OutputHandlerHub( const OutputHandlerHub & toCopy ) // dont delete on destruction (should be done by original) to avoid double cleanup , deleteOutListOnDestruction(false) { + exactPartition=toCopy.exactPartition; } ///////////////////////////////////////////////////////////////////////// @@ -298,6 +299,7 @@ operator= ( const OutputHandlerHub & toCopy) outList.clear(); // copy data + exactPartition=toCopy.exactPartition; outList = toCopy.outList; // ensure this copy doesnt delete the list content deleteOutListOnDestruction = false; diff --git a/src/IntaRNA/SeededPartitionFunction.cpp b/src/IntaRNA/SeededPartitionFunction.cpp index 2caa278c..63e2007f 100644 --- a/src/IntaRNA/SeededPartitionFunction.cpp +++ b/src/IntaRNA/SeededPartitionFunction.cpp @@ -20,7 +20,7 @@ SeededPartitionFunction::Result SeededPartitionFunction::compute( seeds.forEachStart([&](size_t p1,size_t p2) { const Pair p{p1,p2}; if (!w.valid(p)) return; const size_t n=std::min(d.span1,d.n-p1),m=std::min(d.span2,d.m-p2); - Matrix h(n*m,states),dh; + Matrix h(matrix_detail::product(n,m),states),dh; Matrix> total(n,m),dt; Matrix valid(n,m); Matrix ending(n,m); diff --git a/src/bin/CommandLineParsing.cpp b/src/bin/CommandLineParsing.cpp index 8a1518e7..dc864b8c 100644 --- a/src/bin/CommandLineParsing.cpp +++ b/src/bin/CommandLineParsing.cpp @@ -69,6 +69,7 @@ extern "C" { #include "IntaRNA/SeedHandlerMfe.h" #include "IntaRNA/BasePairProbabilityWriter.h" +#include #include "IntaRNA/SeedHandlerNoBulge.h" #include "IntaRNA/OutputStreamHandlerSortedCsv.h" @@ -2491,6 +2492,13 @@ getTemperature() const { bool CommandLineParsing::hasBasePairProbabilityOutput() const { return !outPrefix2streamName.at(OutPrefixCode::OP_bpProb).empty(); } +BasePairProbabilities * CommandLineParsing::getBasePairProbabilityResult(const InteractionEnergy & energy) const { + if (!hasBasePairProbabilityOutput()) return nullptr; + std::unique_ptr handler(getSeedHandler(energy)); + if (!handler->guaranteesStackOnlySeeds()) + throw std::invalid_argument("bpProb requires a stack-only seed handler; bulged seeds are unsupported"); + return new BasePairProbabilities(energy.size1(),energy.size2()); +} void CommandLineParsing::writeBasePairProbabilities(const BasePairProbabilities & result,const InteractionEnergy & energy) const { const auto & t=energy.getAccessibility1().getSequence(); const auto & q=energy.getAccessibility2().getAccessibilityOrigin().getSequence(); @@ -2787,6 +2795,8 @@ const SeedConstraint & CommandLineParsing:: getSeedConstraint( const InteractionEnergy & energy ) const { + static std::mutex seedInitialization; + const std::lock_guard lock(seedInitialization); if (seedConstraint == NULL) { // setup according to user data seedConstraint = new SeedConstraint( diff --git a/src/bin/CommandLineParsing.h b/src/bin/CommandLineParsing.h index efcc3c11..fff52480 100644 --- a/src/bin/CommandLineParsing.h +++ b/src/bin/CommandLineParsing.h @@ -291,6 +291,10 @@ class CommandLineParsing { /** @return whether actual base-pair matrix output was requested */ bool hasBasePairProbabilityOutput() const; + /** Allocate a pair result after validating the actual seed capability. + * @return owned result or nullptr when pair output is not requested + */ + BasePairProbabilities * getBasePairProbabilityResult(const InteractionEnergy & energy) const; /** Publish a successful sequence-pair result using ordinary filename rules. */ void writeBasePairProbabilities(const BasePairProbabilities & result,const InteractionEnergy & energy) const; diff --git a/src/bin/IntaRNA.cpp b/src/bin/IntaRNA.cpp index 15d02b8c..bb971e29 100644 --- a/src/bin/IntaRNA.cpp +++ b/src/bin/IntaRNA.cpp @@ -137,7 +137,7 @@ int main(int argc, char **argv){ { if (!threadAborted) { // store exception information - exceptionPtrDuringOmp = std::make_exception_ptr(e); + exceptionPtrDuringOmp = std::current_exception(); exceptionInfoDuringOmp <<" #thread "< pairProbabilities; - if (parameters.hasBasePairProbabilityOutput()) - pairProbabilities=std::make_unique(energy->size1(),energy->size2()); + std::unique_ptr pairProbabilities(parameters.getBasePairProbabilityResult(*energy)); // run prediction for all range combinations for(const IndexRange & tRange : parameters.getTargetRanges(*energy, targetNumber, *targetAcc)) { @@ -309,7 +307,7 @@ int main(int argc, char **argv){ { if (!threadAborted) { // store exception information - exceptionPtrDuringOmp = std::make_exception_ptr(e); + exceptionPtrDuringOmp = std::current_exception(); exceptionInfoDuringOmp <<" #thread "< Please report (including input) to the IntaRNA development team! Thanks!\n"; + LOG(ERROR) < Please report (including input) to the IntaRNA development team! Thanks!\n"; el::Loggers::flushAll(); return -1; diff --git a/tests/Makefile.am b/tests/Makefile.am index 0a0f3e62..5a919fb1 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -27,6 +27,7 @@ runApiTests_SOURCES = \ SeededTheoryFixtures.h \ SeededStackKernel.h \ SeededPartitionFunction_test.cpp \ + SeededNativeBenchmark_test.cpp \ StackSeedDomain_test.cpp \ BasePairProbabilities_test.cpp \ testEasyLoggingSetup.icc \ diff --git a/tests/OutputHandlerHub_test.cpp b/tests/OutputHandlerHub_test.cpp index 508eadfb..c83a7496 100644 --- a/tests/OutputHandlerHub_test.cpp +++ b/tests/OutputHandlerHub_test.cpp @@ -49,3 +49,14 @@ TEST_CASE("OutputHandlerHub reports the largest child count", "[OutputHandlerHub REQUIRE(second.reported() == 2); REQUIRE(hub.reported() == 2); } + +TEST_CASE("exact-zero partition status follows copied hubs and new children", "[OutputHandlerHub]") { + OutputConstraint constraint; + CountingOutputHandler output(constraint),other(constraint); + OutputHandlerHub hub(constraint,false);hub.addOutputHandler(&output);hub.setExactPartition(true); + hub.incrementZ(1e-100); + REQUIRE(hub.hasNonzeroZ()); + OutputHandlerHub copy(hub);REQUIRE(copy.usesExactPartition());REQUIRE(copy.hasNonzeroZ()); + copy.addOutputHandler(&other);REQUIRE(other.usesExactPartition()); + OutputHandlerHub assigned(constraint,false);assigned=hub;REQUIRE(assigned.usesExactPartition()); +} diff --git a/tests/PredictorSeedOracle_test.cpp b/tests/PredictorSeedOracle_test.cpp index 7801b8a4..27779cc9 100644 --- a/tests/PredictorSeedOracle_test.cpp +++ b/tests/PredictorSeedOracle_test.cpp @@ -670,6 +670,7 @@ TEST_CASE("tiny exhaustive seed oracle for exact predictor families", } #include "IntaRNA/AccessibilityBasePair.h" +#include "IntaRNA/AccessibilityVrna.h" #include "IntaRNA/InteractionEnergyVrna.h" #include "IntaRNA/SeedHandlerNoBulge.h" #include "IntaRNA/OutputHandlerHub.h" @@ -717,7 +718,9 @@ TEST_CASE("native exact stacked partitions agree beyond the unique-anchor domain ReverseAccessibility ar(aq); InteractionEnergyBasePair simple(at,ar,2,1); VrnaHandler vrna; - InteractionEnergyVrna nearest(at,ar,vrna,2,1); + AccessibilityVrna nativeTarget(t,6,nullptr,vrna),nativeQuery(q,5,nullptr,vrna); + ReverseAccessibility nativeReverse(nativeQuery); + InteractionEnergyVrna nearest(nativeTarget,nativeReverse,vrna,2,1); for(bool noLP:{false,true}) for(bool noGU:{false,true}) { checkNativeStackPartition(simple,noLP,noGU); checkNativeStackPartition(nearest,noLP,noGU); diff --git a/tests/SeededNativeBenchmark_test.cpp b/tests/SeededNativeBenchmark_test.cpp new file mode 100644 index 00000000..14439244 --- /dev/null +++ b/tests/SeededNativeBenchmark_test.cpp @@ -0,0 +1,68 @@ +#include "catch.hpp" +#include "IntaRNA/AccessibilityDisabled.h" +#include "IntaRNA/AccessibilityVrna.h" +#include "IntaRNA/InteractionEnergyVrna.h" +#include "IntaRNA/SeedHandlerNoBulge.h" +#include "IntaRNA/PredictorMfeEns2dSeedExtension.h" +#include "IntaRNA/OutputHandlerInteractionList.h" +#include +#include +#include +#include + +using namespace IntaRNA; +namespace { +using Clock=std::chrono::steady_clock; +double elapsed(Clock::time_point start) { return std::chrono::duration(Clock::now()-start).count(); } +class TimedStackSeeds:public SeedHandlerNoBulge { + double & ms; +public: + TimedStackSeeds(const InteractionEnergy & e,const SeedConstraint & c,double & ms):SeedHandlerNoBulge(e,c),ms(ms) {} + size_t fillSeed(size_t i,size_t j,size_t k,size_t l) override { + auto start=Clock::now();auto count=SeedHandlerNoBulge::fillSeed(i,j,k,l);ms=elapsed(start);return count; + } +}; +} +TEST_CASE("native seeded preprocessing partition and outside benchmark", "[.][SeededNativeBenchmark]") { + #include "testEasyLoggingSetup.icc" + for(std::string name:{"none","sparse100","sparse400","dense","OxyS-fhlA"}) { + const char * requested=std::getenv("INTARNA_BENCH_CASE"); + if(requested && name!=requested) continue; + const size_t n=name=="sparse400"?400:100; + std::string target(n,'A'),query(n,'A'); + if(name=="sparse100" || name=="sparse400") { target.replace(n/2,8,8,'G');query.replace(n/2,8,8,'C'); } + if(name=="dense") { target=std::string(40,'G');query=std::string(40,'C'); } + if(name=="OxyS-fhlA") { target="AGUUAGUCAAUGACCUUUUGCACCGCUUUGCGGUGCUUUCCUGGAACAACAAAAUGUCAUAUACACCGAUGAGUGAUCUCGGACAACAAGGGUUGUUCGACAUCACUCGGAC";query="GAAACGGAGCGGCACCUCUUUUAACCCUUGAAGUCACUGCCCGUUUCGAGAGUUUCUCAACUCGAAUAACUAAAGCCAACGUGAACUUUUGCGGAUCUCCAGGAUCCG"; } + RnaSequence t("target",target),q("query",query); + VrnaHandler vrna; + auto start=Clock::now(); + std::unique_ptr at,aq; + if(name=="OxyS-fhlA") { + at=std::make_unique(t,30,nullptr,vrna,0); + aq=std::make_unique(q,30,nullptr,vrna,0); + } else { + at=std::make_unique(t,30,nullptr); + aq=std::make_unique(q,30,nullptr); + } + const double accMs=elapsed(start); + ReverseAccessibility ar(*aq); + InteractionEnergyVrna energy(*at,ar,vrna,3,3); + SeedConstraint sc(4,0,0,0,0,Accessibility::ED_UPPER_BOUND,E_INF,IndexRangeList(),IndexRangeList(),"",false,false,false); + Z_type reference=0; + for(bool pairs:{false,true}) { + const char * mode=std::getenv("INTARNA_BENCH_OUTSIDE"); + if(mode && pairs!=(std::string(mode)=="1")) continue; + OutputConstraint oc(0,OutputConstraint::OVERLAP_BOTH,E_INF,E_INF,false,false,false,true,false); + OutputHandlerInteractionList output(oc,0); + std::unique_ptr result; + start=Clock::now(); + if(pairs) result=std::make_unique(t.size(),q.size()); + double seedMs=0; + PredictorMfeEns2dSeedExtension p(energy,output,nullptr,new TimedStackSeeds(energy,sc,seedMs),result.get()); + p.predict();if(result) result->finalize(); + const double ms=elapsed(start); + if(!pairs) reference=p.getZall();else if(!mode) REQUIRE(p.getZall()==reference); + std::cout<::min(),Z_type(.1)),std::range_error); + REQUIRE_THROWS_AS(A::divide(std::numeric_limits::min(),std::numeric_limits::max()),std::range_error); REQUIRE_THROWS_AS(A::check(std::numeric_limits::quiet_NaN()),std::range_error); REQUIRE_THROWS_AS(A::add(std::numeric_limits::max(),std::numeric_limits::max()),std::range_error); } diff --git a/tests/StackSeedDomain_test.cpp b/tests/StackSeedDomain_test.cpp index 2e1a57c2..454e7210 100644 --- a/tests/StackSeedDomain_test.cpp +++ b/tests/StackSeedDomain_test.cpp @@ -70,3 +70,18 @@ TEST_CASE("stack-domain admission preserves handler-specific threshold equality" SeedHandlerExplicit ex(e,explicitC);REQUIRE(ex.fillSeed(0,2,0,2)==2); REQUIRE(StackSeedDomain(ex,3,3,3,3).maxSeedLength()==2); } + +TEST_CASE("explicit stack capability inspects the retained minimum-energy pattern", "[StackSeedDomain]") { + #include "testEasyLoggingSetup.icc" + RnaSequence t("t","GGGG"),q("q","CCCC"); + AccessibilityDisabled at(t,0,nullptr),aq(q,0,nullptr);ReverseAccessibility ar(aq); + InteractionEnergyBasePair e(at,ar); + SeedConstraint sc(2,0,0,0,E_INF,Accessibility::ED_UPPER_BOUND,E_INF, + IndexRangeList(),IndexRangeList(),"1|.|&2|.|,1|||&2|||",false,false,false); + SeedHandlerExplicit handler(e,sc); + REQUIRE(handler.guaranteesStackOnlySeeds()); + REQUIRE(handler.fillSeed(0,3,0,3)==1); + StackSeedDomain domain(handler,4,4,4,4); + REQUIRE(domain.seedLength(0,0)==3); + REQUIRE(domain.maxSeedLength()==3); // constraint's minimum BP is only two +} diff --git a/tests/testBasePairProbabilities.py b/tests/testBasePairProbabilities.py index 6ae33bba..1c5f8c8d 100644 --- a/tests/testBasePairProbabilities.py +++ b/tests/testBasePairProbabilities.py @@ -20,6 +20,8 @@ def run(t='GGAGGG', q='CCCC', options=(), success=True): p = subprocess.run([BIN, f'--target={t}', f'--query={q}', *common, *options], text=True, capture_output=True) assert (p.returncode == 0) == success, (p.args, p.returncode, p.stdout, p.stderr) + if not success: + assert p.returncode>0 and 'ERROR' in p.stdout+p.stderr, (p.returncode,p.stdout,p.stderr) return p def matrix(path): @@ -86,13 +88,19 @@ def predict(t='GGAGGG',q='CCCC',extra=()): tiny,tiny_values=predict('GGGG','CCCC',seedopt+['--energyAdd=100','--outMaxE=999']) same(tiny_values,single) ztext,etext=tiny.stdout.splitlines()[1].split(';');assert 00 ensemble=run('GGGG','CCCC',seedopt+['--energyAdd=100','--outMode=E']) assert 'Eall 0.00\n' not in ensemble.stdout + # Explicit GU seed admission is separate from complete-interaction GU ends. + _,gu=predict('GGG','CUC',['--seedTQ=2|&2|','--seedNoGU','--seedNoGUend','--outNoGUend']) + same(gu,[[0,0,1],[0,1,0],[1,0,0]]) # Labels use original sequence order and signed display shifts that skip zero. _,normal=predict('GAGGG','CCUCC') _,shifted=predict('GAGGG','CCUCC',['--tIdxPos0=-2','--qIdxPos0=5']) cols,rows,_=matrix(path);assert cols==['C_5','C_6','U_7','C_8','C_9'];assert rows==['G_-2','A_-1','G_1','G_2','G_3'];same(normal,shifted) _,empty=predict('AAAA','AAAA');assert all(v is None for row in empty for v in row) + _,short=predict('G','C');assert short==[[None]] # Coverage and actual pairing differ at the unpaired A bulge. spot=d/'spot.csv';_,with_spot=predict(extra=[f'--out=spotProb:{spot}']) same(with_spot,values) From 20af34770ceb0c76bcaadd31184ee34f02bc43fe Mon Sep 17 00:00:00 2001 From: AlexanderMitrofanov Date: Fri, 9 Oct 2026 11:59:50 +0200 Subject: [PATCH 09/21] feat: add SVG base-pair probability plots (step 8) --- ChangeLog | 19 ++ README.md | 60 ++++- src/IntaRNA/BasePairProbabilities.cpp | 10 +- src/IntaRNA/BasePairProbabilities.h | 15 +- src/IntaRNA/BasePairProbabilitySvg.cpp | 210 ++++++++++++++++++ src/IntaRNA/BasePairProbabilityWriter.cpp | 8 +- src/IntaRNA/BasePairProbabilityWriter.h | 20 ++ src/IntaRNA/Makefile.am | 1 + .../PredictorMfeEns2dSeedExtension.cpp | 9 +- src/bin/CommandLineParsing.cpp | 21 +- src/bin/CommandLineParsing.h | 4 +- tests/BasePairProbabilities_test.cpp | 41 ++++ tests/Makefile.am | 2 +- tests/runBasePairProbabilities.sh | 1 + tests/testBasePairProbabilitySvg.py | 157 +++++++++++++ 15 files changed, 559 insertions(+), 19 deletions(-) create mode 100644 src/IntaRNA/BasePairProbabilitySvg.cpp create mode 100644 tests/testBasePairProbabilitySvg.py diff --git a/ChangeLog b/ChangeLog index bd016930..d04228f5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,6 +14,10 @@ ## Interface and handling +- --out=bpsvg:FILE renders actual-pair probabilities with nucleotide/accessibility + frames, a shared CSS palette, signed-coordinate guides, hover values and admitted + seed outlines (PR #258, step 8) + - --out=bpProb:FILE writes actual-pair conditional probabilities for exact model P/mode M stack-seed ensembles, with disjoint-region merging, original coordinates and success-only publication (issue #257, implementation step 6) @@ -156,6 +160,21 @@ energies, restricted partition sums, and trackers. ################################################################################ ################################################################################ +261009 Alexander Mitrofanov + * BasePairProbabilityWriter, BasePairProbabilitySvg, CommandLineParsing : + + add success-only SVG dot plots on files, gzip and synchronized standard + streams; share CSV normalization and use original sequence coordinates + + show sequence labels, 1-nt accessibility, seven CSS probability classes, + legends, signed 10/50-nt guides, missing-zero boundary and hover values + * BasePairProbabilities, PredictorMfeEns2dSeedExtension : + + optionally retain admitted seed-cell masks with completed regional masses; + annotate seed cells without changing probability or ranked-output semantics + * tests, README.md, src/IntaRNA/Makefile.am, tests/Makefile.am : + + document the SVG contract and register the writer and regression coverage + for coordinates, seed admission, accessibility, empty/failed results and I/O + + investigate the referenced dev-frank profile tracker files: their current + versions contain profile output but no SVG implementation (PR #258 step 8) + 261008 Alexander Mitrofanov * tests, README.md, doc/analysis, doc/seeded-probabilities-example.cpp : + finish probability regression and native performance gates, document the diff --git a/README.md b/README.md index 32f77132..fcb80537 100644 --- a/README.md +++ b/README.md @@ -1876,6 +1876,7 @@ targeted file/stream name: - `qSpotProb:`/`tSpotProb:` [query/target's spot probability profile](#profileSpotProb) (CSV format), respectively - `spotProb:` [all spot probabilities](#spotProb) (CSV format) +- `bpsvg:` [SVG base-pair probability dot plot](#bpsvg), with accessibility frames and seed outlines - `bpProb:` [actual base-pair probabilities](#bpProb) for exact stack-seeded ensembles (CSV matrix) - `qMinE:`/`tMinE:` [the query/target's minimal interaction energy profile](profileMinE) (CSV format), respectively - `pMinE:` [minimal interaction energy for all query-target index pairs](pairMinE) (CSV format) @@ -1883,7 +1884,7 @@ targeted file/stream name: - `qPu:`/`tPu:` the [query/target's unpaired probabilities](#accessibility) (RNAplfold format; rounded!!), respectively Note, for *multiple sequences* in FASTA input, the provided file names are suffixed by -- `-t#q#` : for `bpProb`, `*spotProb` and `*minE` output, and +- `-t#q#` : for `bpProb`, `bpsvg`, `*spotProb` and `*minE` output, and - `-s#` : for `*Acc` and `*Pu` output, where `#` denotes the according target/query sequence number within the input where numbering starts with 1. @@ -2064,6 +2065,63 @@ constraint must enable `needZall`. The [standalone API example](doc/seeded-proba and [implementation validation report](doc/analysis/seeded-probabilities-validation.md) show the public API and measured limits. + + +### SVG base-pair probability dot plots + +`--out=bpsvg:FILE` renders the same actual-pair probabilities as `bpProb` in a +standalone SVG. Both outputs can be requested together. The same exact +`--model=P --mode=M` stack-seed restrictions, regional ensemble, normalization +and success-only publication rules apply. + +```sh +IntaRNA -t GGAGGG -q CCCC --energy=B --acc=N --seedBP=2 \ + --model=P --mode=M --out=bpsvg:pairs.svg --out=bpProb:pairs.csv +``` + +The query is the horizontal axis and the target the vertical axis, both in +original 5' to 3' order. Sequence names label the axes; nucleotides appear on all +four sides. Their colored backgrounds show **single-nucleotide unpaired +probabilities**, computed from the prediction accessibility model's opening +energies. These are distinct from the interaction-conditional probabilities in +the matrix. Disabled accessibility gives probability one at unconstrained bases. +Each probability rectangle has a hover title with its index (pair), type and +full-precision value. An empty interaction ensemble uses gray `NA` cells while +its accessibility frame remains defined. + +A shared seven-step, white-to-dark-blue palette encodes both probability types: +`[0,0.01)`, `[0.01,0.1)`, `[0.1,0.25)`, `[0.25,0.5)`, `[0.5,0.75)`, +`[0.75,0.9)`, and `[0.9,1]`. The legend appears below the plot. Edit the `.p0` +through `.p6` fill rules in the SVG's ` +)SVG"; + out<<"\n"; + auto text=[&](double tx,double ty,const std::string & value,const std::string & cls,const char * anchor="middle") { + out<<""<\n"; + }; + text(width/2,30,"Base-pair probabilities","heading"); + text(x+w/2,y-65,q.getId()+" (5' to 3')","axis"); + out<<""<\n"; + auto rect=[&](double rx,double ry,Z_type value,bool missing,const std::string & attributes,const std::string & title) { + out<<""<<xml(title)<<": "; + if (missing) out<<"NA (empty interaction ensemble)"; else out<<value; + out<<"\n"; + }; + out<<"\n"; + for(size_t i=0;i\n\n"; + for(bool target:{false,true}) { + const auto & seq=target?t:q; + const auto & acc=target?at:aq; + for(size_t i=0;i=.75?"nt nt-light":"nt"); + } + } + } + out<<"\n\n"; + for(bool target:{false,true}) { + const auto & seq=target?t:q; + for(size_t i=0;i0 && seq.getInOutIndex(i-1)==-1; + if (idx%10!=0 && idx!=1) continue; + // Negative multiples: before the labelled nt (-11|-10); positive: + // after it (10|11). At the missing zero: -1|+1. + const double offset=cell*(i+(idx>0 && !origin?1:0)); + if (idx%10==0 || origin) out<<"\n"; + const std::string label=idx==1?"+1":std::to_string(idx); + if(target) { + text(x-26,y+cell*(i+.5)+4,label,"index","end"); + text(x+w+26,y+cell*(i+.5)+4,label,"index","start"); + } else { + text(x+cell*(i+.5),y-28,label,"index"); + text(x+cell*(i+.5),y+h+38,label,"index"); + } + } + } + out<<"\n\n"; + bool annotated=false; + if(result.collectsSeedPairs()) { + out<<"\n"; + for(size_t i=0;i\n"; + } + out<<"\n"; + } + const double legendX=(width-7*86)/2, legendY=y+h+85; + text(width/2,legendY-14,"Probability ranges (base pairs and single-nucleotide accessibility)","legend"); + out<<"\n"; + for(size_t k=0;k\n"; + std::ostringstream range; + range.imbue(std::locale::classic()); + range<<'['<\n"; + if (annotated) { + out<<"\n"; + text(legendX+28,legendY+61,"Orange outline: pair in an admitted seed within a searched region","legend","start"); + } + if(empty) text(width/2,legendY+90,"Gray / NA: empty interaction ensemble; accessibility remains defined","legend"); + out<<"\n"; + return out.str(); +} + +void BasePairProbabilityWriter::writeSvg(std::ostream & out,const BasePairProbabilities & result,const InteractionEnergy & energy) +{ + emit(out,svgBlock(result,energy)); +} + +void BasePairProbabilityWriter::writeSvgFile(const std::string & filename,const BasePairProbabilities & result,const InteractionEnergy & energy) +{ + emitFile(filename,svgBlock(result,energy)); +} + +} // namespace IntaRNA diff --git a/src/IntaRNA/BasePairProbabilityWriter.cpp b/src/IntaRNA/BasePairProbabilityWriter.cpp index d0aea7af..6d679fdd 100644 --- a/src/IntaRNA/BasePairProbabilityWriter.cpp +++ b/src/IntaRNA/BasePairProbabilityWriter.cpp @@ -36,7 +36,7 @@ void BasePairProbabilityWriter::emit(std::ostream & out,const std::string & data { try { out< file(out==&std::cout || out==&std::cerr?nullptr:out); diff --git a/src/IntaRNA/BasePairProbabilityWriter.h b/src/IntaRNA/BasePairProbabilityWriter.h index 48578daf..41d7c1a2 100644 --- a/src/IntaRNA/BasePairProbabilityWriter.h +++ b/src/IntaRNA/BasePairProbabilityWriter.h @@ -6,6 +6,7 @@ #include namespace IntaRNA { +class InteractionEnergy; /** Explicit writer for a completed actual-pair matrix, independent of trackers. * Whole blocks are synchronized for shared streams. No destructor emits data. */ @@ -30,7 +31,26 @@ class BasePairProbabilityWriter { */ static void writeFile(const std::string & filename,const BasePairProbabilities & result, const RnaSequence & target,const RnaSequence & query,const std::string & separator=";"); + /** Write a complete SVG dot plot with original target rows/query columns. + * Includes 1-nt accessibility, signed coordinate guides and a CSS color legend. + * Seed outlines are included if the result collected admitted seed pairs. + * @param out destination stream; an I/O failure throws + * @param result explicitly finalized raw result + * @param energy original, unshifted energy/accessibility model used in prediction + */ + static void writeSvg(std::ostream & out,const BasePairProbabilities & result, + const InteractionEnergy & energy); + /** Write a complete SVG to a file or STDOUT/STDERR, including gzip support. + * Validates the whole document before opening the destination. + * @param filename destination (already expanded for multi-FASTA) + * @param result explicitly finalized raw result + * @param energy original, unshifted energy/accessibility model + */ + static void writeSvgFile(const std::string & filename,const BasePairProbabilities & result, + const InteractionEnergy & energy); private: + static std::string svgBlock(const BasePairProbabilities & result,const InteractionEnergy & energy); + static void emitFile(const std::string & name,const std::string & data); static std::string block(const BasePairProbabilities & result,const RnaSequence & target, const RnaSequence & query,const std::string & separator); static void emit(std::ostream & out,const std::string & data); diff --git a/src/IntaRNA/Makefile.am b/src/IntaRNA/Makefile.am index 4fc5db3e..178691d6 100644 --- a/src/IntaRNA/Makefile.am +++ b/src/IntaRNA/Makefile.am @@ -106,6 +106,7 @@ libIntaRNA_a_SOURCES = \ StackSeedDomain.cpp \ BasePairProbabilities.cpp \ BasePairProbabilityWriter.cpp \ + BasePairProbabilitySvg.cpp \ SeededPartitionFunction.cpp \ $(libmylib_a_HEADERS) \ Accessibility.cpp \ diff --git a/src/IntaRNA/PredictorMfeEns2dSeedExtension.cpp b/src/IntaRNA/PredictorMfeEns2dSeedExtension.cpp index 4f50a61e..fb7c8929 100644 --- a/src/IntaRNA/PredictorMfeEns2dSeedExtension.cpp +++ b/src/IntaRNA/PredictorMfeEns2dSeedExtension.cpp @@ -185,11 +185,18 @@ PredictorMfeEns2dSeedExtension::predictStackSeeds(const IndexRange & r1,const In const auto first=energy.getBasePair(0,0), last=energy.getBasePair(n-1,m-1); const IndexRange target(first.first,last.first), query(last.second,first.second); Matrix original(n,m,0); + const bool annotate=pairProbabilities->collectsSeedPairs(); + Matrix seedPairs(annotate?n:0,annotate?m:0,0); for(size_t i=0;iaddRegion(target,query,result.z,original); + pairProbabilities->addRegion(target,query,result.z,original,annotate?&seedPairs:nullptr); } } diff --git a/src/bin/CommandLineParsing.cpp b/src/bin/CommandLineParsing.cpp index dc864b8c..77455d1e 100644 --- a/src/bin/CommandLineParsing.cpp +++ b/src/bin/CommandLineParsing.cpp @@ -957,6 +957,7 @@ CommandLineParsing::CommandLineParsing( const Personality personality ) "\n 'tAcc:' (target) ED accessibility values ('tPu'-like format OR '.agz' file ending for IntaRNA's binary format)." "\n 'tPu:' (target) unpaired probability values (RNAplfold format OR '.agz' file ending for IntaRNA's binary format)." "\n 'pMinE:' (target+query) for each index pair the minimal energy of any interaction covering the pair (CSV format)" + "\n 'bpsvg:' (target+query) SVG actual-pair probability plot with accessibility frame and seed annotations; same requirements as bpProb" "\n 'bpProb:' (target+query) actual-pair conditional probabilities for exact --model=P --mode=M stack-seed ensembles (CSV matrix, original strand order; NA for an empty ensemble)" "\n 'spotProb:' (target+query) tracks for a given set of interaction spots their probability to be covered by an interaction. If no spots are provided, probabilities for all index combinations are computed. Spots are encoded by comma-separated 'idxT&idxQ' pairs (target-query). For each spot a probability is provided in concert with the probability that none of the spots (encoded by '0&0') is covered (CSV format). The spot encoding is followed colon-separated by the output stream/file name, eg. '--out=\"spotProb:3&76,59&2:STDERR\"'. NOTE: value has to be quoted due to '&' symbol!" "\nFor each, provide a file name or STDOUT/STDERR to write to the respective output stream." @@ -1246,7 +1247,7 @@ parse(int argc, char** argv) if (hasBasePairProbabilityOutput()) { if (model.val!='P' || mode.val!='M' || noSeedRequired || !rri.empty() || windowWidth.val!=0) - throw error("bpProb requires --model=P --mode=M with stack-only seeds and no windows"); + throw error("bpProb/bpsvg requires --model=P --mode=M with stack-only seeds and no windows"); outNeedsZall=true; } // K needs a seed even before the usual --noSeed model normalization. @@ -1582,7 +1583,7 @@ parse(int argc, char** argv) for (auto c2=c1; noDuplicate && (++c2)!=outPrefix2streamName.end();) { if ( ! c2->second.empty() && boost::iequals( c1->second, c2->second ) ) { // Pair matrices emit synchronized complete blocks on shared standard streams. - if ((c1->first==OP_bpProb || c2->first==OP_bpProb) + if ((c1->first==OP_bpProb || c2->first==OP_bpProb || c1->first==OP_bpsvg || c2->first==OP_bpsvg) && (boost::iequals(c1->second,"STDOUT") || boost::iequals(c1->second,"STDERR"))) continue; noDuplicate = false; throw error("--out argument shows multiple times '"+toString(c1->second)+"' as target file/stream."); @@ -2490,19 +2491,23 @@ getTemperature() const { //////////////////////////////////////////////////////////////////////////// bool CommandLineParsing::hasBasePairProbabilityOutput() const { - return !outPrefix2streamName.at(OutPrefixCode::OP_bpProb).empty(); + return !outPrefix2streamName.at(OutPrefixCode::OP_bpProb).empty() + || !outPrefix2streamName.at(OutPrefixCode::OP_bpsvg).empty(); } BasePairProbabilities * CommandLineParsing::getBasePairProbabilityResult(const InteractionEnergy & energy) const { if (!hasBasePairProbabilityOutput()) return nullptr; std::unique_ptr handler(getSeedHandler(energy)); if (!handler->guaranteesStackOnlySeeds()) - throw std::invalid_argument("bpProb requires a stack-only seed handler; bulged seeds are unsupported"); - return new BasePairProbabilities(energy.size1(),energy.size2()); + throw std::invalid_argument("bpProb/bpsvg requires a stack-only seed handler; bulged seeds are unsupported"); + return new BasePairProbabilities(energy.size1(),energy.size2(),!outPrefix2streamName.at(OP_bpsvg).empty()); } void CommandLineParsing::writeBasePairProbabilities(const BasePairProbabilities & result,const InteractionEnergy & energy) const { const auto & t=energy.getAccessibility1().getSequence(); const auto & q=energy.getAccessibility2().getAccessibilityOrigin().getSequence(); - BasePairProbabilityWriter::writeFile(getFullFilename(outPrefix2streamName.at(OutPrefixCode::OP_bpProb),&t,&q),result,t,q,outSep); + if (!outPrefix2streamName.at(OP_bpProb).empty()) + BasePairProbabilityWriter::writeFile(getFullFilename(outPrefix2streamName.at(OP_bpProb),&t,&q),result,t,q,outSep); + if (!outPrefix2streamName.at(OP_bpsvg).empty()) + BasePairProbabilityWriter::writeSvgFile(getFullFilename(outPrefix2streamName.at(OP_bpsvg),&t,&q),result,energy); } Predictor* @@ -2512,10 +2517,10 @@ getPredictor( const InteractionEnergy & energy, OutputHandler & output, BasePair std::unique_ptr pairSeeds; if (pairProbabilities) { if(model.val!='P' || mode.val!='M' || noSeedRequired || !rri.empty() || windowWidth.val!=0) - throw std::invalid_argument("bpProb requires --model=P --mode=M with stack-only seeds and no windows"); + throw std::invalid_argument("bpProb/bpsvg requires --model=P --mode=M with stack-only seeds and no windows"); pairSeeds.reset(getSeedHandler(energy)); if(!pairSeeds->guaranteesStackOnlySeeds()) - throw std::invalid_argument("bpProb requires a stack-only seed handler; bulged seeds are unsupported"); + throw std::invalid_argument("bpProb/bpsvg requires a stack-only seed handler; bulged seeds are unsupported"); } // set up hub for prediction tracking (if needed) PredictionTrackerHub * predTracker = new PredictionTrackerHub(); diff --git a/src/bin/CommandLineParsing.h b/src/bin/CommandLineParsing.h index fff52480..f0216b37 100644 --- a/src/bin/CommandLineParsing.h +++ b/src/bin/CommandLineParsing.h @@ -289,7 +289,7 @@ class CommandLineParsing { Predictor* getPredictor( const InteractionEnergy & energy , OutputHandler & output, BasePairProbabilities * pairProbabilities = nullptr ) const; - /** @return whether actual base-pair matrix output was requested */ + /** @return whether actual base-pair CSV or SVG output was requested */ bool hasBasePairProbabilityOutput() const; /** Allocate a pair result after validating the actual seed capability. * @return owned result or nullptr when pair output is not requested @@ -416,6 +416,7 @@ class CommandLineParsing { OP_spotProb, OP_spotProbAll, OP_bpProb, + OP_bpsvg, OP_UNKNOWN }; @@ -442,6 +443,7 @@ class CommandLineParsing { if (prefLC == "tacc") { return OutPrefixCode::OP_tAcc; } else if (prefLC == "qpu") { return OutPrefixCode::OP_qPu; } else if (prefLC == "tpu") { return OutPrefixCode::OP_tPu; } else + if (prefLC == "bpsvg") { return OutPrefixCode::OP_bpsvg; } else if (prefLC == "bpprob") { return OutPrefixCode::OP_bpProb; } else if (prefLC == "spotprob") { return OutPrefixCode::OP_spotProb; } else // not known diff --git a/tests/BasePairProbabilities_test.cpp b/tests/BasePairProbabilities_test.cpp index 500c306c..669071cb 100644 --- a/tests/BasePairProbabilities_test.cpp +++ b/tests/BasePairProbabilities_test.cpp @@ -48,3 +48,44 @@ TEST_CASE("pair writer validates before emitting and checks stream failure", "[B BasePairProbabilityWriter::write(na,empty,t,q); REQUIRE(na.str()=="bpProb;U_1;C_2\nG_1;NA;NA\nA_2;NA;NA\n"); } + +#include "IntaRNA/AccessibilityDisabled.h" +#include "IntaRNA/InteractionEnergyBasePair.h" +TEST_CASE("seed annotations commit with regional masses and SVG requires success", "[BasePairProbabilities]") { + #include "testEasyLoggingSetup.icc" + RnaSequence t("target<&", "GGGG"),q("query", "CCCCC"); + AccessibilityDisabled at(t,0,nullptr),aq(q,0,nullptr); + ReverseAccessibility ar(aq); InteractionEnergyBasePair energy(at,ar); + BasePairProbabilities r(4,5,true); + Matrix mass(2,2,0);mass(0,1)=2;mass(1,0)=2; + Matrix seeds(2,2,0);seeds(0,1)=1; + r.addRegion({0,1},{1,2},2,mass,&seeds); + r.addRegion({2,3},{3,4},2,mass,&seeds); + REQUIRE(r.collectsSeedPairs());REQUIRE(r.seedPairs()(0,2)==1); + REQUIRE(r.seedPairs()(2,4)==1);REQUIRE(r.seedPairs()(1,1)==0); + std::ostringstream pending; + REQUIRE_THROWS(BasePairProbabilityWriter::writeSvg(pending,r,energy)); + REQUIRE(pending.str().empty()); + r.finalize();std::ostringstream svg; + BasePairProbabilityWriter::writeSvg(svg,r,energy); + REQUIRE(svg.str().find("target<&")!=std::string::npos); + REQUIRE(svg.str().find("Orange outline:")!=std::string::npos); + std::ostringstream broken;broken.setstate(std::ios::badbit); + REQUIRE_THROWS(BasePairProbabilityWriter::writeSvg(broken,r,energy)); + r.fail();std::ostringstream failed; + REQUIRE_THROWS(BasePairProbabilityWriter::writeSvg(failed,r,energy)); + REQUIRE(failed.str().empty()); + BasePairProbabilities missing(4,5,true); + REQUIRE_THROWS(missing.addRegion({0,1},{1,2},2,mass)); + REQUIRE(missing.status()==BasePairProbabilities::Status::failed); + REQUIRE(missing.getZ()==0);REQUIRE(missing.seedPairs()(0,2)==0); + BasePairProbabilities plain(4,5); + REQUIRE_FALSE(plain.collectsSeedPairs());REQUIRE(plain.seedPairs().size1()==0); + plain.finalize();std::ostringstream empty; + BasePairProbabilityWriter::writeSvg(empty,plain,energy); + REQUIRE(empty.str().find("data-probability=\"NA\"")!=std::string::npos); + REQUIRE(empty.str().find("Orange outline:")==std::string::npos); + BasePairProbabilities wrongSize(1,1);wrongSize.finalize();std::ostringstream wrong; + REQUIRE_THROWS(BasePairProbabilityWriter::writeSvg(wrong,wrongSize,energy)); + REQUIRE(wrong.str().empty()); +} diff --git a/tests/Makefile.am b/tests/Makefile.am index 5a919fb1..4d184d6b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -85,4 +85,4 @@ runApiTests_CXXFLAGS = -I$(top_builddir)/src \ -EXTRA_DIST = tools/export-seeded-theory.py testBasePairProbabilities.py +EXTRA_DIST = tools/export-seeded-theory.py testBasePairProbabilities.py testBasePairProbabilitySvg.py diff --git a/tests/runBasePairProbabilities.sh b/tests/runBasePairProbabilities.sh index be6d002c..b68221c6 100644 --- a/tests/runBasePairProbabilities.sh +++ b/tests/runBasePairProbabilities.sh @@ -2,3 +2,4 @@ set -euo pipefail script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) python3 "$script_dir/testBasePairProbabilities.py" "$INTARNABINPATH/src/bin/IntaRNA" +python3 "$script_dir/testBasePairProbabilitySvg.py" "$INTARNABINPATH/src/bin/IntaRNA" diff --git a/tests/testBasePairProbabilitySvg.py b/tests/testBasePairProbabilitySvg.py new file mode 100644 index 00000000..29047ef3 --- /dev/null +++ b/tests/testBasePairProbabilitySvg.py @@ -0,0 +1,157 @@ +"""SVG semantics, original coordinates, seed provenance and output lifecycle.""" +import csv +import gzip +import math +from pathlib import Path +import re +import subprocess +import sys +import tempfile +import xml.etree.ElementTree as ET + +BIN = sys.argv[1] +COMMON = ['--energy=B', '--acc=N', '--model=P', '--mode=M', '--seedBP=2', + '--threads=1', '--outNoLP=false', '--outNoGUend=false', '--outNumber=0', + '--default-log-file=/dev/null'] +NS = {'s': 'http://www.w3.org/2000/svg'} + + +def run(t='GGAGGG', q='CCCC', options=(), success=True): + keys = {o.split('=')[0] for o in options} + p = subprocess.run([BIN, f'--target={t}', f'--query={q}', + *[o for o in COMMON if o.split('=')[0] not in keys], *options], + text=True, capture_output=True) + assert (p.returncode == 0) == success, (options, p.stdout, p.stderr) + return p + + +def load(path): + return ET.fromstring(gzip.decompress(path.read_bytes()) if str(path).endswith('.gz') else path.read_bytes()) + + +def pairs(root): + return {(int(r.attrib['data-target']), int(r.attrib['data-query'])): r + for r in root.findall('.//s:rect[@data-type="base-pair"]', NS)} + + +def seeds(root): + return {(int(r.attrib['data-target']), int(r.attrib['data-query'])) + for r in root.findall('.//s:rect[@class="seed"][@data-target]', NS)} + + +with tempfile.TemporaryDirectory(prefix='intarna-bpsvg-') as tmp: + d = Path(tmp) + svg, table = d/'pairs.svg', d/'pairs.csv' + + def plot(t='GGAGGG', q='CCCC', opts=()): + run(t, q, [f'--out=bpsvg:{svg}', *opts]) + return load(svg) + + root = plot(opts=[f'--out=bpProb:{table}']) + cells = pairs(root) + rows = list(csv.reader(table.open(), delimiter=';')) + assert len(cells) == 24 + assert '+1' in [e.text for e in root.findall('.//s:text[@class="index"]', NS)] + assert not root.findall('.//s:line[@data-index="1"]', NS) + for i, row in enumerate(rows[1:], 1): + for j, value in enumerate(row[1:], 1): + r = cells[i, j] + assert float(r.attrib['data-probability']) == float(value) + bounds = [0.01, 0.1, 0.25, 0.5, 0.75, 0.9] + expected_color = sum(float(value) >= boundary for boundary in bounds) + assert f'p{expected_color}' in r.attrib['class'].split() + assert 'Base-pair probability' in r.find('s:title', NS).text + assert all(float(cells[3, j].attrib['data-probability']) == 0 for j in range(1, 5)) + frame = root.findall('.//s:rect[@data-type="unpaired"]', NS) + assert len(frame) == 2*(6+4) + assert all(float(r.attrib['data-probability']) == 1 for r in frame) + assert all('Unpaired probability' in r.find('s:title', NS).text for r in frame) + css = root.find('s:style', NS).text + assert all(f'.p{i} {{ fill:' in css for i in range(7)) + assert len(root.findall('.//s:g[@class="probability-legend"]/s:rect', NS)) == 7 + # All admitted computed two-pair stacks, in original query orientation. + expected = {(i+k+1, 4-j-k) for i in (0, 3, 4) for j in range(3) for k in range(2)} + assert seeds(root) == expected, seeds(root) + # Requesting SVG must not affect CSV or ensemble/ranked output. + baseline = run(options=['--outNumber=1', '--outMode=C', '--outCsvCols=Zall,Eall']) + plotted = run(options=['--outNumber=1', '--outMode=C', '--outCsvCols=Zall,Eall', f'--out=bpsvg:{svg}']) + assert baseline.stdout == plotted.stdout + # Explicit singleton/mixed seed masks exclude extension-only cells. + opts = ['--seedTQ=1|&4|,2||&2||'] + mixed = plot('GGGG', 'CCCC', opts) + assert seeds(mixed) == {(1,4), (2,3), (3,2)} + restricted = plot('GGGG', 'CCCC', [*opts, '--tRegion=2-4', '--qRegion=1-3']) + assert seeds(restricted) == {(2,3), (3,2)} + # A seed crossing a searched region boundary is not annotated. + cut = plot('GGGG', 'CCCC', ['--seedTQ=2||&2||', '--tRegion=1-2,3-4']) + assert not seeds(cut) + assert all(r.attrib['data-probability'] == 'NA' for r in pairs(cut).values()) + # Four disjoint rectangles merge both probabilities and masks. + regional = plot('GGGG', 'CCCC', ['--tRegion=1-2,3-4', '--qRegion=1-2,3-4']) + assert seeds(regional) == {(1,2),(2,1),(1,4),(2,3),(3,2),(4,1),(3,4),(4,3)} + # Signed guides follow displayed coordinates; there is no zero nucleotide. + signed = plot('A'*72, 'A'*18, ['--tIdxPos0=-15', '--qIdxPos0=-15']) + signed_cells = pairs(signed) + for strand, length in (('target',72), ('query',18)): + guides = signed.findall(f'.//s:line[@data-strand="{strand}"]', NS) + expected_indices = {-10, 1} | ({10,20,30,40,50} if length == 72 else set()) + assert {int(g.attrib['data-index']) for g in guides} == expected_indices + assert not any(0 in k for k in signed_cells) + for g in guides: + idx = int(g.attrib['data-index']) + r = signed_cells[idx,-15] if strand == 'target' else signed_cells[-15,idx] + axis = 'y' if strand == 'target' else 'x' + expected_pos = float(r.attrib[axis]) + (20 if idx > 1 else 0) + assert float(g.attrib[axis+'1']) == expected_pos + assert ('major' in g.attrib['class']) == (idx % 50 == 0) + assert ('origin' in g.attrib['class']) == (idx == 1) + negative = plot('A'*13, 'A'*13, ['--tIdxPos0=-55', '--qIdxPos0=45']) + assert 'major' in negative.find('.//s:line[@data-strand="target"][@data-index="-50"]', NS).attrib['class'] + # User sequence identifiers must round-trip through XML escaping. + name = '' + named = plot(opts=[f'--tId={name}']) + assert name in named.find('s:title', NS).text + assert name+" (5' to 3')" in [e.text for e in named.findall('.//s:text', NS)] + # Native accessibility values must use original (not reversed) query order. + pu_t, pu_q = d/'target.pu', d/'query.pu' + native = plot('GGGGAAAACCCC', 'GCGCGAAAACGCGC', + ['--energy=V', '--acc=C', f'--out=tPu:{pu_t}', f'--out=qPu:{pu_q}']) + for strand, path in (('target', pu_t), ('query', pu_q)): + expected_pu = [float(line.split()[1]) for line in path.read_text().splitlines() + if line.strip() and not line.lstrip().startswith('#')] + assert any(0 < v < .9 for v in expected_pu) + for r in native.findall(f'.//s:rect[@data-type="unpaired"][@data-strand="{strand}"]', NS): + assert math.isclose(float(r.attrib['data-probability']), expected_pu[int(r.attrib['data-index'])-1], + rel_tol=2e-5, abs_tol=1e-6) + for t,q in (('AAAA','AAAA'), ('G','C')): + empty = plot(t,q) + assert all(r.attrib['data-probability'] == 'NA' for r in pairs(empty).values()) + assert not seeds(empty) + assert 'empty interaction ensemble' in ''.join(empty.itertext()) + compressed = d/'pairs.svg.gz' + run(options=[f'--out=bpsvg:{compressed}']) + assert len(pairs(load(compressed))) == 24 + # Validation/numerical failures must not publish a partial document. + for opts in (['--mode=H'], ['--noSeed'], ['--seedMaxUP=1'], ['--model=X', '--mode=K'], + ['--windowWidth=3'], ['--seedTQ=1|&4|','--energyAdd=900']): + failure = d/'failure.svg' + run(options=[f'--out=bpsvg:{failure}', *opts], success=False) + assert not failure.exists() + run(options=['--out=bpsvg:/dev/full'], success=False) + run(options=[f'--out=bpsvg:{svg}', f'--out=bpProb:{svg}'], success=False) + # Multi-FASTA creates one SVG per pair; shared streams emit indivisible roots. + fasta=d/'targets.fa'; fasta.write_text('>a\nGGGG\n>b\nGAGG\n') + for threads in (1,2): + prefix=d/f'multi{threads}.svg' + run(str(fasta), 'CCCC', [f'--threads={threads}', f'--out=bpsvg:{prefix}']) + files=sorted(d.glob(f'multi{threads}*.svg')) + assert len(files)==2 + assert all(len(pairs(load(file)))==16 for file in files) + for stream in ('STDOUT', 'STDERR'): + shared=run(str(fasta), 'CCCC', [f'--threads={threads}', f'--out=bpsvg:{stream}']) + data=shared.stdout if stream=='STDOUT' else shared.stderr + blocks=re.findall(r'', data, re.S) + assert len(blocks)==2 + assert all(len(pairs(ET.fromstring(block)))==16 for block in blocks) + +print('base-pair probability SVG regressions passed') From fa2f84d6cdbb1e120a98eab9d2dfe3f8154ebad5 Mon Sep 17 00:00:00 2001 From: AlexanderMitrofanov Date: Fri, 9 Oct 2026 12:11:59 +0200 Subject: [PATCH 10/21] docs: depict ensemble and pair-probability recurrences (step 9) --- ChangeLog | 13 ++++ doc/recursions/IntaRNA.PredictorMfeEns2d.svg | 60 +++++++++++++++++ .../IntaRNA.PredictorMfeEns2dHeuristic.svg | 51 ++++++++++++++ ...redictorMfeEns2dHeuristicSeedExtension.svg | 51 ++++++++++++++ ....PredictorMfeEns2dSeedExtension.legacy.svg | 61 +++++++++++++++++ ...IntaRNA.PredictorMfeEns2dSeedExtension.svg | 54 +++++++++++++++ .../IntaRNA.PredictorMfeEnsSeedOnly.svg | 41 ++++++++++++ ...IntaRNA.SeededPartitionFunction.inside.svg | 59 ++++++++++++++++ ...ntaRNA.SeededPartitionFunction.outside.svg | 67 +++++++++++++++++++ 9 files changed, 457 insertions(+) create mode 100644 doc/recursions/IntaRNA.PredictorMfeEns2d.svg create mode 100644 doc/recursions/IntaRNA.PredictorMfeEns2dHeuristic.svg create mode 100644 doc/recursions/IntaRNA.PredictorMfeEns2dHeuristicSeedExtension.svg create mode 100644 doc/recursions/IntaRNA.PredictorMfeEns2dSeedExtension.legacy.svg create mode 100644 doc/recursions/IntaRNA.PredictorMfeEns2dSeedExtension.svg create mode 100644 doc/recursions/IntaRNA.PredictorMfeEnsSeedOnly.svg create mode 100644 doc/recursions/IntaRNA.SeededPartitionFunction.inside.svg create mode 100644 doc/recursions/IntaRNA.SeededPartitionFunction.outside.svg diff --git a/ChangeLog b/ChangeLog index d04228f5..613764ff 100644 --- a/ChangeLog +++ b/ChangeLog @@ -50,6 +50,9 @@ ## Technical changes and Optimizations +- depict ensemble predictor recurrences and the exact base-pair inside/outside + computation in internal SVG documentation (PR #258, step 9) + - validate exact pair probabilities on independent mathematical/native oracles, release/debug suites and installed consumers; document measured runtime and storage, and supply the required logging link dependency (issue #257, step 7) @@ -160,6 +163,16 @@ energies, restricted partition sums, and trackers. ################################################################################ ################################################################################ +261009 Alexander Mitrofanov + * doc/recursions/IntaRNA.PredictorMfeEns*.svg, + doc/recursions/IntaRNA.SeededPartitionFunction.*.svg : + + add eight standalone internal SVG depictions for unseeded exact/heuristic, + seed-only, exact stack-seeded, legacy and heuristic seed-extension paths + + show noLP transitions, seed admission and energy ownership, the production + suffix inside/outside recurrences, actual-pair marking and regional merging + + include implementation anchors and retain editable vector text; validate + XML, glyph coverage and rendered layouts (PR #258 step 9, PR #259) + 261009 Alexander Mitrofanov * BasePairProbabilityWriter, BasePairProbabilitySvg, CommandLineParsing : + add success-only SVG dot plots on files, gzip and synchronized standard diff --git a/doc/recursions/IntaRNA.PredictorMfeEns2d.svg b/doc/recursions/IntaRNA.PredictorMfeEns2d.svg new file mode 100644 index 00000000..674ba774 --- /dev/null +++ b/doc/recursions/IntaRNA.PredictorMfeEns2d.svg @@ -0,0 +1,60 @@ + +Unseeded ensemble · fixed right boundary +PredictorMfeEns2d | --model=P --mode=M --noSeed. Internal recurrence documentation for step 9 of PR 258. Equations describe the current implementation; RNA 2 uses reversed energy coordinates. + + + +INTARNA / RECURRENCE NOTES +Unseeded ensemble · fixed right boundary +PredictorMfeEns2d | --model=P --mode=M --noSeed + +Pair indices i=(i₁,i₂), k and j increase on both strands; RNA 2 is reversed. +i ≺ k means strict increase in both coordinates. d=BW(E_init), t(i,k)=BW(E_interLeft(i,k)). +Hⱼ(i) = hybrid partition for all admitted chains from i to a fixed j + +Initiation + +Direct pair-to-pair step + +Recursive continuation + + + +i = j +d + + + +i + +j +t(i,j) · d + +Hⱼ(k) + + + +i + +k + +j +t(i,k) · Hⱼ(k) +Lonely pairs allowed +Hⱼ(j)=d; Hⱼ(i)=t(i,j)d + ∑ t(i,k)Hⱼ(k) (i ≺ k ≺ j) +All other or noncomplementary states are zero. Sum only loop-size-admissible steps. +For every valid right pair j, fill i in decreasing order within the span limits. + +noLP: the left boundary must stack to i⁺ = i + (1,1) +Hⱼ(j)=0; Hⱼ(i)=t(i,i⁺) · [ (d if i⁺=j, else Hⱼ(i⁺)) + ∑ t(i⁺,k)Hⱼ(k) ] +The sum requires i⁺ ≺ k ≺ j and k ≠ i⁺+(1,1): the direct stack is already in Hⱼ(i⁺). +Require a complementary i⁺. Unreachable suffixes are zero; the adjacent two-pair case contributes t(i,j)d. +Thus initialization is a stack, and each nonstack continuation starts another stacked suffix. +Zall += B(i,j) · Hⱼ(i); E_site = energy.getE(i,j, energy.getE(Hⱼ(i))) +B(i,j)=BW(energy.getE(i₁,j₁,i₂,j₂,0)) for admitted boundaries; otherwise B=0. +This adds full-interval ED and terminal terms once; updateCompleteZ submits each boundary once. + +Implementation anchors (src/IntaRNA/) · BW(E)=exp(−E/RT) after native energy-unit conversion +PredictorMfeEns2d.cpp: predict(), fillHybridZ() +PredictorMfeEns.cpp: updateCompleteZ(), addPartitionContribution() + diff --git a/doc/recursions/IntaRNA.PredictorMfeEns2dHeuristic.svg b/doc/recursions/IntaRNA.PredictorMfeEns2dHeuristic.svg new file mode 100644 index 00000000..fd048c48 --- /dev/null +++ b/doc/recursions/IntaRNA.PredictorMfeEns2dHeuristic.svg @@ -0,0 +1,51 @@ + +Unseeded ensemble · heuristic continuation +PredictorMfeEns2dHeuristic | --model=P --mode=H --noSeed. Internal recurrence documentation for step 9 of PR 258. Equations describe the current implementation; RNA 2 uses reversed energy coordinates. + + + +INTARNA / RECURRENCE NOTES +Unseeded ensemble · heuristic continuation +PredictorMfeEns2dHeuristic | --model=P --mode=H --noSeed + +C(i)=(vᵢ,jᵢ) retains one hybrid weight and right boundary for each left pair i. +Use d=BW(E_init), t(i,k)=BW(E_interLeft(i,k)); all pair coordinates increase internally. + +Enumerate candidates at i, visiting i in decreasing order + +vₖ + + + +i + +k + +jₖ +Lonely pairs allowed: + initial candidate (d, i) + continuation (t(i,k) · vₖ, jₖ) for each reachable k ≻ i + within loop limits and the complete span limits. + + +Accumulate every considered candidate +updateZ(i,j,v,true) +Adds B(i,j)v to Zall and v to the boundary map. +B is the admitted complete-boundary Boltzmann factor. + +Retain only the best continuation at i +C(i) ← argmin E_full(i,j,v) +Compare complete energy for each candidate. +Strict improvement replaces vᵢ and jᵢ. + +noLP candidate set +Let i⁺=i+(1,1) be complementary and s=t(i,i⁺). +Initialize (s·d, i⁺); add direct continuation (s·vᵢ⁺, jᵢ⁺). +Other candidates are (s·t(i⁺,k)·vₖ, jₖ), with k ≻ i⁺ and k ≠ i⁺+(1,1). +The adjacent continuation is excluded from the loop sum because it was handled directly. +The boundary map sums contributions, but the DP cell keeps one right continuation: this is a restricted ensemble. + +Implementation anchors (src/IntaRNA/) · BW(E)=exp(−E/RT) after native energy-unit conversion +PredictorMfeEns2dHeuristic.cpp: fillHybridZ() +PredictorMfeEns.cpp: updateZ(), updateOptimaUsingZ() + diff --git a/doc/recursions/IntaRNA.PredictorMfeEns2dHeuristicSeedExtension.svg b/doc/recursions/IntaRNA.PredictorMfeEns2dHeuristicSeedExtension.svg new file mode 100644 index 00000000..6f7c7fa8 --- /dev/null +++ b/doc/recursions/IntaRNA.PredictorMfeEns2dHeuristicSeedExtension.svg @@ -0,0 +1,51 @@ + +Seeded ensemble · one selected right extension +PredictorMfeEns2dHeuristicSeedExtension | --model=P --mode=H. Internal recurrence documentation for step 9 of PR 258. Equations describe the current implementation; RNA 2 uses reversed energy coordinates. + + + +INTARNA / RECURRENCE NOTES +Seeded ensemble · one selected right extension +PredictorMfeEns2dHeuristicSeedExtension | --model=P --mode=H + +For anchor seed a…b: S=BW(E_seed), d=BW(E_init), L=Lₐ(i), R=R_b(j). +L and R use the inherited legacy extension recurrences, even when the seed handler is stack-only. + +1 Compute R, submit true right extensions, and select j* +updateZ(a,j, d · S · R_b(j), true) for j ≻ b +j* = argmin E_full(a,j, d · S · R_b(j)) over right-end-admissible candidates +updateOptRightZ compares complete energy and the right GU-end restriction; ties retain the first candidate. + + +2 Compute corrected L and submit left-side combinations + +L + + + + +i + +a + + +b + +j* +updateZ(i,b, Lₐ(i) · S, true) +Includes the seed-only case i=a. +updateZ(i,j*, Lₐ(i) · S · R_b(j*), true) +Only for a true left extension and a true selected right extension, +with both complete spans within their limits. + +Candidate family per anchor +All true right-only extensions + all corrected left-only extensions + left extensions paired with just j*. +The second phase runs if noGUend is off, or a valid right optimum exists, or anchor end b is not GU. +Initialize j*=b and E_right_opt=∞. A positive selected R is required before combining both sides. +No full Cartesian product of left and right boundaries is retained, and bpProb / bpsvg are unsupported. +Every update is filtered and accumulated by PredictorMfeEns::updateZ; ranked reporting is a separate step. + +Implementation anchors (src/IntaRNA/) · BW(E)=exp(−E/RT) after native energy-unit conversion +PredictorMfeEns2dHeuristicSeedExtension.cpp: predict(), fillHybridZ_right(), fillHybridZ_left() +PredictorMfeEns2dHeuristicSeedExtension.h: updateOptRightZ(); inherited legacy fillHybridZ kernels + diff --git a/doc/recursions/IntaRNA.PredictorMfeEns2dSeedExtension.legacy.svg b/doc/recursions/IntaRNA.PredictorMfeEns2dSeedExtension.legacy.svg new file mode 100644 index 00000000..f19dc623 --- /dev/null +++ b/doc/recursions/IntaRNA.PredictorMfeEns2dSeedExtension.legacy.svg @@ -0,0 +1,61 @@ + +Legacy seeded extensions · anchor factorization +Bulged-seed fallback in mode M; also the extension kernels used by the seeded mode H predictor. Internal recurrence documentation for step 9 of PR 258. Equations describe the current implementation; RNA 2 uses reversed energy coordinates. + + + +INTARNA / RECURRENCE NOTES +Legacy seeded extensions · anchor factorization +Bulged-seed fallback in mode M; also the extension kernels used by the seeded mode H predictor + +For one retained anchor seed a…b, use S=BW(E_seed(a)), d=BW(E_init), t(i,k)=BW(E_interLeft(i,k)). +Lₐ(i) extends left to a (includes initiation); R_b(j) extends right from b (excludes initiation). + +Lₐ(i) + + + + +i + +a + + + + +b + +j + + +R_b(j) + + + + +hybrid contribution = Lₐ(i) · S · R_b(j) + +Lonely pairs allowed +Lₐ(a)=d; Lₐ(i)=∑ t(i,k)Lₐ(k) − Cₐ(i) (i ≺ k ≼ a) +R_b(b)=1; R_b(j)=∑ R_b(k)t(k,j) (b ≼ k ≺ j) +Only nonzero, complementary states and loop-size-admissible terms participate. Sums use componentwise bounds. + +noLP: outward boundary stacks are explicit +Lₐ(i)=t(i,i⁺) · [Lₐ(i⁺) + ∑ t(i⁺,k)Lₐ(k)] − Cₐ(i) (i⁺ ≺ k ≼ a) +R_b(j)=t(j⁻,j) · [1{j⁻=b}R_b(b) + ∑ R_b(k)t(k,j⁻)] (b ≼ k ≺ j⁻) +i⁺=i+(1,1), j⁻=j−(1,1); require the extra stacked pair. Anchor bases still have Lₐ(a)=d and R_b(b)=1. +These are the legacy loop bounds. The exact stack-seed path instead uses the suffix-state recurrence. + +Left-seed correction Cₐ(i) +At a competing seed start i: process it if its end is left of a, or it loop-overlaps the anchor. +If a leftmost loop-overlapping seed h is found, subtract BW(getNonOverlappingEnergy(i,h)) · Lₐ(h). +Otherwise subtract its seed weight times the continuation at its end; noLP adds explicit loop continuations. +Apply the implementation’s overlap/loop guards, then clamp a negative corrected L value to zero. +updateZ(i,j, Lₐ(i) · S · R_b(j), true) for each nonzero span-admissible combination +Complete-site filters and B(i,j) are applied by updateZ. The anchor’s hybrid seed energy is charged once. +This legacy subtraction-based path has no actual-pair outside pass; do not substitute it for the exact seeded union. + +Implementation anchors (src/IntaRNA/) · BW(E)=exp(−E/RT) after native energy-unit conversion +PredictorMfeEns2dSeedExtension.cpp: predict() legacy branch, fillHybridZ_left(), fillHybridZ_right() +PredictorMfeEns2dSeedExtension.cpp: getNonOverlappingEnergy(); PredictorMfeEns.cpp: updateZ() + diff --git a/doc/recursions/IntaRNA.PredictorMfeEns2dSeedExtension.svg b/doc/recursions/IntaRNA.PredictorMfeEns2dSeedExtension.svg new file mode 100644 index 00000000..b04a6fe1 --- /dev/null +++ b/doc/recursions/IntaRNA.PredictorMfeEns2dSeedExtension.svg @@ -0,0 +1,54 @@ + +Seeded ensemble · exact stack-seed adapter +PredictorMfeEns2dSeedExtension | --model=P --mode=M with stack-only seed capability. Internal recurrence documentation for step 9 of PR 258. Equations describe the current implementation; RNA 2 uses reversed energy coordinates. + + + +INTARNA / RECURRENCE NOTES +Seeded ensemble · exact stack-seed adapter +PredictorMfeEns2dSeedExtension | --model=P --mode=M with stack-only seed capability + + +SeedHandler: guaranteesStackOnlySeeds() +true → predictStackSeeds(): unique seeded-chain partition +false → legacy anchor extensions; no pair-probability sink + +Capability is geometric +Computed or explicit seeds; mixed lengths and singletons. +Preserve handler admission and per-start selection rules. + +1 Compile active seed occurrences and eligible left boundaries + + + + +p + +a + + +b + +q +max(0, bₖ − Wₖ + 1) ≤ pₖ ≤ aₖ (k=1,2) +Admitted stack a…b must fit both the region and span limits W. +Enumerate the union of these p-boxes once, then require a valid p. +At p, clip the working grid to both inclusive spans. + +2 Give the suffix kernel one consistent energy objective +d(p)=BW(E_init); t(r,q)=BW(E_interLeft(r₁,q₁,r₂,q₂)) +B(p,q)=BW(energy.getE(p₁,q₁,p₂,q₂,0)) if the complete site is admitted +Invalid / inaccessible / noncomplementary vertices and forbidden transitions cannot contribute. +B owns complete-span ED, native dangles, terminal penalties and energyAdd. Seed energies only admit seeds. + +3 Commit a completed region +Z_region = ∑ B(p,q) · T₁,p(q) +Complete boundary callback and outside initialization share exactly the same B. +updateExactCompleteZ preserves the partition objective. +Pair masses and optional seed masks map through energy.getBasePair(). +Only a successful computation reaches BasePairProbabilities::addRegion(). + +Implementation anchors (src/IntaRNA/) · BW(E)=exp(−E/RT) after native energy-unit conversion +PredictorMfeEns2dSeedExtension.cpp: predict(), predictStackSeeds(), exactBoundaryWeight() +StackSeedDomain.cpp; SeededPartitionFunction.cpp; PredictorMfeEns.cpp: updateExactCompleteZ() + diff --git a/doc/recursions/IntaRNA.PredictorMfeEnsSeedOnly.svg b/doc/recursions/IntaRNA.PredictorMfeEnsSeedOnly.svg new file mode 100644 index 00000000..0a10ebe9 --- /dev/null +++ b/doc/recursions/IntaRNA.PredictorMfeEnsSeedOnly.svg @@ -0,0 +1,41 @@ + +Seed-only ensemble · retained seed enumeration +PredictorMfeEnsSeedOnly | --model=P --mode=S. Internal recurrence documentation for step 9 of PR 258. Equations describe the current implementation; RNA 2 uses reversed energy coordinates. + + + +INTARNA / RECURRENCE NOTES +Seed-only ensemble · retained seed enumeration +PredictorMfeEnsSeedOnly | --model=P --mode=S + + +1 Fill the seed handler for the active region +Retain the handler-selected seed at each admitted start a; its end is e. +Both endpoints must lie in the region. The handler supplies seed pairs and hybrid energy E_seed(a). +A filled handler with no admitted seeds reports an empty result. + + +2 One complete contribution per retained seed + + + + +a + + + + +e +H_seed = E_seed(a) + E_init +E_full = energy.getE(a₁,e₁,a₂,e₂,H_seed) +Zall += BW(E_full) when needZall is enabled + +3 Report and trace the retained seed +updateOptima(..., isHybridE=true, incrementZall=true) applies the complete-site filters and ranking. +traceBackSeed() supplies its interior pairs; initiation is charged exactly once. +There is no extension recurrence, no sum over alternative seed structures at the same start, and no bpProb output. + +Implementation anchors (src/IntaRNA/) · BW(E)=exp(−E/RT) after native energy-unit conversion +PredictorMfeEnsSeedOnly.cpp: predict(), traceBack() +PredictorMfe.cpp: updateOptima(); Predictor.h: updateZall() (inherited update path) + diff --git a/doc/recursions/IntaRNA.SeededPartitionFunction.inside.svg b/doc/recursions/IntaRNA.SeededPartitionFunction.inside.svg new file mode 100644 index 00000000..b944efbb --- /dev/null +++ b/doc/recursions/IntaRNA.SeededPartitionFunction.inside.svg @@ -0,0 +1,59 @@ + +Exact seeded inside recurrence · suffix automaton +SeededPartitionFunction::compute() | fixed left boundary p; visit q in increasing pair order. Internal recurrence documentation for step 9 of PR 258. Equations describe the current implementation; RNA 2 uses reversed energy coordinates. + + + +INTARNA / RECURRENCE NOTES +Exact seeded inside recurrence · suffix automaton +SeededPartitionFunction::compute() | fixed left boundary p; visit q in increasing pair order + +C=max(2, longest admitted seed length). ℓ is the current consecutive stack-suffix length, capped at C. +e(q)=shortest admitted seed ending at q, or 0. A run accepts a seed iff 0 < e(q) ≤ ℓ. + +Uℓ: still seed-free +ℓ=1…C; no seed has occurred. +Stack increments ℓ; a loop resets it. + +S₁: seeded, singleton suffix +A seed has occurred; current run is length 1. +Under noLP, must stack before leaving. + +S₂: seeded, usable suffix +Under noLP: current run has length ≥2. +Otherwise: all seeded suffixes use S₂. + + + +first seed accepted on a stack +stack → S₂ + + +1 Initialize and extend every state +H(p,c₀)=d(p); other H=0. c₀ = accept(p,1) ? (noLP ? S₁ : S₂) : U₁ +Stack r=q−(1,1): H(q,D(c,stack)) += t(r,q) · H(r,c) +For Uℓ: let ℓ′=min(C,ℓ+1); D=Uℓ′ unless the ending seed is accepted, then D=S₂. +For S₁ or S₂: D=S₂. Once seeded, a later seed never creates a second copy of the path. + +2 Aggregate eligible departures, then handle nonstack edges +T₀(q)=∑ H(q,Uℓ) over ℓ≥(noLP ? 2 : 1) +T₁(q)=H(q,S₂) + (noLP ? 0 : H(q,S₁)) +For each nonstack r→q and b∈{0,1}: H(q,D(b,loop)) += t(r,q) · T_b(r) +Nonstack means both coordinates increase, within loop limits, excluding r=q−(1,1). +Reset the suffix to 1; remain seeded if b=1, or accept a singleton seed at q if b=0. + +3 Complete seeded paths at every q +Z += B(p,q) · T₁(q) +Seed-free states never terminate an interaction. +With noLP, singleton runs cannot terminate or cross a nonstack edge. +Such states remain available for a later stack. +Loop destinations: seeded → S₁ under noLP, otherwise S₂; unseeded → U₁ unless a singleton seed accepts. +The Boolean seeded state counts each ordered pair chain once, including paths with several seed witnesses. +Termination-only GU / ED filters belong to B; they do not discard prefixes that can still extend. +d, t and B are the initiation, transition and complete-boundary factors supplied by Weights. + + +Implementation anchors (src/IntaRNA/) · BW(E)=exp(−E/RT) after native energy-unit conversion +SeededPartitionFunction.cpp: accepts, dest, nonstack, h, total; StackSeedDomain::seedEndingLength() +Code states: Uℓ ↔ c=ℓ−1; S₁ ↔ c=cap; S₂ ↔ c=cap+1. Checked nonnegative arithmetic throughout. + diff --git a/doc/recursions/IntaRNA.SeededPartitionFunction.outside.svg b/doc/recursions/IntaRNA.SeededPartitionFunction.outside.svg new file mode 100644 index 00000000..c98b9271 --- /dev/null +++ b/doc/recursions/IntaRNA.SeededPartitionFunction.outside.svg @@ -0,0 +1,67 @@ + +Actual base-pair probabilities · outside recurrence +Reverse differentiation of the suffix inside computation; same fixed p and same boundary weights B. Internal recurrence documentation for step 9 of PR 258. Equations describe the current implementation; RNA 2 uses reversed energy coordinates. + + + +INTARNA / RECURRENCE NOTES +Actual base-pair probabilities · outside recurrence +Reverse differentiation of the suffix inside computation; same fixed p and same boundary weights B + +H and T are forward state/aggregate weights. Their adjoints are A=∂Z/∂H and G=∂Z/∂T. +M(q) is the raw mass of complete chains containing actual pair q; it is not site-coverage mass. + +H(r,c) + + + +p + +r + +q + +terminal + +Reverse the incoming edge r → q. +Only actual pair q receives this edge’s mass. + + +1 Initialize the reverse objective +A(q,S₂)=B(p,q); A(q,S₁)=B(p,q) only without noLP; other A and G = 0 +Initialize at reachable positive seeded totals; a zero terminal coefficient contributes nothing. + +2 Reverse q in decreasing order; first scatter aggregate adjoints +A(q,Uℓ) += G₀(q) for the same departure-eligible ℓ as in the forward sum +A(q,S₂) += G₁(q); A(q,S₁) += G₁(q) only without noLP +This scatter must precede reversing the incoming edges at q. + +3a Reverse a stack edge r→q +a = A(q,D(c,stack)) · t(r,q) +A(r,c) += a +M(q) += a · H(r,c) +Repeat for every forward source state c. +The transition marker belongs to destination q. + +3b Reverse a nonstack edge r→q +a = A(q,D(b,loop)) · t(r,q) +Gᵦ(r) += a +M(q) += a · T_b(r) +Repeat for b=0 and b=1 using the same forward totals. +Do not mark the unpaired nucleotides in the loop. + +4 Mark the source pair after the reverse sweep +M(p) += A(p,c₀) · d(p) +Every other pair was marked when its incoming edge was reversed. + +5 Merge successful disjoint search regions before normalization +Z_total = ∑ Z_region; M_total(i,j) = ∑ M_region(i,j); P(i,j)=M_total(i,j)/Z_total +Map regional pairs with energy.getBasePair() into original target/query coordinates, then finalize explicitly. +Z_total=0 → NA. Failed/cancelled computation → no matrix. No unbound-state weight is added. +Seed admission and B are fixed while differentiating. Masses sum across every eligible left boundary p. + + +Implementation anchors (src/IntaRNA/) · BW(E)=exp(−E/RT) after native energy-unit conversion +SeededPartitionFunction.cpp: dh (A), dt (G), mass and initial-pair contribution +PredictorMfeEns2dSeedExtension::predictStackSeeds(); BasePairProbabilities::addRegion(), finalize(), probabilities() + From 202651e792e01ed188c0253a5251decb193a2b77 Mon Sep 17 00:00:00 2001 From: AlexanderMitrofanov Date: Fri, 9 Oct 2026 12:29:07 +0200 Subject: [PATCH 11/21] fix: address probability output and recurrence audit findings --- ChangeLog | 24 ++++ README.md | 8 +- .../seeded-probabilities-validation.md | 113 ++++++++++++++++++ .../IntaRNA.PredictorMfeEns2dHeuristic.svg | 9 +- .../IntaRNA.PredictorMfeEnsSeedOnly.svg | 3 +- ...IntaRNA.SeededPartitionFunction.inside.svg | 12 +- ...ntaRNA.SeededPartitionFunction.outside.svg | 2 +- src/IntaRNA/BasePairProbabilitySvg.cpp | 25 ++-- src/IntaRNA/BasePairProbabilityWriter.cpp | 3 +- src/IntaRNA/BasePairProbabilityWriter.h | 12 +- src/bin/CommandLineParsing.cpp | 16 ++- src/bin/CommandLineParsing.h | 19 ++- tests/BasePairProbabilities_test.cpp | 19 ++- tests/testBasePairProbabilitySvg.py | 53 ++++++-- 14 files changed, 267 insertions(+), 51 deletions(-) diff --git a/ChangeLog b/ChangeLog index 613764ff..44268e50 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,6 +14,9 @@ ## Interface and handling +- BUGFIX : use each strand's accessibility energy scale for SVG frames and + unpaired-probability exports, including mixed computed/imported inputs + - --out=bpsvg:FILE renders actual-pair probabilities with nucleotide/accessibility frames, a shared CSS palette, signed-coordinate guides, hover values and admitted seed outlines (PR #258, step 8) @@ -50,6 +53,9 @@ ## Technical changes and Optimizations +- transfer completed probability-output buffers without copying; independently + audit performance, accessibility conversion and recurrence depictions (PR #259) + - depict ensemble predictor recurrences and the exact base-pair inside/outside computation in internal SVG documentation (PR #258, step 9) @@ -163,6 +169,24 @@ energies, restricted partition sums, and trackers. ################################################################################ ################################################################################ +261009 Alexander Mitrofanov + * BasePairProbabilityWriter, BasePairProbabilitySvg, CommandLineParsing : + * pass and validate separate target/query accessibility RT values for SVG + frames; imported probabilities no longer inherit the interaction model RT + * share the source-specific conversion with tPu/qPu, correcting their earlier + physical-temperature conversion of computed base-pair accessibility (RT=1) + * move completed SVG/CSV stream buffers instead of copying large documents + * tests, README.md, doc/analysis/seeded-probabilities-validation.md : + + cover imported Pu/ED, mixed sources, nondefault temperatures and invalid RT; + compare against input probabilities and independent ED conversion + + document independent review, controlled runtime/RSS comparisons and final + release/debug, installation and public-header checks (PR #259) + * doc/recursions/IntaRNA.PredictorMfeEns2dHeuristic.svg, + doc/recursions/IntaRNA.PredictorMfeEnsSeedOnly.svg, + doc/recursions/IntaRNA.SeededPartitionFunction.*.svg : + * show the heuristic initial right-end GU gate and complete-site filters; + place nonstack arrivals before inside aggregation and clarify outside notation + 261009 Alexander Mitrofanov * doc/recursions/IntaRNA.PredictorMfeEns*.svg, doc/recursions/IntaRNA.SeededPartitionFunction.*.svg : diff --git a/README.md b/README.md index fcb80537..d627414e 100644 --- a/README.md +++ b/README.md @@ -1893,6 +1893,9 @@ The column separator within tabular CSV output (defaulting to `;`) can be change using `--outSep`, e.g. to produce tab-separated `.tsv` output. Note further, `qPu:`|`tPu:` will report unpaired probability values based on rounded accessibility (ED) values. +The ED-to-probability conversion uses each strand's accessibility energy scale: +computed base-pair accessibility uses RT=1, while ViennaRNA and imported +accessibility use the configured temperature, independently of the interaction model. Thus, these values will most likely differ from values eg. produced by the program RNAplfold. We therefore strongly recommend to store `qAcc:`|`tAcc:` values when you want to use them as input for subsequent IntaRNA calls! @@ -2116,7 +2119,10 @@ a standalone SVG on standard output, redirect ordinary output, for example produce consecutive SVG documents; use filenames for separate viewable files. Library callers can use `BasePairProbabilityWriter::writeSvg()` or -`writeSvgFile()` with a finalized result and the original energy model. Construct +`writeSvgFile()` with a finalized result, the original energy model, and separate +target/query accessibility RT values. These must match the ED conversion scales +of the accessibility sources, which can differ from the interaction model's RT +(for example, imported Pu with a base-pair interaction model). Construct `BasePairProbabilities(targetLength, queryLength, true)` to retain seed annotations; the default CSV-only result does not allocate that mask. SVG creation buffers the document and uses one rectangle per pair plus the frames, so its size grows diff --git a/doc/analysis/seeded-probabilities-validation.md b/doc/analysis/seeded-probabilities-validation.md index a08848d0..3449a5ba 100644 --- a/doc/analysis/seeded-probabilities-validation.md +++ b/doc/analysis/seeded-probabilities-validation.md @@ -157,3 +157,116 @@ OMP_NUM_THREADS=1 OPENBLAS_NUM_THREADS=1 /usr/bin/time -v src/bin/IntaRNA \ Both runs report Eall=-6.52 kcal/mol with the native presentation convention. These measurements quantify added output work; they are not a speedup claim over the legacy seeded ensemble, whose multi-anchor partition is a different result. + + +## Steps 8–9: independent output and documentation audit (2026-10-09) + +Separate agents reviewed code correctness, recurrence depictions, and performance +before the audit fixes were pushed to PR #259. The audit found and corrected: + +- SVG accessibility frames used the interaction model's RT for imported Pu/ED. + The writer now requires separate target/query accessibility RT values. CLI + conversion selects RT=1 for computed base-pair accessibility and the configured + physical temperature for ViennaRNA/imported accessibility. The same selection + fixes the pre-existing `tPu`/`qPu` conversion of computed base-pair ED. +- SVG and CSV stream buffers were copied when returned; moving the completed + strings removes that duplicate allocation without changing document bytes. +- The heuristic depiction omitted its initial right-end GU gate, and the inside + depiction placed aggregation before incoming nonstack contributions. These + were corrected, along with complete-site filtering and outside-index notation. + +The added CLI regressions fail on the pre-audit binary and pass after the fix. +They cover Pu/ED imports, mixed computed/imported strands, 22/37°C, original +query orientation, independent input-Pu round trips (allowing ED quantization), +and computed-base-pair ED conversion at RT=1. API tests reject nonpositive or +nonfinite accessibility scales without writing output. GCC 14.4 release and +debug `make tests -j2` each pass all seven suites, with 91,394 API assertions in +86 cases. Installed public headers and an installed SVG consumer compile; the +consumer produces the expected matrix and seed annotations. Corrected SVG +recurrence documents parse, render, and were visually inspected. Apple Clang +was not available locally. + +### Performance method and existing-mode comparison + +Compared base `48efc541e23571ce1bab88e2754e1db7445cbc89` with steps 8–9 at +`fa2f84d6cdbb1e120a98eab9d2dfe3f8154ebad5`, then compared that saved binary with +the audit fixes. All builds use identical GCC 14.4 C++23 `-O3 +-fno-strict-aliasing -fopenmp`, ViennaRNA 2.7.2, Boost 1.85 and Kokkos mdspan +settings on Linux x86-64 / Ryzen 5 7530U. Processes are pinned to CPU 0 with +`--threads=1`, `OMP_NUM_THREADS=1`, `OPENBLAS_NUM_THREADS=1`, and +`OMP_DYNAMIC=FALSE`. Builds and tests are stopped during measurements. + +There is one warmup per configuration, then seven fresh-process runs in shuffled, +interleaved order for the base comparison. Time is wall time around the GNU time +subprocess; RSS is GNU time `%M`, including executable/libraries, prediction and +serialization. Output goes to the same local filesystem. Initial median seconds: + +| Input | Base ensemble only | Steps 8–9 ensemble only | Base CSV | Steps 8–9 CSV | Steps 8–9 SVG | Steps 8–9 both | +| --- | ---: | ---: | ---: | ---: | ---: | ---: | +| OxyS/fhlA | 0.0975 | 0.0978 | 0.1710 | 0.1703 | 0.1910 | 0.1947 | +| dense40 | 0.3876 | 0.3913 | 0.8958 | 0.9026 | 0.9090 | 0.9060 | +| sparse400 | 0.1191 | 0.1202 | 0.1616 | 0.1633 | 0.7326 | 0.8260 | +| sparse1000 | 1.5816 | 1.5801 | 1.8284 | 1.8372 | 4.0202 | 4.2578 | + +Existing-mode medians differ by −0.4% to +1.1%, within observed timing variation. +Ensemble outputs and CSVs are byte-identical across base/candidate and modes; +all SVG pair values equal their CSV values. Sparse SVG timings have wider +variation than the compute-heavy cases; these are local workload measurements, +not a general throughput guarantee. Full SVG size scales with all target/query +pairs: the sparse1000 document is 220,685,460 bytes despite having few seed cells. + +Reproduce each process with the following command from the corresponding build; +add either/both output options for the CSV/SVG configurations: + +```sh +OMP_NUM_THREADS=1 OPENBLAS_NUM_THREADS=1 OMP_DYNAMIC=FALSE \ + /usr/bin/time -f '%e %U %S %M' taskset -c 0 src/bin/IntaRNA \ + --target=doc/handson/fhlA.fasta --query=doc/handson/OxyS.fasta \ + --model=P --mode=M --seedBP=4 --intLenMax=30 \ + --qIntLoopMax=3 --tIntLoopMax=3 --threads=1 \ + --outNoLP=false --outNoGUend=false --outNumber=0 --outMode=E \ + --default-log-file=/dev/null --out=ensemble.txt +# Optional: --out=bpProb:pairs.csv --out=bpsvg:plot.svg +``` + +For dense40, replace the inputs with `G`×40 and `C`×40 and add `--tAcc=N +--qAcc=N`. For sparse length n (400 or 1000), use target `A`×(n/2) + `G`×8 + +`A`×(n/2−8), query with `C`×8 instead of `G`×8, and the same disabled-accessibility +options. All other flags remain identical. + + +### Audit-fix comparison + +Five interleaved fresh-process runs per configuration compare the retained +`fa2f84d` binary with the rebuilt audit fix. All complete SVG, CSV and ensemble +outputs match byte-for-byte on these native-energy inputs. Time is median +[min, max] seconds; RSS is the maximum over the five runs, in KiB. + +| Input/output | Before time | Fixed time | Before RSS | Fixed RSS | +| --- | ---: | ---: | ---: | ---: | +| OxyS SVG | 0.1938 [0.1932, 0.1968] | 0.1934 [0.1918, 0.1938] | 22,132 | 20,720 | +| OxyS both | 0.1965 [0.1945, 0.1976] | 0.1959 [0.1955, 0.1967] | 22,004 | 20,596 | +| sparse400 SVG | 0.5020 [0.5003, 0.7993] | 0.7491 [0.4806, 0.9672] | 87,876 | 84,548 | +| sparse400 both | 0.5553 [0.5441, 0.8527] | 0.7544 [0.5118, 0.8899] | 87,872 | 84,420 | +| sparse1000 SVG | 4.0260 [3.9535, 5.8240] | 3.8527 [3.8373, 5.5779] | 470,084 | 301,128 | +| sparse1000 both | 4.2407 [4.2148, 6.2242] | 4.0592 [4.0216, 4.1580] | 469,960 | 301,260 | + +Transferring the document buffer reduces 1000×1000 SVG peak RSS by **35.9%**. +There is no general elapsed-time speedup claim: filesystem writes varied widely, +and the sparse400 median increased even though its median process CPU time fell +from 0.44 to 0.42 seconds (SVG) and 0.48 to 0.46 seconds (both). Dense40 controls +remain comparable: ensemble-only 0.3848→0.3902 seconds (+1.4%) and CSV +0.8982→0.8869 seconds (−1.3%), with unchanged output bytes. The output is still +buffered as a full document, so very large matrices remain memory intensive. + +One comparison process received an unexplained SIGTERM after the shorter cases; +partial long-case warmups were discarded and the long case completed in a new +process. The table includes only complete five-run groups. + +To separate serializer cost from file-write stalls, a final sparse400 control +sent SVG to `/dev/null` and ensemble output to STDOUT redirected to `/dev/null`. +Seven interleaved runs gave wall medians 0.412419→0.390979 seconds (ranges +0.411222–0.413401 and 0.388902–0.392267), CPU medians 0.40→0.38 seconds, and peak +RSS 87,744→84,544 KiB. The slowdown did not reproduce without filesystem writes; +the fixed serializer was 5.2% faster in this specific control. Use the same +sparse400 command with `--out=STDOUT --out=bpsvg:/dev/null > /dev/null` to repeat. diff --git a/doc/recursions/IntaRNA.PredictorMfeEns2dHeuristic.svg b/doc/recursions/IntaRNA.PredictorMfeEns2dHeuristic.svg index fd048c48..aceeb06c 100644 --- a/doc/recursions/IntaRNA.PredictorMfeEns2dHeuristic.svg +++ b/doc/recursions/IntaRNA.PredictorMfeEns2dHeuristic.svg @@ -10,6 +10,7 @@ C(i)=(vᵢ,jᵢ) retains one hybrid weight and right boundary for each left pair i. Use d=BW(E_init), t(i,k)=BW(E_interLeft(i,k)); all pair coordinates increase internally. +B(i,j)=BW(energy.getE(i₁,j₁,i₂,j₂,0)) is the complete-boundary Boltzmann factor. Enumerate candidates at i, visiting i in decreasing order @@ -23,15 +24,15 @@ jₖ Lonely pairs allowed: - initial candidate (d, i) + initial candidate (d, i), only if !noGUend or i is not GU continuation (t(i,k) · vₖ, jₖ) for each reachable k ≻ i within loop limits and the complete span limits. Accumulate every considered candidate updateZ(i,j,v,true) -Adds B(i,j)v to Zall and v to the boundary map. -B is the admitted complete-boundary Boltzmann factor. +For admitted complete sites: add B(i,j)v to Zall +and v to the boundary map; otherwise discard the update. Retain only the best continuation at i C(i) ← argmin E_full(i,j,v) @@ -40,7 +41,7 @@ noLP candidate set Let i⁺=i+(1,1) be complementary and s=t(i,i⁺). -Initialize (s·d, i⁺); add direct continuation (s·vᵢ⁺, jᵢ⁺). +Initialize (s·d, i⁺) only if !noGUend or i⁺ is not GU; direct continuation is (s·vᵢ⁺, jᵢ⁺). Other candidates are (s·t(i⁺,k)·vₖ, jₖ), with k ≻ i⁺ and k ≠ i⁺+(1,1). The adjacent continuation is excluded from the loop sum because it was handled directly. The boundary map sums contributions, but the DP cell keeps one right continuation: this is a restricted ensemble. diff --git a/doc/recursions/IntaRNA.PredictorMfeEnsSeedOnly.svg b/doc/recursions/IntaRNA.PredictorMfeEnsSeedOnly.svg index 0a10ebe9..0eabab07 100644 --- a/doc/recursions/IntaRNA.PredictorMfeEnsSeedOnly.svg +++ b/doc/recursions/IntaRNA.PredictorMfeEnsSeedOnly.svg @@ -28,7 +28,8 @@ e H_seed = E_seed(a) + E_init E_full = energy.getE(a₁,e₁,a₂,e₂,H_seed) -Zall += BW(E_full) when needZall is enabled +Zall += BW(E_full) +Only when needZall is enabled and complete-site filters pass. 3 Report and trace the retained seed updateOptima(..., isHybridE=true, incrementZall=true) applies the complete-site filters and ranking. diff --git a/doc/recursions/IntaRNA.SeededPartitionFunction.inside.svg b/doc/recursions/IntaRNA.SeededPartitionFunction.inside.svg index b944efbb..e41542a1 100644 --- a/doc/recursions/IntaRNA.SeededPartitionFunction.inside.svg +++ b/doc/recursions/IntaRNA.SeededPartitionFunction.inside.svg @@ -35,12 +35,12 @@ For Uℓ: let ℓ′=min(C,ℓ+1); D=Uℓ′ unless the ending seed is accepted, then D=S₂. For S₁ or S₂: D=S₂. Once seeded, a later seed never creates a second copy of the path. -2 Aggregate eligible departures, then handle nonstack edges -T₀(q)=∑ H(q,Uℓ) over ℓ≥(noLP ? 2 : 1) -T₁(q)=H(q,S₂) + (noLP ? 0 : H(q,S₁)) -For each nonstack r→q and b∈{0,1}: H(q,D(b,loop)) += t(r,q) · T_b(r) -Nonstack means both coordinates increase, within loop limits, excluding r=q−(1,1). -Reset the suffix to 1; remain seeded if b=1, or accept a singleton seed at q if b=0. +2 Add nonstack arrivals, then aggregate eligible departures +For each nonstack r→q and b∈{0,1}: H(q,D(b,loop)) += t(r,q) · T_b(r) +T₀(q)=∑ H(q,Uℓ) over ℓ≥(noLP ? 2 : 1) +T₁(q)=H(q,S₂) + (noLP ? 0 : H(q,S₁)) +T_b(r) is already computed. Nonstack: strict increase within loop limits, excluding r=q−(1,1). +Reset the suffix to 1; remain seeded if b=1, or accept a singleton seed at q if b=0. 3 Complete seeded paths at every q Z += B(p,q) · T₁(q) diff --git a/doc/recursions/IntaRNA.SeededPartitionFunction.outside.svg b/doc/recursions/IntaRNA.SeededPartitionFunction.outside.svg index c98b9271..fe546876 100644 --- a/doc/recursions/IntaRNA.SeededPartitionFunction.outside.svg +++ b/doc/recursions/IntaRNA.SeededPartitionFunction.outside.svg @@ -45,7 +45,7 @@ 3b Reverse a nonstack edge r→q a = A(q,D(b,loop)) · t(r,q) -Gᵦ(r) += a +G_b(r) += a M(q) += a · T_b(r) Repeat for b=0 and b=1 using the same forward totals. Do not mark the unpaired nucleotides in the loop. diff --git a/src/IntaRNA/BasePairProbabilitySvg.cpp b/src/IntaRNA/BasePairProbabilitySvg.cpp index 1b9e5b91..fda2d1cd 100644 --- a/src/IntaRNA/BasePairProbabilitySvg.cpp +++ b/src/IntaRNA/BasePairProbabilitySvg.cpp @@ -7,6 +7,7 @@ #include #include #include +#include namespace IntaRNA { namespace { @@ -42,10 +43,10 @@ size_t colorClass(Z_type probability) return breaks.size()-2; } -Z_type unpaired(const Accessibility & accessibility,size_t i,const InteractionEnergy & energy) +Z_type unpaired(const Accessibility & accessibility,size_t i,Z_type RT) { const E_type ed=accessibility.getED(i,i); - const Z_type p=E_isINF(ed)?Z_type(0):energy.getBoltzmannWeight(ed); + const Z_type p=E_isINF(ed)?Z_type(0):Z_exp(-E_2_Z(ed)/RT); if (!std::isfinite(p) || p<0 || p>1) throw std::runtime_error("bpsvg: invalid single-nucleotide unpaired probability"); return p; @@ -54,8 +55,11 @@ Z_type unpaired(const Accessibility & accessibility,size_t i,const InteractionEn } // namespace std::string -BasePairProbabilityWriter::svgBlock(const BasePairProbabilities & result,const InteractionEnergy & energy) +BasePairProbabilityWriter::svgBlock(const BasePairProbabilities & result,const InteractionEnergy & energy, + Z_type targetRT,Z_type queryRT) { + if (!std::isfinite(targetRT) || targetRT<=0 || !std::isfinite(queryRT) || queryRT<=0) + throw std::invalid_argument("bpsvg: accessibility energy scales must be positive and finite"); const auto & at=energy.getAccessibility1(); const auto & aq=energy.getAccessibility2().getAccessibilityOrigin(); const auto & t=at.getSequence(); @@ -131,7 +135,7 @@ text { font-family: sans-serif; fill: #243247; } const auto & seq=target?t:q; const auto & acc=target?at:aq; for(size_t i=0;i\n"; - return out.str(); + // Transfer the potentially large document instead of copying its buffer. + return std::move(out).str(); } -void BasePairProbabilityWriter::writeSvg(std::ostream & out,const BasePairProbabilities & result,const InteractionEnergy & energy) +void BasePairProbabilityWriter::writeSvg(std::ostream & out,const BasePairProbabilities & result,const InteractionEnergy & energy, + Z_type targetRT,Z_type queryRT) { - emit(out,svgBlock(result,energy)); + emit(out,svgBlock(result,energy,targetRT,queryRT)); } -void BasePairProbabilityWriter::writeSvgFile(const std::string & filename,const BasePairProbabilities & result,const InteractionEnergy & energy) +void BasePairProbabilityWriter::writeSvgFile(const std::string & filename,const BasePairProbabilities & result,const InteractionEnergy & energy, + Z_type targetRT,Z_type queryRT) { - emitFile(filename,svgBlock(result,energy)); + emitFile(filename,svgBlock(result,energy,targetRT,queryRT)); } } // namespace IntaRNA diff --git a/src/IntaRNA/BasePairProbabilityWriter.cpp b/src/IntaRNA/BasePairProbabilityWriter.cpp index 6d679fdd..d38a744b 100644 --- a/src/IntaRNA/BasePairProbabilityWriter.cpp +++ b/src/IntaRNA/BasePairProbabilityWriter.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include namespace IntaRNA { @@ -25,7 +26,7 @@ std::string BasePairProbabilityWriter::block(const BasePairProbabilities & resul for(size_t j=0;j::infinity(), + std::numeric_limits::quiet_NaN()}) { + std::ostringstream invalid; + REQUIRE_THROWS(BasePairProbabilityWriter::writeSvg(invalid,r,energy,rt,1)); + REQUIRE_THROWS(BasePairProbabilityWriter::writeSvg(invalid,r,energy,1,rt)); + REQUIRE(invalid.str().empty()); + } + BasePairProbabilityWriter::writeSvg(svg,r,energy,1,1); REQUIRE(svg.str().find("target<&")!=std::string::npos); REQUIRE(svg.str().find("Orange outline:")!=std::string::npos); std::ostringstream broken;broken.setstate(std::ios::badbit); - REQUIRE_THROWS(BasePairProbabilityWriter::writeSvg(broken,r,energy)); + REQUIRE_THROWS(BasePairProbabilityWriter::writeSvg(broken,r,energy,1,1)); r.fail();std::ostringstream failed; - REQUIRE_THROWS(BasePairProbabilityWriter::writeSvg(failed,r,energy)); + REQUIRE_THROWS(BasePairProbabilityWriter::writeSvg(failed,r,energy,1,1)); REQUIRE(failed.str().empty()); BasePairProbabilities missing(4,5,true); REQUIRE_THROWS(missing.addRegion({0,1},{1,2},2,mass)); @@ -82,10 +89,10 @@ TEST_CASE("seed annotations commit with regional masses and SVG requires success BasePairProbabilities plain(4,5); REQUIRE_FALSE(plain.collectsSeedPairs());REQUIRE(plain.seedPairs().size1()==0); plain.finalize();std::ostringstream empty; - BasePairProbabilityWriter::writeSvg(empty,plain,energy); + BasePairProbabilityWriter::writeSvg(empty,plain,energy,1,1); REQUIRE(empty.str().find("data-probability=\"NA\"")!=std::string::npos); REQUIRE(empty.str().find("Orange outline:")==std::string::npos); BasePairProbabilities wrongSize(1,1);wrongSize.finalize();std::ostringstream wrong; - REQUIRE_THROWS(BasePairProbabilityWriter::writeSvg(wrong,wrongSize,energy)); + REQUIRE_THROWS(BasePairProbabilityWriter::writeSvg(wrong,wrongSize,energy,1,1)); REQUIRE(wrong.str().empty()); } diff --git a/tests/testBasePairProbabilitySvg.py b/tests/testBasePairProbabilitySvg.py index 29047ef3..55e5e576 100644 --- a/tests/testBasePairProbabilitySvg.py +++ b/tests/testBasePairProbabilitySvg.py @@ -18,6 +18,8 @@ def run(t='GGAGGG', q='CCCC', options=(), success=True): keys = {o.split('=')[0] for o in options} + if keys & {'--tAcc', '--qAcc'}: + keys.add('--acc') p = subprocess.run([BIN, f'--target={t}', f'--query={q}', *[o for o in COMMON if o.split('=')[0] not in keys], *options], text=True, capture_output=True) @@ -112,17 +114,48 @@ def plot(t='GGAGGG', q='CCCC', opts=()): named = plot(opts=[f'--tId={name}']) assert name in named.find('s:title', NS).text assert name+" (5' to 3')" in [e.text for e in named.findall('.//s:text', NS)] - # Native accessibility values must use original (not reversed) query order. + # Accessibility uses its own per-strand scale and original query order. pu_t, pu_q = d/'target.pu', d/'query.pu' - native = plot('GGGGAAAACCCC', 'GCGCGAAAACGCGC', - ['--energy=V', '--acc=C', f'--out=tPu:{pu_t}', f'--out=qPu:{pu_q}']) - for strand, path in (('target', pu_t), ('query', pu_q)): - expected_pu = [float(line.split()[1]) for line in path.read_text().splitlines() - if line.strip() and not line.lstrip().startswith('#')] - assert any(0 < v < .9 for v in expected_pu) - for r in native.findall(f'.//s:rect[@data-type="unpaired"][@data-strand="{strand}"]', NS): - assert math.isclose(float(r.attrib['data-probability']), expected_pu[int(r.attrib['data-index'])-1], - rel_tol=2e-5, abs_tol=1e-6) + + def one_nt(path): + return [float(line.split()[1]) for line in path.read_text().splitlines() + if line.strip() and not line.lstrip().startswith('#')] + + def check_frame(root, target_pu, query_pu): + for strand, values in (('target', target_pu), ('query', query_pu)): + assert any(0 < v < .9 for v in values) + for r in root.findall(f'.//s:rect[@data-type="unpaired"][@data-strand="{strand}"]', NS): + assert math.isclose(float(r.attrib['data-probability']), values[int(r.attrib['data-index'])-1], + rel_tol=2e-5, abs_tol=1e-6), (strand, r.attrib, values) + + for temperature in (22, 37): + acc_options = [f'--temperature={temperature}', f'--out=tPu:{pu_t}', f'--out=qPu:{pu_q}'] + native = plot('GGGGAAAACCCC', 'GCGCGAAAACGCGC', ['--energy=V', '--acc=C', *acc_options]) + check_frame(native, one_nt(pu_t), one_nt(pu_q)) + input_t, input_q = d/'input-target.pu', d/'input-query.pu' + input_t.write_bytes(pu_t.read_bytes()); input_q.write_bytes(pu_q.read_bytes()) + for t_mode, q_mode in (('P', 'P'), ('P', 'C'), ('C', 'P'), ('E', 'E'), ('C', 'C')): + ed_t, ed_q = d/'target.ed', d/'query.ed' + options = ['--energy=B', f'--tAcc={t_mode}', f'--qAcc={q_mode}', *acc_options] + if t_mode in ('P', 'E'): + options.append(f'--tAccFile={input_t if t_mode == "P" else ed_t}') + if q_mode in ('P', 'E'): + options.append(f'--qAccFile={input_q if q_mode == "P" else ed_q}') + # The first imported-Pu run also supplies ED fixtures for the E case. + if (t_mode, q_mode) in (('P', 'P'), ('C', 'C')): + options += [f'--out=tAcc:{ed_t}', f'--out=qAcc:{ed_q}'] + converted = plot('GGGGAAAACCCC', 'GCGCGAAAACGCGC', options) + check_frame(converted, one_nt(pu_t), one_nt(pu_q)) + for mode, input_pu, output_pu in ((t_mode, input_t, pu_t), (q_mode, input_q, pu_q)): + if mode in ('P', 'E'): + # Independent input reference; ED quantization loses <2% + # at either temperature, but using interaction RT loses far more. + assert all(math.isclose(actual, original, rel_tol=.02, abs_tol=1e-10) + for actual, original in zip(one_nt(output_pu), one_nt(input_pu))) + if t_mode == q_mode == 'C': + # Nussinov accessibility has RT=1, independent of temperature. + check_frame(converted, [math.exp(-ed) for ed in one_nt(ed_t)], + [math.exp(-ed) for ed in one_nt(ed_q)]) for t,q in (('AAAA','AAAA'), ('G','C')): empty = plot(t,q) assert all(r.attrib['data-probability'] == 'NA' for r in pairs(empty).values()) From b492ed695b0ba66ebcc84988347c4bcdd9bf7edc Mon Sep 17 00:00:00 2001 From: AlexanderMitrofanov Date: Fri, 9 Oct 2026 22:14:58 +0200 Subject: [PATCH 12/21] feat: revise probability SVG layout and highlight best interaction --- ChangeLog | 13 ++++ README.md | 28 +++++---- src/IntaRNA/BasePairProbabilitySvg.cpp | 84 ++++++++++++++++++------- src/IntaRNA/BasePairProbabilityWriter.h | 11 ++-- src/bin/CommandLineParsing.cpp | 9 +-- src/bin/CommandLineParsing.h | 8 ++- src/bin/IntaRNA.cpp | 8 ++- tests/testBasePairProbabilitySvg.py | 65 ++++++++++++++++--- 8 files changed, 169 insertions(+), 57 deletions(-) diff --git a/ChangeLog b/ChangeLog index 44268e50..19fb5983 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,6 +14,9 @@ ## Interface and handling +- revise SVG axes, sequence labels and rounded tooltips; show intramolecular + pairing (1-Pu) frames and the best interaction region (PR #259 review) + - BUGFIX : use each strand's accessibility energy scale for SVG frames and unpaired-probability exports, including mixed computed/imported inputs @@ -169,6 +172,16 @@ energies, restricted partition sums, and trackers. ################################################################################ ################################################################################ +261009 Alexander Mitrofanov + * BasePairProbabilitySvg, BasePairProbabilityWriter, CommandLineParsing, IntaRNA : + * place target origin at bottom left and query name below the matrix; include + nondefault sequence names in a subtitle and names in rounded hover values + * show 1-Pu intramolecular pairing probabilities on the nucleotide frame + + outline the best reported interaction region in green, including when + ranked output is disabled; preserve ordinary output counts (PR #259 review) + * README.md, tests/testBasePairProbabilitySvg.py : + * document and cover coordinates, frame probabilities, tooltips and MFE bounds + 261009 Alexander Mitrofanov * BasePairProbabilityWriter, BasePairProbabilitySvg, CommandLineParsing : * pass and validate separate target/query accessibility RT values for SVG diff --git a/README.md b/README.md index d627414e..ca099554 100644 --- a/README.md +++ b/README.md @@ -1876,7 +1876,7 @@ targeted file/stream name: - `qSpotProb:`/`tSpotProb:` [query/target's spot probability profile](#profileSpotProb) (CSV format), respectively - `spotProb:` [all spot probabilities](#spotProb) (CSV format) -- `bpsvg:` [SVG base-pair probability dot plot](#bpsvg), with accessibility frames and seed outlines +- `bpsvg:` [SVG base-pair probability dot plot](#bpsvg), with pairing-probability frames and seed/MFE outlines - `bpProb:` [actual base-pair probabilities](#bpProb) for exact stack-seeded ensembles (CSV matrix) - `qMinE:`/`tMinE:` [the query/target's minimal interaction energy profile](profileMinE) (CSV format), respectively - `pMinE:` [minimal interaction energy for all query-target index pairs](pairMinE) (CSV format) @@ -2082,15 +2082,18 @@ IntaRNA -t GGAGGG -q CCCC --energy=B --acc=N --seedBP=2 \ --model=P --mode=M --out=bpsvg:pairs.svg --out=bpProb:pairs.csv ``` -The query is the horizontal axis and the target the vertical axis, both in -original 5' to 3' order. Sequence names label the axes; nucleotides appear on all -four sides. Their colored backgrounds show **single-nucleotide unpaired -probabilities**, computed from the prediction accessibility model's opening -energies. These are distinct from the interaction-conditional probabilities in -the matrix. Disabled accessibility gives probability one at unconstrained bases. -Each probability rectangle has a hover title with its index (pair), type and -full-precision value. An empty interaction ensemble uses gray `NA` cells while -its accessibility frame remains defined. +The query runs left to right and the target bottom to top, both in original +5' to 3' order, starting at the bottom-left corner. Sequence names label the +axes, with the query name below the matrix. A subtitle names both sequences +when either name differs from the defaults `query` and `target`. Nucleotides +appear on all four sides. Their colored backgrounds show **intramolecular +pairing probability**, `1-Pu`, computed from the accessibility model's opening +energies. These are distinct from the interaction-conditional pair probabilities +in the matrix. Disabled accessibility gives zero at unconstrained bases. +Each probability rectangle has a hover title with sequence names, indices, +probability type and three decimal places (scientific notation with two decimal +places below 0.001). Full-precision values remain in `data-probability` attributes. +An empty interaction ensemble uses gray `NA` cells while its frame remains defined. A shared seven-step, white-to-dark-blue palette encodes both probability types: `[0,0.01)`, `[0.01,0.1)`, `[0.1,0.25)`, `[0.25,0.5)`, `[0.5,0.75)`, @@ -2110,7 +2113,10 @@ contained in searched regions, including overlapping, singleton and mixed-length explicit seeds. This annotation uses the predictor's retained seed family and span limits; it is independent of ranked interaction reporting and can include zero-probability cells. Extension-only pairs have no outline. A seed legend is -included whenever an outline is present. +included whenever an outline is present. A green rectangle encloses the best +reported interaction's site, with a matching legend. The best site is retained +for SVG even with `--outNumber=0`, without adding ranked text output. If no site +passes the reporting filters, the rectangle and its legend are omitted. Filenames support `.gz` compression and the usual `-t#q#` multi-FASTA suffixes. `STDOUT` and `STDERR` emit each complete SVG as one synchronized block. To obtain diff --git a/src/IntaRNA/BasePairProbabilitySvg.cpp b/src/IntaRNA/BasePairProbabilitySvg.cpp index fda2d1cd..d350547f 100644 --- a/src/IntaRNA/BasePairProbabilitySvg.cpp +++ b/src/IntaRNA/BasePairProbabilitySvg.cpp @@ -1,5 +1,6 @@ #include "IntaRNA/BasePairProbabilityWriter.h" #include "IntaRNA/InteractionEnergy.h" +#include "IntaRNA/Interaction.h" #include #include #include @@ -56,7 +57,7 @@ Z_type unpaired(const Accessibility & accessibility,size_t i,Z_type RT) std::string BasePairProbabilityWriter::svgBlock(const BasePairProbabilities & result,const InteractionEnergy & energy, - Z_type targetRT,Z_type queryRT) + Z_type targetRT,Z_type queryRT,const Interaction * mfe) { if (!std::isfinite(targetRT) || targetRT<=0 || !std::isfinite(queryRT) || queryRT<=0) throw std::invalid_argument("bpsvg: accessibility energy scales must be positive and finite"); @@ -72,21 +73,35 @@ BasePairProbabilityWriter::svgBlock(const BasePairProbabilities & result,const I const auto p=empty?Matrix():result.probabilities(); const double w=cell*q.size(), h=cell*t.size(); // Leave space for names even for very short sequences; keep a fixed nt pitch. - const double x=std::max(130.0,(std::max(820.0,9.0*q.getId().size()+80)-w)/2); + const double nameWidth=std::max(9.0*q.getId().size()+80,7.0*(t.getId().size()+q.getId().size())+100); + const double x=std::max(130.0,(std::max(820.0,nameWidth)-w)/2); const double y=std::max(120.0,(9.0*t.getId().size()-h)/2+60); - const double width=2*x+w, height=2*y+h+160; + const double width=2*x+w, height=2*y+h+185; + // SVG y increases downwards, while target coordinates increase upwards. + auto targetY=[&](size_t i) { return y+cell*(t.size()-1-i); }; + const bool markMfe=mfe && !mfe->isEmpty(); + size_t tStart=t.size(),tEnd=0,qStart=q.size(),qEnd=0; + if (markMfe) { + for (const auto & bp:mfe->basePairs) { + if (bp.first>=t.size() || bp.second>=q.size()) + throw std::invalid_argument("bpsvg: MFE interaction coordinates exceed sequence dimensions"); + tStart=std::min(tStart,bp.first); tEnd=std::max(tEnd,bp.first); + qStart=std::min(qStart,bp.second); qEnd=std::max(qEnd,bp.second); + } + } std::ostringstream out; out.imbue(std::locale::classic()); out<::max_digits10); out<<"\n" <<"Base-pair probabilities: "<\n" - <<"Target rows and query columns run 5' to 3'. Pair probabilities are conditional on an allowed interaction. " - <<"The frame shows single-nucleotide unpaired probabilities from the accessibility model.\n" + <<"Target rows run 5' to 3' upwards and query columns run 5' to 3' to the right. Pair probabilities are conditional on an allowed interaction. " + <<"The frame shows single-nucleotide intramolecular pairing probabilities (1 - Pu) from the accessibility model.\n" < text { font-family: sans-serif; fill: #243247; } .heading { font-size: 18px; font-weight: bold; } .axis { font-size: 15px; } +.subtitle { font-size: 13px; } .index, .legend { font-size: 11px; } .nt { font-family: monospace; font-size: 13px; pointer-events: none; } .nt-light { fill: #fff; } @@ -104,6 +119,7 @@ text { font-family: sans-serif; fill: #243247; } .origin { stroke: #888; stroke-width: 1.2; stroke-dasharray: 3 2; } .border { fill: none; stroke: #aaa; stroke-width: 0.7; pointer-events: none; } .seed { fill: none; stroke: #c65d00; stroke-width: 1.8; pointer-events: none; } +.mfe { fill: none; stroke: #16823b; stroke-width: 2.5; pointer-events: none; } )SVG"; out<<"\n"; @@ -111,7 +127,9 @@ text { font-family: sans-serif; fill: #243247; } out<<""<\n"; }; text(width/2,30,"Base-pair probabilities","heading"); - text(x+w/2,y-65,q.getId()+" (5' to 3')","axis"); + if (t.getId()!="target" || q.getId()!="query") + text(width/2,53,t.getId()+" / "+q.getId(),"subtitle"); + text(x+w/2,y+h+65,q.getId()+" (5' to 3')","axis"); out<<""<\n"; auto rect=[&](double rx,double ry,Z_type value,bool missing,const std::string & attributes,const std::string & title) { @@ -120,28 +138,33 @@ text { font-family: sans-serif; fill: #243247; } <<" data-probability=\""; if (missing) out<<"NA"; else out<"<<xml(title)<<": "; - if (missing) out<<"NA (empty interaction ensemble)"; else out<<value; + if (missing) out<<"NA (empty interaction ensemble)"; + else { + if (value<0.001) out<<std::scientific<<std::setprecision(2); + else out<<std::fixed<<std::setprecision(3); + out<<value<<std::defaultfloat<<std::setprecision(std::numeric_limits<Z_type>::max_digits10); + } out<<"\n"; }; out<<"\n"; for(size_t i=0;i\n\n"; for(bool target:{false,true}) { const auto & seq=target?t:q; const auto & acc=target?at:aq; for(size_t i=0;i=.75?"nt nt-light":"nt"); } } @@ -158,12 +181,12 @@ text { font-family: sans-serif; fill: #243247; } const double offset=cell*(i+(idx>0 && !origin?1:0)); if (idx%10==0 || origin) out<<"\n"; + <<"\" x1=\""<<(target?x-cell:x+offset)<<"\" y1=\""<<(target?y+h-offset:y-cell) + <<"\" x2=\""<<(target?x+w+cell:x+offset)<<"\" y2=\""<<(target?y+h-offset:y+h+cell)<<"\"/>\n"; const std::string label=idx==1?"+1":std::to_string(idx); if(target) { - text(x-26,y+cell*(i+.5)+4,label,"index","end"); - text(x+w+26,y+cell*(i+.5)+4,label,"index","start"); + text(x-26,targetY(i)+cell/2+4,label,"index","end"); + text(x+w+26,targetY(i)+cell/2+4,label,"index","start"); } else { text(x+cell*(i+.5),y-28,label,"index"); text(x+cell*(i+.5),y+h+38,label,"index"); @@ -177,12 +200,20 @@ text { font-family: sans-serif; fill: #243247; } for(size_t i=0;i\n"; + <<"\" x=\""<\n"; } out<<"\n"; } - const double legendX=(width-7*86)/2, legendY=y+h+85; - text(width/2,legendY-14,"Probability ranges (base pairs and single-nucleotide accessibility)","legend"); + if (markMfe) { + out<<"\n"; + } + const double legendX=(width-7*86)/2, legendY=y+h+110; + text(width/2,legendY-14,"Probability ranges (intermolecular base pairs and intramolecular pairing)","legend"); out<<"\n"; for(size_t k=0;k\n"; @@ -196,6 +227,11 @@ text { font-family: sans-serif; fill: #243247; } out<<"\n"; text(legendX+28,legendY+61,"Orange outline: pair in an admitted seed within a searched region","legend","start"); } + if (markMfe) { + const double mfeLegendY=legendY+(annotated?76:48); + out<<"\n"; + text(legendX+28,mfeLegendY+13,"Green outline: minimum-free-energy interaction region","legend","start"); + } if(empty) text(width/2,legendY+90,"Gray / NA: empty interaction ensemble; accessibility remains defined","legend"); out<<"\n"; // Transfer the potentially large document instead of copying its buffer. @@ -203,15 +239,15 @@ text { font-family: sans-serif; fill: #243247; } } void BasePairProbabilityWriter::writeSvg(std::ostream & out,const BasePairProbabilities & result,const InteractionEnergy & energy, - Z_type targetRT,Z_type queryRT) + Z_type targetRT,Z_type queryRT,const Interaction * mfe) { - emit(out,svgBlock(result,energy,targetRT,queryRT)); + emit(out,svgBlock(result,energy,targetRT,queryRT,mfe)); } void BasePairProbabilityWriter::writeSvgFile(const std::string & filename,const BasePairProbabilities & result,const InteractionEnergy & energy, - Z_type targetRT,Z_type queryRT) + Z_type targetRT,Z_type queryRT,const Interaction * mfe) { - emitFile(filename,svgBlock(result,energy,targetRT,queryRT)); + emitFile(filename,svgBlock(result,energy,targetRT,queryRT,mfe)); } } // namespace IntaRNA diff --git a/src/IntaRNA/BasePairProbabilityWriter.h b/src/IntaRNA/BasePairProbabilityWriter.h index 56acabf3..64773536 100644 --- a/src/IntaRNA/BasePairProbabilityWriter.h +++ b/src/IntaRNA/BasePairProbabilityWriter.h @@ -7,6 +7,7 @@ namespace IntaRNA { class InteractionEnergy; +class Interaction; /** Explicit writer for a completed actual-pair matrix, independent of trackers. * Whole blocks are synchronized for shared streams. No destructor emits data. */ @@ -32,7 +33,7 @@ class BasePairProbabilityWriter { static void writeFile(const std::string & filename,const BasePairProbabilities & result, const RnaSequence & target,const RnaSequence & query,const std::string & separator=";"); /** Write a complete SVG dot plot with original target rows/query columns. - * Includes 1-nt accessibility, signed coordinate guides and a CSS color legend. + * Includes intramolecular pairing, signed coordinate guides and a CSS color legend. * Seed outlines are included if the result collected admitted seed pairs. * @param out destination stream; an I/O failure throws * @param result explicitly finalized raw result @@ -40,9 +41,10 @@ class BasePairProbabilityWriter { * @param targetRT positive finite energy scale used to convert target ED to Pu * @param queryRT positive finite energy scale used to convert query ED to Pu; * accessibility scales can differ from the interaction model's RT + * @param mfe optional best interaction in original coordinates for a region outline */ static void writeSvg(std::ostream & out,const BasePairProbabilities & result, - const InteractionEnergy & energy,Z_type targetRT,Z_type queryRT); + const InteractionEnergy & energy,Z_type targetRT,Z_type queryRT,const Interaction * mfe = nullptr); /** Write a complete SVG to a file or STDOUT/STDERR, including gzip support. * Validates the whole document before opening the destination. * @param filename destination (already expanded for multi-FASTA) @@ -50,12 +52,13 @@ class BasePairProbabilityWriter { * @param energy original, unshifted energy/accessibility model * @param targetRT positive finite target accessibility energy scale * @param queryRT positive finite query accessibility energy scale + * @param mfe optional best interaction in original coordinates for a region outline */ static void writeSvgFile(const std::string & filename,const BasePairProbabilities & result, - const InteractionEnergy & energy,Z_type targetRT,Z_type queryRT); + const InteractionEnergy & energy,Z_type targetRT,Z_type queryRT,const Interaction * mfe = nullptr); private: static std::string svgBlock(const BasePairProbabilities & result,const InteractionEnergy & energy, - Z_type targetRT,Z_type queryRT); + Z_type targetRT,Z_type queryRT,const Interaction * mfe); static void emitFile(const std::string & name,const std::string & data); static std::string block(const BasePairProbabilities & result,const RnaSequence & target, const RnaSequence & query,const std::string & separator); diff --git a/src/bin/CommandLineParsing.cpp b/src/bin/CommandLineParsing.cpp index 756d8b0f..7f6f1423 100644 --- a/src/bin/CommandLineParsing.cpp +++ b/src/bin/CommandLineParsing.cpp @@ -2234,7 +2234,7 @@ getEnergyHandler( const Accessibility& accTarget, const ReverseAccessibility& ac OutputConstraint CommandLineParsing:: -getOutputConstraint( const InteractionEnergy & energy ) const +getOutputConstraint( const InteractionEnergy & energy, bool forPrediction ) const { checkIfParsed(); if (!rri.empty()) { @@ -2250,7 +2250,7 @@ getOutputConstraint( const InteractionEnergy & energy ) const default : throw std::runtime_error("CommandLineParsing::getOutputConstraint() : unsupported outOverlap value "+toString(outOverlap.val)); } return OutputConstraint( - outNumber.val + (forPrediction && !outPrefix2streamName.at(OP_bpsvg).empty() ? std::max(size_t(1),size_t(outNumber.val)) : outNumber.val) , overlap , Ekcal_2_E(outMaxE.val) , Ekcal_2_E(outDeltaE.val) @@ -2501,14 +2501,15 @@ BasePairProbabilities * CommandLineParsing::getBasePairProbabilityResult(const I throw std::invalid_argument("bpProb/bpsvg requires a stack-only seed handler; bulged seeds are unsupported"); return new BasePairProbabilities(energy.size1(),energy.size2(),!outPrefix2streamName.at(OP_bpsvg).empty()); } -void CommandLineParsing::writeBasePairProbabilities(const BasePairProbabilities & result,const InteractionEnergy & energy) const { +void CommandLineParsing::writeBasePairProbabilities(const BasePairProbabilities & result,const InteractionEnergy & energy, + const Interaction * mfe) const { const auto & t=energy.getAccessibility1().getSequence(); const auto & q=energy.getAccessibility2().getAccessibilityOrigin().getSequence(); if (!outPrefix2streamName.at(OP_bpProb).empty()) BasePairProbabilityWriter::writeFile(getFullFilename(outPrefix2streamName.at(OP_bpProb),&t,&q),result,t,q,outSep); if (!outPrefix2streamName.at(OP_bpsvg).empty()) BasePairProbabilityWriter::writeSvgFile(getFullFilename(outPrefix2streamName.at(OP_bpsvg),&t,&q),result,energy, - getAccessibilityRT(tAcc.val),getAccessibilityRT(qAcc.val)); + getAccessibilityRT(tAcc.val),getAccessibilityRT(qAcc.val),mfe); } Predictor* diff --git a/src/bin/CommandLineParsing.h b/src/bin/CommandLineParsing.h index 14e010f5..f0e796ad 100644 --- a/src/bin/CommandLineParsing.h +++ b/src/bin/CommandLineParsing.h @@ -282,7 +282,7 @@ class CommandLineParsing { * parameters * @param energy the interaction energy handler to be used * @param output the output handler to be used - * @param pairProbabilities optional non-owning raw result sink for exact stack seeds + * @param pairProbabilities optional non-owning raw result sink for supported ensemble predictors * @return the newly allocated Predictor object to be deleted by the calling * function */ @@ -296,7 +296,8 @@ class CommandLineParsing { */ BasePairProbabilities * getBasePairProbabilityResult(const InteractionEnergy & energy) const; /** Publish a successful sequence-pair result using ordinary filename rules. */ - void writeBasePairProbabilities(const BasePairProbabilities & result,const InteractionEnergy & energy) const; + void writeBasePairProbabilities(const BasePairProbabilities & result,const InteractionEnergy & energy, + const Interaction * mfe = nullptr) const; /** * Provides the seed constraint according to the user settings @@ -331,9 +332,10 @@ class CommandLineParsing { /** * The constraints to be applied to the interaction output generation * @param energy the interaction energy to be used for computation + * @param forPrediction retain a best site for SVG even with zero ranked output * @return the output constraints to be applied */ - OutputConstraint getOutputConstraint( const InteractionEnergy & energy ) const; + OutputConstraint getOutputConstraint( const InteractionEnergy & energy, bool forPrediction = false ) const; /** * The stream to write the interaction output to diff --git a/src/bin/IntaRNA.cpp b/src/bin/IntaRNA.cpp index bb971e29..e67b4876 100644 --- a/src/bin/IntaRNA.cpp +++ b/src/bin/IntaRNA.cpp @@ -239,9 +239,9 @@ int main(int argc, char **argv){ // setup collecting output handler to ensure // k-best output per query-target combination // and not per region combination if not requested - OutputHandlerInteractionList bestInteractions( parameters.getOutputConstraint(*energy), + OutputHandlerInteractionList bestInteractions( parameters.getOutputConstraint(*energy,true), (parameters.reportBestPerRegion() ? std::numeric_limits::max() : 1 ) - * parameters.getOutputConstraint(*energy).reportMax ); + * parameters.getOutputConstraint(*energy,true).reportMax ); // One owner spans all disjoint searched regions for this sequence pair. std::unique_ptr pairProbabilities(parameters.getBasePairProbabilityResult(*energy)); @@ -356,12 +356,14 @@ int main(int argc, char **argv){ : (*bestInteractions.begin())->energy + bestInteractions.getOutputConstraint().deltaE; // The collector is sorted by energy, so all later entries are worse. for( const Interaction * inter : bestInteractions) { + if (output->getOutputConstraint().reportMax==0) break; if (inter->energy > maxMergedE) { break; } output->add(*inter); } } - if (pairProbabilities) parameters.writeBasePairProbabilities(*pairProbabilities,*energy); + if (pairProbabilities) parameters.writeBasePairProbabilities(*pairProbabilities,*energy, + bestInteractions.empty()?nullptr:*bestInteractions.begin()); } // successful sequence-pair computation #if INTARNA_MULITHREADING diff --git a/tests/testBasePairProbabilitySvg.py b/tests/testBasePairProbabilitySvg.py index 55e5e576..597afd6a 100644 --- a/tests/testBasePairProbabilitySvg.py +++ b/tests/testBasePairProbabilitySvg.py @@ -55,6 +55,15 @@ def plot(t='GGAGGG', q='CCCC', opts=()): assert len(cells) == 24 assert '+1' in [e.text for e in root.findall('.//s:text[@class="index"]', NS)] assert not root.findall('.//s:line[@data-index="1"]', NS) + assert root.find('.//s:text[@class="subtitle"]', NS) is None + query_axis = root.find('.//s:text[@class="axis"][@x]', NS) + assert query_axis.text == "query (5' to 3')" + assert float(query_axis.attrib['y']) > max(float(r.attrib['y']) for r in cells.values())+20 + # Original target coordinate 1 is at the bottom; query coordinate 1 at left. + for i in range(1, 7): + for j in range(1, 5): + assert float(cells[i, j].attrib['y']) == float(cells[1, 1].attrib['y'])-20*(i-1) + assert float(cells[i, j].attrib['x']) == float(cells[1, 1].attrib['x'])+20*(j-1) for i, row in enumerate(rows[1:], 1): for j, value in enumerate(row[1:], 1): r = cells[i, j] @@ -62,22 +71,57 @@ def plot(t='GGAGGG', q='CCCC', opts=()): bounds = [0.01, 0.1, 0.25, 0.5, 0.75, 0.9] expected_color = sum(float(value) >= boundary for boundary in bounds) assert f'p{expected_color}' in r.attrib['class'].split() - assert 'Base-pair probability' in r.find('s:title', NS).text + title = r.find('s:title', NS).text + assert title.startswith(f'Base-pair probability (target {i}, query {j}): ') + formatted = f'{float(value):.2e}' if float(value) < .001 else f'{float(value):.3f}' + assert title.endswith(': '+formatted), title assert all(float(cells[3, j].attrib['data-probability']) == 0 for j in range(1, 5)) - frame = root.findall('.//s:rect[@data-type="unpaired"]', NS) + frame = root.findall('.//s:rect[@data-type="intramolecular-pairing"]', NS) assert len(frame) == 2*(6+4) - assert all(float(r.attrib['data-probability']) == 1 for r in frame) - assert all('Unpaired probability' in r.find('s:title', NS).text for r in frame) + assert all(float(r.attrib['data-probability']) == 0 for r in frame) + assert all('Intramolecular pairing probability' in r.find('s:title', NS).text for r in frame) css = root.find('s:style', NS).text assert all(f'.p{i} {{ fill:' in css for i in range(7)) assert len(root.findall('.//s:g[@class="probability-legend"]/s:rect', NS)) == 7 # All admitted computed two-pair stacks, in original query orientation. expected = {(i+k+1, 4-j-k) for i in (0, 3, 4) for j in range(3) for k in range(2)} assert seeds(root) == expected, seeds(root) + for r in root.findall('.//s:rect[@class="seed"][@data-target]', NS): + bp = cells[int(r.attrib['data-target']), int(r.attrib['data-query'])] + assert float(r.attrib['x']) == float(bp.attrib['x'])+1 + assert float(r.attrib['y']) == float(bp.attrib['y'])+1 + for r in frame: + idx = int(r.attrib['data-index']) + axis, bp = ('y', cells[idx, 1]) if r.attrib['data-strand'] == 'target' else ('x', cells[1, idx]) + assert float(r.attrib[axis]) == float(bp.attrib[axis]) # Requesting SVG must not affect CSV or ensemble/ranked output. baseline = run(options=['--outNumber=1', '--outMode=C', '--outCsvCols=Zall,Eall']) plotted = run(options=['--outNumber=1', '--outMode=C', '--outCsvCols=Zall,Eall', f'--out=bpsvg:{svg}']) assert baseline.stdout == plotted.stdout + # The green rectangle covers the reported MFE region, including when + # ranked output is disabled. Query coordinates retain their original order. + for target, query, options in ( + ('GGAGGG', 'CCCC', []), + ('AAGGGGAA', 'AACCCCAA', []), + ('GGAGGG', 'CCCC', ['--tIdxPos0=-4', '--qIdxPos0=-2']), + ): + reference = run(target, query, [*options, '--outNumber=1', '--outMode=C', + '--outCsvCols=start1,end1,start2,end2']) + row = next(csv.DictReader(reference.stdout.splitlines(), delimiter=';')) + for count in (0, 1): + mfe_plot = plot(target, query, [*options, f'--outNumber={count}']) + outline = mfe_plot.find('.//s:rect[@class="mfe"][@data-target-start]', NS) + assert outline is not None + bounds = tuple(int(outline.attrib[k]) for k in ( + 'data-target-start', 'data-target-end', 'data-query-start', 'data-query-end')) + assert bounds == tuple(int(row[k]) for k in ('start1', 'end1', 'start2', 'end2')) + ts, te, qs, qe = bounds + matrix = pairs(mfe_plot) + assert float(outline.attrib['x']) == float(matrix[ts, qs].attrib['x']) + assert float(outline.attrib['y']) == float(matrix[te, qs].attrib['y']) + assert float(outline.attrib['width']) == float(matrix[ts, qe].attrib['x'])-float(matrix[ts, qs].attrib['x'])+20 + assert float(outline.attrib['height']) == float(matrix[ts, qs].attrib['y'])-float(matrix[te, qs].attrib['y'])+20 + assert 'Green outline:' in ''.join(mfe_plot.itertext()) # Explicit singleton/mixed seed masks exclude extension-only cells. opts = ['--seedTQ=1|&4|,2||&2||'] mixed = plot('GGGG', 'CCCC', opts) @@ -103,7 +147,7 @@ def plot(t='GGAGGG', q='CCCC', opts=()): idx = int(g.attrib['data-index']) r = signed_cells[idx,-15] if strand == 'target' else signed_cells[-15,idx] axis = 'y' if strand == 'target' else 'x' - expected_pos = float(r.attrib[axis]) + (20 if idx > 1 else 0) + expected_pos = float(r.attrib[axis]) + (0 if idx > 1 else 20) if strand == 'target' else float(r.attrib[axis]) + (20 if idx > 1 else 0) assert float(g.attrib[axis+'1']) == expected_pos assert ('major' in g.attrib['class']) == (idx % 50 == 0) assert ('origin' in g.attrib['class']) == (idx == 1) @@ -113,6 +157,10 @@ def plot(t='GGAGGG', q='CCCC', opts=()): name = '' named = plot(opts=[f'--tId={name}']) assert name in named.find('s:title', NS).text + assert named.find('.//s:text[@class="subtitle"]', NS).text == name+' / query' + assert all(name in r.find('s:title', NS).text for r in pairs(named).values()) + assert all(name in r.find('s:title', NS).text for r in named.findall( + './/s:rect[@data-type="intramolecular-pairing"][@data-strand="target"]', NS)) assert name+" (5' to 3')" in [e.text for e in named.findall('.//s:text', NS)] # Accessibility uses its own per-strand scale and original query order. pu_t, pu_q = d/'target.pu', d/'query.pu' @@ -124,9 +172,9 @@ def one_nt(path): def check_frame(root, target_pu, query_pu): for strand, values in (('target', target_pu), ('query', query_pu)): assert any(0 < v < .9 for v in values) - for r in root.findall(f'.//s:rect[@data-type="unpaired"][@data-strand="{strand}"]', NS): - assert math.isclose(float(r.attrib['data-probability']), values[int(r.attrib['data-index'])-1], - rel_tol=2e-5, abs_tol=1e-6), (strand, r.attrib, values) + for r in root.findall(f'.//s:rect[@data-type="intramolecular-pairing"][@data-strand="{strand}"]', NS): + assert math.isclose(float(r.attrib['data-probability']), 1-values[int(r.attrib['data-index'])-1], + rel_tol=2e-5, abs_tol=5e-6), (strand, r.attrib, values) for temperature in (22, 37): acc_options = [f'--temperature={temperature}', f'--out=tPu:{pu_t}', f'--out=qPu:{pu_q}'] @@ -160,6 +208,7 @@ def check_frame(root, target_pu, query_pu): empty = plot(t,q) assert all(r.attrib['data-probability'] == 'NA' for r in pairs(empty).values()) assert not seeds(empty) + assert not empty.findall('.//s:rect[@class="mfe"]', NS) assert 'empty interaction ensemble' in ''.join(empty.itertext()) compressed = d/'pairs.svg.gz' run(options=[f'--out=bpsvg:{compressed}']) From 322031fc124eec6d01667fbf1f8bedf0ff35f038 Mon Sep 17 00:00:00 2001 From: AlexanderMitrofanov Date: Fri, 9 Oct 2026 22:16:07 +0200 Subject: [PATCH 13/21] feat: add exact unseeded base-pair probabilities (step 10) --- ChangeLog | 12 ++ README.md | 17 +- src/IntaRNA/PredictorMfeEns2d.cpp | 122 ++++++++++- src/IntaRNA/PredictorMfeEns2d.h | 24 ++- src/bin/CommandLineParsing.cpp | 30 +-- tests/Makefile.am | 1 + tests/PredictorUnseededProbability_test.cpp | 217 ++++++++++++++++++++ tests/testBasePairProbabilities.py | 15 +- tests/testBasePairProbabilitySvg.py | 7 +- 9 files changed, 418 insertions(+), 27 deletions(-) create mode 100644 tests/PredictorUnseededProbability_test.cpp diff --git a/ChangeLog b/ChangeLog index 19fb5983..e818a899 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,6 +14,9 @@ ## Interface and handling +- enable base-pair CSV/SVG probabilities for exact unseeded model P/mode M + predictions (PR #259, step 10) + - revise SVG axes, sequence labels and rounded tooltips; show intramolecular pairing (1-Pu) frames and the best interaction region (PR #259 review) @@ -172,6 +175,15 @@ energies, restricted partition sums, and trackers. ################################################################################ ################################################################################ +261009 Alexander Mitrofanov + * PredictorMfeEns2d, CommandLineParsing : + + compute actual-pair masses by reversing the existing unseeded recurrence; + preserve site filters, noLP and numerical cutoffs, and merge disjoint regions + * enable CSV/SVG with --noSeed; fix default-ended region offset truncation + * tests/PredictorUnseededProbability_test.cpp, tests/Makefile.am, README.md : + + compare against independent chain enumeration, filters, regions and failures; + document the public optional sink (PR #259 step 10) + 261009 Alexander Mitrofanov * BasePairProbabilitySvg, BasePairProbabilityWriter, CommandLineParsing, IntaRNA : * place target origin at bottom left and query name below the matrix; include diff --git a/README.md b/README.md index ca099554..888f143f 100644 --- a/README.md +++ b/README.md @@ -2016,8 +2016,8 @@ or `STDERR` instead of a file name. ## Actual base-pair probabilities `--out=bpProb:FILE` writes the probability that each target/query nucleotide pair -actually pairs, conditional on an allowed seeded interaction. It requires -`--model=P --mode=M` and a stack-only seed handler. For example: +actually pairs, conditional on an allowed interaction. It requires +`--model=P --mode=M` with `--noSeed` or a stack-only seed handler. For example: ```sh IntaRNA -t GGAGGG -q CCCC --energy=B --acc=N --seedBP=2 \ @@ -2031,7 +2031,7 @@ Computed seeds preserve their handler-specific admission thresholds. Explicit stacked seeds may have different lengths, including singletons; competing explicit patterns at the same start still retain only the selected minimum-energy pattern. Other predictors retain their existing behavior. Heuristic, kinetic, -evaluation, seed-only, unseeded and bulged-seed `bpProb` requests are rejected. +evaluation, seed-only and bulged-seed `bpProb` requests are rejected. Rows follow the original target and columns the original query, both 5' to 3'. The header starts with `bpProb`; labels contain each nucleotide and its display @@ -2054,14 +2054,19 @@ bulge can have positive site coverage and zero actual-pair probability. There is no added unbound-state weight. Individual pair events can coexist, so `1 - sum(pair probabilities)` is not a probability of no interaction. -The backend checks nonnegative arithmetic and reports numerical range failures +The unseeded exact predictor is enabled by `--noSeed` with the same CSV/SVG +outputs. Its outside pass follows the existing fixed-right-boundary recurrence, +including its numerical zero cutoffs, without changing ordinary prediction. + +The seeded backend checks nonnegative arithmetic and reports numerical range failures as errors, including underflow, overflow and NaN. Positive subnormals are rejected; there is currently no scaling fallback. Failed or cancelled regional work never produces a successful-looking probability matrix. Ordinary floating-point rounding remains; "exact" describes the enumerated ensemble, not real arithmetic. For library use, keep a `BasePairProbabilities` owner alive across predictions, -pass its optional non-owning pointer to `PredictorMfeEns2dSeedExtension`, and call +pass its optional non-owning pointer to `PredictorMfeEns2dSeedExtension` (stack +seeds) or `PredictorMfeEns2d` (unseeded), and call `finalize()` only after all requested disjoint regions succeed. A writer is called explicitly after finalization; its destructor publishes nothing. The output constraint must enable `needZall`. The [standalone API example](doc/seeded-probabilities-example.cpp) @@ -2074,7 +2079,7 @@ show the public API and measured limits. `--out=bpsvg:FILE` renders the same actual-pair probabilities as `bpProb` in a standalone SVG. Both outputs can be requested together. The same exact -`--model=P --mode=M` stack-seed restrictions, regional ensemble, normalization +`--model=P --mode=M` unseeded/stack-seed restrictions, regional ensemble, normalization and success-only publication rules apply. ```sh diff --git a/src/IntaRNA/PredictorMfeEns2d.cpp b/src/IntaRNA/PredictorMfeEns2d.cpp index 9b9bb28e..490bfe9b 100644 --- a/src/IntaRNA/PredictorMfeEns2d.cpp +++ b/src/IntaRNA/PredictorMfeEns2d.cpp @@ -1,5 +1,6 @@ #include "IntaRNA/PredictorMfeEns2d.h" +#include "IntaRNA/PartitionArithmetic.h" #include @@ -11,10 +12,14 @@ PredictorMfeEns2d:: PredictorMfeEns2d( const InteractionEnergy & energy , OutputHandler & output - , PredictionTracker * predTracker ) + , PredictionTracker * predTracker + , BasePairProbabilities * pairProbabilities ) : PredictorMfeEns(energy,output,predTracker) + , pairProbabilities(pairProbabilities) , hybridZ( 0,0 ) { + if (pairProbabilities && !output.getOutputConstraint().needZall) + throw std::invalid_argument("unseeded pair probabilities require needZall"); } @@ -33,6 +38,13 @@ void PredictorMfeEns2d:: predict( const IndexRange & r1 , const IndexRange & r2 ) +{ + try { predictRegion(r1,r2); } + catch (...) { if (pairProbabilities) pairProbabilities->fail(); throw; } +} + +void +PredictorMfeEns2d::predictRegion(const IndexRange & r1,const IndexRange & r2) { #if INTARNA_MULITHREADING #pragma omp critical(intarna_omp_logOutput) @@ -47,20 +59,34 @@ predict( const IndexRange & r1 throw std::runtime_error("PredictorMfeEns2d::predict("+toString(r1)+","+toString(r2)+") is not sane"); #endif + if (pairProbabilities && (!r1.isAscending() || !r2.isAscending() + || r1.from>=energy.getAccessibility1().getSequence().size() + || r2.from>=energy.getAccessibility2().getSequence().size())) + throw std::invalid_argument("unseeded pair probabilities: invalid region"); + if (pairProbabilities && pairProbabilities->status()!=BasePairProbabilities::Status::pending) + throw std::logic_error("unseeded pair probabilities: accumulator is not pending"); + // set index offset energy.setOffset1(r1.from); energy.setOffset2(r2.from); // resize matrix hybridZ.resize( std::min( energy.size1() - , (r1.to==RnaSequence::lastPos?energy.size1()-1:r1.to)-r1.from+1 ) + , r1.to==RnaSequence::lastPos?energy.size1():r1.to-r1.from+1 ) , std::min( energy.size2() - , (r2.to==RnaSequence::lastPos?energy.size2()-1:r2.to)-r2.from+1 ) ); + , r2.to==RnaSequence::lastPos?energy.size2():r2.to-r2.from+1 ) ); // initialize mfe interaction for updates initOptima(); // initialize overall partition function for updates initZ(); + // No probability buffers or reverse work are needed for ordinary prediction. + Z2dMatrix outside, masses; + Z_type denominator=0; + if (pairProbabilities) { + outside.resize(hybridZ.size1(),hybridZ.size2()); + masses.resize(hybridZ.size1(),hybridZ.size2()); + } // for all right ends j1 for (size_t j1 = hybridZ.size1(); j1-- > 0; ) { @@ -78,12 +104,26 @@ predict( const IndexRange & r1 // fill matrix and store best interaction fillHybridZ( j1, j2, 0, 0, true ); + if (pairProbabilities) + accumulatePairMasses(j1,j2,outside,masses,denominator); } } + if (pairProbabilities && denominator!=PartitionArithmetic::check(Zall)) + throw std::logic_error("unseeded pair probabilities: updateZ override changed the partition objective"); // report mfe interaction reportOptima(); + if (pairProbabilities) { + const size_t n=hybridZ.size1(), m=hybridZ.size2(); + const auto first=energy.getBasePair(0,0), last=energy.getBasePair(n-1,m-1); + // An unseeded prediction has no seed annotations, even for an API sink + // that requested a mask for use by a shared writer. + const bool annotate=pairProbabilities->collectsSeedPairs(); + Matrix seeds(annotate?n:0,annotate?m:0,0); + pairProbabilities->addRegion(IndexRange(first.first,last.first), + IndexRange(last.second,first.second),denominator,masses,annotate?&seeds:nullptr); + } } //////////////////////////////////////////////////////////////////////////// @@ -201,5 +241,81 @@ fillHybridZ( const size_t j1, const size_t j2 //////////////////////////////////////////////////////////////////////////// +void +PredictorMfeEns2d::accumulatePairMasses(size_t j1,size_t j2,Z2dMatrix & outside, + Z2dMatrix & masses,Z_type & denominator) const +{ + using A=PartitionArithmetic; + const bool noLP=output.getOutputConstraint().noLP; + const size_t shift=noLP?1:0; + // Use exactly the rectangle and epsilon gates of fillHybridZ/updateZ: this + // reverses the represented ensemble, including its existing zero cutoff. + const size_t begin1=j1-std::min(j1,energy.getAccessibility1().getMaxLength()+1); + const size_t begin2=j2-std::min(j2,energy.getAccessibility2().getMaxLength()+1); + for(size_t i1=j1+1;i1-- > begin1;) for(size_t i2=j2+1;i2-- > begin2;) { + outside(i1,i2)=0; + const Z_type h=A::check(hybridZ(i1,i2)); + if (!Z_equal(h,0) && isValidOutputSite(i1,j1,i2,j2)) { + const Z_type b=A::check(energy.getBoltzmannWeight(energy.getE(i1,j1,i2,j2,E_type(0)))); + outside(i1,i2)=b; + denominator=A::add(denominator,A::multiply(h,b)); + } + } + + const auto first=energy.getBasePair(0,0); + const auto last=energy.getBasePair(masses.size1()-1,masses.size2()-1); + auto addMass=[&](size_t i1,size_t i2,Z_type value) { + const auto bp=energy.getBasePair(i1,i2); + auto & mass=masses(bp.first-first.first,bp.second-last.second); + mass=A::add(mass,value); + }; + const Z_type initiation=A::check(energy.getBoltzmannWeight(energy.getE_init())); + // Every suffix state contains its left pair once. Reverse topological + // traversal gathers all enclosing left boundaries before visiting a suffix. + for(size_t i1=begin1;i1<=j1;++i1) for(size_t i2=begin2;i2<=j2;++i2) { + const Z_type a=outside(i1,i2), h=hybridZ(i1,i2); + if (a==0 || h==0) continue; + addMass(i1,i2,A::multiply(a,h)); + const size_t w1=j1-i1+1, w2=j2-i2+1; + if (w1<=1 || w2<=1) continue; + + Z_type stack=1; + if (!noLP) { + const Z_type edge=A::multiply(a, + energy.getBoltzmannWeight(energy.getE_interLeft(i1,j1,i2,j2))); + outside(j1,j2)=A::add(outside(j1,j2),edge); + } else { + if (!energy.areComplementary(i1+1,i2+1)) continue; + stack=A::check(energy.getBoltzmannWeight(energy.getE_interLeft(i1,i1+1,i2,i2+1))); + const Z_type edge=A::multiply(a,stack); + if (w1==2 && w2==2) { + // The noLP terminal has no singleton H state: its second pair + // is implicit in stack * initiation and must be counted here. + addMass(j1,j2,A::multiply(edge,initiation)); + } else { + outside(i1+1,i2+1)=A::add(outside(i1+1,i2+1),edge); + } + } + if (w1<=2 || w2<=2) continue; + for(size_t k1=std::min(j1-1,i1+energy.getMaxInternalLoopSize1()+1+shift);k1>i1+shift;--k1) { + for(size_t k2=std::min(j2-1,i2+energy.getMaxInternalLoopSize2()+1+shift);k2>i2+shift;--k2) { + if (noLP && k1-1==i1+shift && k2-1==i2+shift) continue; + if (Z_equal(hybridZ(k1,k2),0)) continue; + const Z_type loop=A::check(energy.getBoltzmannWeight( + energy.getE_interLeft(i1+shift,k1,i2+shift,k2))); + const Z_type edge=A::multiply(a,A::multiply(stack,loop)); + outside(k1,k2)=A::add(outside(k1,k2),edge); + if (noLP) { + // This decomposition consumes (i,i+) before jumping over + // the loop to k; only i and k have explicit suffix states. + addMass(i1+1,i2+1,A::multiply(edge,hybridZ(k1,k2))); + } + } + } + } +} + +//////////////////////////////////////////////////////////////////////////// + } // namespace diff --git a/src/IntaRNA/PredictorMfeEns2d.h b/src/IntaRNA/PredictorMfeEns2d.h index 57b7f5c3..169b9881 100644 --- a/src/IntaRNA/PredictorMfeEns2d.h +++ b/src/IntaRNA/PredictorMfeEns2d.h @@ -3,6 +3,7 @@ #define INTARNA_PREDICTORMFEENS2D_H_ #include "IntaRNA/PredictorMfeEns.h" +#include "IntaRNA/BasePairProbabilities.h" #include "IntaRNA/Interaction.h" #include "IntaRNA/Matrix.h" @@ -34,10 +35,13 @@ class PredictorMfeEns2d: public PredictorMfeEns { * @param predTracker the prediction tracker to be used or NULL if no * tracking is to be done; if non-NULL, the tracker gets deleted * on this->destruction. + * @param pairProbabilities optional non-owning sink; requires needZall and + * must remain pending until all disjoint regions have succeeded */ PredictorMfeEns2d( const InteractionEnergy & energy , OutputHandler & output - , PredictionTracker * predTracker ); + , PredictionTracker * predTracker + , BasePairProbabilities * pairProbabilities = nullptr ); virtual ~PredictorMfeEns2d(); @@ -58,6 +62,9 @@ class PredictorMfeEns2d: public PredictorMfeEns { protected: + //! optional sequence-pair owner, never deleted or finalized by this predictor + BasePairProbabilities * pairProbabilities; + //! access to the interaction energy handler of the super class using PredictorMfeEns::energy; @@ -70,6 +77,21 @@ class PredictorMfeEns2d: public PredictorMfeEns { protected: + /** Compute one region, allowing predict() to fail the sink on any exception. */ + void predictRegion(const IndexRange & r1,const IndexRange & r2); + + /** Reverse the current fixed-right hybrid recurrence. Adjoint seeds obey the + * same site filters and numerical-zero tests as updateZ(). Implicit noLP + * stacking partners are counted in addition to the explicit DP-state pairs. + * @param j1 right boundary in local target coordinates + * @param j2 right boundary in local reversed-query coordinates + * @param outside scratch adjoints, same dimensions as hybridZ + * @param masses accumulated numerators in original regional orientation + * @param denominator accumulated boundary contributions, checked against Zall + */ + void accumulatePairMasses(size_t j1,size_t j2,Z2dMatrix & outside, + Z2dMatrix & masses,Z_type & denominator) const; + /** * Computes all entries of the hybridE matrix for interactions ending in * p=j1 and q=j2 and reports every complete boundary via updateCompleteZ(), diff --git a/src/bin/CommandLineParsing.cpp b/src/bin/CommandLineParsing.cpp index 7f6f1423..d5a0f30e 100644 --- a/src/bin/CommandLineParsing.cpp +++ b/src/bin/CommandLineParsing.cpp @@ -958,7 +958,7 @@ CommandLineParsing::CommandLineParsing( const Personality personality ) "\n 'tPu:' (target) unpaired probability values (RNAplfold format OR '.agz' file ending for IntaRNA's binary format)." "\n 'pMinE:' (target+query) for each index pair the minimal energy of any interaction covering the pair (CSV format)" "\n 'bpsvg:' (target+query) SVG actual-pair probability plot with accessibility frame and seed annotations; same requirements as bpProb" - "\n 'bpProb:' (target+query) actual-pair conditional probabilities for exact --model=P --mode=M stack-seed ensembles (CSV matrix, original strand order; NA for an empty ensemble)" + "\n 'bpProb:' (target+query) actual-pair conditional probabilities for --model=P --mode=M with --noSeed or stack-only seeds (CSV matrix, original strand order; NA for an empty ensemble)" "\n 'spotProb:' (target+query) tracks for a given set of interaction spots their probability to be covered by an interaction. If no spots are provided, probabilities for all index combinations are computed. Spots are encoded by comma-separated 'idxT&idxQ' pairs (target-query). For each spot a probability is provided in concert with the probability that none of the spots (encoded by '0&0') is covered (CSV format). The spot encoding is followed colon-separated by the output stream/file name, eg. '--out=\"spotProb:3&76,59&2:STDERR\"'. NOTE: value has to be quoted due to '&' symbol!" "\nFor each, provide a file name or STDOUT/STDERR to write to the respective output stream." ).c_str()) @@ -1246,8 +1246,8 @@ parse(int argc, char** argv) outSep = unescaped_string::getUnescaped( outSep ); if (hasBasePairProbabilityOutput()) { - if (model.val!='P' || mode.val!='M' || noSeedRequired || !rri.empty() || windowWidth.val!=0) - throw error("bpProb/bpsvg requires --model=P --mode=M with stack-only seeds and no windows"); + if (model.val!='P' || mode.val!='M' || !rri.empty() || windowWidth.val!=0) + throw error("bpProb/bpsvg requires --model=P --mode=M with --noSeed or stack-only seeds and no windows"); outNeedsZall=true; } // K needs a seed even before the usual --noSeed model normalization. @@ -2496,10 +2496,12 @@ bool CommandLineParsing::hasBasePairProbabilityOutput() const { } BasePairProbabilities * CommandLineParsing::getBasePairProbabilityResult(const InteractionEnergy & energy) const { if (!hasBasePairProbabilityOutput()) return nullptr; - std::unique_ptr handler(getSeedHandler(energy)); - if (!handler->guaranteesStackOnlySeeds()) - throw std::invalid_argument("bpProb/bpsvg requires a stack-only seed handler; bulged seeds are unsupported"); - return new BasePairProbabilities(energy.size1(),energy.size2(),!outPrefix2streamName.at(OP_bpsvg).empty()); + if (!noSeedRequired) { + std::unique_ptr handler(getSeedHandler(energy)); + if (!handler->guaranteesStackOnlySeeds()) + throw std::invalid_argument("bpProb/bpsvg requires a stack-only seed handler; bulged seeds are unsupported"); + } + return new BasePairProbabilities(energy.size1(),energy.size2(),!noSeedRequired && !outPrefix2streamName.at(OP_bpsvg).empty()); } void CommandLineParsing::writeBasePairProbabilities(const BasePairProbabilities & result,const InteractionEnergy & energy, const Interaction * mfe) const { @@ -2518,11 +2520,13 @@ getPredictor( const InteractionEnergy & energy, OutputHandler & output, BasePair { std::unique_ptr pairSeeds; if (pairProbabilities) { - if(model.val!='P' || mode.val!='M' || noSeedRequired || !rri.empty() || windowWidth.val!=0) - throw std::invalid_argument("bpProb/bpsvg requires --model=P --mode=M with stack-only seeds and no windows"); - pairSeeds.reset(getSeedHandler(energy)); - if(!pairSeeds->guaranteesStackOnlySeeds()) - throw std::invalid_argument("bpProb/bpsvg requires a stack-only seed handler; bulged seeds are unsupported"); + if(model.val!='P' || mode.val!='M' || !rri.empty() || windowWidth.val!=0) + throw std::invalid_argument("bpProb/bpsvg requires --model=P --mode=M with --noSeed or stack-only seeds and no windows"); + if (!noSeedRequired) { + pairSeeds.reset(getSeedHandler(energy)); + if(!pairSeeds->guaranteesStackOnlySeeds()) + throw std::invalid_argument("bpProb/bpsvg requires a stack-only seed handler; bulged seeds are unsupported"); + } } // set up hub for prediction tracking (if needed) PredictionTrackerHub * predTracker = new PredictionTrackerHub(); @@ -2624,7 +2628,7 @@ getPredictor( const InteractionEnergy & energy, OutputHandler & output, BasePair case 'P' : { switch ( mode.val ) { case 'H' : return new PredictorMfeEns2dHeuristic( energy, output, predTracker ); - case 'M' : return new PredictorMfeEns2d( energy, output, predTracker ); + case 'M' : return new PredictorMfeEns2d( energy, output, predTracker, pairProbabilities ); default : INTARNA_NOT_IMPLEMENTED("mode "+toString(mode.val)+" not available for model "+toString(model.val)); } } break; diff --git a/tests/Makefile.am b/tests/Makefile.am index 4d184d6b..a500da8e 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -30,6 +30,7 @@ runApiTests_SOURCES = \ SeededNativeBenchmark_test.cpp \ StackSeedDomain_test.cpp \ BasePairProbabilities_test.cpp \ + PredictorUnseededProbability_test.cpp \ testEasyLoggingSetup.icc \ AccessibilityConstraint_test.cpp \ AccessibilityFromStream_test.cpp \ diff --git a/tests/PredictorUnseededProbability_test.cpp b/tests/PredictorUnseededProbability_test.cpp new file mode 100644 index 00000000..7124d6e5 --- /dev/null +++ b/tests/PredictorUnseededProbability_test.cpp @@ -0,0 +1,217 @@ +#include "catch.hpp" + +#include "IntaRNA/AccessibilityConstraint.h" +#include "IntaRNA/AccessibilityDisabled.h" +#include "IntaRNA/BasePairProbabilities.h" +#include "IntaRNA/InteractionEnergyBasePair.h" +#include "IntaRNA/OutputHandlerInteractionList.h" +#include "IntaRNA/PredictorMfeEns2d.h" +#include "IntaRNA/ReverseAccessibility.h" + +#include +#include +#include +#include +#include + +using namespace IntaRNA; + +namespace { + +struct UnseededOracle { + Z_type z=0; + Matrix mass; + UnseededOracle(size_t n,size_t m) : mass(n,m,0) {} +}; + +// Enumerate increasing pair chains directly, without the predictor's suffix +// recurrence. Filter lonely pairs by inspecting both neighbours in the chain. +UnseededOracle enumerateUnseeded(const InteractionEnergy & energy, + const OutputConstraint & constraint,const IndexRange & r1,const IndexRange & r2) +{ + UnseededOracle result(energy.size1(),energy.size2()); + const size_t end1=r1.to==RnaSequence::lastPos?energy.size1()-1:r1.to; + const size_t end2=r2.to==RnaSequence::lastPos?energy.size2()-1:r2.to; + std::vector> chain; + std::function visit=[&](E_type hybrid) { + const auto [i1,i2]=chain.front(); + const auto [j1,j2]=chain.back(); + bool accepted=true; + if (constraint.noLP) { + for(size_t k=0;k0 && chain[k-1].first+1==chain[k].first + && chain[k-1].second+1==chain[k].second; + const bool right=k+1constraint.maxED || energy.getED2(i2,j2)>constraint.maxED) accepted=false; + const E_type complete=energy.getE(i1,j1,i2,j2,hybrid); + if (accepted && E_isNotINF(complete)) { + const Z_type weight=energy.getBoltzmannWeight(complete); + result.z+=weight; + for (const auto & p:chain) { + const auto bp=energy.getBasePair(p.first,p.second); + result.mass(bp.first,bp.second)+=weight; + } + } + for(size_t k1=j1+1;k1<=end1;++k1) for(size_t k2=j2+1;k2<=end2;++k2) { + if (!energy.isAccessible1(k1) || !energy.isAccessible2(k2) + || !energy.areComplementary(k1,k2)) continue; + const E_type loop=energy.getE_interLeft(j1,k1,j2,k2); + if (E_isINF(loop)) continue; + chain.emplace_back(k1,k2);visit(hybrid+loop);chain.pop_back(); + } + }; + for(size_t i1=r1.from;i1<=end1;++i1) for(size_t i2=r2.from;i2<=end2;++i2) { + if (!energy.isAccessible1(i1) || !energy.isAccessible2(i2) + || !energy.areComplementary(i1,i2)) continue; + chain.emplace_back(i1,i2);visit(energy.getE_init());chain.pop_back(); + } + return result; +} + +void compareUnseeded(const InteractionEnergy & energy,const OutputConstraint & constraint, + const IndexRange & r1,const IndexRange & r2,bool compareOracle=true) +{ + OutputHandlerInteractionList ordinary(constraint,10), annotated(constraint,10); + PredictorMfeEns2d baseline(energy,ordinary,nullptr); + BasePairProbabilities result(energy.size1(),energy.size2(),true); + PredictorMfeEns2d predictor(energy,annotated,nullptr,&result); + baseline.predict(r1,r2); + predictor.predict(r1,r2); + result.finalize(); + REQUIRE(predictor.getZall()==baseline.getZall()); + REQUIRE(result.getZ()==baseline.getZall()); + REQUIRE(std::distance(ordinary.begin(),ordinary.end())==std::distance(annotated.begin(),annotated.end())); + auto a=ordinary.begin(), b=annotated.begin(); + for(;a!=ordinary.end();++a,++b) { + REQUIRE((*a)->energy==(*b)->energy); + REQUIRE((*a)->basePairs==(*b)->basePairs); + } + for(size_t i=0;igetMaxLength()+1?ED_UPPER_BOUND:E_type((to-from+1)*perNt); + } +private: + E_type perNt; +}; + +class TinyInitiationEnergy : public InteractionEnergyBasePair { +public: + using InteractionEnergyBasePair::InteractionEnergyBasePair; + E_type getE_init() const override { return Ekcal_2_E(60); } +}; + +class ChangedObjectivePredictor : public PredictorMfeEns2d { +public: + using PredictorMfeEns2d::PredictorMfeEns2d; +protected: + void updateZ(size_t i1,size_t j1,size_t i2,size_t j2,Z_type z,bool hybrid) override { + PredictorMfeEns::updateZ(i1,j1,i2,j2,2*z,hybrid); + } +}; + +} + +TEST_CASE("exact unseeded pair probabilities enumerate physical pair chains", "[UnseededProbability][PredictorTinyOracle]") { + #include "testEasyLoggingSetup.icc" + for (const auto & sequence:std::vector>{ + {"GGGGGG","CCCCCC"},{"GUGCA","UGCGC"},{"AAGGGAA","ACCCUAA"}, + {"AAAA","AAAA"},{"G","C"}}) { + for(bool noLP:{false,true}) for(bool noGU:{false,true}) for(size_t loop:{0,2}) { + CAPTURE(sequence.first,sequence.second,noLP,noGU,loop); + RnaSequence target("target",sequence.first), query("query",sequence.second); + AccessibilityDisabled targetAcc(target,0,nullptr), queryAcc(query,0,nullptr); + ReverseAccessibility reverse(queryAcc); + InteractionEnergyBasePair energy(targetAcc,reverse,loop,loop,false,0.7,Ekcal_2_E(-0.8),3,Ekcal_2_E(0.13)); + OutputConstraint constraint(4,OutputConstraint::OVERLAP_BOTH,E_INF,E_INF,false,noLP,noGU,true,true); + compareUnseeded(energy,constraint,{0,RnaSequence::lastPos},{0,RnaSequence::lastPos}); + } + } +} + +TEST_CASE("unseeded pair probabilities preserve filtered offset ensembles", "[UnseededProbability]") { + #include "testEasyLoggingSetup.icc" + RnaSequence target("target","GUGGGCG"),query("query","CUCCCCC"); + for(bool noLP:{false,true}) for(bool noGU:{false,true}) { + ProbabilityWidthAccessibility targetAcc(target,3,Ekcal_2_E(0.10)); + ProbabilityWidthAccessibility queryAcc(query,4,Ekcal_2_E(0.15)); + ReverseAccessibility reverse(queryAcc); + InteractionEnergyBasePair energy(targetAcc,reverse,1,2,false,1,Ekcal_2_E(-1),3,0,true,false); + OutputConstraint constraint(5,OutputConstraint::OVERLAP_NONE,E_INF,E_INF,false,noLP,noGU,true,true,Ekcal_2_E(0.45)); + compareUnseeded(energy,constraint,{1,5},{2,6}); + compareUnseeded(energy,constraint,{2,RnaSequence::lastPos},{1,RnaSequence::lastPos}); + } + AccessibilityConstraint blocked(target,"...b...",0,"","",""); + AccessibilityDisabled targetAcc(target,0,&blocked),queryAcc(query,0,nullptr); + ReverseAccessibility reverse(queryAcc); + InteractionEnergyBasePair energy(targetAcc,reverse,2,2); + OutputConstraint constraint(1,OutputConstraint::OVERLAP_BOTH,E_INF,E_INF,false,false,false,true,true); + compareUnseeded(energy,constraint,{1,5},{1,5}); + + BasePairProbabilities result(target.size(),query.size()); + OutputHandlerInteractionList output(constraint,4); + PredictorMfeEns2d predictor(energy,output,nullptr,&result); + predictor.predict({0,2},{0,2}); + predictor.predict({4,6},{3,6}); + result.finalize(); + const auto first=enumerateUnseeded(energy,constraint,{0,2},{0,2}); + const auto second=enumerateUnseeded(energy,constraint,{4,6},{3,6}); + REQUIRE(result.getZ()==Approx(first.z+second.z).epsilon(2e-12)); + for(size_t i=0;i0 for v in covered[3][1:]);assert all(v==0 for v in with_spot[2]) compressed=d/'pairs.csv.gz';run(options=[f'--out=bpProb:{compressed}']);same(matrix(compressed)[2],values) # Unsupported requests fail explicitly and never create a probability file. - for opts in (['--mode=H'],['--mode=S'],['--model=X','--mode=K'],['--noSeed'],['--windowWidth=3','--windowOverlap=2'],['--seedMaxUP=1'],['--seedTQ=1|.|&2||']): + for opts in (['--mode=H'],['--mode=S'],['--model=X','--mode=K'],['--windowWidth=3','--windowOverlap=2'],['--seedMaxUP=1'],['--seedTQ=1|.|&2||']): fail=d/'unsupported.csv';run(options=[f'--out=bpProb:{fail}',*opts],success=False);assert not fail.exists() fail=d/'range.csv';run('GGGG','CCCC',[f'--out=bpProb:{fail}',*seedopt,'--energyAdd=900'],success=False);assert not fail.exists() run(options=['--out=bpProb:/dev/full'],success=False) diff --git a/tests/testBasePairProbabilitySvg.py b/tests/testBasePairProbabilitySvg.py index 597afd6a..0cbb64b6 100644 --- a/tests/testBasePairProbabilitySvg.py +++ b/tests/testBasePairProbabilitySvg.py @@ -122,6 +122,11 @@ def plot(t='GGAGGG', q='CCCC', opts=()): assert float(outline.attrib['width']) == float(matrix[ts, qe].attrib['x'])-float(matrix[ts, qs].attrib['x'])+20 assert float(outline.attrib['height']) == float(matrix[ts, qs].attrib['y'])-float(matrix[te, qs].attrib['y'])+20 assert 'Green outline:' in ''.join(mfe_plot.itertext()) + unseeded = plot(opts=['--noSeed', f'--out=bpProb:{table}']) + assert not seeds(unseeded) + rows = list(csv.reader(table.open(), delimiter=';')) + assert all(float(pairs(unseeded)[i,j].attrib['data-probability']) == float(rows[i][j]) + for i in range(1,7) for j in range(1,5)) # Explicit singleton/mixed seed masks exclude extension-only cells. opts = ['--seedTQ=1|&4|,2||&2||'] mixed = plot('GGGG', 'CCCC', opts) @@ -214,7 +219,7 @@ def check_frame(root, target_pu, query_pu): run(options=[f'--out=bpsvg:{compressed}']) assert len(pairs(load(compressed))) == 24 # Validation/numerical failures must not publish a partial document. - for opts in (['--mode=H'], ['--noSeed'], ['--seedMaxUP=1'], ['--model=X', '--mode=K'], + for opts in (['--mode=H'], ['--seedMaxUP=1'], ['--model=X', '--mode=K'], ['--windowWidth=3'], ['--seedTQ=1|&4|','--energyAdd=900']): failure = d/'failure.svg' run(options=[f'--out=bpsvg:{failure}', *opts], success=False) From ae0eb78da255c76765e6745d2dc4040766f7b791 Mon Sep 17 00:00:00 2001 From: AlexanderMitrofanov Date: Fri, 9 Oct 2026 22:30:47 +0200 Subject: [PATCH 14/21] feat: add approximate heuristic pair probabilities (step 11) --- ChangeLog | 22 ++ README.md | 32 ++- .../seeded-probabilities-validation.md | 48 ++++ .../IntaRNA.PredictorMfeEns2d.outside.svg | 69 ++++++ ...edictorMfeEns2dHeuristic.probabilities.svg | 80 ++++++ src/IntaRNA/BasePairProbabilities.cpp | 4 + src/IntaRNA/BasePairProbabilities.h | 8 + src/IntaRNA/BasePairProbabilitySvg.cpp | 7 +- src/IntaRNA/BasePairProbabilityWriter.cpp | 3 +- src/IntaRNA/PartitionArithmetic.h | 12 +- src/IntaRNA/PredictorMfeEns2d.cpp | 5 +- src/IntaRNA/PredictorMfeEns2d.h | 4 +- src/IntaRNA/PredictorMfeEns2dHeuristic.cpp | 99 +++++++- src/IntaRNA/PredictorMfeEns2dHeuristic.h | 36 ++- ...redictorMfeEns2dHeuristicSeedExtension.cpp | 41 ++- .../PredictorMfeEns2dHeuristicSeedExtension.h | 4 +- .../PredictorMfeEns2dSeedExtension.cpp | 211 +++++++++++++++- src/IntaRNA/PredictorMfeEns2dSeedExtension.h | 22 ++ src/bin/CommandLineParsing.cpp | 18 +- tests/Makefile.am | 2 + tests/PredictorHeuristicProbability_test.cpp | 234 ++++++++++++++++++ ...edictorHeuristicSeededProbability_test.cpp | 201 +++++++++++++++ tests/PredictorUnseededProbability_test.cpp | 6 + tests/testBasePairProbabilities.py | 12 +- tests/testBasePairProbabilitySvg.py | 11 +- 25 files changed, 1137 insertions(+), 54 deletions(-) create mode 100644 doc/recursions/IntaRNA.PredictorMfeEns2d.outside.svg create mode 100644 doc/recursions/IntaRNA.PredictorMfeEns2dHeuristic.probabilities.svg create mode 100644 tests/PredictorHeuristicProbability_test.cpp create mode 100644 tests/PredictorHeuristicSeededProbability_test.cpp diff --git a/ChangeLog b/ChangeLog index e818a899..eaea2fe1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,6 +14,12 @@ ## Interface and handling +- enable approximate actual-pair CSV/SVG probabilities for unseeded and seeded + heuristic ensembles, labelled explicitly as approximate (PR #259, step 11) + +- reject nonfinite partition totals and finite-energy boundary underflow before + publishing exact unseeded or heuristic pair probabilities (PR #259 review) + - enable base-pair CSV/SVG probabilities for exact unseeded model P/mode M predictions (PR #259, step 10) @@ -175,6 +181,22 @@ energies, restricted partition sums, and trackers. ################################################################################ ################################################################################ +261009 Alexander Mitrofanov + * PredictorMfeEns2dHeuristic, PredictorMfeEns2dHeuristicSeedExtension, + PredictorMfeEns2dSeedExtension, BasePairProbabilities, probability writers : + + reverse retained candidate chains and signed seed-extension recurrences to + obtain marginals of the existing heuristic ensemble; preserve denominator + and seed-overlap corrections, validate all masses before publication + + expose approximation metadata in CSV/SVG and retain seed provenance + * bound cropped noLP continuations by the active region and correct default + region offsets; reject unsupported singleton heuristic seeds explicitly + * CommandLineParsing, tests, README.md, doc/recursions : + + enable model P/mode H probability output; add independent tiny-chain and + signed-extension checks plus CLI parity/metadata coverage (PR #259 step 11) + * PredictorMfeEns2d, probability validation tests and report : + * reject finite-energy boundary underflow and nonfinite heuristic denominators + before publication; record independent review, full suites and performance + 261009 Alexander Mitrofanov * PredictorMfeEns2d, CommandLineParsing : + compute actual-pair masses by reversing the existing unseeded recurrence; diff --git a/README.md b/README.md index 888f143f..f3089346 100644 --- a/README.md +++ b/README.md @@ -2017,7 +2017,8 @@ or `STDERR` instead of a file name. `--out=bpProb:FILE` writes the probability that each target/query nucleotide pair actually pairs, conditional on an allowed interaction. It requires -`--model=P --mode=M` with `--noSeed` or a stack-only seed handler. For example: +`--model=P --mode=M` with `--noSeed` or a stack-only seed handler, or +`--model=P --mode=H` for an approximate heuristic ensemble. For example: ```sh IntaRNA -t GGAGGG -q CCCC --energy=B --acc=N --seedBP=2 \ @@ -2030,12 +2031,19 @@ is also used without `bpProb`, so requesting the matrix does not change `Zall`. Computed seeds preserve their handler-specific admission thresholds. Explicit stacked seeds may have different lengths, including singletons; competing explicit patterns at the same start still retain only the selected minimum-energy -pattern. Other predictors retain their existing behavior. Heuristic, kinetic, -evaluation, seed-only and bulged-seed `bpProb` requests are rejected. +pattern. With `--mode=H`, probabilities describe the predictor's retained +candidate ensemble, not all possible interactions. Unseeded H retains one +continuation per left pair; seeded H retains its seed-extension candidates and +selected right extension, including the existing seed-overlap corrections. +Seeded H supports computed or explicit seeds with at least two pairs, including +bulged seeds. These heuristic ensembles can retain path multiplicities and +must not be interpreted as the exact unique-chain ensemble of mode M. +Kinetic, evaluation, seed-only and exact bulged-seed probability requests remain +unsupported. Rows follow the original target and columns the original query, both 5' to 3'. -The header starts with `bpProb`; labels contain each nucleotide and its display -index (including `tIdxPos0`/`qIdxPos0` shifts). Entries use sufficient significant +The header starts with `bpProb` (exact) or `bpProbApproximate` (heuristic); labels +contain each nucleotide and its display index (including `tIdxPos0`/`qIdxPos0` shifts). Entries use sufficient significant digits for the partition type, with scientific notation for small probabilities. A successful empty ensemble contains `NA`; pairs absent from a nonempty ensemble have probability zero. The output uses `outSep`, the usual multi-FASTA filename @@ -2061,12 +2069,14 @@ including its numerical zero cutoffs, without changing ordinary prediction. The seeded backend checks nonnegative arithmetic and reports numerical range failures as errors, including underflow, overflow and NaN. Positive subnormals are rejected; there is currently no scaling fallback. Failed or cancelled regional work never -produces a successful-looking probability matrix. Ordinary floating-point -rounding remains; "exact" describes the enumerated ensemble, not real arithmetic. +produces a successful-looking probability matrix. Heuristic reverse passes likewise +validate finite arithmetic and reject invalid masses before publication. Ordinary +floating-point rounding remains; "exact" describes the enumerated ensemble, not +real arithmetic. For library use, keep a `BasePairProbabilities` owner alive across predictions, pass its optional non-owning pointer to `PredictorMfeEns2dSeedExtension` (stack -seeds) or `PredictorMfeEns2d` (unseeded), and call +seeds), `PredictorMfeEns2d` (unseeded), or their heuristic subclasses, and call `finalize()` only after all requested disjoint regions succeed. A writer is called explicitly after finalization; its destructor publishes nothing. The output constraint must enable `needZall`. The [standalone API example](doc/seeded-probabilities-example.cpp) @@ -2078,9 +2088,9 @@ show the public API and measured limits. ### SVG base-pair probability dot plots `--out=bpsvg:FILE` renders the same actual-pair probabilities as `bpProb` in a -standalone SVG. Both outputs can be requested together. The same exact -`--model=P --mode=M` unseeded/stack-seed restrictions, regional ensemble, normalization -and success-only publication rules apply. +standalone SVG. Both outputs can be requested together. The same supported +model/mode combinations, regional ensemble, normalization and success-only +publication rules apply. Heuristic SVGs are explicitly labelled approximate. ```sh IntaRNA -t GGAGGG -q CCCC --energy=B --acc=N --seedBP=2 \ diff --git a/doc/analysis/seeded-probabilities-validation.md b/doc/analysis/seeded-probabilities-validation.md index 3449a5ba..56c83716 100644 --- a/doc/analysis/seeded-probabilities-validation.md +++ b/doc/analysis/seeded-probabilities-validation.md @@ -270,3 +270,51 @@ Seven interleaved runs gave wall medians 0.412419→0.390979 seconds (ranges RSS 87,744→84,544 KiB. The slowdown did not reproduce without filesystem writes; the fixed serializer was 5.2% faster in this specific control. Use the same sparse400 command with `--out=STDOUT --out=bpsvg:/dev/null > /dev/null` to repeat. + +## PR #259 review: SVG revisions and steps 10–11 (2026-10-09) + +Martin's review adds unseeded and heuristic probability outputs to the original +SVG/documentation scope. Exact unseeded mode M now reverses each fixed-right-end +inside table. Unseeded mode H reverses its retained continuation chains; seeded +mode H traces its signed left/right extension arithmetic, including the existing +seed-overlap corrections and selected right extensions. Heuristic output is +explicitly approximate (`bpProbApproximate` and an approximate SVG title). Its +candidate ensemble can retain path multiplicities and is not the exact seeded +unique-chain ensemble. Existing numerical-zero cutoffs remain in the legacy +unseeded/heuristic objectives. + +The SVG now starts both strands at the bottom-left origin, places the query name +below the matrix, uses sequence names and rounded values in tooltips, displays +intramolecular pairing as `1-Pu`, and outlines the best reported interaction region +in green. Machine-readable probability attributes keep full precision. The MFE +outline is available with `--outNumber=0`; ordinary ranked output stays suppressed. +An outline is omitted if no interaction passes the reporting filters. + +Independent agents implemented and reviewed the recurrences, checked actual-pair +ownership, and evaluated performance before push. The new API tests compare exact +and unseeded heuristic results with independently enumerated tiny-chain ensembles. +Seeded heuristic tests change one pair's Boltzmann fugacity and compare the change +in the scalar partition function with that pair's numerator. They freeze the +baseline selected right extension and concrete computed seed family, so the test +checks marginals of the implemented conditional ensemble rather than a different +family selected after perturbation. Cases include overlapping/disjoint and bulged +seeds, LP/noLP, regions, seed annotations, successful empty results, singleton seed +rejection, and failure publication. Separate symbolic checks of 500 randomized +small legacy seeded extension polynomials found no negative or over-total pair +masses in the sampled cases. + +The review found and fixed active-region offset/dimension errors, finite-boundary +Boltzmann underflow masquerading as an empty result, and a nonfinite seeded-H +denominator bypassing a relative-tolerance comparison. These fixes have regression +coverage. CSV/SVG CLI tests cover approximation metadata, numeric parity, seed +masks, MFE geometry, signed coordinates and unchanged ordinary output. + +The final GCC 14.4 release and debug runs each pass all seven `make tests -j2` +suites and 100,947 API assertions in 97 cases. All 74 installed public headers +compile independently. Installed pkg-config consumers for exact/heuristic, +seeded/unseeded predictors compile, link and produce CSV/SVG with the expected +approximation metadata. `make dist` contains the new predictor tests +and implementation. All revised text is UTF-8/LF and `git diff --check` passes. +Both new recurrence SVGs parse, render and passed independent equation review; +representative output SVGs were rendered and visually inspected. Apple Clang was +not available locally. diff --git a/doc/recursions/IntaRNA.PredictorMfeEns2d.outside.svg b/doc/recursions/IntaRNA.PredictorMfeEns2d.outside.svg new file mode 100644 index 00000000..a44c7205 --- /dev/null +++ b/doc/recursions/IntaRNA.PredictorMfeEns2d.outside.svg @@ -0,0 +1,69 @@ + +Unseeded pair probabilities · fixed-right outside pass +PredictorMfeEns2d | --model=P --mode=M --noSeed | reverse the existing hybrid recurrence. Internal recurrence documentation for step 9 of PR 258. Equations describe the current implementation; RNA 2 uses reversed energy coordinates. + + + +INTARNA / RECURRENCE NOTES +Unseeded pair probabilities · fixed-right outside pass +PredictorMfeEns2d | --model=P --mode=M --noSeed | reverse the existing hybrid recurrence + +A pair i=(i₁,i₂) uses local energy coordinates; RNA 2 is reversed. i ≺ k increases both coordinates. +Fix right pair j. Hⱼ(i) is the forward hybrid weight; Aⱼ(i)=∂Z/∂Hⱼ(i) is its outside adjoint. +M(i) sums complete-interaction weights containing actual pair i, over every right boundary j. +d=BW(E_init); t(i,k)=BW(E_interLeft(i,k)); i⁺=i+(1,1); s=t(i,i⁺) + +1 Initialize the same completed-boundary objective +Aⱼ(i) ← B(i,j); Z += B(i,j)Hⱼ(i) +B(i,j)=BW(energy.getE(i₁,j₁,i₂,j₂,0)) only when !Z_equal(Hⱼ(i),0) and isValidOutputSite() pass. +Otherwise B=0. Complete ED / GU-end filters and native terminal terms match updateZ(). + +2 Reverse i in increasing order; credit its explicit pair +M(i) += Aⱼ(i)Hⱼ(i) +Every represented suffix contains its left pair i exactly once. Process only nonzero Aⱼ(i) and Hⱼ(i). +Then propagate Aⱼ(i) through each forward term below; later suffix states receive all enclosing mass. + +3a Lonely pairs allowed +Hⱼ(j)=d +Aⱼ(k) += Aⱼ(i)t(i,k) +Direct terminal: k=j; its pair is counted at j. +Intermediate k: i ≺ k ≺ j, allowed loop, +and !Z_equal(Hⱼ(k),0) as in the forward sum. + +3b noLP: direct stacking +Aⱼ(i⁺) += Aⱼ(i)s if i⁺ ≠ j +M(j) += Aⱼ(i)s d if i⁺ = j +A noLP terminal has Hⱼ(j)=0. +Its second pair j is implicit in the two-pair +initialization and is credited separately. + +3c noLP: stack, then a nonstack loop + +Hⱼ(k) + + + +i + +i⁺ + +k + +j +a = Aⱼ(i)s t(i⁺,k) +Aⱼ(k) += a +M(i⁺) += a Hⱼ(k) +Require complementary i⁺; i⁺ ≺ k ≺ j; k ≠ i⁺+(1,1); the same loop limits and epsilon gate on Hⱼ(k). +Here i⁺ is an actual pair skipped by the DP-state jump. Unpaired loop positions receive no mass. + +4 Commit successful regions and normalize only once +P(i,j) = ∑ M_region(i,j) / ∑ Z_region +Check the accumulated objective equals the unchanged Zall; map pairs with energy.getBasePair(). +Original target/query orientation is stored in the sink. Z=0 → NA; failed arithmetic → no result. +Conditional on an allowed interaction; no unbound-state weight. No outside buffers when output is disabled. +Exact for the existing forward recurrence, including its numerical-zero gates; no alternative ensemble is substituted. + +Implementation anchors (src/IntaRNA/) · BW(E)=exp(−E/RT) after native energy-unit conversion +PredictorMfeEns2d.cpp: fillHybridZ(), accumulatePairMasses(), predictRegion() +PredictorMfeEns.cpp: addPartitionContribution(); BasePairProbabilities: addRegion(), finalize() + diff --git a/doc/recursions/IntaRNA.PredictorMfeEns2dHeuristic.probabilities.svg b/doc/recursions/IntaRNA.PredictorMfeEns2dHeuristic.probabilities.svg new file mode 100644 index 00000000..3a11d160 --- /dev/null +++ b/doc/recursions/IntaRNA.PredictorMfeEns2dHeuristic.probabilities.svg @@ -0,0 +1,80 @@ + +Unseeded heuristic probabilities · candidate flow +PredictorMfeEns2dHeuristic | --model=P --mode=H --noSeed | approximate retained ensemble. Internal recurrence documentation for step 9 of PR 258. Equations describe the current implementation; RNA 2 uses reversed energy coordinates. + + + +INTARNA / RECURRENCE NOTES +Unseeded heuristic probabilities · candidate flow +PredictorMfeEns2dHeuristic | --model=P --mode=H --noSeed | approximate retained ensemble + +Each retained cell C(i) represents one selected pair chain, with hybrid weight vᵢ and right boundary jᵢ. +Pair coordinates increase on both strands internally; RNA 2 is reversed. Set i⁺=i+(1,1). +d=BW(E_init), t(i,k)=BW(E_interLeft(i,k)), and B(i,j)=BW(energy.getE(i₁,j₁,i₂,j₂,0)). + +Approximate means the continuation ensemble is pruned +Visit i in decreasing order. Generate candidates from already selected child chains C(k). +Every admitted candidate contributes to Z; only the candidate with the lowest complete site energy +is retained as C(i) for later extensions. Strict improvement wins; native energy rounding and ties are preserved. + +1 Record which new pairs each candidate owns +Candidate +Hybrid weight v +Owned pairs S +Child k +LP: initial pair +d +{i} +none +LP: loop / stack to k +t(i,k)vₖ +{i} +k +noLP: initial stack +s d, s=t(i,i⁺) +{i, i⁺} +none +noLP: direct stacking +s vᵢ⁺ +{i} +i⁺ +noLP: nonstack loop to k +s t(i⁺,k)vₖ +{i, i⁺} +k +Native pair, loop/span and right-end GU constraints apply; noLP loops exclude the adjacent child k=i⁺+(1,1). + +2 Initialize mass and flow from every admitted candidate +w = B(i,j)v; Z += w; M(p) += w for p ∈ S; F(k) += w if a child exists +M starts at zero; F is accumulated incoming weight for a retained child chain. This includes unselected candidates. +Use exactly updateZ() admission: !Z_equal(v,0), complete-site GU / ED filters, and finite arithmetic. +The current candidate owns S; every remaining pair belongs to its selected child continuation. + +3 Propagate incoming mass through selected chains + +C(k) + + + +i + +k + +jₖ +Sweep i in increasing order. Let Sᵢ and kᵢ describe C(i). +M(p) += F(i) for every p ∈ Sᵢ; +F(kᵢ) += F(i) when C(i) has a child. +Every edge increases both indices, so all parents arrive first. +No division by vᵢ is needed: a retained cell represents one chain, so its full incoming weight follows every pair. + +4 Publish marginals of the retained candidate ensemble +P(i,j) = ∑ M_region(i,j) / ∑ Z_region +Map energy coordinates back to original strand order, merge disjoint regions, then validate and normalize. +The denominator must equal the unchanged heuristic Zall. Mark the result approximate, including empty results. +Missing continuation chains are not recovered. These marginals differ from the exact --mode=M ensemble. +Only actual paired nucleotides receive mass; positions merely enclosed by a retained interaction remain unmarked. + +Implementation anchors (src/IntaRNA/) · BW(E)=exp(−E/RT) after native energy-unit conversion +PredictorMfeEns2dHeuristic.cpp: fillHybridZ(), recordProbabilityCandidate(), commitProbabilityRegion() +BasePairProbabilities: markApproximate(), addRegion(), finalize(); PredictorMfeEns.cpp: updateZ() + diff --git a/src/IntaRNA/BasePairProbabilities.cpp b/src/IntaRNA/BasePairProbabilities.cpp index 0496e534..4d06f327 100644 --- a/src/IntaRNA/BasePairProbabilities.cpp +++ b/src/IntaRNA/BasePairProbabilities.cpp @@ -4,6 +4,10 @@ #include namespace IntaRNA { +void BasePairProbabilities::markApproximate() { + if (state!=Status::pending) throw std::logic_error("pair probabilities: accumulator is not pending"); + approximate=true; +} BasePairProbabilities::BasePairProbabilities(size_t n,size_t m,bool collectSeedPairs) : mass(n,m,0), collectSeeds(collectSeedPairs), seeds(collectSeedPairs?n:0,collectSeedPairs?m:0,0) {} void BasePairProbabilities::addRegion(const IndexRange & t,const IndexRange & q, diff --git a/src/IntaRNA/BasePairProbabilities.h b/src/IntaRNA/BasePairProbabilities.h index bae84b8d..9e62d048 100644 --- a/src/IntaRNA/BasePairProbabilities.h +++ b/src/IntaRNA/BasePairProbabilities.h @@ -49,6 +49,12 @@ class BasePairProbabilities { const Matrix & rawMasses() const; /** @return whether this sink requests admitted seed-cell annotations */ bool collectsSeedPairs() const; + /** Mark an ensemble restricted by heuristic continuation choices. + * Must be called while pending, before publication. + */ + void markApproximate(); + /** @return whether the represented interaction ensemble is heuristic */ + bool isApproximate() const; /** @return seed-cell mask in original coordinates, empty when not requested */ const Matrix & seedPairs() const; /** @return validated matrix; only available for finalized nonempty results. @@ -57,6 +63,7 @@ class BasePairProbabilities { Matrix probabilities() const; private: Status state=Status::pending; + bool approximate=false; Z_type z=0; Matrix mass; const bool collectSeeds; @@ -67,6 +74,7 @@ inline BasePairProbabilities::Status BasePairProbabilities::status() const { ret inline Z_type BasePairProbabilities::getZ() const { return z; } inline const Matrix & BasePairProbabilities::rawMasses() const { return mass; } inline bool BasePairProbabilities::collectsSeedPairs() const { return collectSeeds; } +inline bool BasePairProbabilities::isApproximate() const { return approximate; } inline const Matrix & BasePairProbabilities::seedPairs() const { return seeds; } inline void BasePairProbabilities::fail() noexcept { state=Status::failed; } } diff --git a/src/IntaRNA/BasePairProbabilitySvg.cpp b/src/IntaRNA/BasePairProbabilitySvg.cpp index d350547f..5b7620ee 100644 --- a/src/IntaRNA/BasePairProbabilitySvg.cpp +++ b/src/IntaRNA/BasePairProbabilitySvg.cpp @@ -94,9 +94,10 @@ BasePairProbabilityWriter::svgBlock(const BasePairProbabilities & result,const I out<::max_digits10); out<<"\n" - <<"Base-pair probabilities: "<\n" + <<""<<(result.isApproximate()?"Approximate base-pair probabilities: ":"Base-pair probabilities: ")<<xml(t.getId())<<" / "<<xml(q.getId())<<"\n" <<"Target rows run 5' to 3' upwards and query columns run 5' to 3' to the right. Pair probabilities are conditional on an allowed interaction. " - <<"The frame shows single-nucleotide intramolecular pairing probabilities (1 - Pu) from the accessibility model.\n" + <<"The frame shows single-nucleotide intramolecular pairing probabilities (1 - Pu) from the accessibility model. " + <<(result.isApproximate()?"Approximate probabilities describe the retained heuristic ensemble.":"Probabilities describe the exact predictor ensemble.")<<"\n" < text { font-family: sans-serif; fill: #243247; } .heading { font-size: 18px; font-weight: bold; } @@ -126,7 +127,7 @@ text { font-family: sans-serif; fill: #243247; } auto text=[&](double tx,double ty,const std::string & value,const std::string & cls,const char * anchor="middle") { out<<""<\n"; }; - text(width/2,30,"Base-pair probabilities","heading"); + text(width/2,30,result.isApproximate()?"Approximate base-pair probabilities":"Base-pair probabilities","heading"); if (t.getId()!="target" || q.getId()!="query") text(width/2,53,t.getId()+" / "+q.getId(),"subtitle"); text(x+w/2,y+h+65,q.getId()+" (5' to 3')","axis"); diff --git a/src/IntaRNA/BasePairProbabilityWriter.cpp b/src/IntaRNA/BasePairProbabilityWriter.cpp index d38a744b..b8ee89bf 100644 --- a/src/IntaRNA/BasePairProbabilityWriter.cpp +++ b/src/IntaRNA/BasePairProbabilityWriter.cpp @@ -18,7 +18,8 @@ std::string BasePairProbabilityWriter::block(const BasePairProbabilities & resul // Validate every normalized value before opening a file or writing a header. const auto p=empty?Matrix():result.probabilities(); std::ostringstream data; - data<::max_digits10)<<"bpProb"; + data<::max_digits10) + <<(result.isApproximate()?"bpProbApproximate":"bpProb"); for(size_t j=0;j namespace IntaRNA { -/** Checked nonnegative arithmetic for exact seeded partitions only. +/** Checked nonnegative arithmetic for pair-probability partitions. * Structural zero is exactly zero. Positive subnormals are rejected because * their relative precision is not guaranteed. Ordinary sum rounding remains. */ @@ -24,7 +24,7 @@ class PartitionArithmetic { inline Z_type PartitionArithmetic::check(const Z_type x) { if (!(x>=0 && x<=std::numeric_limits::max()) || (x>0 && x::min())) - throw std::range_error("exact seeded partition: numerical range exceeded"); + throw std::range_error("partition arithmetic: numerical range exceeded"); return x; } inline Z_type PartitionArithmetic::add(const Z_type a,const Z_type b) { @@ -34,19 +34,19 @@ inline Z_type PartitionArithmetic::multiply(const Z_type a,const Z_type b) { check(a); check(b); if (a==0 || b==0) return 0; const Z_type r=check(a*b); - if (r==0) throw std::range_error("exact seeded partition: product underflow"); + if (r==0) throw std::range_error("partition arithmetic: product underflow"); return r; } inline Z_type PartitionArithmetic::divide(const Z_type a,const Z_type b) { check(a); check(b); - if (b==0) throw std::range_error("exact seeded partition: zero denominator"); + if (b==0) throw std::range_error("partition arithmetic: zero denominator"); const Z_type r=check(a/b); - if (a>0 && r==0) throw std::range_error("exact seeded partition: quotient underflow"); + if (a>0 && r==0) throw std::range_error("partition arithmetic: quotient underflow"); return r; } inline Z_type PartitionArithmetic::exp(const Z_type exponent) { const Z_type r=check(Z_exp(exponent)); - if (r==0) throw std::range_error("exact seeded partition: exponential underflow"); + if (r==0) throw std::range_error("partition arithmetic: exponential underflow"); return r; } } diff --git a/src/IntaRNA/PredictorMfeEns2d.cpp b/src/IntaRNA/PredictorMfeEns2d.cpp index 490bfe9b..a03506da 100644 --- a/src/IntaRNA/PredictorMfeEns2d.cpp +++ b/src/IntaRNA/PredictorMfeEns2d.cpp @@ -256,7 +256,10 @@ PredictorMfeEns2d::accumulatePairMasses(size_t j1,size_t j2,Z2dMatrix & outside, outside(i1,i2)=0; const Z_type h=A::check(hybridZ(i1,i2)); if (!Z_equal(h,0) && isValidOutputSite(i1,j1,i2,j2)) { - const Z_type b=A::check(energy.getBoltzmannWeight(energy.getE(i1,j1,i2,j2,E_type(0)))); + const E_type boundaryEnergy=energy.getE(i1,j1,i2,j2,E_type(0)); + const Z_type b=A::check(energy.getBoltzmannWeight(boundaryEnergy)); + if (b==0 && E_isNotINF(boundaryEnergy)) + throw std::range_error("unseeded pair probabilities: boundary weight underflow"); outside(i1,i2)=b; denominator=A::add(denominator,A::multiply(h,b)); } diff --git a/src/IntaRNA/PredictorMfeEns2d.h b/src/IntaRNA/PredictorMfeEns2d.h index 169b9881..2b77bb67 100644 --- a/src/IntaRNA/PredictorMfeEns2d.h +++ b/src/IntaRNA/PredictorMfeEns2d.h @@ -36,7 +36,9 @@ class PredictorMfeEns2d: public PredictorMfeEns { * tracking is to be done; if non-NULL, the tracker gets deleted * on this->destruction. * @param pairProbabilities optional non-owning sink; requires needZall and - * must remain pending until all disjoint regions have succeeded + * must remain pending until all disjoint regions have succeeded. + * Collection reverses this class's fillHybridZ recurrence; subclasses + * changing that recurrence must also supply their own collection. */ PredictorMfeEns2d( const InteractionEnergy & energy , OutputHandler & output diff --git a/src/IntaRNA/PredictorMfeEns2dHeuristic.cpp b/src/IntaRNA/PredictorMfeEns2dHeuristic.cpp index 806ea98a..93b57cbf 100644 --- a/src/IntaRNA/PredictorMfeEns2dHeuristic.cpp +++ b/src/IntaRNA/PredictorMfeEns2dHeuristic.cpp @@ -1,5 +1,6 @@ #include "IntaRNA/PredictorMfeEns2dHeuristic.h" +#include "IntaRNA/PartitionArithmetic.h" #include @@ -11,8 +12,9 @@ PredictorMfeEns2dHeuristic:: PredictorMfeEns2dHeuristic( const InteractionEnergy & energy , OutputHandler & output - , PredictionTracker * predTracker ) - : PredictorMfeEns2d(energy,output,predTracker) + , PredictionTracker * predTracker + , BasePairProbabilities * pairProbabilities ) + : PredictorMfeEns2d(energy,output,predTracker,pairProbabilities) { } @@ -33,6 +35,14 @@ PredictorMfeEns2dHeuristic:: predict( const IndexRange & r1 , const IndexRange & r2 ) +{ + try { predictRegionHeuristic(r1,r2); } + catch (...) { if (pairProbabilities) pairProbabilities->fail(); throw; } +} + +void +PredictorMfeEns2dHeuristic:: +predictRegionHeuristic(const IndexRange & r1,const IndexRange & r2) { #if INTARNA_MULITHREADING #pragma omp critical(intarna_omp_logOutput) @@ -48,15 +58,28 @@ predict( const IndexRange & r1 #endif + if (!r1.isAscending() || !r2.isAscending() + || r1.from>=energy.getAccessibility1().getSequence().size() + || r2.from>=energy.getAccessibility2().getSequence().size()) + throw std::invalid_argument("heuristic ensemble prediction: invalid region"); + if (pairProbabilities && pairProbabilities->status()!=BasePairProbabilities::Status::pending) + throw std::logic_error("heuristic pair probabilities: accumulator is not pending"); + if (pairProbabilities) pairProbabilities->markApproximate(); // set index offset energy.setOffset1(r1.from); energy.setOffset2(r2.from); // resize matrix hybridZ.resize( std::min( energy.size1() - , (r1.to==RnaSequence::lastPos?energy.size1()-1:r1.to)-r1.from+1 ) + , r1.to==RnaSequence::lastPos?energy.size1():r1.to-r1.from+1 ) , std::min( energy.size2() - , (r2.to==RnaSequence::lastPos?energy.size2()-1:r2.to)-r2.from+1 ) ); + , r2.to==RnaSequence::lastPos?energy.size2():r2.to-r2.from+1 ) ); + if (pairProbabilities) { + probabilityContinuation = Matrix(hybridZ.size1(),hybridZ.size2()); + probabilityFlow = Matrix(hybridZ.size1(),hybridZ.size2(),0); + probabilityMass = Matrix(hybridZ.size1(),hybridZ.size2(),0); + probabilityDenominator = 0; + } // init mfe for later updates initOptima(); @@ -68,6 +91,7 @@ predict( const IndexRange & r1 // trace back and output handler update reportOptima(); + if (pairProbabilities) commitProbabilityRegion(); } @@ -109,8 +133,8 @@ fillHybridZ() // no lp allowed if (noLpShift != 0) { // check if right-side stacking of (i1,i2) is possible - if ( i1+noLpShift < energy.size1() - && i2+noLpShift < energy.size2() + if ( i1+noLpShift < hybridZ.size1() + && i2+noLpShift < hybridZ.size2() && energy.areComplementary(i1+noLpShift,i2+noLpShift)) { // get stacking term to avoid recomputation @@ -130,6 +154,10 @@ fillHybridZ() curCellEtotal = energy.getE(i1,i1+noLpShift, i2,i2+noLpShift ,energy.getE(curCell->val)); // update overall partition function information for initial bps only updateZ( i1,curCell->j1, i2,curCell->j2, curCell->val, true ); + if (pairProbabilities) { + probabilityContinuation(i1,i2)={RnaSequence::lastPos,RnaSequence::lastPos,noLpShift!=0}; + recordProbabilityCandidate(i1,curCell->j1,i2,curCell->j2,curCell->val,probabilityContinuation(i1,i2)); + } } @@ -150,6 +178,8 @@ fillHybridZ() // update overall partition function information for current right extension updateZ( i1,rightExt->j1, i2,rightExt->j2, curZ, true ); + if (pairProbabilities) + recordProbabilityCandidate(i1,rightExt->j1,i2,rightExt->j2,curZ,{i1+noLpShift,i2+noLpShift,false}); // check if this combination yields better energy curEtotal = energy.getE(i1,rightExt->j1, i2,rightExt->j2, energy.getE(curZ)); @@ -164,6 +194,8 @@ fillHybridZ() curCell->val = curZ; // store total energy to avoid recomputation curCellEtotal = curEtotal; + if (pairProbabilities) + probabilityContinuation(i1,i2)={i1+noLpShift,i2+noLpShift,false}; } } } @@ -196,6 +228,8 @@ fillHybridZ() // update overall partition function information for current right extension updateZ( i1,rightExt->j1, i2,rightExt->j2, curZ, true ); + if (pairProbabilities) + recordProbabilityCandidate(i1,rightExt->j1,i2,rightExt->j2,curZ,{i1+noLpShift+w1,i2+noLpShift+w2,noLpShift!=0}); // check if this combination yields better energy curEtotal = energy.getE(i1,rightExt->j1, i2,rightExt->j2, energy.getE(curZ)); @@ -210,6 +244,8 @@ fillHybridZ() curCell->val = curZ; // store total energy to avoid recomputation curCellEtotal = curEtotal; + if (pairProbabilities) + probabilityContinuation(i1,i2)={i1+noLpShift+w1,i2+noLpShift+w2,noLpShift!=0}; } } // w2 @@ -224,4 +260,55 @@ fillHybridZ() //////////////////////////////////////////////////////////////////////////// +void PredictorMfeEns2dHeuristic::recordProbabilityCandidate(size_t i1,size_t j1, + size_t i2,size_t j2,Z_type hybrid,const ProbabilityContinuation & continuation) +{ + // Match the legacy heuristic's numerical-zero and output-site admission. + if (Z_equal(hybrid,0) || !isValidOutputSite(i1,j1,i2,j2)) return; + const E_type boundaryEnergy=energy.getE(i1,j1,i2,j2,E_type(0)); + const Z_type boundary=energy.getBoltzmannWeight(boundaryEnergy); + if (boundary==0 && !E_isINF(boundaryEnergy)) + throw std::range_error("heuristic pair probabilities: boundary weight underflow"); + const Z_type weight=PartitionArithmetic::multiply(hybrid,boundary); + probabilityDenominator=PartitionArithmetic::add(probabilityDenominator,weight); + probabilityMass(i1,i2)=PartitionArithmetic::add(probabilityMass(i1,i2),weight); + if (continuation.extraPair) + probabilityMass(i1+1,i2+1)=PartitionArithmetic::add(probabilityMass(i1+1,i2+1),weight); + if (continuation.next1!=RnaSequence::lastPos) + probabilityFlow(continuation.next1,continuation.next2)=PartitionArithmetic::add( + probabilityFlow(continuation.next1,continuation.next2),weight); +} + +void PredictorMfeEns2dHeuristic::commitProbabilityRegion() +{ + if (probabilityDenominator!=Zall) + throw std::logic_error("heuristic updateZ override did not preserve the pair-probability objective"); + const size_t n=hybridZ.size1(),m=hybridZ.size2(); + // Every retained cell represents exactly one chain. Its incoming candidate + // mass can therefore pass unchanged to the selected child, without division. + for(size_t i=0;i original(n,m,0); + for(size_t i=0;icollectsSeedPairs(); + Matrix seeds(annotate?n:0,annotate?m:0,0); + pairProbabilities->addRegion(target,query,Zall,original,annotate?&seeds:nullptr); +} + +//////////////////////////////////////////////////////////////////////////// + } // namespace diff --git a/src/IntaRNA/PredictorMfeEns2dHeuristic.h b/src/IntaRNA/PredictorMfeEns2dHeuristic.h index 8167c1c5..75e5b935 100644 --- a/src/IntaRNA/PredictorMfeEns2dHeuristic.h +++ b/src/IntaRNA/PredictorMfeEns2dHeuristic.h @@ -18,6 +18,10 @@ namespace IntaRNA { * all possible interaction ranges. * * This yields a quadratic time and space complexity. + * Optional pair probabilities refer to all admitted candidate chains considered + * by this pruning rule, with the same Zall as ordinary heuristic prediction. + * They approximate the unrestricted interaction ensemble. Collection adds + * quadratic storage and a reverse traversal of the retained continuations. * * @author Martin Raden * @author Frank Gelhausen @@ -40,10 +44,13 @@ class PredictorMfeEns2dHeuristic: public PredictorMfeEns2d { * @param predTracker the prediction tracker to be used or NULL if no * tracking is to be done; if non-NULL, the tracker gets deleted * on this->destruction. + * @param pairProbabilities optional non-owning sink for probabilities of the + * pruned candidate ensemble; requires needZall */ PredictorMfeEns2dHeuristic( const InteractionEnergy & energy , OutputHandler & output - , PredictionTracker * predTracker ); + , PredictionTracker * predTracker + , BasePairProbabilities * pairProbabilities = nullptr ); virtual ~PredictorMfeEns2dHeuristic(); @@ -75,8 +82,35 @@ class PredictorMfeEns2dHeuristic: public PredictorMfeEns2d { //! energy of all interaction hybrids starting in i1,i2 Z2dMatrix hybridZ; + //! The selected chain owns its first pair and, optionally, its next stack pair. + struct ProbabilityContinuation { + size_t next1 = RnaSequence::lastPos, next2 = RnaSequence::lastPos; + bool extraPair = false; + }; + //! Allocated only for probability output; selected continuations form a DAG. + Matrix probabilityContinuation; + //! Complete candidate weight flowing into each retained continuation. + Matrix probabilityFlow; + //! Numerators in local target/reversed-query coordinates until region commit. + Matrix probabilityMass; + //! Independently accumulated objective, required to agree exactly with Zall. + Z_type probabilityDenominator = 0; + protected: + /** Compute one region under predict()'s failure guard. */ + void predictRegionHeuristic(const IndexRange & r1,const IndexRange & r2); + + /** Record precisely the accepted updateZ candidate, crediting newly prepended + * pairs and routing its full weight to the retained child chain. Coordinates + * are local and the query is reversed; lastPos denotes an initial candidate. + */ + void recordProbabilityCandidate(size_t i1,size_t j1,size_t i2,size_t j2, + Z_type hybrid,const ProbabilityContinuation & continuation); + + /** Propagate candidate weights through selected chains and commit this region. */ + void commitProbabilityRegion(); + /** * Computes all entries of the hybridE matrix * and reports all valid interactions via updateOptima() diff --git a/src/IntaRNA/PredictorMfeEns2dHeuristicSeedExtension.cpp b/src/IntaRNA/PredictorMfeEns2dHeuristicSeedExtension.cpp index 4cf8aeaa..278eb740 100644 --- a/src/IntaRNA/PredictorMfeEns2dHeuristicSeedExtension.cpp +++ b/src/IntaRNA/PredictorMfeEns2dHeuristicSeedExtension.cpp @@ -9,14 +9,16 @@ PredictorMfeEns2dHeuristicSeedExtension( const InteractionEnergy & energy , OutputHandler & output , PredictionTracker * predTracker - , SeedHandler * seedHandlerInstance ) + , SeedHandler * seedHandlerInstance + , BasePairProbabilities * pairProbabilities ) : - PredictorMfeEns2dSeedExtension(energy,output,predTracker,seedHandlerInstance) + PredictorMfeEns2dSeedExtension(energy,output,predTracker,seedHandlerInstance,pairProbabilities) , E_right_opt(E_INF) , j1opt(0) , j2opt(0) { - assert( seedHandler.getConstraint().getBasePairs() > 1 ); + if(seedHandler.getConstraint().getBasePairs()<2 && seedHandler.getConstraint().getExplicitSeeds().empty()) + throw std::invalid_argument("heuristic seed extension requires at least two seed pairs"); } ////////////////////////////////////////////////////////////////////////// @@ -32,6 +34,12 @@ void PredictorMfeEns2dHeuristicSeedExtension:: predict( const IndexRange & r1, const IndexRange & r2 ) { + try { + if(pairProbabilities) pairProbabilities->markApproximate(); + if(!r1.isAscending() || !r2.isAscending() + || r1.from>=energy.getAccessibility1().getSequence().size() + || r2.from>=energy.getAccessibility2().getAccessibilityOrigin().getSequence().size()) + throw std::invalid_argument("heuristic seeded prediction: invalid region"); #if INTARNA_MULITHREADING #pragma omp critical(intarna_omp_logOutput) #endif @@ -52,16 +60,21 @@ predict( const IndexRange & r1, const IndexRange & r2 ) seedHandler.setOffset2(r2.from); const size_t range_size1 = std::min( energy.size1() - , (r1.to==RnaSequence::lastPos?energy.size1()-1:r1.to)-r1.from+1 ); + , r1.to==RnaSequence::lastPos?energy.size1():r1.to-r1.from+1 ); const size_t range_size2 = std::min( energy.size2() - , (r2.to==RnaSequence::lastPos?energy.size2()-1:r2.to)-r2.from+1 ); + , r2.to==RnaSequence::lastPos?energy.size2():r2.to-r2.from+1 ); + + initExtensionProbabilities(range_size1,range_size2); // compute seed interactions for whole range // and check if any seed possible - if (seedHandler.fillSeed( 0, range_size1-1, 0, range_size2-1 ) == 0) { + if ((seedHandler.getConstraint().getExplicitSeeds().empty() + && (range_size1 range_size1 || sj2 > range_size2) + if (sj1 >= range_size1 || sj2 >= range_size2 + || sl1>energy.getAccessibility1().getMaxLength() || sl2>energy.getAccessibility2().getMaxLength()) continue; const size_t maxMatrixLen1 = energy.getAccessibility1().getMaxLength()-sl1+1; const size_t maxMatrixLen2 = energy.getAccessibility2().getMaxLength()-sl2+1; @@ -93,6 +108,8 @@ predict( const IndexRange & r1, const IndexRange & r2 ) j2opt = sj2; E_right_opt = E_INF; + beginExtensionProbabilitySeed(si1,si2); + // ER hybridZ_right.resize( std::min(range_size1-sj1, maxMatrixLen1), std::min(range_size2-sj2, maxMatrixLen2) ); fillHybridZ_right(sj1, sj2, si1, si2); @@ -104,10 +121,13 @@ predict( const IndexRange & r1, const IndexRange & r2 ) fillHybridZ_left(si1, si2); } + finishExtensionProbabilitySeed(); } // si1 / si2 // report mfe interaction + commitExtensionProbabilities(); reportOptima(); + } catch (...) { if(pairProbabilities) pairProbabilities->fail(); throw; } } @@ -141,6 +161,7 @@ fillHybridZ_right( const size_t sj1, const size_t sj2 // update overall partition function information for true right-extensions of the current seed // seed only not covered due to min-val of r1,r2 updateZ(si1, sj1+r1, si2, sj2+r2, seedZ * rightExtZ * initZ, true); + addExtensionProbabilityRoot(si1,sj1+r1,si2,sj2+r2,seedZ*rightExtZ*initZ,false,true); } } @@ -175,6 +196,7 @@ fillHybridZ_left( const size_t si1, const size_t si2 ) // Z( left + seed ); covers seed only updateZ(si1-l1, sj1, si2-l2, sj2, curZ * seedZ, true); + addExtensionProbabilityRoot(si1-l1,sj1,si2-l2,sj2,curZ*seedZ,true,false); // Z( left + seed + rightOpt ) and rightOpt true seed extension if ( l1 > 0 // true left seed extension @@ -186,6 +208,7 @@ fillHybridZ_left( const size_t si1, const size_t si2 ) ) { updateZ(si1-l1, j1opt, si2-l2, j2opt, curZ * seedZ * rightOptZ, true); + addExtensionProbabilityRoot(si1-l1,j1opt,si2-l2,j2opt,curZ*seedZ*rightOptZ,true,true); } } } // i2 diff --git a/src/IntaRNA/PredictorMfeEns2dHeuristicSeedExtension.h b/src/IntaRNA/PredictorMfeEns2dHeuristicSeedExtension.h index ff8deada..a0ea94c7 100644 --- a/src/IntaRNA/PredictorMfeEns2dHeuristicSeedExtension.h +++ b/src/IntaRNA/PredictorMfeEns2dHeuristicSeedExtension.h @@ -32,13 +32,15 @@ class PredictorMfeEns2dHeuristicSeedExtension: public PredictorMfeEns2dSeedExten * @param predTracker the prediction tracker to be used or NULL if no * tracking is to be done; if non-NULL, the tracker gets deleted * on this->destruction. + * @param pairProbabilities optional non-owning sink for this approximate ensemble * @param seedHandler the seed handler to be used */ PredictorMfeEns2dHeuristicSeedExtension( const InteractionEnergy & energy , OutputHandler & output , PredictionTracker * predTracker - , SeedHandler * seedHandler ); + , SeedHandler * seedHandler + , BasePairProbabilities * pairProbabilities = nullptr ); /** diff --git a/src/IntaRNA/PredictorMfeEns2dSeedExtension.cpp b/src/IntaRNA/PredictorMfeEns2dSeedExtension.cpp index fb7c8929..7fd217f0 100644 --- a/src/IntaRNA/PredictorMfeEns2dSeedExtension.cpp +++ b/src/IntaRNA/PredictorMfeEns2dSeedExtension.cpp @@ -2,9 +2,188 @@ #include "IntaRNA/PredictorMfeEns2dSeedExtension.h" #include "IntaRNA/SeededPartitionFunction.h" #include "IntaRNA/PartitionArithmetic.h" +#include +#include namespace IntaRNA { +// The heuristic objective contains signed seed-overlap corrections. Trace the +// implemented arithmetic directly, retaining pair ownership on every term. +// This is allocated only for requested probability output; ordinary prediction +// follows its original arithmetic and storage path. +struct PredictorMfeEns2dSeedExtension::ExtensionProbabilityTrace { + using Pair=Interaction::BasePair; + struct Edge { size_t child; Z_type weight; std::vector pairs; }; + struct Tape { + size_t columns=0; + std::vector> edges; + std::vector adjoint; + void reset(size_t n,size_t m); + void add(size_t p1,size_t p2,size_t c1,size_t c2,Z_type weight,std::vector pairs); + void reverse(const Matrix & values,ExtensionProbabilityTrace & trace); + }; + Matrix mass,absoluteMass; + Matrix seeds; + Tape left,right; + std::vector anchor; + size_t si1=0,si2=0,sj1=0,sj2=0; + Z_type seedZ=0,z=0; + explicit ExtensionProbabilityTrace(size_t n,size_t m); + static Z_type finite(Z_type x); + static Z_type product(Z_type a,Z_type b); + void addMass(const Pair & bp,Z_type value); +}; + +void +PredictorMfeEns2dSeedExtension::ExtensionProbabilityTrace::Tape::reset(size_t n,size_t m) +{ + columns=m; + edges.assign(n*m,{}); + adjoint.assign(n*m,0); +} + +void +PredictorMfeEns2dSeedExtension::ExtensionProbabilityTrace::Tape::add( + size_t p1,size_t p2,size_t c1,size_t c2,Z_type weight,std::vector pairs) +{ + finite(weight); + edges.at(p1*columns+p2).push_back({c1*columns+c2,weight,std::move(pairs)}); +} + +void +PredictorMfeEns2dSeedExtension::ExtensionProbabilityTrace::Tape::reverse( + const Matrix & values,ExtensionProbabilityTrace & trace) +{ + for(size_t parent=edges.size();parent-- >0;) { + finite(values(parent/columns,parent%columns)); + for(const auto & edge:edges[parent]) { + const Z_type a=product(adjoint[parent],edge.weight); + adjoint[edge.child]=finite(adjoint[edge.child]+a); + const Z_type mass=product(a,values(edge.child/columns,edge.child%columns)); + for(const auto & bp:edge.pairs) trace.addMass(bp,mass); + } + } +} + +PredictorMfeEns2dSeedExtension::ExtensionProbabilityTrace::ExtensionProbabilityTrace(size_t n,size_t m) + : mass(n,m,0),absoluteMass(n,m,0),seeds(n,m,0) +{} + +Z_type +PredictorMfeEns2dSeedExtension::ExtensionProbabilityTrace::finite(Z_type x) +{ + if (!std::isfinite(x)) throw std::range_error("heuristic seeded probabilities: nonfinite arithmetic"); + return x; +} + +Z_type +PredictorMfeEns2dSeedExtension::ExtensionProbabilityTrace::product(Z_type a,Z_type b) +{ + finite(a); finite(b); + const Z_type value=finite(a*b); + if(a!=0 && b!=0 && (value==0 || std::abs(value)::min())) + throw std::range_error("heuristic seeded probabilities: product underflow"); + return value; +} + +void +PredictorMfeEns2dSeedExtension::ExtensionProbabilityTrace::addMass(const Pair & bp,Z_type value) +{ + mass(bp.first,bp.second)=finite(mass(bp.first,bp.second)+value); + absoluteMass(bp.first,bp.second)=finite(absoluteMass(bp.first,bp.second)+std::abs(value)); +} + +void PredictorMfeEns2dSeedExtension::initExtensionProbabilities(size_t n,size_t m) +{ + if(pairProbabilities) extensionProbabilityTrace=std::make_unique(n,m); +} + +std::vector +PredictorMfeEns2dSeedExtension::extensionSeedPrefix(size_t i1,size_t i2,size_t before) const +{ + Interaction seed(energy.getAccessibility1().getSequence(),energy.getAccessibility2().getAccessibilityOrigin().getSequence()); + seed.basePairs.push_back(energy.getBasePair(i1,i2)); + seedHandler.traceBackSeed(seed,i1,i2); + seed.basePairs.push_back(energy.getBasePair(i1+seedHandler.getSeedLength1(i1,i2)-1, + i2+seedHandler.getSeedLength2(i1,i2)-1)); + std::vector pairs; + for(const auto & bp:seed.basePairs) { + const size_t p=energy.getIndex1(bp),q=energy.getIndex2(bp); + if(p::epsilon()*Z_type(n+m+1); + if(std::abs(Zall-trace.z)>tolerance*std::max(std::abs(trace.z),std::abs(Zall))) + throw std::logic_error("heuristic seeded probabilities: outside objective differs from reported partition"); + const auto first=energy.getBasePair(0,0),last=energy.getBasePair(n-1,m-1); + const IndexRange target(first.first,last.first),query(last.second,first.second); + Matrix original(n,m,0); + Matrix annotations(n,m,0); + for(size_t i=0;iaddRegion(target,query,trace.z,original,&annotations); + extensionProbabilityTrace.reset(); +} + ////////////////////////////////////////////////////////////////////////// PredictorMfeEns2dSeedExtension:: @@ -21,8 +200,8 @@ PredictorMfeEns2dSeedExtension( , hybridZ_left( 0,0 ) , hybridZ_right( 0,0 ) { - if (pairProbabilities && (!seedHandler.guaranteesStackOnlySeeds() || !output.getOutputConstraint().needZall)) - throw std::invalid_argument("pair probabilities require a stack-only exact predictor and needZall"); + if (pairProbabilities && !output.getOutputConstraint().needZall) + throw std::invalid_argument("pair probabilities require needZall"); } ////////////////////////////////////////////////////////////////////////// @@ -43,6 +222,10 @@ predict( const IndexRange & r1, const IndexRange & r2 ) catch (...) { if (pairProbabilities) pairProbabilities->fail(); throw; } return; } + if (pairProbabilities) { + pairProbabilities->fail(); + throw std::invalid_argument("exact bulged-seed pair probabilities are unsupported"); + } if (seedHandler.getConstraint().getBasePairs()<2) throw std::invalid_argument("legacy bulged seed extension requires at least two seed pairs"); #if INTARNA_MULITHREADING @@ -252,6 +435,7 @@ void PredictorMfeEns2dSeedExtension:: fillHybridZ_left( const size_t si1, const size_t si2 ) { + if(extensionProbabilityTrace) extensionProbabilityTrace->left.reset(hybridZ_left.size1(),hybridZ_left.size2()); // temporary access const OutputConstraint & outConstraint = output.getOutputConstraint(); #if INTARNA_IN_DEBUG_MODE @@ -297,6 +481,7 @@ fillHybridZ_left( const size_t si1, const size_t si2 ) iStackZ = energy.getBoltzmannWeight(energy.getE_interLeft(i1,i1+noLpShift,i2,i2+noLpShift)); // check just stacked curZ += iStackZ * hybridZ_left(l1-noLpShift,l2-noLpShift); + if(extensionProbabilityTrace) extensionProbabilityTrace->left.add(l1,l2,l1-noLpShift,l2-noLpShift,iStackZ,{{i1,i2}}); } // check all combinations of decompositions into (i1,i2)..(k1,k2)-(j1,j2) @@ -311,6 +496,12 @@ fillHybridZ_left( const size_t si1, const size_t si2 ) curZ += (iStackZ * energy.getBoltzmannWeight(energy.getE_interLeft(i1+noLpShift,k1,i2+noLpShift,k2)) * hybridZ_left(si1-k1,si2-k2)); + if(extensionProbabilityTrace) { + std::vector pairs{{i1,i2}}; + if(noLpShift) pairs.emplace_back(i1+1,i2+1); + extensionProbabilityTrace->left.add(l1,l2,si1-k1,si2-k2, + iStackZ*energy.getBoltzmannWeight(energy.getE_interLeft(i1+noLpShift,k1,i2+noLpShift,k2)),std::move(pairs)); + } } } // k2 } // k1 @@ -356,9 +547,12 @@ fillHybridZ_left( const size_t si1, const size_t si2 ) Z_type correctionTerm = energy.getBoltzmannWeight( nonOverlapE ) * hybridZ_left( si1-si1overlap, si2-si2overlap); curZ -= correctionTerm; + if(extensionProbabilityTrace) extensionProbabilityTrace->left.add(l1,l2,si1-si1overlap,si2-si2overlap, + -energy.getBoltzmannWeight(nonOverlapE),extensionSeedPrefix(i1,i2,si1overlap)); // sanity insurance if (curZ < 0) { curZ = Z_type(0.0); + if(extensionProbabilityTrace) extensionProbabilityTrace->left.edges[l1*extensionProbabilityTrace->left.columns+l2].clear(); } } } else { @@ -371,6 +565,8 @@ fillHybridZ_left( const size_t si1, const size_t si2 ) Z_type correctionTerm = seedZ_rm * hybridZ_left( si1-sj1_rm , si2-sj2_rm ); + if(extensionProbabilityTrace) extensionProbabilityTrace->left.add(l1,l2,si1-sj1_rm,si2-sj2_rm, + -seedZ_rm,extensionSeedPrefix(i1,i2,sj1_rm)); // if noLP : handle explicit loop right of current seed if (outConstraint.noLP) { for (k1=sj1_rm; k1++ < si1; ) { @@ -386,6 +582,8 @@ fillHybridZ_left( const size_t si1, const size_t si2 ) correctionTerm += (seedZ_rm * energy.getBoltzmannWeight(energy.getE_interLeft(sj1_rm,k1,sj2_rm,k2)) * hybridZ_left(si1-k1,si2-k2) ); + if(extensionProbabilityTrace) extensionProbabilityTrace->left.add(l1,l2,si1-k1,si2-k2, + -seedZ_rm*energy.getBoltzmannWeight(energy.getE_interLeft(sj1_rm,k1,sj2_rm,k2)),extensionSeedPrefix(i1,i2,k1)); } } // k2 } // k1 @@ -395,6 +593,7 @@ fillHybridZ_left( const size_t si1, const size_t si2 ) // sanity insurance if (curZ < 0) { curZ = Z_type(0.0); + if(extensionProbabilityTrace) extensionProbabilityTrace->left.edges[l1*extensionProbabilityTrace->left.columns+l2].clear(); } } } // substractThisSeed @@ -413,6 +612,7 @@ void PredictorMfeEns2dSeedExtension:: fillHybridZ_right( const size_t sj1, const size_t sj2 ) { + if(extensionProbabilityTrace) extensionProbabilityTrace->right.reset(hybridZ_right.size1(),hybridZ_right.size2()); // temporary access const OutputConstraint & outConstraint = output.getOutputConstraint(); #if INTARNA_IN_DEBUG_MODE @@ -457,6 +657,7 @@ fillHybridZ_right( const size_t sj1, const size_t sj2 ) // check just stacked seed extension if (j1-noLpShift==sj1 && j2-noLpShift==sj2) { curZ += iStackZ * hybridZ_right(0,0); + if(extensionProbabilityTrace) extensionProbabilityTrace->right.add(j1-sj1,j2-sj2,0,0,iStackZ,{{j1,j2}}); } } @@ -473,6 +674,12 @@ fillHybridZ_right( const size_t sj1, const size_t sj2 ) curZ += ( hybridZ_right(k1-sj1,k2-sj2) * energy.getBoltzmannWeight(energy.getE_interLeft(k1,j1-noLpShift,k2,j2-noLpShift)) * iStackZ ); + if(extensionProbabilityTrace) { + std::vector pairs{{j1,j2}}; + if(noLpShift) pairs.emplace_back(j1-1,j2-1); + extensionProbabilityTrace->right.add(j1-sj1,j2-sj2,k1-sj1,k2-sj2, + energy.getBoltzmannWeight(energy.getE_interLeft(k1,j1-noLpShift,k2,j2-noLpShift))*iStackZ,std::move(pairs)); + } } } // k2 } // k1 diff --git a/src/IntaRNA/PredictorMfeEns2dSeedExtension.h b/src/IntaRNA/PredictorMfeEns2dSeedExtension.h index e046de5b..0b344e4a 100644 --- a/src/IntaRNA/PredictorMfeEns2dSeedExtension.h +++ b/src/IntaRNA/PredictorMfeEns2dSeedExtension.h @@ -6,6 +6,7 @@ #include "IntaRNA/BasePairProbabilities.h" #include "IntaRNA/Matrix.h" #include "IntaRNA/SeedHandlerIdxOffset.h" +#include namespace IntaRNA { @@ -85,6 +86,27 @@ class PredictorMfeEns2dSeedExtension: public PredictorMfeEns { /** Run the selected disjoint stack-seed partition backend. */ void predictStackSeeds(const IndexRange & r1,const IndexRange & r2); + //! Optional signed reverse trace for the legacy anchored extension recurrences. + struct ExtensionProbabilityTrace; + std::unique_ptr extensionProbabilityTrace; + /** Begin a regional trace; no allocation if no probability sink was requested. */ + void initExtensionProbabilities(size_t n,size_t m); + /** Store the current anchor seed's actual pairs, including its endpoints. */ + void beginExtensionProbabilitySeed(size_t i1,size_t i2); + /** Add one accepted left/seed/right objective to the optional reverse trace. + * All coordinates are local, with seed boundaries in increasing DP order. + * @param left whether the left matrix is a factor (otherwise use initiation) + * @param right whether the right matrix is a factor + */ + void addExtensionProbabilityRoot(size_t i1,size_t j1,size_t i2,size_t j2, + Z_type partZ,bool left,bool right); + /** Reverse both extension traces and accumulate actual pair numerators. */ + void finishExtensionProbabilitySeed(); + /** Validate and atomically commit this region in original sequence order. */ + void commitExtensionProbabilities(); + /** Actual seed pairs strictly before the given local target coordinate. */ + std::vector extensionSeedPrefix(size_t i1,size_t i2,size_t before) const; + //! optional sequence-pair owner, never deleted or finalized by the predictor BasePairProbabilities * pairProbabilities; diff --git a/src/bin/CommandLineParsing.cpp b/src/bin/CommandLineParsing.cpp index d5a0f30e..623235d3 100644 --- a/src/bin/CommandLineParsing.cpp +++ b/src/bin/CommandLineParsing.cpp @@ -958,7 +958,7 @@ CommandLineParsing::CommandLineParsing( const Personality personality ) "\n 'tPu:' (target) unpaired probability values (RNAplfold format OR '.agz' file ending for IntaRNA's binary format)." "\n 'pMinE:' (target+query) for each index pair the minimal energy of any interaction covering the pair (CSV format)" "\n 'bpsvg:' (target+query) SVG actual-pair probability plot with accessibility frame and seed annotations; same requirements as bpProb" - "\n 'bpProb:' (target+query) actual-pair conditional probabilities for --model=P --mode=M with --noSeed or stack-only seeds (CSV matrix, original strand order; NA for an empty ensemble)" + "\n 'bpProb:' (target+query) actual-pair conditional probabilities for --model=P --mode=M/H (M: --noSeed or stack-only seeds; H: approximate retained ensemble) (CSV matrix, original strand order; NA for an empty ensemble)" "\n 'spotProb:' (target+query) tracks for a given set of interaction spots their probability to be covered by an interaction. If no spots are provided, probabilities for all index combinations are computed. Spots are encoded by comma-separated 'idxT&idxQ' pairs (target-query). For each spot a probability is provided in concert with the probability that none of the spots (encoded by '0&0') is covered (CSV format). The spot encoding is followed colon-separated by the output stream/file name, eg. '--out=\"spotProb:3&76,59&2:STDERR\"'. NOTE: value has to be quoted due to '&' symbol!" "\nFor each, provide a file name or STDOUT/STDERR to write to the respective output stream." ).c_str()) @@ -1246,8 +1246,8 @@ parse(int argc, char** argv) outSep = unescaped_string::getUnescaped( outSep ); if (hasBasePairProbabilityOutput()) { - if (model.val!='P' || mode.val!='M' || !rri.empty() || windowWidth.val!=0) - throw error("bpProb/bpsvg requires --model=P --mode=M with --noSeed or stack-only seeds and no windows"); + if (model.val!='P' || (mode.val!='M' && mode.val!='H') || !rri.empty() || windowWidth.val!=0) + throw error("bpProb/bpsvg requires --model=P --mode=M/H with no windows (M: --noSeed or stack-only seeds)"); outNeedsZall=true; } // K needs a seed even before the usual --noSeed model normalization. @@ -2498,7 +2498,7 @@ BasePairProbabilities * CommandLineParsing::getBasePairProbabilityResult(const I if (!hasBasePairProbabilityOutput()) return nullptr; if (!noSeedRequired) { std::unique_ptr handler(getSeedHandler(energy)); - if (!handler->guaranteesStackOnlySeeds()) + if (mode.val=='M' && !handler->guaranteesStackOnlySeeds()) throw std::invalid_argument("bpProb/bpsvg requires a stack-only seed handler; bulged seeds are unsupported"); } return new BasePairProbabilities(energy.size1(),energy.size2(),!noSeedRequired && !outPrefix2streamName.at(OP_bpsvg).empty()); @@ -2520,11 +2520,11 @@ getPredictor( const InteractionEnergy & energy, OutputHandler & output, BasePair { std::unique_ptr pairSeeds; if (pairProbabilities) { - if(model.val!='P' || mode.val!='M' || !rri.empty() || windowWidth.val!=0) - throw std::invalid_argument("bpProb/bpsvg requires --model=P --mode=M with --noSeed or stack-only seeds and no windows"); + if(model.val!='P' || (mode.val!='M' && mode.val!='H') || !rri.empty() || windowWidth.val!=0) + throw std::invalid_argument("bpProb/bpsvg requires --model=P --mode=M/H with no windows (M: --noSeed or stack-only seeds)"); if (!noSeedRequired) { pairSeeds.reset(getSeedHandler(energy)); - if(!pairSeeds->guaranteesStackOnlySeeds()) + if(mode.val=='M' && !pairSeeds->guaranteesStackOnlySeeds()) throw std::invalid_argument("bpProb/bpsvg requires a stack-only seed handler; bulged seeds are unsupported"); } } @@ -2627,7 +2627,7 @@ getPredictor( const InteractionEnergy & energy, OutputHandler & output, BasePair // single-site mfe ensemble interactions (contain only interior loops) case 'P' : { switch ( mode.val ) { - case 'H' : return new PredictorMfeEns2dHeuristic( energy, output, predTracker ); + case 'H' : return new PredictorMfeEns2dHeuristic( energy, output, predTracker, pairProbabilities ); case 'M' : return new PredictorMfeEns2d( energy, output, predTracker, pairProbabilities ); default : INTARNA_NOT_IMPLEMENTED("mode "+toString(mode.val)+" not available for model "+toString(model.val)); } @@ -2672,7 +2672,7 @@ getPredictor( const InteractionEnergy & energy, OutputHandler & output, BasePair // single-site max-prob interactions (contain only interior loops) case 'P' : { switch ( mode.val ) { - case 'H' : return new PredictorMfeEns2dHeuristicSeedExtension( energy, output, predTracker, getSeedHandler( energy ) ); + case 'H' : return new PredictorMfeEns2dHeuristicSeedExtension( energy, output, predTracker, pairSeeds ? pairSeeds.release() : getSeedHandler(energy), pairProbabilities ); case 'M' : return new PredictorMfeEns2dSeedExtension( energy, output, predTracker, pairSeeds ? pairSeeds.release() : getSeedHandler( energy ), pairProbabilities ); case 'S' : return new PredictorMfeEnsSeedOnly( energy, output, predTracker, getSeedHandler(energy) ); default : INTARNA_NOT_IMPLEMENTED("mode "+toString(mode.val)+" not available for model "+toString(model.val)); diff --git a/tests/Makefile.am b/tests/Makefile.am index a500da8e..7ff2a868 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -31,6 +31,8 @@ runApiTests_SOURCES = \ StackSeedDomain_test.cpp \ BasePairProbabilities_test.cpp \ PredictorUnseededProbability_test.cpp \ + PredictorHeuristicProbability_test.cpp \ + PredictorHeuristicSeededProbability_test.cpp \ testEasyLoggingSetup.icc \ AccessibilityConstraint_test.cpp \ AccessibilityFromStream_test.cpp \ diff --git a/tests/PredictorHeuristicProbability_test.cpp b/tests/PredictorHeuristicProbability_test.cpp new file mode 100644 index 00000000..96fdf6b8 --- /dev/null +++ b/tests/PredictorHeuristicProbability_test.cpp @@ -0,0 +1,234 @@ +#include "catch.hpp" + +#undef NDEBUG + +#include "IntaRNA/AccessibilityDisabled.h" +#include "IntaRNA/AccessibilityBasePair.h" +#include "IntaRNA/InteractionEnergyBasePair.h" +#include "IntaRNA/InteractionEnergyIdxOffset.h" +#include "IntaRNA/OutputHandlerInteractionList.h" +#include "IntaRNA/PredictorMfeEns2dHeuristic.h" +#include "IntaRNA/ReverseAccessibility.h" + +#include +#include +#include +#include +#include +#include +#include + +using namespace IntaRNA; + +namespace { + +using Pair=std::array; +using Chain=std::vector; + +struct ChainCandidate { + Chain chain; + E_type hybrid; +}; + +struct HeuristicReference { + Z_type z=0; + std::map mass; + size_t candidates=0; +}; + +bool adjacent(Pair p,Pair q) { + return p[0]+1==q[0] && p[1]+1==q[1]; +} + +/** Enumerate complete chains first, then filter by the documented selected + * suffix rule. Unlike the implementation, this stores complete pair lists, + * sums integer chain energies and directly counts pairs in admitted chains. + */ +HeuristicReference enumerateHeuristic(const InteractionEnergy & energy, + const OutputConstraint & constraint,size_t n,size_t m) +{ + std::map> chains; + Chain chain; + std::function enumerate=[&](E_type hybrid) { + const Pair left=chain.front(),right=chain.back(); + if (right[0]-left[0]+1>energy.getAccessibility1().getMaxLength() + || right[1]-left[1]+1>energy.getAccessibility2().getMaxLength()) return; + chains[left].push_back({chain,hybrid}); + for(size_t i=right[0]+1;i selected; + for(size_t i=n;i-- >0;) for(size_t j=m;j-- >0;) { + const Pair left{i,j}; + std::vector,const ChainCandidate *>> admitted; + for(const auto & candidate:chains[left]) { + const auto & c=candidate.chain; + if (constraint.noGUend && energy.isGU(c.back()[0],c.back()[1])) continue; + size_t suffix=1; + std::array order{0,0,0}; + if (constraint.noLP) { + if (c.size()<2 || !adjacent(c[0],c[1])) continue; + if (c.size()==2) suffix=c.size(); + else if (selected[c[1]]==Chain(c.begin()+1,c.end())) order={1,0,0}; + else { + if (adjacent(c[1],c[2])) continue; + suffix=2;order={2,c[2][0],c[2][1]}; + } + } else if (c.size()>1) order={1,c[1][0],c[1][1]}; + if (suffixconstraint.maxED || energy.getED2(j,right[1])>constraint.maxED)) continue; + const Z_type weight=energy.getBoltzmannWeight(full); + result.z+=weight;++result.candidates; + for(const Pair pair:candidate.chain) result.mass[pair]+=weight; + } + } + return result; +} + +class FailingHeuristic : public PredictorMfeEns2dHeuristic { +public: + using PredictorMfeEns2dHeuristic::PredictorMfeEns2dHeuristic; + bool reject=false; +protected: + void updateZ(size_t i1,size_t j1,size_t i2,size_t j2,Z_type z,bool hybrid) override { + if (reject) throw std::runtime_error("test probability failure"); + PredictorMfeEns::updateZ(i1,j1,i2,j2,z,hybrid); + } +}; + +class HeuristicTinyInitiation : public InteractionEnergyBasePair { +public: + using InteractionEnergyBasePair::InteractionEnergyBasePair; + E_type getE_init() const override { return Ekcal_2_E(60); } +}; + +} + +TEST_CASE("heuristic pair probabilities count the retained candidate chains", "[BasePairProbabilities][PredictorHeuristicProbability]") { + #include "testEasyLoggingSetup.icc" + for(const auto & sequences:std::vector>{ + {"GGGGG","CCCCC"},{"GGAGG","CCUCC"},{"GUGGC","GCCUU"}}) { + RnaSequence target("target",sequences.first),query("query",sequences.second); + AccessibilityBasePair at(target,4,nullptr),aq(query,4,nullptr);ReverseAccessibility reverse(aq); + InteractionEnergyBasePair energy(at,reverse,2,1); + for(bool noLP:{false,true}) for(bool noGU:{false,true}) for(unsigned regionKind:{0u,1u,2u}) for(E_type maxED:{Accessibility::ED_UPPER_BOUND,E_type(50)}) { + const IndexRange region=regionKind==0?IndexRange(0,4):regionKind==1?IndexRange(1,3):IndexRange(2,RnaSequence::lastPos); + OutputConstraint constraint(1,OutputConstraint::OVERLAP_BOTH,E_INF,E_INF,false,noLP,noGU,true,true,maxED); + InteractionEnergyIdxOffset shifted(energy,region.from,region.from); + const size_t length=region.to==RnaSequence::lastPos?target.size()-region.from:region.to-region.from+1; + const auto reference=enumerateHeuristic(shifted,constraint,length,length); + OutputHandlerInteractionList enabled(constraint,1),disabled(constraint,1); + BasePairProbabilities result(target.size(),query.size(),true); + PredictorMfeEns2dHeuristic on(energy,enabled,nullptr,&result),off(energy,disabled,nullptr); + on.predict(region,region);off.predict(region,region);result.finalize(); + REQUIRE(result.isApproximate()); + CAPTURE(sequences.first,sequences.second,noLP,noGU,regionKind,maxED); + REQUIRE(on.getZall()==off.getZall()); + REQUIRE(result.getZ()==on.getZall()); + REQUIRE(result.getZ()==Approx(reference.z).epsilon(3e-12)); + Matrix expected(target.size(),query.size(),0); + for(const auto & entry:reference.mass) { + const auto bp=shifted.getBasePair(entry.first[0],entry.first[1]); + expected(bp.first,bp.second)=entry.second; + } + for(size_t i=0;ienergy==(*b)->energy); + REQUIRE((*a)->basePairs==(*b)->basePairs); + } + } + } +} + +TEST_CASE("heuristic pair probabilities handle empty and singleton domains", "[BasePairProbabilities][PredictorHeuristicProbability]") { + #include "testEasyLoggingSetup.icc" + for(const std::string & queryText:{std::string("C"),std::string("A")}) for(bool noLP:{false,true}) { + RnaSequence target("target","G"),query("query",queryText); + AccessibilityDisabled at(target,0,nullptr),aq(query,0,nullptr);ReverseAccessibility reverse(aq); + InteractionEnergyBasePair energy(at,reverse); + OutputConstraint constraint(1,OutputConstraint::OVERLAP_BOTH,E_INF,E_INF,false,noLP,false,true,false); + OutputHandlerInteractionList output(constraint,1); + BasePairProbabilities result(1,1); + PredictorMfeEns2dHeuristic predictor(energy,output,nullptr,&result); + predictor.predict();result.finalize(); + REQUIRE(result.isApproximate()); + const bool empty=noLP || queryText=="A"; + REQUIRE((result.status()==BasePairProbabilities::Status::empty)==empty); + if (!empty) REQUIRE(result.probabilities()(0,0)==1); + } +} + +TEST_CASE("heuristic pair owner merges disjoint regions and rejects failed results", "[BasePairProbabilities][PredictorHeuristicProbability]") { + #include "testEasyLoggingSetup.icc" + RnaSequence target("target","GGGGGG"),query("query","CCCCCC"); + AccessibilityDisabled at(target,0,nullptr),aq(query,0,nullptr);ReverseAccessibility reverse(aq); + InteractionEnergyBasePair energy(at,reverse,2,2); + OutputConstraint constraint(1,OutputConstraint::OVERLAP_BOTH,E_INF,E_INF,false,true,false,true,false); + OutputHandlerInteractionList output(constraint,1); + BasePairProbabilities result(6,6); + FailingHeuristic predictor(energy,output,nullptr,&result); + predictor.predict({0,2},{0,2});const Z_type first=predictor.getZall(); + predictor.predict({3,5},{3,5});result.finalize(); + REQUIRE(result.getZ()==2*first); + REQUIRE(result.probabilities()(0,0)==0); + BasePairProbabilities failed(6,6);OutputHandlerInteractionList failedOutput(constraint,1); + FailingHeuristic failing(energy,failedOutput,nullptr,&failed); + failing.predict({0,2},{0,2});failing.reject=true; + REQUIRE_THROWS(failing.predict({3,5},{3,5})); + REQUIRE(failed.status()==BasePairProbabilities::Status::failed); + REQUIRE_THROWS(failed.finalize()); + BasePairProbabilities invalid(6,6);OutputHandlerInteractionList invalidOutput(constraint,1); + FailingHeuristic badRange(energy,invalidOutput,nullptr,&invalid); + REQUIRE_THROWS(badRange.predict({8,9},{0,2})); + REQUIRE(invalid.status()==BasePairProbabilities::Status::failed); +} + +TEST_CASE("heuristic probability collection preserves numerical-zero admission", "[BasePairProbabilities][PredictorHeuristicProbability]") { + #include "testEasyLoggingSetup.icc" + RnaSequence target("target","GGGGG"),query("query","CCCCC"); + AccessibilityDisabled at(target,0,nullptr),aq(query,0,nullptr);ReverseAccessibility reverse(aq); + HeuristicTinyInitiation tiny(at,reverse,2,2,false,1,Ekcal_2_E(-40)); + InteractionEnergyBasePair vanishing(at,reverse,2,2,false,1,Ekcal_2_E(50)); + for(const InteractionEnergy * energy:{static_cast(&tiny),static_cast(&vanishing)}) for(bool noLP:{false,true}) { + OutputConstraint constraint(1,OutputConstraint::OVERLAP_BOTH,E_INF,E_INF,false,noLP,false,true,false); + OutputHandlerInteractionList baselineOut(constraint,1),probabilityOut(constraint,1); + BasePairProbabilities result(5,5); + PredictorMfeEns2dHeuristic baseline(*energy,baselineOut,nullptr),predictor(*energy,probabilityOut,nullptr,&result); + baseline.predict();predictor.predict();result.finalize(); + REQUIRE(result.getZ()==baseline.getZall()); + REQUIRE(predictor.getZall()==baseline.getZall()); + if (energy==&vanishing) REQUIRE(result.status()==BasePairProbabilities::Status::empty); + } + OutputConstraint constraint(0,OutputConstraint::OVERLAP_BOTH,E_INF,E_INF,false,false,false,true,false); + OutputHandlerInteractionList output(constraint,1); + BasePairProbabilities failed(5,5); + InteractionEnergyBasePair underflow(at,reverse,2,2,false,0.01,Ekcal_2_E(-1),3,Ekcal_2_E(1000)); + PredictorMfeEns2dHeuristic predictor(underflow,output,nullptr,&failed); + REQUIRE_THROWS(predictor.predict()); + REQUIRE(failed.status()==BasePairProbabilities::Status::failed); +} diff --git a/tests/PredictorHeuristicSeededProbability_test.cpp b/tests/PredictorHeuristicSeededProbability_test.cpp new file mode 100644 index 00000000..6a15c116 --- /dev/null +++ b/tests/PredictorHeuristicSeededProbability_test.cpp @@ -0,0 +1,201 @@ +#include "catch.hpp" +#include "IntaRNA/AccessibilityDisabled.h" +#include "IntaRNA/InteractionEnergyBasePair.h" +#include "IntaRNA/OutputHandlerInteractionList.h" +#include "IntaRNA/PredictorMfeEns2dHeuristicSeedExtension.h" +#include "IntaRNA/SeedHandlerExplicit.h" +#include "IntaRNA/SeedHandlerMfe.h" +#include +#include +#include +#include + +using namespace IntaRNA; + +namespace { +// Introduce an independent fugacity x at one actual pair: every loop pays for +// its left pair, and the complete boundary pays for the last pair. Every +// physical chain is multilinear in x, including signed overlap corrections. +// Consequently Z(x)=Z_without+x*M_pair and a finite difference gives M exactly, +// without consulting the reverse tape or its pair-ownership bookkeeping. +class PairFugacityEnergy: public InteractionEnergyBasePair { +public: + using InteractionEnergyBasePair::InteractionEnergyBasePair; + size_t marked1=RnaSequence::lastPos,marked2=RnaSequence::lastPos; + E_type penalty=0; + E_type getE_interLeft(size_t i1,size_t j1,size_t i2,size_t j2) const override { + const E_type e=InteractionEnergyBasePair::getE_interLeft(i1,j1,i2,j2); + return E_isINF(e)?e:e+((i1==marked1 && i2==marked2)?penalty:0); + } + E_type getE(size_t i1,size_t j1,size_t i2,size_t j2,E_type hybrid) const override { + const E_type e=InteractionEnergyBasePair::getE(i1,j1,i2,j2,hybrid); + return E_isINF(e)?e:e+((j1==marked1 && j2==marked2)?penalty:0); + } +}; + +class FixedChoiceSeededHeuristic: public PredictorMfeEns2dHeuristicSeedExtension { +public: + using PredictorMfeEns2dHeuristicSeedExtension::PredictorMfeEns2dHeuristicSeedExtension; + using Key=std::array; + struct Choice { size_t j1,j2; Z_type e; }; + using Choices=std::map; + Choices choices; + const Choices * fixed=nullptr; +protected: + void fillHybridZ_right(size_t sj1,size_t sj2,size_t si1,size_t si2) override { + PredictorMfeEns2dHeuristicSeedExtension::fillHybridZ_right(sj1,sj2,si1,si2); + // Condition on the original heuristic's chosen domain; a fugacity is a + // counting variable and must not change the domain being differentiated. + if(fixed) { + const auto & c=fixed->at({si1,si2}); j1opt=c.j1; j2opt=c.j2; E_right_opt=c.e; + } else choices[{si1,si2}]={j1opt,j2opt,E_right_opt}; + } +}; + +class CorruptSeededHeuristicPartition: public PredictorMfeEns2dHeuristicSeedExtension { +public: + using PredictorMfeEns2dHeuristicSeedExtension::PredictorMfeEns2dHeuristicSeedExtension; + Z_type injected=0; +protected: + void updateZ(size_t i1,size_t j1,size_t i2,size_t j2,Z_type partZ,bool isHybridZ) override; +}; + +void CorruptSeededHeuristicPartition::updateZ(size_t i1,size_t j1,size_t i2,size_t j2, + Z_type partZ,bool isHybridZ) +{ + PredictorMfeEns2dHeuristicSeedExtension::updateZ(i1,j1,i2,j2,partZ,isHybridZ); + Zall=injected; +} + +SeedConstraint explicitSeeds(const std::string & patterns,size_t nominal=2) { + return SeedConstraint(nominal,6,3,3,E_INF,E_INF,E_INF,IndexRangeList(),IndexRangeList(),patterns,true,true,true); +} +OutputConstraint constraints(bool noLP,bool noGU=false) { + return OutputConstraint(0,OutputConstraint::OVERLAP_BOTH,E_INF,E_INF,false,noLP,noGU,true,false); +} +} + +TEST_CASE("seeded heuristic outside agrees with independent pair fugacities", "[BasePairProbabilities][HeuristicSeededProbability]") { + #include "testEasyLoggingSetup.icc" + RnaSequence t("t","GGGGGG"),q("q","CCCCCC"); + AccessibilityDisabled at(t,0,nullptr),aq(q,0,nullptr); ReverseAccessibility ar(aq); + PairFugacityEnergy energy(at,ar,2,2); + // Isolated and competing seeds exercise left/right/both objectives, + // overlapping and nonoverlapping subtraction, and bulged actual pairs. + for(const auto & patterns:{"3||&3||","2||&4||,3||&3||","1||&5||,4||&2||", + "2|.|&3||","1|.||&3|||,3||&3||","2|||&3|||,4||&2||"}) { + const auto sc=explicitSeeds(patterns); + for(bool noLP:{false,true}) { + CAPTURE(patterns,noLP); + const auto oc=constraints(noLP); + energy.penalty=0; + BasePairProbabilities result(t.size(),q.size(),true); + OutputHandlerInteractionList output(oc,0); + FixedChoiceSeededHeuristic predictor(energy,output,nullptr,new SeedHandlerExplicit(energy,sc),&result); + predictor.predict(); result.finalize(); + REQUIRE(result.isApproximate()); + REQUIRE(result.getZ()==Approx(predictor.getZall()).epsilon(2e-12)); + const Z_type baseline=result.getZ(); + for(size_t i=0;i0); + predictor.predict({3,RnaSequence::lastPos},{3,RnaSequence::lastPos});result.finalize(); + REQUIRE(result.getZ()==Approx(2*first).epsilon(2e-12)); + REQUIRE(result.seedPairs()(0,5)==1);REQUIRE(result.seedPairs()(1,4)==1); + REQUIRE(result.seedPairs()(3,2)==1);REQUIRE(result.seedPairs()(4,1)==1); + REQUIRE(result.probabilities()(0,0)==0); + for(const std::string pattern:{"2||&4||","1|||&4|||"}) { + const auto shortSc=explicitSeeds(pattern); + BasePairProbabilities empty(6,6,true);OutputHandlerInteractionList emptyOutput(oc,0); + FixedChoiceSeededHeuristic p(energy,emptyOutput,nullptr,new SeedHandlerExplicit(energy,shortSc),&empty); + p.predict({0,1},{0,1});empty.finalize(); + REQUIRE(empty.status()==BasePairProbabilities::Status::empty); + } + const auto singleton=explicitSeeds("2|&4|",2); + BasePairProbabilities failed(6,6);OutputHandlerInteractionList failedOutput(oc,0); + FixedChoiceSeededHeuristic bad(energy,failedOutput,nullptr,new SeedHandlerExplicit(energy,singleton),&failed); + REQUIRE_THROWS(bad.predict());REQUIRE(failed.status()==BasePairProbabilities::Status::failed); +} + +TEST_CASE("computed bulged seeded heuristic marginals condition on the selected seed family", "[BasePairProbabilities][HeuristicSeededProbability]") { + #include "testEasyLoggingSetup.icc" + RnaSequence t("t","GGAGGCG"),q("q","CCGCACC"); + AccessibilityDisabled at(t,0,nullptr),aq(q,0,nullptr);ReverseAccessibility ar(aq); + PairFugacityEnergy energy(at,ar,2,2); + const SeedConstraint sc(3,2,1,1,E_INF,E_INF,E_INF,IndexRangeList(),IndexRangeList(),"",true,true,true); + // Freeze the concrete MFE seed selected at every start by encoding its + // actual pairs explicitly. Perturbations then cannot select another seed. + SeedHandlerMfe selected(energy,sc);selected.fillSeed(0,t.size()-1,0,q.size()-1); + std::string patterns; + size_t i=RnaSequence::lastPos,j=RnaSequence::lastPos; + while(selected.updateToNextSeed(i,j,0,t.size()-1,0,q.size()-1)) { + const size_t sl1=selected.getSeedLength1(i,j),sl2=selected.getSeedLength2(i,j); + Interaction seed(t,q);seed.basePairs.push_back(energy.getBasePair(i,j)); + selected.traceBackSeed(seed,i,j);seed.basePairs.push_back(energy.getBasePair(i+sl1-1,j+sl2-1)); + const size_t qStart=q.size()-j-sl2; + std::string ts(sl1,'.'),qs(sl2,'.'); + for(const auto & bp:seed.basePairs) { ts[bp.first-i]='|';qs[bp.second-qStart]='|'; } + if(!patterns.empty()) patterns+=','; + patterns+=std::to_string(i+1)+ts+'&'+std::to_string(qStart+1)+qs; + } + REQUIRE_FALSE(patterns.empty()); + const auto fixedSeeds=explicitSeeds(patterns,3); + for(bool noLP:{false,true}) { + const auto oc=constraints(noLP);energy.penalty=0; + BasePairProbabilities result(t.size(),q.size());OutputHandlerInteractionList output(oc,0); + FixedChoiceSeededHeuristic predictor(energy,output,nullptr,new SeedHandlerMfe(energy,sc),&result); + predictor.predict();result.finalize(); + for(size_t a=0;a::infinity(),std::numeric_limits::quiet_NaN()}) { + CAPTURE(injected); + BasePairProbabilities result(t.size(),q.size());OutputHandlerInteractionList output(oc,0); + CorruptSeededHeuristicPartition predictor(energy,output,nullptr,new SeedHandlerExplicit(energy,sc),&result); + predictor.injected=injected; + REQUIRE_THROWS_AS(predictor.predict(),std::range_error); + REQUIRE(result.status()==BasePairProbabilities::Status::failed); + REQUIRE(result.getZ()==0); + REQUIRE_THROWS(result.finalize()); + } +} diff --git a/tests/PredictorUnseededProbability_test.cpp b/tests/PredictorUnseededProbability_test.cpp index 7124d6e5..c45858e4 100644 --- a/tests/PredictorUnseededProbability_test.cpp +++ b/tests/PredictorUnseededProbability_test.cpp @@ -214,4 +214,10 @@ TEST_CASE("unseeded probability collection follows legacy numerical gates and fa PredictorMfeEns2d huge(extreme,output,nullptr,&overflow); REQUIRE_THROWS(huge.predict()); REQUIRE(overflow.status()==BasePairProbabilities::Status::failed); + BasePairProbabilities underflow(5,5); + InteractionEnergyBasePair underflowEnergy(targetAcc,reverse,2,2,false,1, + Ekcal_2_E(-1),3,Ekcal_2_E(1000)); + PredictorMfeEns2d disappearing(underflowEnergy,output,nullptr,&underflow); + REQUIRE_THROWS(disappearing.predict()); + REQUIRE(underflow.status()==BasePairProbabilities::Status::failed); } diff --git a/tests/testBasePairProbabilities.py b/tests/testBasePairProbabilities.py index 09572802..bafed239 100644 --- a/tests/testBasePairProbabilities.py +++ b/tests/testBasePairProbabilities.py @@ -27,7 +27,7 @@ def run(t='GGAGGG', q='CCCC', options=(), success=True): def matrix(path): with (gzip.open(path, 'rt') if str(path).endswith('.gz') else open(path)) as f: rows = list(csv.reader(f, delimiter=';')) - assert rows[0][0] == 'bpProb', rows + assert rows[0][0] in ('bpProb', 'bpProbApproximate'), rows return rows[0][1:], [r[0] for r in rows[1:]], [[None if v=='NA' else float(v) for v in r[1:]] for r in rows[1:]] def oracle(t, q, regions=None, no_lp=False, seeds=None, unseeded=False): @@ -116,8 +116,16 @@ def predict(t='GGAGGG',q='CCCC',extra=()): covered=list(csv.reader(spot.open(),delimiter=';')) assert any(float(v)>0 for v in covered[3][1:]);assert all(v==0 for v in with_spot[2]) compressed=d/'pairs.csv.gz';run(options=[f'--out=bpProb:{compressed}']);same(matrix(compressed)[2],values) + # Heuristic outputs retain their own denominator and declare approximation. + for seed_opts in ([], ['--noSeed'], ['--seedMaxUP=1']): + for no_lp in ('false', 'true'): + opts=['--mode=H', f'--outNoLP={no_lp}', *seed_opts] + predicted, probs=predict(extra=opts) + assert predicted.stdout==run(options=opts).stdout + assert path.read_text().startswith('bpProbApproximate;') + assert all(v is None or 0<=v<=1 for row in probs for v in row) # Unsupported requests fail explicitly and never create a probability file. - for opts in (['--mode=H'],['--mode=S'],['--model=X','--mode=K'],['--windowWidth=3','--windowOverlap=2'],['--seedMaxUP=1'],['--seedTQ=1|.|&2||']): + for opts in (['--mode=S'],['--model=X','--mode=K'],['--windowWidth=3','--windowOverlap=2'],['--seedMaxUP=1'],['--seedTQ=1|.|&2||']): fail=d/'unsupported.csv';run(options=[f'--out=bpProb:{fail}',*opts],success=False);assert not fail.exists() fail=d/'range.csv';run('GGGG','CCCC',[f'--out=bpProb:{fail}',*seedopt,'--energyAdd=900'],success=False);assert not fail.exists() run(options=['--out=bpProb:/dev/full'],success=False) diff --git a/tests/testBasePairProbabilitySvg.py b/tests/testBasePairProbabilitySvg.py index 0cbb64b6..1e7fab9d 100644 --- a/tests/testBasePairProbabilitySvg.py +++ b/tests/testBasePairProbabilitySvg.py @@ -127,6 +127,15 @@ def plot(t='GGAGGG', q='CCCC', opts=()): rows = list(csv.reader(table.open(), delimiter=';')) assert all(float(pairs(unseeded)[i,j].attrib['data-probability']) == float(rows[i][j]) for i in range(1,7) for j in range(1,5)) + for seed_opts in ([], ['--noSeed'], ['--seedMaxUP=1']): + approximate=plot(opts=['--mode=H', f'--out=bpProb:{table}', *seed_opts]) + assert 'Approximate' in approximate.find('s:title', NS).text + rows=list(csv.reader(table.open(), delimiter=';')) + assert rows[0][0]=='bpProbApproximate' + assert all(float(pairs(approximate)[i,j].attrib['data-probability']) == float(rows[i][j]) + for i in range(1,7) for j in range(1,5)) + if '--noSeed' in seed_opts: + assert not seeds(approximate) # Explicit singleton/mixed seed masks exclude extension-only cells. opts = ['--seedTQ=1|&4|,2||&2||'] mixed = plot('GGGG', 'CCCC', opts) @@ -219,7 +228,7 @@ def check_frame(root, target_pu, query_pu): run(options=[f'--out=bpsvg:{compressed}']) assert len(pairs(load(compressed))) == 24 # Validation/numerical failures must not publish a partial document. - for opts in (['--mode=H'], ['--seedMaxUP=1'], ['--model=X', '--mode=K'], + for opts in (['--mode=S'], ['--seedMaxUP=1'], ['--model=X', '--mode=K'], ['--windowWidth=3'], ['--seedTQ=1|&4|','--energyAdd=900']): failure = d/'failure.svg' run(options=[f'--out=bpsvg:{failure}', *opts], success=False) From 5fc10e99ba46af6ff95720753acbb2fe94c57272 Mon Sep 17 00:00:00 2001 From: AlexanderMitrofanov Date: Fri, 9 Oct 2026 22:34:20 +0200 Subject: [PATCH 15/21] docs: record revision audits and probability performance --- ChangeLog | 8 +++ .../seeded-probabilities-validation.md | 65 +++++++++++++++++++ ...redictorMfeEns2dHeuristicSeedExtension.svg | 4 +- 3 files changed, 75 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index eaea2fe1..e1911f1d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -65,6 +65,9 @@ ## Technical changes and Optimizations +- document independent release/debug, installed-API and performance validation + for the reviewed unseeded and heuristic probability outputs (PR #259) + - transfer completed probability-output buffers without copying; independently audit performance, accessibility conversion and recurrence depictions (PR #259) @@ -181,6 +184,11 @@ energies, restricted partition sums, and trackers. ################################################################################ ################################################################################ +261009 Alexander Mitrofanov + * doc/analysis/seeded-probabilities-validation.md, doc/recursions : + * record final review validation and controlled runtime/memory measurements; + update the seeded-heuristic depiction for approximate pair output (PR #259) + 261009 Alexander Mitrofanov * PredictorMfeEns2dHeuristic, PredictorMfeEns2dHeuristicSeedExtension, PredictorMfeEns2dSeedExtension, BasePairProbabilities, probability writers : diff --git a/doc/analysis/seeded-probabilities-validation.md b/doc/analysis/seeded-probabilities-validation.md index 56c83716..b3c44bd6 100644 --- a/doc/analysis/seeded-probabilities-validation.md +++ b/doc/analysis/seeded-probabilities-validation.md @@ -318,3 +318,68 @@ and implementation. All revised text is UTF-8/LF and `git diff --check` passes. Both new recurrence SVGs parse, render and passed independent equation review; representative output SVGs were rendered and visually inspected. Apple Clang was not available locally. + +### Controlled revision performance + +A separate agent compared the retained `202651e` executable with the final +implementation at `ae0eb78`, using the same GCC 14.4 release configuration, +ViennaRNA 2.7.2, Boost 1.85 and Kokkos mdspan on the machine described above. +Each configuration has one correctness/warmup run and seven deterministically +shuffled, interleaved fresh-process measurements, pinned to CPU 0 and one thread. +No build or test ran during timing. Both ensemble and probability outputs went to +`/dev/null` for timing; separate file-output checks compared complete ensemble +bytes and every CSV/SVG probability cell. + +Wall seconds (median [minimum, maximum], including process startup): + +| Input / predictor | Before, output off | Revised, output off | Revised CSV | Revised SVG | +| --- | ---: | ---: | ---: | ---: | +| OxyS-fhlA / noSeed-M | 0.4116 [0.4077, 0.4262] | 0.4165 [0.4105, 0.4220] | 0.7309 [0.7236, 0.7500] | 0.8490 [0.8415, 0.8668] | +| OxyS-fhlA / noSeed-H | 0.0644 [0.0641, 0.0661] | 0.0646 [0.0637, 0.0668] | 0.0728 [0.0720, 0.0767] | 0.0971 [0.0962, 0.1041] | +| OxyS-fhlA / seeded-H | 0.0517 [0.0510, 0.0532] | 0.0517 [0.0513, 0.0557] | 0.0566 [0.0562, 0.0569] | 0.0772 [0.0771, 0.0784] | +| dense40 / noSeed-M | 0.3409 [0.3396, 0.3412] | 0.3489 [0.3455, 0.3559] | 0.6691 [0.6619, 0.6936] | 0.7231 [0.7143, 0.7377] | +| dense40 / noSeed-H | 0.0195 [0.0194, 0.0207] | 0.0195 [0.0191, 0.0197] | 0.0227 [0.0223, 0.0234] | 0.0264 [0.0261, 0.0271] | +| dense40 / seeded-H | 1.8790 [1.8324, 1.8980] | 1.8767 [1.8584, 1.8861] | 2.7876 [2.7391, 2.8202] | 2.8354 [2.7850, 2.8720] | +| dense32-noLP / noSeed-M | 0.1001 [0.0991, 0.1021] | 0.1014 [0.1000, 0.1042] | 0.1873 [0.1861, 0.1903] | 0.2041 [0.2023, 0.2078] | +| dense32-noLP / noSeed-H | 0.0159 [0.0158, 0.0169] | 0.0157 [0.0155, 0.0159] | 0.0174 [0.0172, 0.0186] | 0.0198 [0.0195, 0.0204] | +| dense32-noLP / seeded-H | 0.5690 [0.5631, 0.5791] | 0.5692 [0.5652, 0.5783] | 0.8398 [0.8290, 0.9217] | 0.8561 [0.8473, 0.8731] | + +Maximum observed process RSS (KiB): + +| Input / predictor | Before, output off | Revised, output off | Revised CSV | Revised SVG | +| --- | ---: | ---: | ---: | ---: | +| OxyS-fhlA / noSeed-M | 17,180 | 17,308 | 17,312 | 20,844 | +| OxyS-fhlA / noSeed-H | 18,208 | 18,204 | 18,844 | 22,328 | +| OxyS-fhlA / seeded-H | 17,184 | 17,180 | 17,184 | 20,848 | +| dense40 / noSeed-M | 16,388 | 16,392 | 16,256 | 16,292 | +| dense40 / noSeed-H | 16,736 | 16,608 | 16,720 | 16,724 | +| dense40 / seeded-H | 34,740 | 34,744 | 35,564 | 35,696 | +| dense32-noLP / noSeed-M | 16,376 | 16,380 | 16,256 | 16,152 | +| dense32-noLP / noSeed-H | 16,564 | 16,564 | 16,608 | 16,604 | +| dense32-noLP / seeded-H | 21,508 | 21,504 | 22,324 | 22,592 | + +Existing output-off medians vary from −1.2% to +2.4% against the pre-revision +binary across these nine cases. All ensemble outputs are byte-identical across +both binaries and all output configurations; every SVG pair value matches CSV. +Probability collection has a measured additional cost: CSV is 1.09–1.92 times +revised output-off wall time here, and SVG is 1.26–2.07 times. These are local +workload measurements, not a universal overhead bound or speedup claim. + +Reproduce one process from each corresponding build (change mode to H for the +unseeded heuristic; remove `--noSeed` for seeded H): + +```sh +OMP_NUM_THREADS=1 OPENBLAS_NUM_THREADS=1 OMP_DYNAMIC=FALSE \ + /usr/bin/time -f '%e %U %S %M' taskset -c 0 src/bin/IntaRNA \ + --target=doc/handson/fhlA.fasta --query=doc/handson/OxyS.fasta \ + --model=P --mode=M --noSeed --seedBP=4 --intLenMax=30 \ + --qIntLoopMax=3 --tIntLoopMax=3 --threads=1 \ + --outNoLP=false --outNoGUend=false --outNumber=0 --outMode=E \ + --default-log-file=/dev/null --out=STDOUT > /dev/null +# Add --out=bpProb:/dev/null or --out=bpsvg:/dev/null. +``` + +For dense40, replace target/query with G×40/C×40 and add `--tAcc=N --qAcc=N`. +For dense32-noLP, use G×32/C×32 with disabled accessibility and +`--outNoLP=true`. Keep all remaining flags identical. Repeat seven times with +interleaved configurations; capture process RSS with GNU time `%M`. diff --git a/doc/recursions/IntaRNA.PredictorMfeEns2dHeuristicSeedExtension.svg b/doc/recursions/IntaRNA.PredictorMfeEns2dHeuristicSeedExtension.svg index 6f7c7fa8..2d38e87d 100644 --- a/doc/recursions/IntaRNA.PredictorMfeEns2dHeuristicSeedExtension.svg +++ b/doc/recursions/IntaRNA.PredictorMfeEns2dHeuristicSeedExtension.svg @@ -1,6 +1,6 @@ Seeded ensemble · one selected right extension -PredictorMfeEns2dHeuristicSeedExtension | --model=P --mode=H. Internal recurrence documentation for step 9 of PR 258. Equations describe the current implementation; RNA 2 uses reversed energy coordinates. +PredictorMfeEns2dHeuristicSeedExtension | --model=P --mode=H. Internal recurrence documentation for steps 9 and 11 of PR 258 / PR 259. Equations describe the current implementation; RNA 2 uses reversed energy coordinates. @@ -42,7 +42,7 @@ All true right-only extensions + all corrected left-only extensions + left extensions paired with just j*. The second phase runs if noGUend is off, or a valid right optimum exists, or anchor end b is not GU. Initialize j*=b and E_right_opt=∞. A positive selected R is required before combining both sides. -No full Cartesian product of left and right boundaries is retained, and bpProb / bpsvg are unsupported. +No full left/right Cartesian product; bpProb / bpsvg trace this retained family and are labelled approximate. Every update is filtered and accumulated by PredictorMfeEns::updateZ; ranked reporting is a separate step. Implementation anchors (src/IntaRNA/) · BW(E)=exp(−E/RT) after native energy-unit conversion From c0ef61f1603ffc41c2ae4f8bbcf98b56027880e9 Mon Sep 17 00:00:00 2001 From: AlexanderMitrofanov Date: Mon, 12 Oct 2026 12:41:32 +0200 Subject: [PATCH 16/21] fix: align probability dot plots and trace MFE pair outlines --- ChangeLog | 13 ++ README.md | 15 ++- .../seeded-probabilities-validation.md | 9 +- src/IntaRNA/BasePairProbabilitySvg.cpp | 38 ++++-- src/IntaRNA/BasePairProbabilityWriter.h | 4 +- src/bin/CommandLineParsing.cpp | 124 +++++++++++++++++- tests/testBasePairProbabilitySvg.py | 45 ++++++- 7 files changed, 223 insertions(+), 25 deletions(-) diff --git a/ChangeLog b/ChangeLog index e1911f1d..5e0eb3f0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,6 +14,9 @@ ## Interface and handling +- orient probability SVGs from the upper-left corner and highlight every MFE + pair, splitting seed/MFE cell borders into orange and green (PR #259 review) + - enable approximate actual-pair CSV/SVG probabilities for unseeded and seeded heuristic ensembles, labelled explicitly as approximate (PR #259, step 11) @@ -184,6 +187,16 @@ energies, restricted partition sums, and trackers. ################################################################################ ################################################################################ +261012 Alexander Mitrofanov + * BasePairProbabilitySvg, BasePairProbabilityWriter, CommandLineParsing + * restore top-to-bottom target indexing, aligned frames/guides and MFE region + + reconstruct the MFE structure inside the best ensemble site for SVG only + + highlight each MFE pair; shared seed pairs use orange vertical and green + horizontal edges, preserving both annotations (PR #259 review) + * testBasePairProbabilitySvg.py, README.md, seeded-probabilities-validation.md + + verify complete internal MFE pairs, shared borders, signed guides and + output-off parity; document the fixed-boundary traceback and orientation + 261009 Alexander Mitrofanov * doc/analysis/seeded-probabilities-validation.md, doc/recursions : * record final review validation and controlled runtime/memory measurements; diff --git a/README.md b/README.md index f3089346..7a118b25 100644 --- a/README.md +++ b/README.md @@ -2097,8 +2097,8 @@ IntaRNA -t GGAGGG -q CCCC --energy=B --acc=N --seedBP=2 \ --model=P --mode=M --out=bpsvg:pairs.svg --out=bpProb:pairs.csv ``` -The query runs left to right and the target bottom to top, both in original -5' to 3' order, starting at the bottom-left corner. Sequence names label the +The query runs left to right and the target top to bottom, both in original +5' to 3' order, starting at the upper-left corner. Sequence names label the axes, with the query name below the matrix. A subtitle names both sequences when either name differs from the defaults `query` and `target`. Nucleotides appear on all four sides. Their colored backgrounds show **intramolecular @@ -2127,9 +2127,14 @@ Dark orange outlines mark the union of pairs belonging to **admitted seeds** contained in searched regions, including overlapping, singleton and mixed-length explicit seeds. This annotation uses the predictor's retained seed family and span limits; it is independent of ranked interaction reporting and can include -zero-probability cells. Extension-only pairs have no outline. A seed legend is -included whenever an outline is present. A green rectangle encloses the best -reported interaction's site, with a matching legend. The best site is retained +zero-probability cells. A seed legend is included whenever an outline is present. +A green rectangle encloses the best reported ensemble interaction's site, and +green cell borders mark a minimum-energy structure reconstructed within that +site using the seed, loop and noLP constraints. Ensemble predictors ordinarily +report only site boundaries; the SVG requests this additional MFE traceback. +It does not change site ranking or the probability matrix. Where an MFE pair +also belongs to an admitted seed, its left/right edges are orange and its +top/bottom edges are green. Both annotations have legends. The best site is retained for SVG even with `--outNumber=0`, without adding ranked text output. If no site passes the reporting filters, the rectangle and its legend are omitted. diff --git a/doc/analysis/seeded-probabilities-validation.md b/doc/analysis/seeded-probabilities-validation.md index b3c44bd6..924c7048 100644 --- a/doc/analysis/seeded-probabilities-validation.md +++ b/doc/analysis/seeded-probabilities-validation.md @@ -283,10 +283,15 @@ candidate ensemble can retain path multiplicities and is not the exact seeded unique-chain ensemble. Existing numerical-zero cutoffs remain in the legacy unseeded/heuristic objectives. -The SVG now starts both strands at the bottom-left origin, places the query name +The SVG now starts both strands at the upper-left origin, places the query name below the matrix, uses sequence names and rounded values in tooltips, displays intramolecular pairing as `1-Pu`, and outlines the best reported interaction region -in green. Machine-readable probability attributes keep full precision. The MFE +in green. Individual cells mark a minimum-energy structure reconstructed inside +the selected ensemble site. Shared seed/MFE cells have orange vertical edges and +green horizontal edges. This SVG-only fixed-boundary traceback reuses the MFE +recurrences and adds computation proportional to the selected site, without +changing ordinary ensemble output. Machine-readable probability attributes keep +full precision. The MFE outline is available with `--outNumber=0`; ordinary ranked output stays suppressed. An outline is omitted if no interaction passes the reporting filters. diff --git a/src/IntaRNA/BasePairProbabilitySvg.cpp b/src/IntaRNA/BasePairProbabilitySvg.cpp index 5b7620ee..349f2c4f 100644 --- a/src/IntaRNA/BasePairProbabilitySvg.cpp +++ b/src/IntaRNA/BasePairProbabilitySvg.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -77,9 +78,10 @@ BasePairProbabilityWriter::svgBlock(const BasePairProbabilities & result,const I const double x=std::max(130.0,(std::max(820.0,nameWidth)-w)/2); const double y=std::max(120.0,(9.0*t.getId().size()-h)/2+60); const double width=2*x+w, height=2*y+h+185; - // SVG y increases downwards, while target coordinates increase upwards. - auto targetY=[&](size_t i) { return y+cell*(t.size()-1-i); }; + // Both original sequence indices increase from the upper-left corner. + auto targetY=[&](size_t i) { return y+cell*i; }; const bool markMfe=mfe && !mfe->isEmpty(); + std::set mfePairs; size_t tStart=t.size(),tEnd=0,qStart=q.size(),qEnd=0; if (markMfe) { for (const auto & bp:mfe->basePairs) { @@ -87,6 +89,7 @@ BasePairProbabilityWriter::svgBlock(const BasePairProbabilities & result,const I throw std::invalid_argument("bpsvg: MFE interaction coordinates exceed sequence dimensions"); tStart=std::min(tStart,bp.first); tEnd=std::max(tEnd,bp.first); qStart=std::min(qStart,bp.second); qEnd=std::max(qEnd,bp.second); + mfePairs.insert(bp); } } std::ostringstream out; @@ -95,7 +98,7 @@ BasePairProbabilityWriter::svgBlock(const BasePairProbabilities & result,const I out<<"\n" <<""<<(result.isApproximate()?"Approximate base-pair probabilities: ":"Base-pair probabilities: ")<\n" - <<"Target rows run 5' to 3' upwards and query columns run 5' to 3' to the right. Pair probabilities are conditional on an allowed interaction. " + <<"Target rows run 5' to 3' downwards and query columns run 5' to 3' to the right, starting at the upper-left corner. Pair probabilities are conditional on an allowed interaction. " <<"The frame shows single-nucleotide intramolecular pairing probabilities (1 - Pu) from the accessibility model. " <<(result.isApproximate()?"Approximate probabilities describe the retained heuristic ensemble.":"Probabilities describe the exact predictor ensemble.")<<"\n" < @@ -132,7 +135,7 @@ text { font-family: sans-serif; fill: #243247; } text(width/2,53,t.getId()+" / "+q.getId(),"subtitle"); text(x+w/2,y+h+65,q.getId()+" (5' to 3')","axis"); out<<""<\n"; + <<") rotate(90)\" text-anchor=\"middle\">"<\n"; auto rect=[&](double rx,double ry,Z_type value,bool missing,const std::string & attributes,const std::string & title) { out<<"0 && !origin?1:0)); if (idx%10==0 || origin) out<<"\n"; + <<"\" x1=\""<<(target?x-cell:x+offset)<<"\" y1=\""<<(target?y+offset:y-cell) + <<"\" x2=\""<<(target?x+w+cell:x+offset)<<"\" y2=\""<<(target?y+offset:y+h+cell)<<"\"/>\n"; const std::string label=idx==1?"+1":std::to_string(idx); if(target) { text(x-26,targetY(i)+cell/2+4,label,"index","end"); @@ -200,17 +203,35 @@ text { font-family: sans-serif; fill: #243247; } out<<"\n"; for(size_t i=0;i\n" + <<"\n" + <<"\n\n"; + continue; + } out<<"\n"; } out<<"\n"; } if (markMfe) { + out<<"\n"; + for (const auto & bp:mfePairs) { + if (result.collectsSeedPairs() && result.seedPairs()(bp.first,bp.second)) continue; + out<<"\n"; + } + out<<"\n"; out<<"\n"; } const double legendX=(width-7*86)/2, legendY=y+h+110; @@ -231,7 +252,8 @@ text { font-family: sans-serif; fill: #243247; } if (markMfe) { const double mfeLegendY=legendY+(annotated?76:48); out<<"\n"; - text(legendX+28,mfeLegendY+13,"Green outline: minimum-free-energy interaction region","legend","start"); + text(legendX+28,mfeLegendY+13,"Green outline: minimum-free-energy interaction region and base pairs","legend","start"); + if (annotated) text(legendX+28,mfeLegendY+31,"Seed + MFE pair: orange left/right edges, green top/bottom edges","legend","start"); } if(empty) text(width/2,legendY+90,"Gray / NA: empty interaction ensemble; accessibility remains defined","legend"); out<<"\n"; diff --git a/src/IntaRNA/BasePairProbabilityWriter.h b/src/IntaRNA/BasePairProbabilityWriter.h index 64773536..31ec316c 100644 --- a/src/IntaRNA/BasePairProbabilityWriter.h +++ b/src/IntaRNA/BasePairProbabilityWriter.h @@ -41,7 +41,7 @@ class BasePairProbabilityWriter { * @param targetRT positive finite energy scale used to convert target ED to Pu * @param queryRT positive finite energy scale used to convert query ED to Pu; * accessibility scales can differ from the interaction model's RT - * @param mfe optional best interaction in original coordinates for a region outline + * @param mfe optional traced MFE structure in original coordinates for region/pair outlines */ static void writeSvg(std::ostream & out,const BasePairProbabilities & result, const InteractionEnergy & energy,Z_type targetRT,Z_type queryRT,const Interaction * mfe = nullptr); @@ -52,7 +52,7 @@ class BasePairProbabilityWriter { * @param energy original, unshifted energy/accessibility model * @param targetRT positive finite target accessibility energy scale * @param queryRT positive finite query accessibility energy scale - * @param mfe optional best interaction in original coordinates for a region outline + * @param mfe optional traced MFE structure in original coordinates for region/pair outlines */ static void writeSvgFile(const std::string & filename,const BasePairProbabilities & result, const InteractionEnergy & energy,Z_type targetRT,Z_type queryRT,const Interaction * mfe = nullptr); diff --git a/src/bin/CommandLineParsing.cpp b/src/bin/CommandLineParsing.cpp index 623235d3..6650cde4 100644 --- a/src/bin/CommandLineParsing.cpp +++ b/src/bin/CommandLineParsing.cpp @@ -38,6 +38,7 @@ extern "C" { #include "IntaRNA/InteractionEnergyBasePair.h" #include "IntaRNA/InteractionEnergyVrna.h" +#include "IntaRNA/OutputHandlerInteractionList.h" #include "IntaRNA/PredictorMfe2dHeuristic.h" #include "IntaRNA/PredictorMfe2dHelixBlockHeuristic.h" @@ -2503,15 +2504,134 @@ BasePairProbabilities * CommandLineParsing::getBasePairProbabilityResult(const I } return new BasePairProbabilities(energy.size1(),energy.size2(),!noSeedRequired && !outPrefix2streamName.at(OP_bpsvg).empty()); } +namespace { + +// Ensemble output stores boundaries, not a molecular structure. Reuse the +// existing fixed-boundary MFE recurrences solely for the SVG's pair overlay. +class SvgMfeTrace : public PredictorMfe2d { +public: + using PredictorMfe2d::PredictorMfe2d; + void trace(Interaction & interaction); +}; + +void +SvgMfeTrace::trace(Interaction & interaction) +{ + interaction.sort(); + const auto first=interaction.basePairs.front(), last=interaction.basePairs.back(); + energy.setOffset1(first.first); + energy.setOffset2(energy.getAccessibility2().getReversedIndex(first.second)); + hybridE_pq.resize(last.first-first.first+1,first.second-last.second+1); + traceBack(interaction); +} + +class SvgSeededMfeTrace : public PredictorMfe2dSeed { +public: + using PredictorMfe2dSeed::PredictorMfe2dSeed; + bool trace(Interaction & interaction); +}; + +bool +SvgSeededMfeTrace::trace(Interaction & interaction) +{ + interaction.sort(); + const auto first=interaction.basePairs.front(), last=interaction.basePairs.back(); + const size_t offset2=energy.getAccessibility2().getReversedIndex(first.second); + energy.setOffset1(first.first); energy.setOffset2(offset2); + seedHandler.setOffset1(first.first); seedHandler.setOffset2(offset2); + const size_t n=last.first-first.first+1, m=first.second-last.second+1; + hybridE_pq.resize(n,m); hybridE_pq_seed.resize(n,m); + if (seedHandler.fillSeed(0,n-1,0,m-1)==0) return false; + fillHybridE(n-1,m-1,0,0,false); + if (E_isINF(hybridE_pq_seed(0,0))) return false; + interaction.energy=energy.getE(0,n-1,0,m-1,hybridE_pq_seed(0,0)); + traceBack(interaction); + return true; +} + +// Explicit seeds define their own lengths, including singletons. The legacy +// MFE traceback's nominal length check must not reject shorter explicit seeds. +class SvgSeedConstraint : public SeedConstraint { +public: + explicit SvgSeedConstraint(const SeedConstraint & original); +}; + +inline +SvgSeedConstraint::SvgSeedConstraint(const SeedConstraint & original) : SeedConstraint(original) +{ + if (!getExplicitSeeds().empty()) bp=2; +} + +} // namespace + void CommandLineParsing::writeBasePairProbabilities(const BasePairProbabilities & result,const InteractionEnergy & energy, const Interaction * mfe) const { const auto & t=energy.getAccessibility1().getSequence(); const auto & q=energy.getAccessibility2().getAccessibilityOrigin().getSequence(); if (!outPrefix2streamName.at(OP_bpProb).empty()) BasePairProbabilityWriter::writeFile(getFullFilename(outPrefix2streamName.at(OP_bpProb),&t,&q),result,t,q,outSep); - if (!outPrefix2streamName.at(OP_bpsvg).empty()) + if (!outPrefix2streamName.at(OP_bpsvg).empty()) { + std::unique_ptr structure; + if (mfe && !mfe->isEmpty()) { + structure=std::make_unique(*mfe); + const auto original=getOutputConstraint(energy,true); + OutputConstraint constraint(1,OutputConstraint::OVERLAP_BOTH,E_INF,E_INF, + original.bestSeedOnly,original.noLP,original.noGUend,false,true,original.maxED); + OutputHandlerInteractionList unused(constraint,1); + if (noSeedRequired) { + SvgMfeTrace trace(energy,unused,nullptr); + trace.trace(*structure); + } else if (structure->basePairs.size()>1) { + SvgSeedConstraint seedConstraint(getSeedConstraint(energy)); + if (seedConstraint.getExplicitSeeds().empty()) { + SvgSeededMfeTrace trace(energy,unused,nullptr,getSeedHandler(energy)); + if (!trace.trace(*structure)) throw std::runtime_error("bpsvg: no MFE structure in selected seeded site"); + } else { + // Trace each explicit seed separately so mixed lengths and + // alternatives at the same start remain available in this site. + std::vector variants; + const auto first=structure->basePairs.front(), last=structure->basePairs.back(); + const size_t lo2=energy.getAccessibility2().getReversedIndex(first.second); + const size_t hi2=energy.getAccessibility2().getReversedIndex(last.second); + std::istringstream encodings(seedConstraint.getExplicitSeeds()); + for (std::string encoding; std::getline(encodings,encoding,','); ) { + seedConstraint.getExplicitSeeds()=encoding; + SeedHandlerExplicit seed(energy,seedConstraint); + size_t a=RnaSequence::lastPos,b=RnaSequence::lastPos; + if (!seed.updateToNextSeed(a,b,first.first,last.first,lo2,hi2)) continue; + if (seed.getSeedLength1(a,b)>1) { variants.push_back(encoding); continue; } + // A singleton in a multi-pair chain has a neighbor. Expand + // it into each feasible two-pair seed; noLP requires a stack. + for (int direction : {-1,1}) { + const size_t max1=original.noLP?1:energy.getMaxInternalLoopSize1()+1; + const size_t max2=original.noLP?1:energy.getMaxInternalLoopSize2()+1; + for (size_t d1=1; d1<=max1; ++d1) for (size_t d2=1; d2<=max2; ++d2) { + if ((direction<0 && (d1>a-first.first || d2>b-lo2)) + || (direction>0 && (d1>last.first-a || d2>hi2-b))) continue; + const size_t c=direction<0?a-d1:a+d1, d=direction<0?b-d2:b+d2; + if (!energy.areComplementary(c,d)) continue; + variants.push_back(std::to_string(t.getInOutIndex(std::min(a,c)))+"|"+std::string(d1-1,'.')+"|&" + +std::to_string(q.getInOutIndex(energy.getAccessibility2().getReversedIndex(std::max(b,d)))) + +"|"+std::string(d2-1,'.')+"|"); + } + } + } + E_type best=E_INF; + for (const auto & encoding : variants) { + seedConstraint.getExplicitSeeds()=encoding; + SvgSeededMfeTrace trace(energy,unused,nullptr,new SeedHandlerExplicit(energy,seedConstraint)); + Interaction candidate(*mfe); + if (trace.trace(candidate) && candidate.energy max(float(r.attrib['y']) for r in cells.values())+20 - # Original target coordinate 1 is at the bottom; query coordinate 1 at left. + # Both lowest original indices are at the upper-left corner. for i in range(1, 7): for j in range(1, 5): - assert float(cells[i, j].attrib['y']) == float(cells[1, 1].attrib['y'])-20*(i-1) + assert float(cells[i, j].attrib['y']) == float(cells[1, 1].attrib['y'])+20*(i-1) assert float(cells[i, j].attrib['x']) == float(cells[1, 1].attrib['x'])+20*(j-1) for i, row in enumerate(rows[1:], 1): for j, value in enumerate(row[1:], 1): @@ -118,10 +125,36 @@ def plot(t='GGAGGG', q='CCCC', opts=()): ts, te, qs, qe = bounds matrix = pairs(mfe_plot) assert float(outline.attrib['x']) == float(matrix[ts, qs].attrib['x']) - assert float(outline.attrib['y']) == float(matrix[te, qs].attrib['y']) + assert float(outline.attrib['y']) == float(matrix[ts, qs].attrib['y']) assert float(outline.attrib['width']) == float(matrix[ts, qe].attrib['x'])-float(matrix[ts, qs].attrib['x'])+20 - assert float(outline.attrib['height']) == float(matrix[ts, qs].attrib['y'])-float(matrix[te, qs].attrib['y'])+20 + assert float(outline.attrib['height']) == float(matrix[te, qs].attrib['y'])-float(matrix[ts, qs].attrib['y'])+20 assert 'Green outline:' in ''.join(mfe_plot.itertext()) + assert len(mfe_pairs(mfe_plot)) > 2 # includes internal pairs, not just site endpoints + # An unambiguous four-pair stack checks every internal MFE pair against + # independent ordinary MFE output, including the two-color seed overlap. + for seed_options in ([], ['--noSeed'], ['--seedMaxUP=1'], ['--seedTQ=2||&2||']): + for mode in ('M', 'H'): + if '--seedMaxUP=1' in seed_options and mode == 'M': + continue # exact bulged-seed probability output is unsupported + stack = plot('GGGG', 'CCCC', [*seed_options, f'--mode={mode}']) + reference = run('GGGG', 'CCCC', [*seed_options, '--model=X', '--mode=M', + '--outNumber=1', '--outMode=C', '--outCsvCols=bpList']) + row = next(csv.DictReader(reference.stdout.splitlines(), delimiter=';')) + expected = {tuple(map(int, bp)) for bp in re.findall(r'\((\d+),(\d+)\)', row['bpList'])} + assert set(mfe_pairs(stack)) == expected == {(1,4), (2,3), (3,2), (4,1)} + for bp, outline in mfe_pairs(stack).items(): + cell = pairs(stack)[bp] + left, top = float(cell.attrib['x'])+1, float(cell.attrib['y'])+1 + if bp in seeds(stack): + assert outline.tag.endswith('g') + assert outline.find('s:path[@class="seed"]', NS).attrib['d'] == f'M {left:g} {top:g} v 18 M {left+18:g} {top:g} v 18' + assert outline.find('s:path[@class="mfe"]', NS).attrib['d'] == f'M {left:g} {top:g} h 18 M {left:g} {top+18:g} h 18' + else: + assert float(outline.attrib['x']) == left + assert float(outline.attrib['y']) == top + # A sole admitted seed fixes a shorter best site; singleton plotting remains valid. + singleton = plot('GGGG', 'CCCC', ['--seedTQ=4|&1|']) + assert (4,1) in mfe_pairs(singleton) unseeded = plot(opts=['--noSeed', f'--out=bpProb:{table}']) assert not seeds(unseeded) rows = list(csv.reader(table.open(), delimiter=';')) @@ -161,7 +194,7 @@ def plot(t='GGAGGG', q='CCCC', opts=()): idx = int(g.attrib['data-index']) r = signed_cells[idx,-15] if strand == 'target' else signed_cells[-15,idx] axis = 'y' if strand == 'target' else 'x' - expected_pos = float(r.attrib[axis]) + (0 if idx > 1 else 20) if strand == 'target' else float(r.attrib[axis]) + (20 if idx > 1 else 0) + expected_pos = float(r.attrib[axis]) + (20 if idx > 1 else 0) assert float(g.attrib[axis+'1']) == expected_pos assert ('major' in g.attrib['class']) == (idx % 50 == 0) assert ('origin' in g.attrib['class']) == (idx == 1) From 0d61d4b07caca760d64a46ee82afc4e3730ba034 Mon Sep 17 00:00:00 2001 From: Martin Raden Date: Tue, 13 Oct 2026 11:25:31 +0200 Subject: [PATCH 17/21] tmp folder --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 7654a03d..ee819cc0 100644 --- a/.gitignore +++ b/.gitignore @@ -55,7 +55,7 @@ doxygen-doc doxygen-doc/* conf3108* test-driver - +tmp/* # temp dir tmp From 6d8272673d1b8b0c2c4efaff746af03a6e2f09af Mon Sep 17 00:00:00 2001 From: Martin Raden Date: Tue, 13 Oct 2026 11:53:06 +0200 Subject: [PATCH 18/21] compute allSeedStacked only once --- src/IntaRNA/SeedHandlerExplicit.cpp | 10 +++++----- src/IntaRNA/SeedHandlerExplicit.h | 3 +++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/IntaRNA/SeedHandlerExplicit.cpp b/src/IntaRNA/SeedHandlerExplicit.cpp index 7deb8b2c..fa98dd96 100644 --- a/src/IntaRNA/SeedHandlerExplicit.cpp +++ b/src/IntaRNA/SeedHandlerExplicit.cpp @@ -17,6 +17,7 @@ SeedHandlerExplicit( ) : SeedHandler(energy,seedConstraint) , seedForLeftEnd() + , allSeedsStacked(true) { #if INTARNA_IN_DEBUG_MODE if (seedConstraint.getExplicitSeeds().empty()) throw std::runtime_error("SeedHandlerExplicit() : explicit seed encoding is empty"); @@ -41,6 +42,8 @@ SeedHandlerExplicit( if (!seedData.isValid()) { LOG(WARNING) <<"explicit seed '"< seedForLeftEnd; + //! whether or not all seeds are stacked (i.e. no bulges or internal loops) + bool allSeedsStacked; + }; } /* namespace IntaRNA */ From 7a522358274f8ae636634bd89e51e2d8d7ee86b6 Mon Sep 17 00:00:00 2001 From: AlexanderMitrofanov Date: Tue, 13 Oct 2026 12:35:58 +0200 Subject: [PATCH 19/21] fix: address PR #258 seed-domain review Use Interaction::BasePair and hash maps for sparse seed lookup, make the stack-length invariant debug-only, and document probability computation steps and contributor conventions. Validate overlapping seed endings, deterministic traversal, and input rejection. Release and debug make tests -j2 each pass all seven suites (100967 assertions in 98 API cases); installed headers, pkg-config consumer, assertion-mode probe, and before/after CLI output checks also pass. --- AGENTS.md | 15 ++++++++++ ChangeLog | 19 +++++++++++++ src/IntaRNA/BasePairProbabilities.cpp | 5 ++++ .../PredictorMfeEns2dSeedExtension.cpp | 14 +++++++--- src/IntaRNA/SeededPartitionFunction.cpp | 18 ++++++++++++ src/IntaRNA/SeededPartitionFunction.h | 4 +-- src/IntaRNA/StackSeedDomain.cpp | 24 ++++++++++++++-- src/IntaRNA/StackSeedDomain.h | 8 +++--- tests/PredictorHeuristicProbability_test.cpp | 24 ++++++++-------- tests/SeededChainOracle.h | 11 ++++---- tests/SeededPartitionFunction_test.cpp | 18 ++++++------ tests/SeededStackKernel.h | 1 + tests/SeededTheoryFixtures.h | 8 +++--- tests/StackSeedDomain_test.cpp | 28 ++++++++++++++++++- 14 files changed, 153 insertions(+), 44 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 46333509..4f78aaf9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -94,6 +94,17 @@ Consult those checks for build or public API changes. `INTARNA_..._H_` include guards, and existing class/member naming. Keep edits focused; do not reformat unrelated code or modernize vendored `src/easylogging++.*` or `tests/catch.hpp` as part of an ordinary fix. +- Represent base-pair coordinates with `Interaction::BasePair` rather than + `std::pair` or `std::array`; document the coordinate orientation when it differs + from the original sequences. For sparse lookup tables such as seed starts, use + `std::unordered_map`. + Use ordered storage only when ordering is required; preserve deterministic + traversal explicitly when iterating hash-based data affects results or output. +- Check internal invariants with `assert` or debug-only checks guarded by + `#ifndef NDEBUG` (or the existing `INTARNA_IN_DEBUG_MODE` convention). Keep + release checks for public input validation and failures possible during normal + execution, including numerical range errors, I/O errors and unsupported + extension-hook behavior. Assertions must have no required side effects. - Keep class bodies focused on declarations. Define very short functions **explicitly `inline` after the class definition in the same header**, inside the namespace and include guard. Put nontrivial non-template implementations @@ -167,6 +178,10 @@ constraints, ownership and exceptions. Use `//!` for brief member documentation and implementation comments to explain recurrences and assumptions. Update comments with the code; preserve existing author attribution. Doxygen setup is in `doc/doxygen.cfg`; update `README.md` and CLI help for user-visible changes. +Within nontrivial implementations, introduce each logical step with a concise +inline comment explaining its purpose and relevant invariants, especially domain +filtering, recurrence transitions, coordinate conversion and result publication. +Use these comments to make the sequence of operations easy to review. Update **[ChangeLog](ChangeLog)** (exact capitalization) for every introduced change, including documentation, tests and build changes, in the same PR: diff --git a/ChangeLog b/ChangeLog index 5e0eb3f0..b39ddb81 100644 --- a/ChangeLog +++ b/ChangeLog @@ -68,6 +68,10 @@ ## Technical changes and Optimizations +- use hashed base-pair keys for sparse stack-seed lookup, assert internal seed + geometry in debug builds, and document probability computation steps and + contributor conventions (PR #258 review) + - document independent release/debug, installed-API and performance validation for the reviewed unseeded and heuristic probability outputs (PR #259) @@ -187,6 +191,21 @@ energies, restricted partition sums, and trackers. ################################################################################ ################################################################################ +261013 Alexander Mitrofanov + * StackSeedDomain, SeededPartitionFunction, PredictorMfeEns2dSeedExtension + * use Interaction::BasePair coordinates and hashed sparse seed lookup tables + * replace the stack-only handler's equal-length invariant with a debug assert; + retain runtime validation of public input and numerical/extension failures + + explain domain filtering, deterministic start traversal, inside/outside + recurrence steps and coordinate conversion (PR #258 review) + * BasePairProbabilities, AGENTS.md + + explain validation and publication steps; document base-pair/hash storage, + debug-only invariants and implementation-comment conventions + * StackSeedDomain_test, seeded and heuristic probability oracle fixtures/tests + + verify shortest shared seed endings, duplicate and unordered occurrences, + row-major traversal and release-time rejection of invalid seed inputs + * use the common base-pair representation while retaining independent oracles + 261012 Alexander Mitrofanov * BasePairProbabilitySvg, BasePairProbabilityWriter, CommandLineParsing * restore top-to-bottom target indexing, aligned frames/guides and MFE region diff --git a/src/IntaRNA/BasePairProbabilities.cpp b/src/IntaRNA/BasePairProbabilities.cpp index 4d06f327..c97d7988 100644 --- a/src/IntaRNA/BasePairProbabilities.cpp +++ b/src/IntaRNA/BasePairProbabilities.cpp @@ -15,15 +15,18 @@ void BasePairProbabilities::addRegion(const IndexRange & t,const IndexRange & q, { using A=PartitionArithmetic; try { + // Validate the caller's lifecycle, dimensions and optional annotation mask. if (state!=Status::pending) throw std::logic_error("pair probabilities: accumulator is not pending"); if (!t.isAscending() || !q.isAscending() || t.to>=mass.size1() || q.to>=mass.size2() || values.size1()!=t.to-t.from+1 || values.size2()!=q.to-q.from+1) throw std::invalid_argument("pair probabilities: invalid region dimensions"); if (collectSeeds && (!seedPairs || seedPairs->size1()!=values.size1() || seedPairs->size2()!=values.size2())) throw std::invalid_argument("pair probabilities: missing or invalid regional seed mask"); + // Disjoint searched rectangles ensure each interaction contributes once. for (const auto & r:regions) if (t.from<=r.first.to && r.first.from<=t.to && q.from<=r.second.to && r.second.from<=q.to) throw std::invalid_argument("pair probabilities: searched regions overlap"); + // Check every proposed sum before committing any regional data. const Z_type merged=A::add(z,denominator); for (size_t i=0;i BasePairProbabilities::probabilities() const { const Z_type tolerance=512*std::numeric_limits::epsilon() *Z_type(std::max(size_t(1),mass.size1()+mass.size2())); std::vector columns(mass.size2(),0); + // Normalize each mass and validate that a nucleotide has at most one partner. for(size_t i=0;i BasePairProbabilities::probabilities() const { } void BasePairProbabilities::finalize() { try { + // Successful completion includes empty searches; failed results stay failed. if(state!=Status::pending) throw std::logic_error("pair probabilities: completion requires a pending result"); PartitionArithmetic::check(z); state=z==0?Status::empty:Status::nonempty; diff --git a/src/IntaRNA/PredictorMfeEns2dSeedExtension.cpp b/src/IntaRNA/PredictorMfeEns2dSeedExtension.cpp index 7fd217f0..0b6eb098 100644 --- a/src/IntaRNA/PredictorMfeEns2dSeedExtension.cpp +++ b/src/IntaRNA/PredictorMfeEns2dSeedExtension.cpp @@ -336,6 +336,7 @@ PredictorMfeEns2dSeedExtension::exactBoundaryWeight(size_t i1,size_t j1,size_t i void PredictorMfeEns2dSeedExtension::predictStackSeeds(const IndexRange & r1,const IndexRange & r2) { + // Validate public regions before translating both strands to local coordinates. const size_t size1=energy.getAccessibility1().getSequence().size(); const size_t size2=energy.getAccessibility2().getSequence().size(); if (!r1.isAscending() || !r2.isAscending() || r1.from>=size1 || r2.from>=size2) @@ -344,27 +345,31 @@ PredictorMfeEns2dSeedExtension::predictStackSeeds(const IndexRange & r1,const In seedHandler.setOffset1(r1.from); seedHandler.setOffset2(r2.from); const size_t n=r1.to==RnaSequence::lastPos?energy.size1():std::min(energy.size1(),r1.to-r1.from+1); const size_t m=r2.to==RnaSequence::lastPos?energy.size2():std::min(energy.size2(),r2.to-r2.from+1); + // Compile admitted, contained seeds using the active spans for this prediction. initOptima(); initZ(); Zall=0; const size_t seedCount=seedHandler.fillSeed(0,n-1,0,m-1); const size_t span1=std::min(n,energy.getAccessibility1().getMaxLength()); const size_t span2=std::min(m,energy.getAccessibility2().getMaxLength()); StackSeedDomain seeds=seedCount ? StackSeedDomain(seedHandler,n,m,span1,span2) : StackSeedDomain(std::vector(),n,m,span1,span2); + // Supply native weights once per initiation, transition and complete boundary. using K=SeededPartitionFunction; const K::Domain domain{n,m,span1,span2,energy.getMaxInternalLoopSize1(),energy.getMaxInternalLoopSize2(),output.getOutputConstraint().noLP}; auto boltzmann=[&](E_type e) { return E_isINF(e)?Z_type(0):PartitionArithmetic::exp(-E_2_Z(e)/energy.getRT()); }; K::Weights weights{ - [&](K::Pair p){return energy.isAccessible1(p[0]) && energy.isAccessible2(p[1]) && energy.areComplementary(p[0],p[1]);}, + [&](K::Pair p){return energy.isAccessible1(p.first) && energy.isAccessible2(p.second) && energy.areComplementary(p.first,p.second);}, [&](K::Pair){return boltzmann(energy.getE_init());}, - [&](K::Pair p,K::Pair q){return boltzmann(energy.getE_interLeft(p[0],q[0],p[1],q[1]));}, - [&](K::Pair p,K::Pair q){return exactBoundaryWeight(p[0],q[0],p[1],q[1]);}, - [&](K::Pair p,K::Pair q,Z_type h,Z_type b){updateExactCompleteZ(p[0],q[0],p[1],q[1],h,b);} + [&](K::Pair p,K::Pair q){return boltzmann(energy.getE_interLeft(p.first,q.first,p.second,q.second));}, + [&](K::Pair p,K::Pair q){return exactBoundaryWeight(p.first,q.first,p.second,q.second);}, + [&](K::Pair p,K::Pair q,Z_type h,Z_type b){updateExactCompleteZ(p.first,q.first,p.second,q.second,h,b);} }; const auto result=K::compute(domain,seeds,weights,pairProbabilities!=nullptr); + // Custom updateZ overrides can change the objective even in release builds. if (result.z!=Zall) throw std::logic_error("exact seeded updateZ override did not preserve the partition objective"); output.setExactPartition(true); reportOptima(); if (pairProbabilities) { + // Restore original strand orientation and offsets before merging this region. const auto first=energy.getBasePair(0,0), last=energy.getBasePair(n-1,m-1); const IndexRange target(first.first,last.first), query(last.second,first.second); Matrix original(n,m,0); @@ -379,6 +384,7 @@ PredictorMfeEns2dSeedExtension::predictStackSeeds(const IndexRange & r1,const In seedPairs(seedPair.first-target.from,seedPair.second-query.from)=1; } } + // Publish regional masses only after the complete computation has succeeded. pairProbabilities->addRegion(target,query,result.z,original,annotate?&seedPairs:nullptr); } } diff --git a/src/IntaRNA/SeededPartitionFunction.cpp b/src/IntaRNA/SeededPartitionFunction.cpp index 63e2007f..f18a753d 100644 --- a/src/IntaRNA/SeededPartitionFunction.cpp +++ b/src/IntaRNA/SeededPartitionFunction.cpp @@ -1,5 +1,6 @@ #include "IntaRNA/SeededPartitionFunction.h" #include "IntaRNA/PartitionArithmetic.h" +#include // Seed-free suffix lengths plus two absorbing seeded states (singleton/run). // Nonstack edges operate on aggregate totals, independently of seed length. @@ -13,11 +14,13 @@ SeededPartitionFunction::Result SeededPartitionFunction::compute( using A=PartitionArithmetic; using Pair=SeededPartitionFunction::Pair; SeededPartitionFunction::Result out; + // Empty seed families or zero spans admit no interaction, even with pair output. if (pairs) out.mass=Matrix(d.n,d.m,0); if (!seeds.maxSeedLength() || !d.span1 || !d.span2) return out; // At least two length states are necessary for noLP even with singleton seeds. const size_t cap=std::max(size_t(2),seeds.maxSeedLength()), s1=cap, s2=cap+1, states=cap+2; seeds.forEachStart([&](size_t p1,size_t p2) { + // Each eligible left boundary owns a separate forward and reverse problem. const Pair p{p1,p2}; if (!w.valid(p)) return; const size_t n=std::min(d.span1,d.n-p1),m=std::min(d.span2,d.m-p2); Matrix h(matrix_detail::product(n,m),states),dh; @@ -25,31 +28,39 @@ SeededPartitionFunction::Result SeededPartitionFunction::compute( Matrix valid(n,m); Matrix ending(n,m); if (pairs) { dh.resize(n*m,states); dt.resize(n,m); } + // Cache vertex admission and seed endings in this start's cropped domain. for (size_t i=0;i=cap) return stacked || !d.noLP?s2:s1; const size_t len=stacked?std::min(cap,c+2):1; return accepts(i,j,len)?(len>=2 || !d.noLP?s2:s1):len-1; }; + // Enumerate loop predecessors separately from the direct stacking edge. auto nonstack=[&](size_t i,size_t j,const auto & visit) { for(size_t u=1;u<=i && u-1<=d.loop1;++u) for(size_t v=1;v<=j && v-1<=d.loop2;++v) if((u!=1 || v!=1) && valid(i-u,j-v)) visit(i-u,j-v); }; + // Initiation belongs to the leftmost pair exactly once, including singletons. const size_t initial=accepts(0,0,1)?(d.noLP?s1:s2):0; const Z_type init=A::check(w.initiation(p)); h(0,initial)=init; + // Forward pass: extend prefixes and finalize every admitted right boundary. for(size_t i=0;i0) { + // Share the same boundary coefficient with reporting and the outside pass. const Z_type b=A::check(w.boundary(p,{p1+i,p2+j})); out.z=A::add(out.z,A::multiply(b,total(i,j)[1])); if(pairs) { dh(q,s2)=b;if(!d.noLP) dh(q,s1)=b; } @@ -67,12 +80,16 @@ SeededPartitionFunction::Result SeededPartitionFunction::compute( } } if(!pairs) return; + // Reverse pass: propagate boundary derivatives back through the same edges. for(size_t ii=n;ii>0;--ii) for(size_t jj=m;jj>0;--jj) { const size_t i=ii-1,j=jj-1,q=i*m+j; if(!valid(i,j)) continue; + // Distribute derivatives of the two aggregate totals to their suffix states. for(size_t c=d.noLP?1:0;c #include namespace IntaRNA { @@ -14,7 +14,7 @@ namespace IntaRNA { class SeededPartitionFunction { public: //! Local zero-based pair, second strand in reversed coordinates. - using Pair = std::array; + using Pair = Interaction::BasePair; /** Active rectangle, inclusive spans, loop limits and structural restriction. */ struct Domain { size_t n,m,span1,span2,loop1,loop2; bool noLP; }; /** Energy adapter. Complete boundary callbacks are made once per positive diff --git a/src/IntaRNA/StackSeedDomain.cpp b/src/IntaRNA/StackSeedDomain.cpp index baf99c5a..1591d2aa 100644 --- a/src/IntaRNA/StackSeedDomain.cpp +++ b/src/IntaRNA/StackSeedDomain.cpp @@ -1,43 +1,61 @@ #include "IntaRNA/StackSeedDomain.h" #include +#include #include +#include namespace IntaRNA { StackSeedDomain::StackSeedDomain(const SeedHandler & handler, size_t n, size_t m, size_t w1, size_t w2) { + // Reject unsupported input before interpreting seed lengths as diagonal runs. if (!handler.guaranteesStackOnlySeeds()) throw std::invalid_argument("stack seed domain requires a stack-only handler"); if (n==0 || m==0) return; + // Use the range end as an invalid initial cursor, avoiding lastPos+offset wrap. size_t i=n, j=m; while (handler.updateToNextSeed(i,j,0,n-1,0,m-1)) { + // Stack-only admission guarantees equal strand lengths internally. const size_t len=handler.getSeedLength1(i,j); - if (len != handler.getSeedLength2(i,j)) throw std::logic_error("stack seed has unequal strand lengths"); + assert(len == handler.getSeedLength2(i,j)); + // Retain only occurrences fully contained in the active interaction domain. add({i,j,len},n,m,w1,w2); } } StackSeedDomain::StackSeedDomain(const std::vector & seeds, size_t n, size_t m, size_t w1, size_t w2) { + // Apply the same containment and span filters to externally supplied seeds. for (auto s:seeds) add(s,n,m,w1,w2); } void StackSeedDomain::add(Occurrence s, size_t n, size_t m, size_t w1, size_t w2) { + // Check containment using remaining lengths so endpoint arithmetic cannot wrap. w1=std::min(w1,n); w2=std::min(w2,m); if (s.length==0 || s.i>=n || s.j>=m || s.length>n-s.i || s.length>m-s.j || s.length>w1 || s.length>w2) return; - auto [p,inserted]=lengths.emplace(std::make_pair(s.i,s.j),s.length); + + // A start must identify one retained length, including for explicit input. + auto [p,inserted]=lengths.emplace(Interaction::BasePair(s.i,s.j),s.length); if (!inserted && p->second!=s.length) throw std::invalid_argument("multiple retained seed lengths at one start"); - auto [end, fresh]=endingLengths.emplace(std::make_pair(s.i+s.length-1,s.j+s.length-1),s.length); + + // The shortest seed ending here suffices to accept a stacked path suffix. + auto [end, fresh]=endingLengths.emplace(Interaction::BasePair(s.i+s.length-1,s.j+s.length-1),s.length); if (!fresh) end->second=std::min(end->second,s.length); maximum=std::max(maximum,s.length); + + // A left boundary can precede this seed only while its end fits both spans. const size_t end1=s.i+s.length, end2=s.j+s.length; boxes.push_back({end1>w1?end1-w1:0,s.i,end2>w2?end2-w2:0,s.j}); } void StackSeedDomain::forEachStart(const std::function & visit) const { if (boxes.empty()) return; + // Restrict the row sweep to rows covered by at least one eligible-start box. size_t first=boxes.front().i0, last=0; for (auto b:boxes) { first=std::min(first,b.i0); last=std::max(last,b.i1); } + // These pairs are inclusive intervals on strand two, not base-pair coordinates. std::vector> intervals; for (size_t i=first;i<=last;++i) { + // Sort this row's column intervals independently of seed insertion order. intervals.clear(); for (auto b:boxes) if (b.i0<=i && i<=b.i1) intervals.emplace_back(b.j0,b.j1); std::sort(intervals.begin(),intervals.end()); + // Skip already visited columns where boxes overlap; emit row-major order. size_t next=0; for (auto [lo,hi]:intervals) { for (size_t j=std::max(lo,next);j<=hi;++j) visit(i,j); diff --git a/src/IntaRNA/StackSeedDomain.h b/src/IntaRNA/StackSeedDomain.h index a6c82f64..c64f26f8 100644 --- a/src/IntaRNA/StackSeedDomain.h +++ b/src/IntaRNA/StackSeedDomain.h @@ -1,10 +1,10 @@ #ifndef INTARNA_STACKSEEDDOMAIN_H_ #define INTARNA_STACKSEEDDOMAIN_H_ +#include "IntaRNA/Interaction.h" #include "IntaRNA/SeedHandler.h" #include -#include -#include +#include #include namespace IntaRNA { @@ -45,9 +45,9 @@ class StackSeedDomain { void forEachStart(const std::function & visit) const; private: //! admitted occurrences keyed by local start - std::map, size_t> lengths; + std::unordered_map lengths; //! shortest retained length per ending vertex for suffix acceptance - std::map, size_t> endingLengths; + std::unordered_map endingLengths; //! eligible inclusive rectangles [i0,i1] x [j0,j1] struct Box { size_t i0, i1, j0, j1; }; std::vector boxes; diff --git a/tests/PredictorHeuristicProbability_test.cpp b/tests/PredictorHeuristicProbability_test.cpp index 96fdf6b8..d2805808 100644 --- a/tests/PredictorHeuristicProbability_test.cpp +++ b/tests/PredictorHeuristicProbability_test.cpp @@ -22,7 +22,7 @@ using namespace IntaRNA; namespace { -using Pair=std::array; +using Pair=Interaction::BasePair; using Chain=std::vector; struct ChainCandidate { @@ -37,7 +37,7 @@ struct HeuristicReference { }; bool adjacent(Pair p,Pair q) { - return p[0]+1==q[0] && p[1]+1==q[1]; + return p.first+1==q.first && p.second+1==q.second; } /** Enumerate complete chains first, then filter by the documented selected @@ -51,12 +51,12 @@ HeuristicReference enumerateHeuristic(const InteractionEnergy & energy, Chain chain; std::function enumerate=[&](E_type hybrid) { const Pair left=chain.front(),right=chain.back(); - if (right[0]-left[0]+1>energy.getAccessibility1().getMaxLength() - || right[1]-left[1]+1>energy.getAccessibility2().getMaxLength()) return; + if (right.first-left.first+1>energy.getAccessibility1().getMaxLength() + || right.second-left.second+1>energy.getAccessibility2().getMaxLength()) return; chains[left].push_back({chain,hybrid}); - for(size_t i=right[0]+1;i,const ChainCandidate *>> admitted; for(const auto & candidate:chains[left]) { const auto & c=candidate.chain; - if (constraint.noGUend && energy.isGU(c.back()[0],c.back()[1])) continue; + if (constraint.noGUend && energy.isGU(c.back().first,c.back().second)) continue; size_t suffix=1; std::array order{0,0,0}; if (constraint.noLP) { @@ -81,9 +81,9 @@ HeuristicReference enumerateHeuristic(const InteractionEnergy & energy, else if (selected[c[1]]==Chain(c.begin()+1,c.end())) order={1,0,0}; else { if (adjacent(c[1],c[2])) continue; - suffix=2;order={2,c[2][0],c[2][1]}; + suffix=2;order={2,c[2].first,c[2].second}; } - } else if (c.size()>1) order={1,c[1][0],c[1][1]}; + } else if (c.size()>1) order={1,c[1].first,c[1].second}; if (suffixconstraint.maxED || energy.getED2(j,right[1])>constraint.maxED)) continue; + && (energy.getED1(i,right.first)>constraint.maxED || energy.getED2(j,right.second)>constraint.maxED)) continue; const Z_type weight=energy.getBoltzmannWeight(full); result.z+=weight;++result.candidates; for(const Pair pair:candidate.chain) result.mass[pair]+=weight; @@ -148,7 +148,7 @@ TEST_CASE("heuristic pair probabilities count the retained candidate chains", "[ REQUIRE(result.getZ()==Approx(reference.z).epsilon(3e-12)); Matrix expected(target.size(),query.size(),0); for(const auto & entry:reference.mass) { - const auto bp=shifted.getBasePair(entry.first[0],entry.first[1]); + const auto bp=shifted.getBasePair(entry.first.first,entry.first.second); expected(bp.first,bp.second)=entry.second; } for(size_t i=0;i #include #include @@ -11,7 +12,7 @@ // with both strands increasing. Weight callbacks return long double, so expected // values never pass through native integer energy conversion or the tested DP. namespace seeded_oracle { -using Pair = std::array; +using Pair = IntaRNA::Interaction::BasePair; using Boundary = std::array; using Chain = std::vector; struct Model { @@ -28,7 +29,7 @@ struct Result { std::map mass; }; inline bool stack(Pair a, Pair b) { - return a[0]+1 == b[0] && a[1]+1 == b[1]; + return a.first+1 == b.first && a.second+1 == b.second; } inline Result enumerate(const Model & model) { Result out; @@ -46,13 +47,13 @@ inline Result enumerate(const Model & model) { const auto w = hybrid * model.boundary(p, q); if (seeded) { out.z += w; - out.boundaries[{p[0], p[1], q[0], q[1]}] += w; + out.boundaries[{p.first, p.second, q.first, q.second}] += w; out.pairCount += w * chain.size(); for (Pair pair : chain) out.mass[pair] += w; } else out.unseeded += w; } - for (size_t i=q[0]+1; i seeds; - for(const auto & s:m.seeds) seeds.push_back({s[0][0],s[0][1],s.size()}); + for(const auto & s:m.seeds) seeds.push_back({s[0].first,s[0].second,s.size()}); return {seeds,m.n,m.m,m.span1,m.span2}; } Kernel::Weights weightsFor(const seeded_oracle::Model & m) { @@ -76,7 +76,7 @@ void compareKernels(const seeded_oracle::Model & m) { CAPTURE(suffix); auto w=weightsFor(m); std::map boundaries; - w.complete=[&](auto p,auto q,auto h,auto b){boundaries[{p[0],p[1],q[0],q[1]}]+=h*b;}; + w.complete=[&](auto p,auto q,auto h,auto b){boundaries[{p.first,p.second,q.first,q.second}]+=h*b;}; auto got=suffix?Kernel::compute(d,seeds,w,true):seededStack(d,seeds,w,true); REQUIRE(double(got.z)==Approx(double(oracle.z)).epsilon(2e-12)); for(auto [b,z]:oracle.boundaries) REQUIRE(double(boundaries[b])==Approx(double(z)).epsilon(2e-12)); @@ -102,10 +102,10 @@ TEST_CASE("heterogeneous weighted kernels match independent enumeration", "[Seed for(size_t trial=0;trial<100;++trial) { CAPTURE(trial); Model m{6,5,2+rng()%5,2+rng()%4,bool(trial%2),{}, - [trial](Pair p){return (p[0]+3*p[1]+trial)%7!=0;}, - [](Pair p){return .7L+.13L*p[0];}, - [trial](Pair p,Pair q){return (p[0]+q[1]+trial)%11==0?0.L:.1L+.17L*(q[0]-p[0])+.21L*(q[1]-p[1]);}, - [trial](Pair p,Pair q){return (q[0]+p[1]+trial)%5==0?0.L:.2L+.07L*(q[0]+p[1]);}}; + [trial](Pair p){return (p.first+3*p.second+trial)%7!=0;}, + [](Pair p){return .7L+.13L*p.first;}, + [trial](Pair p,Pair q){return (p.first+q.second+trial)%11==0?0.L:.1L+.17L*(q.first-p.first)+.21L*(q.second-p.second);}, + [trial](Pair p,Pair q){return (q.first+p.second+trial)%5==0?0.L:.2L+.07L*(q.first+p.second);}}; for(size_t i=0;i +#include #include inline IntaRNA::SeededPartitionFunction::Result seededStack(const IntaRNA::SeededPartitionFunction::Domain & d, const IntaRNA::StackSeedDomain & seeds, diff --git a/tests/SeededTheoryFixtures.h b/tests/SeededTheoryFixtures.h index c7ae833d..83980445 100644 --- a/tests/SeededTheoryFixtures.h +++ b/tests/SeededTheoryFixtures.h @@ -29,15 +29,15 @@ inline std::vector theoryFixtures() { auto & f=fixtures.back(); if (tag == "Z") file >> f.expected.z; else if (tag == "S") { - Pair p; size_t len; file >> p[0] >> p[1] >> len; - Chain s; for (size_t k=0;k> p.first >> p.second >> len; + Chain s; for (size_t k=0;k> i; file >> f.terminal[b] >> f.seeded[b] >> f.free[b]; f.expected.boundaries[b]=f.terminal[b]*f.seeded[b]; } else if (tag == "P") { - Pair p; file >> p[0] >> p[1] >> f.valid[p] >> f.expected.mass[p]; + Pair p; file >> p.first >> p.second >> f.valid[p] >> f.expected.mass[p]; } } } @@ -46,7 +46,7 @@ inline std::vector theoryFixtures() { f.model.init=[](Pair){return std::exp(1.L);}; f.model.edge=[](Pair,Pair){return std::exp(1.L);}; f.model.boundary=[b=f.terminal](Pair p,Pair q){ - auto it=b.find({p[0],p[1],q[0],q[1]});return it==b.end()?0.L:it->second; + auto it=b.find({p.first,p.second,q.first,q.second});return it==b.end()?0.L:it->second; }; } return fixtures; diff --git a/tests/StackSeedDomain_test.cpp b/tests/StackSeedDomain_test.cpp index 454e7210..4054c13d 100644 --- a/tests/StackSeedDomain_test.cpp +++ b/tests/StackSeedDomain_test.cpp @@ -23,6 +23,7 @@ TEST_CASE("stack capability and active occurrence domain", "[StackSeedDomain]") SeedConstraint bulged(2,1,1,0,E_INF,Accessibility::ED_UPPER_BOUND,E_INF,IndexRangeList(),IndexRangeList(),"",false,false,false); SeedHandlerMfe bulge(energy,bulged); REQUIRE_FALSE(bulge.guaranteesStackOnlySeeds()); + REQUIRE_THROWS_AS(StackSeedDomain(bulge,6,6,6,6),std::invalid_argument); SeedConstraint explicitC(1,0,0,0,E_INF,Accessibility::ED_UPPER_BOUND,E_INF, IndexRangeList(),IndexRangeList(),"1|&6|,2|||&3|||,5||&1||",false,false,false); SeedHandlerIdxOffset explicitH(new SeedHandlerExplicit(energy,explicitC)); @@ -35,7 +36,7 @@ TEST_CASE("stack capability and active occurrence domain", "[StackSeedDomain]") REQUIRE(domain.maxSeedLength()==3); StackSeedDomain mixed({{0,0,1},{2,2,2},{4,4,3}},6,6,4,3); REQUIRE(mixed.maxSeedLength()==2); - std::set> starts; + std::set starts; size_t calls=0; mixed.forEachStart([&](size_t i,size_t j){ ++calls; starts.emplace(i,j); }); REQUIRE(calls==starts.size()); @@ -49,6 +50,31 @@ TEST_CASE("stack capability and active occurrence domain", "[StackSeedDomain]") REQUIRE_FALSE(eb.guaranteesStackOnlySeeds()); } +TEST_CASE("stack-domain lookups and traversal preserve overlapping seed geometry", "[StackSeedDomain]") { + // Different starts can share an ending pair; the shortest suffix must win + // independently of insertion order, while duplicate seeds add no new starts. + std::vector seeds{{3,2,1},{1,0,3},{2,1,2},{3,2,1},{0,4,2}}; + const std::vector expected{{0,0},{0,1},{0,2},{0,3},{0,4}, + {1,0},{1,1},{1,2},{2,0},{2,1},{2,2},{3,0},{3,1},{3,2}}; + for (bool reverse:{false,true}) { + if (reverse) std::reverse(seeds.begin(),seeds.end()); + StackSeedDomain domain(seeds,6,6,4,4); + REQUIRE(domain.seedLength(1,0)==3); + REQUIRE(domain.seedLength(2,1)==2); + REQUIRE(domain.seedLength(3,2)==1); + REQUIRE(domain.seedLength(0,1)==0); // swapped coordinates are a different pair + REQUIRE(domain.seedEndingLength(3,2)==1); + REQUIRE(domain.seedEndingLength(1,5)==2); + REQUIRE(domain.seedEndingLength(2,3)==0); + REQUIRE(domain.maxSeedLength()==3); + std::vector starts; + domain.forEachStart([&](size_t i,size_t j){ starts.emplace_back(i,j); }); + REQUIRE(starts==expected); + } + // Conflicting externally supplied lengths remain an input error in release. + REQUIRE_THROWS_AS((StackSeedDomain({{1,1,1},{1,1,2}},4,4,4,4)),std::invalid_argument); +} + TEST_CASE("stack-domain admission preserves handler-specific threshold equality", "[StackSeedDomain]") { #include "testEasyLoggingSetup.icc" RnaSequence t("t","GGG"),q("q","CCC"); From e3479d693ae335780537c8bf3311aaa1b5ac6f76 Mon Sep 17 00:00:00 2001 From: Martin Raden Date: Tue, 13 Oct 2026 14:41:25 +0200 Subject: [PATCH 20/21] debug-only checks --- src/IntaRNA/BasePairProbabilities.cpp | 27 ++++++++++++++++------ src/IntaRNA/Matrix.h | 2 ++ src/IntaRNA/PredictorMfeEns2d.cpp | 8 +++---- src/IntaRNA/PredictorMfeEns2dHeuristic.cpp | 11 ++++----- src/IntaRNA/SeededPartitionFunction.cpp | 4 +++- src/IntaRNA/StackSeedDomain.cpp | 24 +++++++++++++++---- 6 files changed, 52 insertions(+), 24 deletions(-) diff --git a/src/IntaRNA/BasePairProbabilities.cpp b/src/IntaRNA/BasePairProbabilities.cpp index c97d7988..27fe7e0e 100644 --- a/src/IntaRNA/BasePairProbabilities.cpp +++ b/src/IntaRNA/BasePairProbabilities.cpp @@ -4,11 +4,16 @@ #include namespace IntaRNA { -void BasePairProbabilities::markApproximate() { + +void +BasePairProbabilities:: +markApproximate() { if (state!=Status::pending) throw std::logic_error("pair probabilities: accumulator is not pending"); approximate=true; } -BasePairProbabilities::BasePairProbabilities(size_t n,size_t m,bool collectSeedPairs) + +BasePairProbabilities:: +BasePairProbabilities(size_t n,size_t m,bool collectSeedPairs) : mass(n,m,0), collectSeeds(collectSeedPairs), seeds(collectSeedPairs?n:0,collectSeedPairs?m:0,0) {} void BasePairProbabilities::addRegion(const IndexRange & t,const IndexRange & q, Z_type denominator,const Matrix & values,const Matrix * seedPairs) @@ -17,15 +22,17 @@ void BasePairProbabilities::addRegion(const IndexRange & t,const IndexRange & q, try { // Validate the caller's lifecycle, dimensions and optional annotation mask. if (state!=Status::pending) throw std::logic_error("pair probabilities: accumulator is not pending"); +#if INTARNA_IN_DEBUG_MODE if (!t.isAscending() || !q.isAscending() || t.to>=mass.size1() || q.to>=mass.size2() || values.size1()!=t.to-t.from+1 || values.size2()!=q.to-q.from+1) throw std::invalid_argument("pair probabilities: invalid region dimensions"); if (collectSeeds && (!seedPairs || seedPairs->size1()!=values.size1() || seedPairs->size2()!=values.size2())) throw std::invalid_argument("pair probabilities: missing or invalid regional seed mask"); - // Disjoint searched rectangles ensure each interaction contributes once. - for (const auto & r:regions) + // Disjoint searched rectangles ensure each interaction contributes once. + for (const auto & r:regions) if (t.from<=r.first.to && r.first.from<=t.to && q.from<=r.second.to && r.second.from<=q.to) - throw std::invalid_argument("pair probabilities: searched regions overlap"); + throw std::invalid_argument("pair probabilities: searched regions overlap"); +#endif // Check every proposed sum before committing any regional data. const Z_type merged=A::add(z,denominator); for (size_t i=0;i BasePairProbabilities::probabilities() const { + +Matrix +BasePairProbabilities:: +probabilities() const { using A=PartitionArithmetic; if (state!=Status::nonempty) throw std::logic_error("pair probabilities: no successful nonempty result"); Matrix p(mass.size1(),mass.size2(),0); @@ -66,7 +76,10 @@ Matrix BasePairProbabilities::probabilities() const { for(auto c:columns) if(c>1+tolerance) throw std::logic_error("pair probabilities: query exclusivity violated"); return p; } -void BasePairProbabilities::finalize() { + +void +BasePairProbabilities:: +finalize() { try { // Successful completion includes empty searches; failed results stay failed. if(state!=Status::pending) throw std::logic_error("pair probabilities: completion requires a pending result"); diff --git a/src/IntaRNA/Matrix.h b/src/IntaRNA/Matrix.h index c5390f82..d714ce28 100644 --- a/src/IntaRNA/Matrix.h +++ b/src/IntaRNA/Matrix.h @@ -543,7 +543,9 @@ template inline std::size_t UpperBandedMatrix::width(std::size_t columns, std::size_t lower, std::size_t upper) { +#if INTARNA_IN_DEBUG_MODE if (lower != 0) throw std::invalid_argument("upper-banded matrix requires lower=0"); +#endif return upper >= columns ? columns : upper + 1; } diff --git a/src/IntaRNA/PredictorMfeEns2d.cpp b/src/IntaRNA/PredictorMfeEns2d.cpp index a03506da..63dece5f 100644 --- a/src/IntaRNA/PredictorMfeEns2d.cpp +++ b/src/IntaRNA/PredictorMfeEns2d.cpp @@ -55,14 +55,12 @@ PredictorMfeEns2d::predictRegion(const IndexRange & r1,const IndexRange & r2) #if INTARNA_IN_DEBUG_MODE // check indices - if (!(r1.isAscending() && r2.isAscending()) ) + if (!(r1.isAscending() && r2.isAscending()) + || r1.from>=energy.getAccessibility1().getSequence().size() + || r2.from>=energy.getAccessibility2().getSequence().size())) throw std::runtime_error("PredictorMfeEns2d::predict("+toString(r1)+","+toString(r2)+") is not sane"); #endif - if (pairProbabilities && (!r1.isAscending() || !r2.isAscending() - || r1.from>=energy.getAccessibility1().getSequence().size() - || r2.from>=energy.getAccessibility2().getSequence().size())) - throw std::invalid_argument("unseeded pair probabilities: invalid region"); if (pairProbabilities && pairProbabilities->status()!=BasePairProbabilities::Status::pending) throw std::logic_error("unseeded pair probabilities: accumulator is not pending"); diff --git a/src/IntaRNA/PredictorMfeEns2dHeuristic.cpp b/src/IntaRNA/PredictorMfeEns2dHeuristic.cpp index 93b57cbf..df0f3e75 100644 --- a/src/IntaRNA/PredictorMfeEns2dHeuristic.cpp +++ b/src/IntaRNA/PredictorMfeEns2dHeuristic.cpp @@ -53,17 +53,14 @@ predictRegionHeuristic(const IndexRange & r1,const IndexRange & r2) #if INTARNA_IN_DEBUG_MODE // check indices - if (!(r1.isAscending() && r2.isAscending()) ) + if (!(r1.isAscending() && r2.isAscending()) + || r1.from>=energy.getAccessibility1().getSequence().size() + || r2.from>=energy.getAccessibility2().getSequence().size()) throw std::runtime_error("PredictorMfeEns2dHeuristic::predict("+toString(r1)+","+toString(r2)+") is not sane"); #endif - - if (!r1.isAscending() || !r2.isAscending() - || r1.from>=energy.getAccessibility1().getSequence().size() - || r2.from>=energy.getAccessibility2().getSequence().size()) - throw std::invalid_argument("heuristic ensemble prediction: invalid region"); if (pairProbabilities && pairProbabilities->status()!=BasePairProbabilities::Status::pending) - throw std::logic_error("heuristic pair probabilities: accumulator is not pending"); + throw std::logic_error("PredictorMfeEns2dHeuristic::predict: heuristic pair probabilities: accumulator is not pending"); if (pairProbabilities) pairProbabilities->markApproximate(); // set index offset energy.setOffset1(r1.from); diff --git a/src/IntaRNA/SeededPartitionFunction.cpp b/src/IntaRNA/SeededPartitionFunction.cpp index f18a753d..f5e560e9 100644 --- a/src/IntaRNA/SeededPartitionFunction.cpp +++ b/src/IntaRNA/SeededPartitionFunction.cpp @@ -5,7 +5,9 @@ // Seed-free suffix lengths plus two absorbing seeded states (singleton/run). // Nonstack edges operate on aggregate totals, independently of seed length. namespace IntaRNA { -SeededPartitionFunction::Result SeededPartitionFunction::compute( +SeededPartitionFunction::Result +SeededPartitionFunction:: +compute( const IntaRNA::SeededPartitionFunction::Domain & d, const IntaRNA::StackSeedDomain & seeds, const IntaRNA::SeededPartitionFunction::Weights & w, bool pairs) diff --git a/src/IntaRNA/StackSeedDomain.cpp b/src/IntaRNA/StackSeedDomain.cpp index 1591d2aa..ca486142 100644 --- a/src/IntaRNA/StackSeedDomain.cpp +++ b/src/IntaRNA/StackSeedDomain.cpp @@ -5,9 +5,13 @@ #include namespace IntaRNA { -StackSeedDomain::StackSeedDomain(const SeedHandler & handler, size_t n, size_t m, size_t w1, size_t w2) { + +StackSeedDomain:: +StackSeedDomain(const SeedHandler & handler, size_t n, size_t m, size_t w1, size_t w2) { // Reject unsupported input before interpreting seed lengths as diagonal runs. +#if INTARNA_IN_DEBUG_MODE if (!handler.guaranteesStackOnlySeeds()) throw std::invalid_argument("stack seed domain requires a stack-only handler"); +#endif if (n==0 || m==0) return; // Use the range end as an invalid initial cursor, avoiding lastPos+offset wrap. @@ -20,11 +24,18 @@ StackSeedDomain::StackSeedDomain(const SeedHandler & handler, size_t n, size_t m add({i,j,len},n,m,w1,w2); } } -StackSeedDomain::StackSeedDomain(const std::vector & seeds, size_t n, size_t m, size_t w1, size_t w2) { + + +StackSeedDomain:: +StackSeedDomain(const std::vector & seeds, size_t n, size_t m, size_t w1, size_t w2) { // Apply the same containment and span filters to externally supplied seeds. for (auto s:seeds) add(s,n,m,w1,w2); } -void StackSeedDomain::add(Occurrence s, size_t n, size_t m, size_t w1, size_t w2) { + + +void +StackSeedDomain:: +add(Occurrence s, size_t n, size_t m, size_t w1, size_t w2) { // Check containment using remaining lengths so endpoint arithmetic cannot wrap. w1=std::min(w1,n); w2=std::min(w2,m); if (s.length==0 || s.i>=n || s.j>=m || s.length>n-s.i || s.length>m-s.j @@ -32,7 +43,9 @@ void StackSeedDomain::add(Occurrence s, size_t n, size_t m, size_t w1, size_t w2 // A start must identify one retained length, including for explicit input. auto [p,inserted]=lengths.emplace(Interaction::BasePair(s.i,s.j),s.length); +#if INTARNA_IN_DEBUG_MODE if (!inserted && p->second!=s.length) throw std::invalid_argument("multiple retained seed lengths at one start"); +#endif // The shortest seed ending here suffices to accept a stacked path suffix. auto [end, fresh]=endingLengths.emplace(Interaction::BasePair(s.i+s.length-1,s.j+s.length-1),s.length); @@ -43,7 +56,10 @@ void StackSeedDomain::add(Occurrence s, size_t n, size_t m, size_t w1, size_t w2 const size_t end1=s.i+s.length, end2=s.j+s.length; boxes.push_back({end1>w1?end1-w1:0,s.i,end2>w2?end2-w2:0,s.j}); } -void StackSeedDomain::forEachStart(const std::function & visit) const { + +void +StackSeedDomain:: +forEachStart(const std::function & visit) const { if (boxes.empty()) return; // Restrict the row sweep to rows covered by at least one eligible-start box. size_t first=boxes.front().i0, last=0; From cb1c9d419f96c7d2a10bae864d922dcb0234f4d4 Mon Sep 17 00:00:00 2001 From: Martin Raden Date: Wed, 14 Oct 2026 14:23:00 +0200 Subject: [PATCH 21/21] minor test fixes --- src/IntaRNA/AccessibilityFromStream.cpp | 2 +- src/IntaRNA/PredictorMfeEns2d.cpp | 2 +- src/IntaRNA/SeededPartitionFunction.cpp | 6 +++++- tests/Matrix_test.cpp | 2 +- tests/StackSeedDomain_test.cpp | 11 ++++++----- 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/IntaRNA/AccessibilityFromStream.cpp b/src/IntaRNA/AccessibilityFromStream.cpp index acc747b0..0f9b7b51 100644 --- a/src/IntaRNA/AccessibilityFromStream.cpp +++ b/src/IntaRNA/AccessibilityFromStream.cpp @@ -117,7 +117,7 @@ parseRNAplfold_text( std::istream & inStream, const Z_type RT, const bool parseP #if INTARNA_MULITHREADING #pragma omp critical(intarna_omp_logOutput) #endif - { LOG(INFO) <<"initializing ED data for sequence '"<=energy.getAccessibility1().getSequence().size() - || r2.from>=energy.getAccessibility2().getSequence().size())) + || r2.from>=energy.getAccessibility2().getSequence().size()) throw std::runtime_error("PredictorMfeEns2d::predict("+toString(r1)+","+toString(r2)+") is not sane"); #endif diff --git a/src/IntaRNA/SeededPartitionFunction.cpp b/src/IntaRNA/SeededPartitionFunction.cpp index f5e560e9..3c5113c0 100644 --- a/src/IntaRNA/SeededPartitionFunction.cpp +++ b/src/IntaRNA/SeededPartitionFunction.cpp @@ -54,12 +54,16 @@ compute( // Forward pass: extend prefixes and finalize every admitted right boundary. for(size_t i=0;i(2, 2, 1, 1), std::invalid_argument); + //REQUIRE_THROWS_AS(UpperBandedMatrix(2, 2, 1, 1), std::invalid_argument); // in debug mode only } TEST_CASE("Oversized matrix dimensions fail before allocation", "[Matrix]") { diff --git a/tests/StackSeedDomain_test.cpp b/tests/StackSeedDomain_test.cpp index 4054c13d..be595ada 100644 --- a/tests/StackSeedDomain_test.cpp +++ b/tests/StackSeedDomain_test.cpp @@ -20,10 +20,11 @@ TEST_CASE("stack capability and active occurrence domain", "[StackSeedDomain]") SeedHandlerNoBulge stack(energy,computed); REQUIRE(mfe.guaranteesStackOnlySeeds()); REQUIRE(stack.guaranteesStackOnlySeeds()); - SeedConstraint bulged(2,1,1,0,E_INF,Accessibility::ED_UPPER_BOUND,E_INF,IndexRangeList(),IndexRangeList(),"",false,false,false); - SeedHandlerMfe bulge(energy,bulged); - REQUIRE_FALSE(bulge.guaranteesStackOnlySeeds()); - REQUIRE_THROWS_AS(StackSeedDomain(bulge,6,6,6,6),std::invalid_argument); + // only in debug mode the following checks are enabled + // SeedConstraint bulged(2,1,1,0,E_INF,Accessibility::ED_UPPER_BOUND,E_INF,IndexRangeList(),IndexRangeList(),"",false,false,false); + // SeedHandlerMfe bulge(energy,bulged); + // REQUIRE_FALSE(bulge.guaranteesStackOnlySeeds()); + // REQUIRE_THROWS_AS(StackSeedDomain(bulge,6,6,6,6),std::invalid_argument); SeedConstraint explicitC(1,0,0,0,E_INF,Accessibility::ED_UPPER_BOUND,E_INF, IndexRangeList(),IndexRangeList(),"1|&6|,2|||&3|||,5||&1||",false,false,false); SeedHandlerIdxOffset explicitH(new SeedHandlerExplicit(energy,explicitC)); @@ -105,7 +106,7 @@ TEST_CASE("explicit stack capability inspects the retained minimum-energy patter SeedConstraint sc(2,0,0,0,E_INF,Accessibility::ED_UPPER_BOUND,E_INF, IndexRangeList(),IndexRangeList(),"1|.|&2|.|,1|||&2|||",false,false,false); SeedHandlerExplicit handler(e,sc); - REQUIRE(handler.guaranteesStackOnlySeeds()); + REQUIRE(!handler.guaranteesStackOnlySeeds()); REQUIRE(handler.fillSeed(0,3,0,3)==1); StackSeedDomain domain(handler,4,4,4,4); REQUIRE(domain.seedLength(0,0)==3);