From 98d69025e2909fb9c35d02a7e754667f81b79951 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Wed, 18 Feb 2026 09:10:32 -0500 Subject: [PATCH 1/2] Context: strict_braket_symmetry -> assert_strict_braket_symmetry --- SeQuant/core/attr.hpp | 9 ++++----- SeQuant/core/context.cpp | 15 +++++++++------ SeQuant/core/context.hpp | 26 +++++++++++++++++--------- SeQuant/core/tensor_network/v3.cpp | 3 +-- tests/unit/test_eval_ta.cpp | 4 ++-- 5 files changed, 33 insertions(+), 24 deletions(-) diff --git a/SeQuant/core/attr.hpp b/SeQuant/core/attr.hpp index fdd44ac153..f6bc864e97 100644 --- a/SeQuant/core/attr.hpp +++ b/SeQuant/core/attr.hpp @@ -34,11 +34,10 @@ enum class Symmetry { Symm, Antisymm, Nonsymm }; /// index for a single particle, only whole bra-ket swaps are considered. enum class BraKetSymmetry { Symm, Conjugate, Nonsymm }; -/// describes whether to ignore the vector space semantics of bra/ket slots, -/// i.e. treat them as aux indices. -/// @note StrictBraKetSymmetry::No is a bad idea if working with complex-valued -/// tensors, or nonunit metric, or in general -enum class StrictBraKetSymmetry { Yes, No }; +/// describes whether to SEQUANT_ASSERT the vector space semantics of bra/ket +/// slots in tensor networks +/// @sa Context::assert_strict_braket_symmetry +enum class AssertStrictBraKetSymmetry { Yes, No }; /// describes type of single-particle basis enum class SPBasis { Spinor, Spinfree }; diff --git a/SeQuant/core/context.cpp b/SeQuant/core/context.cpp index b8030ad8ec..e4096661b3 100644 --- a/SeQuant/core/context.cpp +++ b/SeQuant/core/context.cpp @@ -22,7 +22,8 @@ bool operator==(const Context& ctx1, const Context& ctx2) { else return ctx1.vacuum() == ctx2.vacuum() && ctx1.metric() == ctx2.metric() && ctx1.braket_symmetry() == ctx2.braket_symmetry() && - ctx1.strict_braket_symmetry() == ctx2.strict_braket_symmetry() && + ctx1.assert_strict_braket_symmetry() == + ctx2.assert_strict_braket_symmetry() && ctx1.spbasis() == ctx2.spbasis() && ctx1.first_dummy_index_ordinal() == ctx2.first_dummy_index_ordinal() && @@ -128,7 +129,7 @@ Context::Context(Options options) vacuum_(options.vacuum), metric_(options.metric), braket_symmetry_(options.braket_symmetry), - strict_braket_symmetry_(options.strict_braket_symmetry), + assert_strict_braket_symmetry_(options.assert_strict_braket_symmetry), spbasis_(options.spbasis), first_dummy_index_ordinal_(options.first_dummy_index_ordinal), canonicalization_options_(options.canonicalization_options), @@ -158,8 +159,8 @@ IndexSpaceMetric Context::metric() const { return metric_; } BraKetSymmetry Context::braket_symmetry() const { return braket_symmetry_; } -StrictBraKetSymmetry Context::strict_braket_symmetry() const { - return strict_braket_symmetry_; +bool Context::assert_strict_braket_symmetry() const { + return assert_strict_braket_symmetry_; } SPBasis Context::spbasis() const { return spbasis_; } @@ -204,8 +205,10 @@ Context& Context::set(BraKetSymmetry braket_symmetry) { return *this; } -Context& Context::set(StrictBraKetSymmetry strict_braket_symmetry) { - strict_braket_symmetry_ = strict_braket_symmetry; +Context& Context::set( + AssertStrictBraKetSymmetry assert_strict_braket_symmetry) { + assert_strict_braket_symmetry_ = + assert_strict_braket_symmetry == AssertStrictBraKetSymmetry::Yes; return *this; } diff --git a/SeQuant/core/context.hpp b/SeQuant/core/context.hpp index 5096231638..d84f7d7d28 100644 --- a/SeQuant/core/context.hpp +++ b/SeQuant/core/context.hpp @@ -53,7 +53,7 @@ class Context { constexpr static auto vacuum = Vacuum::Physical; constexpr static auto metric = IndexSpaceMetric::Unit; constexpr static auto braket_symmetry = BraKetSymmetry::Conjugate; - constexpr static auto strict_braket_symmetry = StrictBraKetSymmetry::Yes; + constexpr static auto assert_strict_braket_symmetry = true; constexpr static auto spbasis = SPBasis::Spinor; constexpr static auto first_dummy_index_ordinal = 100; constexpr static auto braket_typesetting = BraKetTypesetting::ContraSub; @@ -75,8 +75,9 @@ class Context { IndexSpaceMetric metric = Defaults::metric; /// the BraKetSymmetry object BraKetSymmetry braket_symmetry = Defaults::braket_symmetry; - /// the StrictBraKetSymmetry object - StrictBraKetSymmetry strict_braket_symmetry = Defaults::strict_braket_symmetry; + /// the flag that controls the strictness of bra-ket checks in + /// tensor network construction + bool assert_strict_braket_symmetry = Defaults::assert_strict_braket_symmetry; /// the SPBasis object SPBasis spbasis = Defaults::spbasis; /// the first dummy index ordinal @@ -135,8 +136,15 @@ class Context { IndexSpaceMetric metric() const; /// \return BraKetSymmetry of this context BraKetSymmetry braket_symmetry() const; - /// \return StrictBraKetSymmetry of this context - StrictBraKetSymmetry strict_braket_symmetry() const; + /// \return true if strict bra-ket symmetry is asserted; + /// setting this to false (via `Context::set(AssertStrictBraKetSymmetry::No)`) + /// allows arbitrary contractions of bra/ket modes as if they were aux indices. + /// @note disabling strict bra-ket symmetry assertions is a bad idea if + /// working with complex-valued tensors, or nonunit metric, or in general + /// @warning if SeQuant was configured with `SEQUANT_ASSERT_BEHAVIOR=IGNORE` + /// the strict bra-ket contraction checks are turned off even if + /// this returns true + bool assert_strict_braket_symmetry() const; /// \return SPBasis of this context SPBasis spbasis() const; /// \return first ordinal of the dummy indices generated by calls to @@ -173,10 +181,10 @@ class Context { /// \param braket_symmetry BraKetSymmetry /// \return ref to `*this`, for chaining Context& set(BraKetSymmetry braket_symmetry); - /// Sets the StrictBraKetSymmetry for this context, convenient for chaining - /// \param strict_braket_symmetry StrictBraKetSymmetry + /// Sets the bra-ket strict assertion flag for this context, convenient for chaining + /// \param assert_strict_braket_symmetry AssertStrictBraKetSymmetry /// \return ref to `*this`, for chaining - Context& set(StrictBraKetSymmetry strict_braket_symmetry); + Context& set(AssertStrictBraKetSymmetry assert_strict_braket_symmetry); /// Sets the SPBasis for this context, convenient for chaining /// \param spbasis SPBasis /// \return ref to `*this`, for chaining @@ -202,7 +210,7 @@ class Context { Vacuum vacuum_ = Defaults::vacuum; IndexSpaceMetric metric_ = Defaults::metric; BraKetSymmetry braket_symmetry_ = Defaults::braket_symmetry; - StrictBraKetSymmetry strict_braket_symmetry_ = Defaults::strict_braket_symmetry; + bool assert_strict_braket_symmetry_ = Defaults::assert_strict_braket_symmetry; SPBasis spbasis_ = Defaults::spbasis; std::size_t first_dummy_index_ordinal_ = Defaults::first_dummy_index_ordinal; std::optional canonicalization_options_ = std::nullopt; diff --git a/SeQuant/core/tensor_network/v3.cpp b/SeQuant/core/tensor_network/v3.cpp index 75fb1a3613..7a27313948 100644 --- a/SeQuant/core/tensor_network/v3.cpp +++ b/SeQuant/core/tensor_network/v3.cpp @@ -1210,8 +1210,7 @@ TensorNetworkV3::Graph TensorNetworkV3::create_graph( // strict bra-ket sanity checks if constexpr (assert_enabled()) { - if (get_default_context().strict_braket_symmetry() == - StrictBraKetSymmetry::Yes) { + if (get_default_context().assert_strict_braket_symmetry()) { // dummy (anonymous) edges to // - involve at most 2 bra and/or ket indices (if BraKetSymmetry::Symm) // or 1 bra and 1 ket index diff --git a/tests/unit/test_eval_ta.cpp b/tests/unit/test_eval_ta.cpp index f5a61ba0af..aaa572a462 100644 --- a/tests/unit/test_eval_ta.cpp +++ b/tests/unit/test_eval_ta.cpp @@ -722,10 +722,10 @@ TEST_CASE("eval_with_tiledarray", "[eval]") { REQUIRE(equal_tarrays(eval_rdm, man_rdm, "a2,a1,i1,i2")); } - { // multiple bra or ket indices require StrictBraKetSymm::No + { // multiple bra or ket indices require AssertStrictBraKetSymmetry::No auto ctx_resetter = sequant::set_scoped_default_context( sequant::Context{sequant::get_default_context()}.set( - sequant::StrictBraKetSymmetry::No)); + sequant::AssertStrictBraKetSymmetry::No)); // hyperindex i1 in ket slots of 3 tensors auto expr2 = deserialize(L"T{a1;i1} T{a2;i1} T{a3;i1}"); From fd89d1b5a22daea3da29e5159867eedc9a0e037c Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Wed, 18 Feb 2026 15:28:57 -0500 Subject: [PATCH 2/2] fixups from copilot review --- SeQuant/core/space.hpp | 2 +- SeQuant/core/utility/exception.hpp | 1 + SeQuant/core/wick.hpp | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/SeQuant/core/space.hpp b/SeQuant/core/space.hpp index e0d4891dea..73ff958495 100644 --- a/SeQuant/core/space.hpp +++ b/SeQuant/core/space.hpp @@ -374,7 +374,7 @@ class IndexSpace { using Type = TypeAttr; using QuantumNumbers = QuantumNumbersAttr; - /// exception type thrown when ancountered unknown/invalid + /// exception type thrown when encountered unknown/invalid /// IndexSpace::base_key() or Index::label() struct bad_key : std::invalid_argument { bad_key() : std::invalid_argument("bad key") {} diff --git a/SeQuant/core/utility/exception.hpp b/SeQuant/core/utility/exception.hpp index add83b4674..dd3db7ee55 100644 --- a/SeQuant/core/utility/exception.hpp +++ b/SeQuant/core/utility/exception.hpp @@ -5,6 +5,7 @@ #ifndef SEQUANT_CORE_UTILITY_EXCEPTION_HPP #define SEQUANT_CORE_UTILITY_EXCEPTION_HPP +#include #include namespace sequant { diff --git a/SeQuant/core/wick.hpp b/SeQuant/core/wick.hpp index 21340706bd..36d275dd4b 100644 --- a/SeQuant/core/wick.hpp +++ b/SeQuant/core/wick.hpp @@ -616,7 +616,7 @@ class WickTheorem { get_default_context(S).vacuum() == Vacuum::SingleProduct))) throw std::logic_error( "WickTheorem::compute: spinfree=true supported only for physical " - "vacuum and for Fermi facuum"); + "vacuum and for Fermi vacuum"); if (!all_indices_) { extract_indices(*input_);