Skip to content

Conversation

@alyst
Copy link
Contributor

@alyst alyst commented Feb 4, 2025

These are rather trivial commits cherry-picked from #193 that don't change anything essential, but once they are in, it should be easier to manage the rest.

The changes are:

  • code formatter whitespace fixes for the .md files
  • move some using directives from the individual unit test .jl files to the parent .jl file
  • in RAMSymbolic rename xxx_function to xxx_eval! as that better follows Julia naming conventions and should make the code a bit more readable (and shorter)
  • cleanups to the fitmeasures that simplify some method signatures (remove unused type parameters).
    This is a bit less trivial set of changes than the rest, but in the end it does not really change how the functions are calculated.
    Except for switching p-values calculation to use ccdf(x) instead of 1 - cdf(x) -- this could potentially give more precise results for p-values close to 0.

@codecov
Copy link

codecov bot commented Feb 4, 2025

Codecov Report

❌ Patch coverage is 89.13043% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 72.39%. Comparing base (8b0f880) to head (0cb546e).
⚠️ Report is 58 commits behind head on devel.

Files with missing lines Patch % Lines
src/additional_functions/helper.jl 0.00% 3 Missing ⚠️
src/additional_functions/params_array.jl 33.33% 2 Missing ⚠️
src/frontend/fit/fitmeasures/chi2.jl 92.85% 2 Missing ⚠️
src/implied/RAM/symbolic.jl 93.10% 2 Missing ⚠️
src/optimizer/abstract.jl 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##            devel     #245      +/-   ##
==========================================
- Coverage   72.94%   72.39%   -0.56%     
==========================================
  Files          50       53       +3     
  Lines        2218     2210       -8     
==========================================
- Hits         1618     1600      -18     
- Misses        600      610      +10     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@alyst
Copy link
Contributor Author

alyst commented Mar 22, 2025

I've rebased the PR after the #253 got merged.

@Maximilian-Stefan-Ernst I have also noticed that you have implemented #246.
I am not sure I understand what was exactly the reason for these changes -- I guess it was related to running some examples/tests, but if that's the case we can fix it differently.
To me this change defeats the purpose of using extension mechanism for supporting different optimization engines as it moves the SemOptimizer subtypes back into the main package.
There is no strong reason to make engine-specific SemOptimizer subtypes public and recommend the user constructing them explicitly, especially since these constructors take all their input as keyword arguments.
Yes, before #246 the SemOptimizerEngine type was only available within the extension and was not exposed upon extension activation,
but SemOptimizer(engine = ...) => SemOptimizer{engine}(...) => SemOptimizerEngine(...) mechanism can handle SemOptimizerEngine construction just fine.
It is a standard pattern for implementing Julia extensions.
Also, I think for the user it is easier to memorize the SemOptimizer(engine = ...) construct, and it also makes it easier to switch the engines.

So I have added commits that revert #246 in this PR, but also updated the optimization documentation to be in sync with the actual opt. engine API:

  • SemOptimizationOptim(), SemOptimizationNLopt() etc in the docs are replaced with SemOptimizer(engine = <engine_name>, args...).
  • I have updated the fallback SemOptimizer(engine = ...) constructor to inform the user, which packages should be loaded for NLopt and ProximalAlgorithms, if that was one of the reasons for Fix extensions #246.
  • For NLopt I have replaced NLoptConstraint(f = func, tol = tol) with func => tol.
    That simplifies the syntax and avoids defining NLoptContraint type, which is only really used for SemOptimizerNLopt construction.
    I have also allowed specifying just the function without the tolerance -- in that case the tolerance will be taken from the constraint_tol parameter.
  • In the documentation I have changed the term "backend" into "engine" to match the SemOptimizer keyword, but if you have strong preference for "backend",
    I can revert it and rename the "engine" keyword into "backend".
  • I have also simplified the examples: since the optimizer is now separate from the model, we don't need to duplicate the model if we want to fit it with another optimizer.

Please let me know if you have any concerns regarding these changes, I will be happy to address them.

@alyst alyst closed this Apr 26, 2025
@alyst alyst reopened this Apr 26, 2025
@alyst
Copy link
Contributor Author

alyst commented Nov 24, 2025

