WIP: Add RefinableParProxy to prevent in-place parameter name mutation - #78
Conversation
Introduce RefinableParProxy, a lightweight subclass of RefinablePar that
keeps its own hierarchy-prefixed name while delegating all other operations
(value, limits, flags, type) to the original RefinablePar.
When RefinableObj::AddPar(obj, copyParam=false) is called (e.g. in
LSQNumObj::PrepareRefParList), parameters are now wrapped in
RefinableParProxy instances rather than having their names mutated
with '~' suffixes. Proxy names are built by GetParNameHierarchy(),
which follows the first entry of each object's client registry
recursively up to max_parents levels to produce a name in the form
'GrandParentClass:GrandParentName:ParentClass:ParentName:paramName'.
If the hierarchy-derived name still collides, a warning is printed to
stderr and the pointer address is appended as a disambiguating suffix.
New API:
class RefinableParProxy : public RefinablePar
string RefinableObj::GetParNameHierarchy(RefinablePar&, int max_parents=2)
Unit tests added:
test/unit/api_refinableobj.cpp -- proxy behaviour and hierarchy naming
(one/two/three-level hierarchy, delegation, collision fallback)
test/unit/api_optimization.cpp -- lsqnumobj-preserve-original-parameter-names
extended with two crystalline phases sharing unit-cell parameter names
Fixes #71.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
Thanks, sounds good in principle. I'm not sure what the best "naming scheme" is to solve the ultimate problem of user-friendly access to parameters. In the original issue I complained that unit cell length And what would become the indended way to access parameters by name collected in an I'm asking because I expect these two cases to be different. If I have the parent Crystal I expect to be able to use the canonical name, i.e. But what's the "name" of a PowderPattern? The only thing which has a sensible name for me is a phase, like "Corundum". But a phase is a PowderPatternDiffraction, and technically the name lives on its Crystal? |
|
Sorry if this sounds like bikeshedding. I'm being so meticulous because this change isn't technically needed, but only needed for being more user-friendly. And for being user-friendly the naming has to be "expectable"? There does exist a technical wrinkle though: the number of |
With this approach, the name in the original Crystal object is unchanged - that's the main point of this approach.
You can choose, either use the
It can be anything - the only important point, the name of a |
|
Ok sounds good to me, thanks. It wasn't so clear before if everything would switch to the hierarchical naming, or only lsq(r). Are you comfortable with merging this PR? |
Summary
Fixes #71 by introducing a clean proxy-based approach that prevents
RefinableObj::AddPar(obj, copyParam=false)from mutating the names of the originalRefinableParobjects.Problem
When
LSQNumObj::PrepareRefParList()(or any code callingAddPar(obj, false)) aggregated parameters from multiple objects, duplicate parameter names (e.g.a,b,cfrom two crystal phases) were resolved by appending~suffixes in-place on the original objects. This silently corrupted the parameter names of the source objects.Solution
RefinableParProxy— a new lightweight subclass ofRefinableParthat:ParentClass:ParentName:paramName)RefinablePar, so attribute changes propagate correctlyRefinableObj::GetParNameHierarchy(par, max_parents=2)— new public helper that recursively follows the first entry of each object'smClientObjRegistryto build a unique, human-readable prefix. For example:If the hierarchy-derived name still collides, a warning is printed to
stderrand theRefinableParaddress is appended as a disambiguating suffix.Changes
ObjCryst/RefinableObj/RefinableObj.hRefinableParProxyclass; allRefinableParmethods madevirtual;GetParNameHierarchydeclarationObjCryst/RefinableObj/RefinableObj.cppRefinableParProxyimplementation; recursiveCollectParentPrefixeshelper; updatedAddPar(obj, false)test/unit/api_refinableobj.cpptest/unit/api_optimization.cpplsqnumobj-preserve-original-parameter-namesextended with two crystal phases sharinga,b,cnamesChangeLog.txtRelationship to PR #77
PR #77 addresses the same issue (#71) by making the
~-suffix order deterministic (insertion-ordered vector). This PR takes a different approach: proxy objects carry the decorated name, leaving the originals untouched entirely. See comment on PR #77 for a detailed comparison.