Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@

## Technical changes and Optimizations

- align probability API invalid-input tests with debug-only precondition checks
and avoid an unchecked null seed-mask call in release test runs (PR #258)

- 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)
Expand Down Expand Up @@ -191,6 +194,13 @@ energies, restricted partition sums, and trackers.
################################################################################
################################################################################

261018 Alexander Mitrofanov
* BasePairProbabilities_test.cpp, StackSeedDomain_test.cpp,
PredictorUnseededProbability_test.cpp, PredictorHeuristicProbability_test.cpp
* exercise debug-only region/mask/handler/length preconditions only in debug builds
+ restore the unsupported-handler test under the matching debug guard
* keep ordinary lifecycle, arithmetic and output checks in both configurations

261013 Alexander Mitrofanov
* StackSeedDomain, SeededPartitionFunction, PredictorMfeEns2dSeedExtension
* use Interaction::BasePair coordinates and hashed sparse seed lookup tables
Expand Down
7 changes: 7 additions & 0 deletions tests/BasePairProbabilities_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@ TEST_CASE("raw pair regions commit once and finalize only on success", "[BasePai
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);
#if INTARNA_IN_DEBUG_MODE
// Overlap is a caller precondition; the library checks it only in debug builds.
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());
#endif
BasePairProbabilities cancelled(4,5);cancelled.addRegion({0,1},{1,2},2,m);cancelled.fail();
REQUIRE_THROWS(cancelled.finalize());REQUIRE_THROWS(cancelled.probabilities());
}
Expand Down Expand Up @@ -82,10 +85,14 @@ TEST_CASE("seed annotations commit with regional masses and SVG requires success
r.fail();std::ostringstream failed;
REQUIRE_THROWS(BasePairProbabilityWriter::writeSvg(failed,r,energy,1,1));
REQUIRE(failed.str().empty());
#if INTARNA_IN_DEBUG_MODE
// A collecting sink requires a regional mask. Do not dereference a missing
// mask in release builds, where this precondition is intentionally unchecked.
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);
#endif
BasePairProbabilities plain(4,5);
REQUIRE_FALSE(plain.collectsSeedPairs());REQUIRE(plain.seedPairs().size1()==0);
plain.finalize();std::ostringstream empty;
Expand Down
3 changes: 3 additions & 0 deletions tests/PredictorHeuristicProbability_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,10 +202,13 @@ TEST_CASE("heuristic pair owner merges disjoint regions and rejects failed resul
REQUIRE_THROWS(failing.predict({3,5},{3,5}));
REQUIRE(failed.status()==BasePairProbabilities::Status::failed);
REQUIRE_THROWS(failed.finalize());
#if INTARNA_IN_DEBUG_MODE
// Invalid prediction regions are a debug-checked caller precondition.
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);
#endif
}

TEST_CASE("heuristic probability collection preserves numerical-zero admission", "[BasePairProbabilities][PredictorHeuristicProbability]") {
Expand Down
3 changes: 3 additions & 0 deletions tests/PredictorUnseededProbability_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,10 +205,13 @@ TEST_CASE("unseeded probability collection follows legacy numerical gates and fa
ChangedObjectivePredictor changed(energy,output,nullptr,&unsupported);
REQUIRE_THROWS(changed.predict());
REQUIRE(unsupported.status()==BasePairProbabilities::Status::failed);
#if INTARNA_IN_DEBUG_MODE
// Invalid prediction regions are a debug-checked caller precondition.
BasePairProbabilities invalid(5,5);
PredictorMfeEns2d predictor(energy,output,nullptr,&invalid);
REQUIRE_THROWS(predictor.predict({5,6},{0,4}));
REQUIRE(invalid.status()==BasePairProbabilities::Status::failed);
#endif
BasePairProbabilities overflow(5,5);
InteractionEnergyBasePair extreme(targetAcc,reverse,2,2,false,1,Ekcal_2_E(-1000));
PredictorMfeEns2d huge(extreme,output,nullptr,&overflow);
Expand Down
30 changes: 19 additions & 11 deletions tests/StackSeedDomain_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ TEST_CASE("stack capability and active occurrence domain", "[StackSeedDomain]")
SeedHandlerNoBulge stack(energy,computed);
REQUIRE(mfe.guaranteesStackOnlySeeds());
REQUIRE(stack.guaranteesStackOnlySeeds());
// 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);
#if INTARNA_IN_DEBUG_MODE
// Unsupported handlers are rejected only by the debug precondition check.
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);
#endif
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));
Expand Down Expand Up @@ -72,8 +74,10 @@ TEST_CASE("stack-domain lookups and traversal preserve overlapping seed geometry
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.
#if INTARNA_IN_DEBUG_MODE
// Conflicting lengths violate a debug-checked caller precondition.
REQUIRE_THROWS_AS((StackSeedDomain({{1,1,1},{1,1,2}},4,4,4,4)),std::invalid_argument);
#endif
}

TEST_CASE("stack-domain admission preserves handler-specific threshold equality", "[StackSeedDomain]") {
Expand All @@ -98,17 +102,21 @@ TEST_CASE("stack-domain admission preserves handler-specific threshold equality"
REQUIRE(StackSeedDomain(ex,3,3,3,3).maxSeedLength()==2);
}

TEST_CASE("explicit stack capability inspects the retained minimum-energy pattern", "[StackSeedDomain]") {
TEST_CASE("explicit stack capability remains conservative for mixed encodings", "[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());
// The retained minimum-energy pattern is a stack, but mixed input encodings
// conservatively disable the stack-only handler contract before dispatch.
REQUIRE_FALSE(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
REQUIRE(handler.getSeedLength1(0,0)==3);
REQUIRE(handler.getSeedLength2(0,0)==3);
#if INTARNA_IN_DEBUG_MODE
REQUIRE_THROWS_AS(StackSeedDomain(handler,4,4,4,4),std::invalid_argument);
#endif
}