-
Notifications
You must be signed in to change notification settings - Fork 21
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
Demonstrating errors in code generation #598
Conversation
Also need to update the expected printer string in the tests to reflect the additional variable and connection.
The added test will pass, but the generated variable information is incorrect. Adding this version to show what is currently being generated.
This change breaks the tests as the code being generated is incorrect. Also looks like the ordering is incorrect (variables[2] corresponds to the variable information for index 7). See cellml#597.
I think the problem (besides issue #597) is not with the generator itself, but rather with the flattening. |
I take it back. It is indeed an issue with the generator. Argh! |
phew! was pretty sure I checked the flattened model and it looked good. This issue came up as I try to navigate through the collection of equivalent variables to find the one that is used in the generated code and I can never get a match as the component and variable names are out of sync. |
Yes, I printed the flattened model and that's where I realised my mistake. :) The problem is buried in our generator, but I am slowly getting there, so you will have a fix before the end of the day. Definitely. |
…e one in which its equation is.
…me as the equation variable.
Ok, I am done with this. Happy for you, @nickerso, @hsorby and @kerimoyle, to review and merge this in. |
@nickerso, since you can't review it as such. I am happy to "review" it on your behalf... |
Mild panic as this didn't fix my issue, but then realised that I have the ordering fix from #597 also merged into my local source. So ignoring that, yes, this fixes the bug in the variable names and I would happily approve this if I hadn't started it :) |
Eh, it's not the time for mild panic! :) Anyway, I am going to approve it on your behalf and leave it to @hsorby or @kerimoyle to confirm. |
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.
This is a brilliant PR. I am all in favour of it. No reservations whatsoever! (If only all PRs could be of that quality. One can only dream...)
// The variable has an initial value, so it can either be a constant or | ||
// a state. By default, we consider it to be a constant and, if we find | ||
// an ODE for that variable, we will know that it was actually a state. | ||
|
||
mType = Type::CONSTANT; | ||
|
||
mInitialValueVariable = variable; |
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.
A variable that is reset will have an initial value too? Neither a constant nor a state?
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.
We are not yet generating code for resets, so we will see what needs to be done when we do.
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.
Which is the bit that fixes the bug? There are lots of changes that seem a bit arbitrary?
This PR contains some code clean up (as a result of working on this PR), but otherwise there are a couple of key places that fix the bug. I am going to annotate them. |
variable->mComponent = mComponent; | ||
for (size_t i = 0; i < mComponent->variableCount(); ++i) { | ||
VariablePtr localVariable = mComponent->variable(i); | ||
|
||
if (sameOrEquivalentVariable(variable->mVariable, localVariable)) { | ||
variable->setVariable(localVariable, false); | ||
|
||
break; | ||
} | ||
} |
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.
- This is the change that directly fixes @nickerso's issue. Before we were only updating the component information, but not the variable information which we now do through our call to
setVariable()
. Note, however, that we pass itfalse
since we don't want to check for the initial value.
void GeneratorInternalVariable::setVariable(const VariablePtr &variable) | ||
void GeneratorInternalVariable::setVariable(const VariablePtr &variable, | ||
bool checkInitialValue) | ||
{ | ||
mVariable = variable; | ||
|
||
if (!variable->initialValue().empty()) { | ||
if (checkInitialValue && !variable->initialValue().empty()) { | ||
// The variable has an initial value, so it can either be a constant or | ||
// a state. By default, we consider it to be a constant and, if we find | ||
// an ODE for that variable, we will know that it was actually a state. | ||
|
||
mType = Type::CONSTANT; | ||
|
||
mInitialValueVariable = variable; | ||
} | ||
|
||
mVariable = variable; | ||
mComponent = std::dynamic_pointer_cast<Component>(variable->parent()); | ||
} |
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.
- Our new
setVariable()
method now also updatesmVariable
, but also keeps track of the variable object that contains the initial value of a variable (mInitialValueVariable
).
* variable). It may or may not be the same @c Component as the parent | ||
* component of the @c Variable. | ||
* variable). |
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.
- Because of points 1 and 2, the
component()
is always going to be the parent component ofvariable()
, which makes our API better than before.
return mProfile->indentString() + generateVariableNameCode(variable->mVariable) + " = " + generateDoubleCode(variable->mVariable->initialValue()) + mProfile->commandSeparatorString() + "\n"; | ||
return mProfile->indentString() + generateVariableNameCode(variable->mVariable) + " = " + generateDoubleCode(variable->mInitialValueVariable->initialValue()) + mProfile->commandSeparatorString() + "\n"; |
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.
- This is a side effect of the main change where we now have to retrieve the initial value from
mInitialValueVariable
rather thanmVariable
.
I've got some concerns about the "can't initialise a variable with another variable" thing. We've just finished writing the spec that says that we do support this (at present) ... shouldn't we be maintaining tests and functionality in line with that? I have no problem with this PR other than this sneaking idea that we might be missing stuff by making changes in the background ... ? @nickerso @hsorby @agarny Thoughts? |
CellML allows this, the |
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.
OK with me.
This needs to be done in another PR for which I have created an issue (see issue #602). Will work on that issue once we have merged in this PR and PR #599. |
I have added code generation for my "go to" test model (sine approximations with imports) to demonstrate an issue that I am seeing in the code generation. There is some evidence that this is related to #597, but as well as the ordering being incorrect, the
VARIABLE_INFO
is getting the name of the variables wrong. While the variable info correctly identifies the "source" component, it is using the name of the variable from the top-level component in the encapsulation and import hierarchy.You can see these differences in specifically in nickerso@41db32b. This is a problem in both the C and Python profiles.