Skip to content
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

Merged
merged 13 commits into from
May 13, 2020

Conversation

nickerso
Copy link
Contributor

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.

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.
@agarny
Copy link
Contributor

agarny commented May 12, 2020

Good catch! FWIW, I would indeed expect the behaviour to be the same indepdent on the profile chosen. Anyway, it should be an easy fix. I will do it tomorrow once PRs #596 and #599 have been merged in.

@nickerso
Copy link
Contributor Author

once PRs #596 and #599 have been merged in

Surely the fix can be done without a merge...this is completely blocking me at present...I'm building my own libcellml so not worried about changes being merged in...pretty please :)

@agarny agarny mentioned this pull request May 12, 2020
@agarny
Copy link
Contributor

agarny commented May 13, 2020

I think the problem (besides issue #597) is not with the generator itself, but rather with the flattening.

@agarny
Copy link
Contributor

agarny commented May 13, 2020

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!

@nickerso
Copy link
Contributor Author

I take it back. It is indeed an issue with the generator.

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.

@agarny
Copy link
Contributor

agarny commented May 13, 2020

I take it back. It is indeed an issue with the generator.

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.

@agarny
Copy link
Contributor

agarny commented May 13, 2020

Ok, I am done with this. Happy for you, @nickerso, @hsorby and @kerimoyle, to review and merge this in.

@agarny
Copy link
Contributor

agarny commented May 13, 2020

@nickerso, since you can't review it as such. I am happy to "review" it on your behalf...

@nickerso
Copy link
Contributor Author

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 :)

@agarny
Copy link
Contributor

agarny commented May 13, 2020

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.

Copy link
Contributor

@agarny agarny left a 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;
Copy link
Contributor

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?

Copy link
Contributor

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.

Copy link
Contributor

@kerimoyle kerimoyle left a 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?

@agarny
Copy link
Contributor

agarny commented May 13, 2020

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.

Comment on lines -504 to +527
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;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. 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 it false since we don't want to check for the initial value.

Comment on lines -144 to 161
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());
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Our new setVariable() method now also updates mVariable, 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).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Because of points 1 and 2, the component() is always going to be the parent component of variable(), 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";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. This is a side effect of the main change where we now have to retrieve the initial value from mInitialValueVariable rather than mVariable.

@kerimoyle
Copy link
Contributor

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?

@nickerso
Copy link
Contributor Author

I've got some concerns about the "can't initialise a variable with another variable" thing

CellML allows this, the develop branch of libCellML does not yet support this for code generation. As code generation support for this improves this will be added back in. For this particular test I used the existing sine approximations model to save time, happy for the PR to be updated to use a different model to demonstrate this issue (which I think there were others that @agarny fixed as part of this so they could be sufficient).

Copy link
Contributor

@kerimoyle kerimoyle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK with me.

@agarny
Copy link
Contributor

agarny commented May 13, 2020

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?

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.

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.

None yet

3 participants