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

Do not copy tableau state during push and pop #532

Merged

Conversation

wu-haoze
Copy link
Collaborator

@wu-haoze wu-haoze commented Feb 20, 2022

  • Add assertions in SmtCore that all case splits applying during push and pop contain only bound updates.
  • Due to this assertion, copying of the tableau state is no longer necessary. In particular, when backtracking, we just need to restore the variable bounds from the previous level and the other tableau state do not need to change.
  • Copying of the entire tableau state is used only for precision restoration.
  • Remove the VariableWatcher::notifyVariableValue() function, but instead get the variable assignment directly from the Tableau.

for ( unsigned i = 0; i < _n - _m; ++i )
{
unsigned variable = _nonBasicIndexToVariable[i];
updateVariableToComplyWithLowerBoundUpdate( variable,
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@guykatzz If I don't do this update, the Tableau invariant can be broken (some non-basic variable will go out of bound). Are there better solution than this?
The alternative would be to not call updateVariableToComplyWithLowerBoundUpdate() when _boundsValid is false in the "tightenLower/UpperBounds methods". But doing that seems to result in invariant being broken elsewhere.
I also tried throw InfeasibleQueryException() in those tightenbounds method once the bounds become invalid. But that is also problematic, because now this exception could be thrown in "popSplit()" method..

Copy link
Collaborator

Choose a reason for hiding this comment

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

I guess an alternative would be to store the variables' assignment as part of the stored state? And then have another invariant that says that a stored state is valid, as far as the NB assignments are concerned?

But why do you want to change this? I don't think it's that expensive, performance wise

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ah ok. I think I'll keep the current solution.

Copy link
Collaborator

@guykatzz guykatzz left a comment

Choose a reason for hiding this comment

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

See few comments inside

@@ -49,7 +50,8 @@ DnCWorker::DnCWorker( WorkerQueue *workload, std::shared_ptr<IEngine> engine,

// Obtain the current state of the engine
_initialState = std::make_shared<EngineState>();
_engine->storeState( *_initialState, true );
_engine->storeState( *_initialState,
TableauStateStorageLevel::STORE_ALL_TABLEAU_STATE );
Copy link
Collaborator

Choose a reason for hiding this comment

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

all -> entire?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

done

{
constraint->registerTableau( _tableau );
}

Copy link
Collaborator

Choose a reason for hiding this comment

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

remove empty line

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

done

return ( _gurobi == nullptr ) ?
_assignment.exists( variable )
: _gurobi->existsAssignment( Stringf( "x%u", variable ) );
if ( _gurobi == nullptr && _tableau != nullptr )
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is intended to give preference to Gurobi, right? So lets reorder:

if ( gurobi exists )
return gurobi value;

if ( tableu exists )
return tableu value

fail

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done. Yeah this reads much better..

for ( unsigned i = 0; i < _n - _m; ++i )
{
unsigned variable = _nonBasicIndexToVariable[i];
updateVariableToComplyWithLowerBoundUpdate( variable,
Copy link
Collaborator

Choose a reason for hiding this comment

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

I guess an alternative would be to store the variables' assignment as part of the stored state? And then have another invariant that says that a stored state is valid, as far as the NB assignments are concerned?

But why do you want to change this? I don't think it's that expensive, performance wise

@wu-haoze wu-haoze merged commit ac72848 into NeuralNetworkVerification:master Feb 21, 2022
wu-haoze added a commit that referenced this pull request Feb 21, 2022
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