-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Indexed variables #179
base: master
Are you sure you want to change the base?
Indexed variables #179
Conversation
Most importantly when it comes to Parameters, is that self.params will still contain all parameters, whereas the attributes indexed_params and unindexed_params will allow access to those types seperately.
…be handled seperately.
…ence method to create indices has been added.
134a6b0
to
be64cc1
Compare
An example of this can be a brute-force implementation of least-squares fitting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good start. I won't pretend I understand everything that's happening though. I also feel like there's about 1000 tests missing.
And I think we should implement the Objectives
you describe. Or just make LeastSquares
smarter.
|
||
# A mapping of the vars to their (perhaps) indexed counterparts | ||
self.symbol2indexed = {var if isinstance(var, Variable) else var.base: var | ||
for var in model_dict.keys()} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this also work with brackets? {(var if ... else var.base): var for var in model_dict.keys()}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that might be cleaner
|
||
self.dependent_vars = sorted(self.symbol2indexed.keys(), key=sort_func) | ||
# Ordering is determined by the Variable names, not their indexed | ||
# version. (e.g. `y`, not `y[i]` to prevent possible ambiguities.). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move comment above line. And define sort_func down here.
|
||
# Extract all the params and vars as a sorted, unique list. | ||
expressions = model_dict.values() | ||
_params, self.independent_vars = set([]), set([]) | ||
_params, _independent_vars, _indices = set([]), set([]), set([]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
set()
instead of set([])
?
vars, params = seperate_symbols(expression) | ||
# extract symbols from expression, viewing IndexedSymbols as atoms, | ||
# e.g. returns `y[i]` not `y` when applicable | ||
indexed_vars, indexed_params = seperate_symbols(expression) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add argument for separate_indices
symfit/core/support.py
Outdated
else: | ||
vars.append(symbol) | ||
elif isinstance(symbol, IndexedVariableBase): | ||
vars.append(symbol) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can clean this if/elif tree by making a dict of {classes: lists}, and sorting based on that. At the end you combine some (possibly also based on lists/sets of classes).
outcomes = {Parameter: [], IndexedParameter: [], IndexedParameterBase: [], ...}
for symbol in func.free_symbols:
for class_, items in outcomes.items():
if isinstance(symbol, class_):
items.append(symbol)
etc.
return {expr} | ||
else: | ||
# Call this function recursively | ||
indexed = set([]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
set() instead of set([])
It breaks to much sympy compatibility, and writing a function to extract them from an expression turns out to be rather simple once you get the hang of sympy. Tests have also been updated to reflect that IndexedArguments are no longer free_symbols
Additionally, removed Model.chi, Model.chi_jacobian, and its numerical counterparts. This was a remnant from a dark past when we still had to bow to the will of MINPACK. Removed without deprication, as I seriously doubt anybody even knew about this. Symfit itself didn't even use it internally or test for it.
aa22073
to
4c7c71f
Compare
@pckroon Thanks for the review. Of course, ultimately we should implement those Objectives. However, to give a general solution for least-squares-solving a tensor equation turns out to be non-trivial ;). In order to have an achievable goal, I think this is a good place to draw the line for this PR. |
No problem! |
First version of Indexed-variables support! For more info on the possibilities, also see #175.
The goal with this PR is to get to the point where
IndexedVariable
's are fully implemented and working, but forIndexedParameter
's we just implement the correct infrastructure and handling on Models, but with no means for solving them.This means that after merging this PR, the following things will work:
The following things will be possible for advanced users willing to implement their own subclass of BaseObjective:
{y[i]: A[i, j] * x[j] + b}
.y[i] = y0 + a[i] * exp(- b[i] * x[i])
.p.s. my apologies for the huge PR