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

Bug fixes #77

Merged
merged 67 commits into from
Jul 22, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
97fa3eb
initial work on sparse matrix representation
GuyKatzHuji Jun 18, 2018
f67f40f
store/restore functionality
GuyKatzHuji Jun 18, 2018
9f1ad34
addLastRow functionality
GuyKatzHuji Jun 18, 2018
8315e89
getRow and getColumn
GuyKatzHuji Jun 18, 2018
9f96f81
column-merging functionality
GuyKatzHuji Jun 18, 2018
1ea9792
added an interface class
GuyKatzHuji Jun 19, 2018
1826116
introducing also sparse vectors
GuyKatzHuji Jun 19, 2018
a50b767
added addLastColumn functionality
GuyKatzHuji Jun 19, 2018
5394f30
another unittest
GuyKatzHuji Jun 19, 2018
c509909
get sparse columns/matrices in dense form
GuyKatzHuji Jun 19, 2018
66c00ce
WIP on storing the constraint matrix inside the tableau in sparse form
GuyKatzHuji Jun 19, 2018
b20cc6f
more WIP, fixed a few bugs, still have a couple of failing tests
GuyKatzHuji Jun 19, 2018
7f95cb1
fixed some test issues
GuyKatzHuji Jun 20, 2018
a90fd95
initialization
GuyKatzHuji Jun 20, 2018
dc2af7f
resize _a along with the rest
GuyKatzHuji Jun 20, 2018
4db0052
Merge branch 'master' into sparse_matrices
GuyKatzHuji Jul 8, 2018
f3683fb
sparse lu factors
GuyKatzHuji Jul 8, 2018
ea02f96
store also the transposed versions of F and V
GuyKatzHuji Jul 9, 2018
d3610b3
starting work on the sparse GE
GuyKatzHuji Jul 9, 2018
403decb
some work on changing the values within an existing sparse
GuyKatzHuji Jul 9, 2018
e05eb0e
refactoring and new functionality for CSRMatrix: any kind of
GuyKatzHuji Jul 10, 2018
2f3d16d
support for empty initialization and counting elements
GuyKatzHuji Jul 10, 2018
234b694
sparse GE is now working. minor bug fixes elsewhere
GuyKatzHuji Jul 10, 2018
36b9a60
compute Ft and Vt as part of the G-elimination process
GuyKatzHuji Jul 11, 2018
836d393
tests
GuyKatzHuji Jul 11, 2018
71b70c4
basis oracles can return also sparse columns, not just dense
GuyKatzHuji Jul 11, 2018
7408f3d
sparse LU factorization class
GuyKatzHuji Jul 11, 2018
f3b98ec
switch to using the sparse factorization in the engine/tableau
GuyKatzHuji Jul 11, 2018
64ae293
bug fix in mergeColumns, and nicer printing
GuyKatzHuji Jul 11, 2018
f583be0
bug fix
GuyKatzHuji Jul 11, 2018
d545f15
bug fix
GuyKatzHuji Jul 11, 2018
6120c31
bug fix: merging columns does not delete the actual column, just
GuyKatzHuji Jul 12, 2018
b667c26
configuration changes
GuyKatzHuji Jul 12, 2018
7364641
optimization: since the sparse columns of A are needed all the time,
GuyKatzHuji Jul 12, 2018
cb67ed9
a more efficient implementation of sparse vectors
GuyKatzHuji Jul 12, 2018
05e06de
comments and unit tests
GuyKatzHuji Jul 12, 2018
f0c9c68
cleanup
GuyKatzHuji Jul 12, 2018
ad79fac
Merge branch 'master' into sparse_matrices
GuyKatzHuji Jul 12, 2018
27b0f04
keep _A in dense column-major format, too, instead of repeatedly
GuyKatzHuji Jul 12, 2018
ad630e5
Merge branch 'master' into sparse_matrices
GuyKatzHuji Jul 12, 2018
7df63cd
bad deletes
GuyKatzHuji Jul 15, 2018
f3ab834
bug fix in test
GuyKatzHuji Jul 15, 2018
aa00bbc
bug fixes: relu constraint propagation, and the handling of merged
GuyKatzHuji Jul 15, 2018
b05229b
new test
GuyKatzHuji Jul 15, 2018
8421ff6
compute Ft incrementally, use it whenever sparse columns are required
GuyKatzHuji Jul 15, 2018
ce8968d
did the todo
GuyKatzHuji Jul 15, 2018
6da8e7f
valgrind fixes
GuyKatzHuji Jul 16, 2018
ab6e2a3
Merge branch 'master' into sparse_matrices
GuyKatzHuji Jul 16, 2018
1d42540
debugging
GuyKatzHuji Jul 16, 2018
089097e
un-initialized memory
GuyKatzHuji Jul 18, 2018
11bef7d
merge
GuyKatzHuji Jul 18, 2018
bca044d
cleanup
GuyKatzHuji Jul 18, 2018
518f157
fixing an issue with cost function degradation
GuyKatzHuji Jul 18, 2018
ee74206
Merge branch 'master' into sparse_matrices
GuyKatzHuji Jul 18, 2018
74d4648
reinstating the anti-looping trick
GuyKatzHuji Jul 18, 2018
4b2cb18
debug prints
GuyKatzHuji Jul 19, 2018
6a898f2
verify invariants
GuyKatzHuji Jul 19, 2018
72c2804
debug info for crash
GuyKatzHuji Jul 19, 2018
34eacff
fixing a numerical stability issue
guykatzz Jul 20, 2018
747297c
cleanup
guykatzz Jul 20, 2018
600339f
Merge branch 'master' into sparse_matrices
guykatzz Jul 20, 2018
7f50496
cleanup
guykatzz Jul 20, 2018
7e314e2
Merge branch 'master' into sparse_matrices
guykatzz Jul 21, 2018
45ef5c7
removing the code with the failing assertion
guykatzz Jul 22, 2018
0d187f8
weaken a couple of too-storng assertions
guykatzz Jul 22, 2018
d32f7cc
bug fix and some fine-tuning of PSE
guykatzz Jul 22, 2018
ee81a08
bug fix in LU factorization
guykatzz Jul 22, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/basis_factorization/GaussianEliminator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,18 @@ void GaussianEliminator::eliminate()
{
unsigned fColumnIndex = _luFactors->_P._columnOrdering[_eliminationStep];

/*
The pivot row is not eliminated per se, but it is excluded
from the active submatrix, so we adjust the element counters
*/
_numURowElements[_eliminationStep] = 0;
for ( unsigned uColumn = _eliminationStep; uColumn < _m; ++uColumn )
{
unsigned vColumn = _luFactors->_Q._rowOrdering[uColumn];
if ( !FloatUtils::isZero( _luFactors->_V[_vPivotRow*_m + vColumn] ) )
--_numUColumnElements[uColumn];
}

/*
Eliminate all entries below the pivot element U[k,k]
We know that V[_pivotRow, _pivotColumn] = U[k,k].
Expand Down
9 changes: 6 additions & 3 deletions src/engine/Engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,7 @@ void Engine::fixViolatedPlConstraintIfPossible()

_activeEntryStrategy->prePivotHook( _tableau, false );
_tableau->performDegeneratePivot();
_activeEntryStrategy->prePivotHook( _tableau, false );
_activeEntryStrategy->postPivotHook( _tableau, false );

ASSERT( !_tableau->isBasic( fix._variable ) );
_tableau->setNonBasicAssignment( fix._variable, fix._value, true );
Expand Down Expand Up @@ -817,7 +817,7 @@ void Engine::applySplit( const PiecewiseLinearCaseSplit &split )

_activeEntryStrategy->prePivotHook( _tableau, false );
_tableau->performDegeneratePivot();
_activeEntryStrategy->prePivotHook( _tableau, false );
_activeEntryStrategy->postPivotHook( _tableau, false );
}

if ( _tableau->isBasic( x2 ) )
Expand Down Expand Up @@ -856,13 +856,16 @@ void Engine::applySplit( const PiecewiseLinearCaseSplit &split )

_activeEntryStrategy->prePivotHook( _tableau, false );
_tableau->performDegeneratePivot();
_activeEntryStrategy->prePivotHook( _tableau, false );
_activeEntryStrategy->postPivotHook( _tableau, false );

}

// Both variables are now non-basic, so we can merge their columns
_tableau->mergeColumns( x1, x2 );
DEBUG( _tableau->verifyInvariants() );

// Reset the entry strategy
_activeEntryStrategy->initialize( _tableau );
}
else
{
Expand Down
14 changes: 9 additions & 5 deletions src/engine/PrecisionRestorer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,17 @@ void PrecisionRestorer::restorePrecision( IEngine &engine,

// At this point, the tableau has the appropriate dimensions. Restore the variable bounds
// and basic variables.
// Note that if column merging is enabled, the dimensions may not be precisely those before
// the resotration, because merging sometimes fails - in which case an equation is added. If
// we fail to restore the dimensions, we cannot restore the basics.

ASSERT( tableau.getN() == targetN );
ASSERT( tableau.getM() == targetM );
bool dimensionsRestored = ( tableau.getN() == targetN ) && ( tableau.getM() == targetM );

ASSERT( dimensionsRestored || GlobalConfiguration::USE_COLUMN_MERGING_EQUATIONS );

Set<unsigned> currentBasics = tableau.getBasicVariables();

if ( restoreBasics == RESTORE_BASICS )
if ( dimensionsRestored && restoreBasics == RESTORE_BASICS )
{
List<unsigned> shouldBeBasicList;
for ( const auto &basic : shouldBeBasic )
Expand Down Expand Up @@ -115,8 +119,8 @@ void PrecisionRestorer::restorePrecision( IEngine &engine,

DEBUG({
// Same dimensions
ASSERT( tableau.getN() == targetN );
ASSERT( tableau.getM() == targetM );
ASSERT( GlobalConfiguration::USE_COLUMN_MERGING_EQUATIONS || tableau.getN() == targetN );
ASSERT( GlobalConfiguration::USE_COLUMN_MERGING_EQUATIONS || tableau.getM() == targetM );

// Constraints should be in the same state before and after restoration
for ( const auto &pair : targetEngineState._plConstraintToState )
Expand Down
13 changes: 8 additions & 5 deletions src/engine/ProjectedSteepestEdge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ void ProjectedSteepestEdgeRule::resetReferenceSpace( const ITableau &tableau )
}

_iterationsUntilReset = GlobalConfiguration::PSE_ITERATIONS_BEFORE_RESET;
_errorInGamma = 0.0;

if ( _statistics )
_statistics->pseIncNumResetReferenceSpace();
Expand Down Expand Up @@ -145,7 +146,7 @@ bool ProjectedSteepestEdgeRule::select( ITableau &tableau, const Set<unsigned> &
unsigned bestCandidate = *it;
double gammaValue = _gamma[*it];
double bestValue =
!FloatUtils::isPositive( gammaValue ) ? 0 : ( costFunction[*it] * costFunction[*it] ) / _gamma[*it];
!FloatUtils::isPositive( gammaValue ) ? 0 : ( costFunction[*it] * costFunction[*it] ) / gammaValue;

++it;

Expand All @@ -154,7 +155,7 @@ bool ProjectedSteepestEdgeRule::select( ITableau &tableau, const Set<unsigned> &
unsigned contender = *it;
gammaValue = _gamma[*it];
double contenderValue =
!FloatUtils::isPositive( gammaValue ) ? 0 : ( costFunction[*it] * costFunction[*it] ) / _gamma[*it];
!FloatUtils::isPositive( gammaValue ) ? 0 : ( costFunction[*it] * costFunction[*it] ) / gammaValue;

if ( FloatUtils::gt( contenderValue, bestValue ) )
{
Expand Down Expand Up @@ -184,12 +185,14 @@ void ProjectedSteepestEdgeRule::prePivotHook( const ITableau &tableau, bool fake
}

// When this hook is called, the entering and leaving variables have
// already been determined. These are the actual varaibles, not the indices.
// already been determined.
unsigned entering = tableau.getEnteringVariable();
unsigned enteringIndex = tableau.variableToIndex( entering );
unsigned leaving = tableau.getLeavingVariable();
unsigned leavingIndex = tableau.variableToIndex( leaving );

ASSERT( entering != leaving );

const double *changeColumn = tableau.getChangeColumn();
const TableauRow &pivotRow = *tableau.getPivotRow();

Expand Down Expand Up @@ -222,7 +225,7 @@ void ProjectedSteepestEdgeRule::prePivotHook( const ITableau &tableau, bool fake
if ( i == enteringIndex )
continue;

if ( FloatUtils::isZero( pivotRow[i] ) )
if ( FloatUtils::isZero( pivotRow[i], 1e-9 ) )
continue;

r = pivotRow[i] / -changeColumn[leavingIndex];
Expand Down Expand Up @@ -279,7 +282,7 @@ void ProjectedSteepestEdgeRule::postPivotHook( const ITableau &tableau, bool fak

// If the iteration limit has been exhausted, reset the reference space
--_iterationsUntilReset;
if ( _iterationsUntilReset == 0 )
if ( _iterationsUntilReset <= 0 )
{
log( "PostPivotHook reseting ref space (iterations)" );
resetReferenceSpace( tableau );
Expand Down
2 changes: 1 addition & 1 deletion src/engine/ProjectedSteepestEdge.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ class ProjectedSteepestEdgeRule : public IProjectedSteepestEdgeRule
/*
Remaining iterations before resetting the reference space.
*/
unsigned _iterationsUntilReset;
int _iterationsUntilReset;

/*
The error in gamma compuated in the previous iteration.
Expand Down
62 changes: 31 additions & 31 deletions src/engine/Tableau.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1861,37 +1861,37 @@ void Tableau::updateAssignmentForPivot()

_basicAssignmentStatus = ITableau::BASIC_ASSIGNMENT_UPDATED;

// If the change ratio is 0, just maintain the current assignment
if ( FloatUtils::isZero( _changeRatio ) )
{
ASSERT( !performingFakePivot() );

DEBUG({
// This should only happen when the basic variable is pressed against
// one of its bounds
if ( !( _basicStatus[_leavingVariable] == Tableau::AT_UB ||
_basicStatus[_leavingVariable] == Tableau::AT_LB ||
_basicStatus[_leavingVariable] == Tableau::BETWEEN
) )
{
printf( "Assertion violation!\n" );
printf( "Basic (leaving) variable is: %u\n", _basicIndexToVariable[_leavingVariable] );
printf( "Basic assignment: %.10lf. Bounds: [%.10lf, %.10lf]\n",
_basicAssignment[_leavingVariable],
_lowerBounds[_basicIndexToVariable[_leavingVariable]],
_upperBounds[_basicIndexToVariable[_leavingVariable]] );
printf( "Basic status: %u\n", _basicStatus[_leavingVariable] );
printf( "leavingVariableIncreases = %s", _leavingVariableIncreases ? "yes" : "no" );
exit( 1 );
}
});

double basicAssignment = _basicAssignment[_leavingVariable];
double nonBasicAssignment = _nonBasicAssignment[_enteringVariable];
_basicAssignment[_leavingVariable] = nonBasicAssignment;
_nonBasicAssignment[_enteringVariable] = basicAssignment;
return;
}
// // If the change ratio is 0, just maintain the current assignment
// if ( FloatUtils::isZero( _changeRatio ) )
// {
// ASSERT( !performingFakePivot() );

// DEBUG({
// // This should only happen when the basic variable is pressed against
// // one of its bounds
// if ( !( _basicStatus[_leavingVariable] == Tableau::AT_UB ||
// _basicStatus[_leavingVariable] == Tableau::AT_LB ||
// _basicStatus[_leavingVariable] == Tableau::BETWEEN
// ) )
// {
// printf( "Assertion violation!\n" );
// printf( "Basic (leaving) variable is: %u\n", _basicIndexToVariable[_leavingVariable] );
// printf( "Basic assignment: %.10lf. Bounds: [%.10lf, %.10lf]\n",
// _basicAssignment[_leavingVariable],
// _lowerBounds[_basicIndexToVariable[_leavingVariable]],
// _upperBounds[_basicIndexToVariable[_leavingVariable]] );
// printf( "Basic status: %u\n", _basicStatus[_leavingVariable] );
// printf( "leavingVariableIncreases = %s", _leavingVariableIncreases ? "yes" : "no" );
// exit( 1 );
// }
// });

// double basicAssignment = _basicAssignment[_leavingVariable];
// double nonBasicAssignment = _nonBasicAssignment[_enteringVariable];
// _basicAssignment[_leavingVariable] = nonBasicAssignment;
// _nonBasicAssignment[_enteringVariable] = basicAssignment;
// return;
// }

if ( performingFakePivot() )
{
Expand Down