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

Fixes #148 NaNs in boolean formulas (also in If-Formulas and MinMax-Formulas) #154

Merged

Conversation

Yuri05
Copy link
Member

@Yuri05 Yuri05 commented Oct 21, 2022

No description provided.

@Yuri05 Yuri05 requested review from msevestre and PavelBal October 21, 2022 12:49
@@ -118,7 +120,7 @@ Formula * BooleanFormula::RecursiveSimplify()
if (m_FirstOperandFormula->IsConstant(CONSTANT_CURRENT_RUN)
&& (m_SecondOperandFormula == NULL || m_SecondOperandFormula->IsConstant(CONSTANT_CURRENT_RUN)))
{
ConstantFormula * f = new ConstantFormula( DE_Compute(NULL, 0.0, USE_SCALEFACTOR) );
auto f = new ConstantFormula( DE_Compute(NULL, 0.0, USE_SCALEFACTOR) );
Copy link
Member

Choose a reason for hiding this comment

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

auto is like var?

Copy link
Member Author

Choose a reason for hiding this comment

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

exactly :)

@Yuri05
Copy link
Member Author

Yuri05 commented Oct 21, 2022

There were some more formulas to fix, e.g. min/max
For test, I added the project with 3 groups of parameters:

  • Those which should return NaN
  • Those who sholuld return True (or 1)
  • And Those who should return False (or 0)
    Currently all those highlighted parameters which must be NaN return other values.
    grafik

After the fix all of them are properly set to NaN

if (m_IfStatement->DE_Compute(y, time, USE_SCALEFACTOR) == 1)
auto ifStatementValue = m_IfStatement->DE_Compute(y, time, USE_SCALEFACTOR);
if (isnan(ifStatementValue))
return; //TODO is this ok? or should we throw an error instead?
Copy link
Member Author

Choose a reason for hiding this comment

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

here (and in other functions) it's the question for me, what should happen if NaN appears in the jacobian function:

  • do nothing?
  • throw an error?
  • set the corresponding Jac value to NaN?

Copy link
Member

Choose a reason for hiding this comment

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

all right,. setting to NaN is also a good option...hum
@abdullahhamadeh Any gut feel here? (This is about what do we do when we have an ? operation and the if condition evaluates to NaN ).

Copy link
Member Author

Choose a reason for hiding this comment

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

Actually I think it's OK AS IS (= "do nothing").
Because if we have an NaN in the conditional statement - the corresponding RHS value will be NaN anyways, which will produce the error immediately after the current RHS function evaluation is finished.
Setting additionally some Jac-Values to NaN will then have no additional effect.

BooleanFormula ();
virtual ~BooleanFormula ();
BooleanFormula ();
virtual ~BooleanFormula ();
Copy link
Member Author

Choose a reason for hiding this comment

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

I have to reformat the whole SimModel code once to have the proper indentation...
Will do it after 11.1

Copy link
Member

Choose a reason for hiding this comment

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

yes please. Let's createa an issue for this

Copy link
Member Author

Choose a reason for hiding this comment

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

done #155

@@ -261,18 +287,17 @@ void BooleanFormula::UpdateIndicesOfReferencedVariables()

double AndFormula::DE_Compute (const double * y, const double time, ScaleFactorUsageMode scaleFactorMode)
{
assert (m_SecondOperandFormula != NULL); //first operand is always set
return (m_FirstOperandFormula->DE_Compute(y, time, scaleFactorMode) && m_SecondOperandFormula->DE_Compute(y, time, scaleFactorMode));
return calculate_binaryOperation(y, time, scaleFactorMode, logical_and<>{});
Copy link
Member Author

Choose a reason for hiding this comment

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

Relevant changes are in XXX::DE_Compute() functions and in XXX::DE_Jacobian() functions (where applies)
For all boolean functions I just call calculate_binaryOperation() or calculate_unaryOperation() passing the logical operation itself as the last argument (e.g. here logical_and<>{})

Copy link
Member

@msevestre msevestre left a comment

Choose a reason for hiding this comment

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

Looks good to me


auto secondOperand = m_SecondOperandFormula->DE_Compute(y, time, scaleFactorMode);
if (isnan(secondOperand))
return MathHelper::GetNaN();
Copy link
Member

Choose a reason for hiding this comment

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

some of the spacing is really off here. It looks like 6 spaces?
Can't we run something like resharper and format that code once and for all lol

Copy link
Member Author

Choose a reason for hiding this comment

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

Yep, will try to do this after 11.1


var namePrefix = "Nan_If_Conditional_Min_Max|Organism|";

_nan_parameters = sut.ParameterProperties.Where(p=>p.Name.StartsWith($"{namePrefix}P"));
Copy link
Member

Choose a reason for hiding this comment

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

funky

if (m_IfStatement->DE_Compute(y, time, USE_SCALEFACTOR) == 1)
auto ifStatementValue = m_IfStatement->DE_Compute(y, time, USE_SCALEFACTOR);
if (isnan(ifStatementValue))
return; //TODO is this ok? or should we throw an error instead?
Copy link
Member

Choose a reason for hiding this comment

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

Hum...good question.
It's probably not a good case anyways.
I would not throw an error because we are NOT throwing an error on 102.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yep, I think as well, we should not throw an error.
And if we have an NaN in the if-condition, then RHS would become NaN as well - which will be caught anyways after the solver step is finished.
So probably it's ok to keep it like this (= "do nothing") in the JAc function...

//-------------------------------------------------------------------

double LessFormula::DE_Compute (const double * y, const double time, ScaleFactorUsageMode scaleFactorMode)
{
return (m_FirstOperandFormula->DE_Compute(y, time, scaleFactorMode) < m_SecondOperandFormula->DE_Compute(y, time, scaleFactorMode));
return calculate_binaryOperation(y, time, scaleFactorMode, less<>{});
Copy link
Member

Choose a reason for hiding this comment

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

this syntax is so weird less<> {}.

Copy link
Member Author

Choose a reason for hiding this comment

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

lol.
Actually it is less<double> {}
But VisualStudio C++ code optimization suggests to remove the template argument (double) for clarity... as for me it becomes less clear after that...
The suggestion is described here: https://releases.llvm.org/13.0.0/tools/clang/tools/extra/docs/clang-tidy/checks/modernize-use-transparent-functors.html

return logicalOperation(firstOperand, secondOperand);
}

double BooleanFormula::calculate_unaryOperation(const double* y, const double time,
Copy link
Member

Choose a reason for hiding this comment

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

this is so cool. Lambda in C++?

Copy link
Member Author

Choose a reason for hiding this comment

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

yes. is actually available since C++ 14 (or even C++ 11)

@msevestre
Copy link
Member

I think we can merge. looks good to me Juri

@Yuri05 Yuri05 merged commit 5b57055 into Open-Systems-Pharmacology:master Oct 21, 2022
@Yuri05
Copy link
Member Author

Yuri05 commented Oct 21, 2022

ok, merged. we can update OSPSuite.Core then.
For ospsuite-R, I must create the Centos-package first

@Yuri05 Yuri05 deleted the 148_NaNs_in_boolean_formulas branch November 27, 2023 11:22
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