@Maximilian-Stefan-Ernst @brandmaier @aaronpeikert In the recent months the merging of some of the changes from my staging branch (PR #193) into the main branch was dormant. But I would be still interested in it, if you think it will be beneficial for the SEM.jl. I mention it, because I see there are new issues/PRs, which could at least partially be addressed in PR #193. Thank you!

@alyst alyst closed this Jan 21, 2026
@alyst alyst reopened this Jan 21, 2026
@alyst
Copy link
Contributor Author

alyst commented Jan 21, 2026

The FormatCheck action updates were extracted to PR #296.
It probably has to be merged first.

@Maximilian-Stefan-Ernst
Copy link
Collaborator

Thanks a lot! I merged #296 - is this PR ready for review, or is there anything else you would like to add before?

@alyst alyst closed this Jan 22, 2026
@alyst alyst reopened this Jan 22, 2026
@alyst alyst closed this Jan 22, 2026
@alyst alyst reopened this Jan 22, 2026
@alyst
Copy link
Contributor Author

alyst commented Jan 22, 2026

@Maximilian-Stefan-Ernst Thank you! I've just rebased this branch to the latest devel, but somehow GitHub does not pick up the FormatCheck.yml changes (still uses v1).
Anyway, this PR should be ready for the review.

@Maximilian-Stefan-Ernst
Copy link
Collaborator

Alright, I'll review - I will also try to remind myself why I made the changes related to package extensions and write something about it.

W.r.t. the FormatCheck action - I believe changes to workflows only take effect once they are merged into main - I added the changes to main now, so it should pick up.

@Maximilian-Stefan-Ernst
Copy link
Collaborator

Maximilian-Stefan-Ernst commented Jan 26, 2026

Okay, w.r.t. the package extensions:

I believe the problem was that there was no way to access types defined in extensions at the time. This seems to be fixed now, but it is still cumbersome (https://discourse.julialang.org/t/having-trouble-using-types-defined-in-extension-modules/97260):

using StructuralEquationModels, NLopt

?SemOptimizerNLopt

Couldn't find SemOptimizerNLopt
Perhaps you meant SemOptimizerEmpty
  No documentation found.

  Binding SemOptimizerNLopt does not exist.

m = Base.get_extension(StructuralEquationModels, :SEMNLOptExt)
?m.SemOptimizerNLopt

So out of the box, this leads to some problems - without explicitely using get_extension, users can not access documentation on the extensions, and they can not define methods on types from extensions.

So I thought the main objective of having extensions is to avoid unnecessary dependencies - therefore I moved the types that are defined to the main package, so they are accessible, and their definition does not depend on the dependencies. Definitions of new methods, however, remained in the extension because they actually depend on additonal packages.

However, I really like your changes to the documentation, and the improved syntax for defining constraints, and I would definitely keep those. I am also happy with reverting the changes and moving the types back to the extension, the only thing we would need to fix is the accessibility of the documentation.

I also pushed these changes to another branch because I did not manage to manually trigger the documentation build workflow on this PR, but it is now here (https://github.com/StructuralEquationModels/StructuralEquationModels.jl/actions/runs/21357427498/job/61468060053) and it also seems to have the issue of accessing the documentation of types defined in extensions.

So the only thing I can think of atm would be to move the documentation of all extensions to SemOptimizer - but these docs are pretty long, and that might be quite overwhelming.

@alyst
Copy link
Contributor Author

alyst commented Jan 27, 2026

@Maximilian-Stefan-Ernst I've just pushed commits that address the doc issue for SemOptimizer:

  • I had to introduce the SemOptimizer(Val(engine), ...) ctor to work around Julia issue with parsing SemOptimizer{engine}(...) (see Parsing error for docstring of Foo{:a}() JuliaLang/julia#51906)
  • I moved the engine-specific docstring from the engine-specific structures to SemOptimizer(Val(engine)) ctor.
    With that, ?SemOptimizer correctly displays all overloaded methods depending on which extensions are loaded, and ?SemOptimizer(Val(engine)) shows only the help for the specific engine
  • The issue is that ?SemOptimizer will dump help for all overloads, which might be overwhelming.
    One potential solution is to provide the docs for the engine-specific parameters in the # Extended help section.
    Julia automatically notifies if this section is available and should be accessed with ??SemOptimizer(Val(engine))
  • I have also added optimizer_engines() method that shows all engines (engine keyword argument values) currently supported.

Let me know what you think about this approach.

@alyst
Copy link
Contributor Author

alyst commented Jan 27, 2026

@Maximilian-Stefan-Ernst Sorry for the noise -- because the extended of SemOptimizer changes grew, I have moved them out of this PR into #299 to keep this one easier for review.
Now this PR is mostly no-op formatting changes as the name suggests.

@alyst
Copy link
Contributor Author

alyst commented Jan 27, 2026

I'm not sure why format check fails and generates a lot of noisy suggestions -- when I run it locally there's no issues.

@Maximilian-Stefan-Ernst
Copy link
Collaborator

Thanks a lot for these great changes! I'll merge and then review #299.

@Maximilian-Stefan-Ernst Maximilian-Stefan-Ernst merged commit 9da45e4 into StructuralEquationModels:devel Jan 27, 2026
6 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants