Conversation
…ature/runtime-op-support
All connectivity info is now encoded using plain strings
All connectivity info is now encoded using plain strings
…ation order Constructors now take strings as Operator identifiers
…f perturbation order. Perturbation order does not make any difference on how the operator acts, so it is only for bookkeeping here.
All methods except A and S will check registry make sure the Operator label is registered.
Clarify that lst is a free function and mention mbpt::Context.
…e-op-support # Conflicts: # SeQuant/domain/mbpt/spin.cpp
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 61 out of 61 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
1bb4986 to
6d5e4f6
Compare
cum_to_density should be checking for cumulant label not rdm
|
@ajay-mk @Krzmbrzl hat seems to confuse the parser? https://github.com/ValeevGroup/SeQuant/actions/runs/21360724502/job/61479058146#step:14:110 |
|
I added the cirumflex/hat character to the auto word_components = x3::unicode::alnum
| x3::char_('_') | x3::unicode::char_(L'⁔') | x3::unicode::char_(L'̃') | x3::unicode::char_(to_char_type(0x0302))
// Superscript and Subscript block
| (x3::unicode::char_(to_char_type(0x2070), to_char_type(0x209F)) - x3::unicode::unassigned)
// These are defined in the Latin-1 Supplement block and thus need to be listed explicitly
| x3::unicode::char_(L'¹') | x3::unicode::char_(L'²') | x3::unicode::char_(L'³')
// Arrow block
| (x3::unicode::char_(to_char_type(0x2190), to_char_type(0x21FF)) - x3::unicode::unassigned);
// A name begins with a letter, then can container letters, digits and
// underscores, but can not end with an underscore (to not confuse the parser
// with tensors á la t_{…}^{…}.PS: the third case here is combining tilde, but my editor renders it poorly :( |
|
@ajay-mk yes that's perfectly fine. I would add a comment describing what that character is though. That way, it will be easier to understand the code |
Also switch combining tilder to use to_char_type(0x0303)
perturbation order first, then adjoint label
- Adds SEQUANT_ASSERT to op_registry() and mutable_op_registry() to avoid null registry accesses. - operator== is now a friend, so that it can member variable directly instead of going through the accessor
|
This is good to go.
|
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 62 out of 62 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| : label_(label), | ||
| order_(order), | ||
| cre_spaces_(cre_list.begin(), cre_list.end()), | ||
| ann_spaces_(ann_list.begin(), ann_list.end()) { |
There was a problem hiding this comment.
This OpMaker constructor accepts a raw order but does not validate it. If order > 9 and assertions are disabled, decorate_with_pert_order() will index past pert_superscripts and can cause undefined behavior. Suggest validating order here (or removing this overload in favor of the OpParams-based ctor so all call paths go through OpParams::validate()).
| ann_spaces_(ann_list.begin(), ann_list.end()) { | |
| ann_spaces_(ann_list.begin(), ann_list.end()) { | |
| if (order_ > 9) { | |
| throw std::out_of_range( | |
| "OpMaker: perturbation order out of range [0,9]"); | |
| } |
| int pert_order = 0) { | ||
| if (pert_order == 0) return std::wstring(base_label); | ||
| SEQUANT_ASSERT( | ||
| pert_order >= 0 && pert_order <= 9, | ||
| "decorate_with_pert_order: perturbation order out of range [0,9]"); | ||
|
|
There was a problem hiding this comment.
decorate_with_pert_order() indexes pert_superscripts[pert_order] after a SEQUANT_ASSERT range check. If assertions are compiled out (or pert_order is produced via an unchecked conversion from size_t), this can become out-of-bounds UB. Consider making the range check non-optional (e.g., throw/abort on pert_order > 9) and/or taking std::size_t to avoid lossy conversion from OpParams::order/OpMaker::order_.
| int pert_order = 0) { | |
| if (pert_order == 0) return std::wstring(base_label); | |
| SEQUANT_ASSERT( | |
| pert_order >= 0 && pert_order <= 9, | |
| "decorate_with_pert_order: perturbation order out of range [0,9]"); | |
| std::size_t pert_order = 0) { | |
| if (pert_order == 0) return std::wstring(base_label); | |
| if (pert_order > 9) { | |
| throw std::out_of_range( | |
| "decorate_with_pert_order: perturbation order out of range [0,9]"); | |
| } |
Custom Operator Registry Support
This PR refactors Operator logic from depending on a predefined
OpTypeenum to a runtimeOpRegistry, enabling users to define custom operators beyond the predefined set.Major Changes
OpRegistry: a registry for operator labels and their classificationsmbpt::Contextnow holds anOpRegistryalong with the CSV setting.OpTypeenum is removed, all related logic is gone:OpMakerconstructors now use strings.OpConnectionsnow uses strings to specify operator pairs. For example:{{L"f", L"A"}, {L"g", L"A"}, ...}mbpt::Contextmanipulations are thread-safe, and can be toggled bySEQUANT_CONTEXT_MANIPULATION_THREADSAFEoption; follows the same pattern ascore::Context.Example Usage
Additional Changes
ÂandŜ, respectively. As a result, several tests and examples were updated. Most hardcoded strings were replaced with calls to the reserved label methods; however, some reference outputs and expressions are still constructed from plain strings.The spin-tracing examples intests/integrationwere not usingmbpt::cardinal_tensor_labels()for expression canonicalization. After the label change, symmetrizer and antisymmetrizer tensors were moved to the end during canonicalization. Since the spin-tracing logic assumes all symmetrizer tensors share the same external indices, they must appear first. This was fixed by canonicalizing withmbpt::cardinal_tensor_labels(), which places symmetrizer tensors first and ensures consistent indexing.Some evaluation logic also requires canonical ordering. Accordingly, theeval_{ta,btas}cases now usembpt::cardinal_tensor_labels()with TNC.Sum, they need to appear first in aProduct. When the labels were changed, they appeared at the end of aProduct, which caused problems in spin-tracing and eval logic (see the striked points). To prevent this, antisymmetrizer/symmetrizer labels are prepended to the cardinal tensor labels list whenset_cardinal_tensor_labels()is called.trace_productspin-tracing logic assumed that the symmetrizer tensor always appears first; this has been generalized. cc: @ABesharat