Skip to content

Commit

Permalink
Sparse FT factorization, and other optimizations
Browse files Browse the repository at this point in the history
* initial work

* cleanup

* introducing an Options singleton

* WIP

* boost

download the tar file

* a basic executable, capable of taking an NNET file from the command
line and solving it

* get number of inputs and outputs

* input query supports inputs and outputs

* basic working example of taking as input a network and a property
file, and solving the resulting query

* regress makefile

* fix regress makefile

* when SAT, print inputs and outputs

* added support for properties with equations of the form x1 + x2 >= 5
(as opposed to just bounds on single variables)

* cleanup

* support for input/output variabels also in the preprocessor

* special treatment for properties that include bounds, not just equations

* some easy optimizations

* cleanup: remove the basis factorization flag

* preparing the infrastructure for sparse FT

* more infrastructure

* reset H (the equivalent of emptying the eta queue)

* use H as a marker for when the explicit basis is avaialble

* first version of sparse FT (not tested yet)

* FT unit tests are passing

* include also the sparse bases

* computing the explicit basis stored in the FT factorization (for
debugging purposes)

* debugging: comptue and dump the explicit basis

* a mechanism for fixing the permutation matrix P used for comuting L,
and separating it from the P used for U

* WIP

* refactorization

* cleanup

* cleanup
  • Loading branch information
guykatzz authored Aug 22, 2018
1 parent d39692d commit 1055801
Show file tree
Hide file tree
Showing 43 changed files with 1,828 additions and 197 deletions.
11 changes: 11 additions & 0 deletions src/basis_factorization/BasisFactorizationFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,31 @@
#include "ForrestTomlinFactorization.h"
#include "GlobalConfiguration.h"
#include "LUFactorization.h"
#include "SparseFTFactorization.h"
#include "SparseLUFactorization.h"

IBasisFactorization *BasisFactorizationFactory::createBasisFactorization( unsigned basisSize, const IBasisFactorization::BasisColumnOracle &basisColumnOracle )
{
// LU
if ( GlobalConfiguration::BASIS_FACTORIZATION_TYPE ==
GlobalConfiguration::LU_FACTORIZATION )
return new LUFactorization( basisSize, basisColumnOracle );

// Sparse LU
if ( GlobalConfiguration::BASIS_FACTORIZATION_TYPE ==
GlobalConfiguration::SPARSE_LU_FACTORIZATION )
return new SparseLUFactorization( basisSize, basisColumnOracle );

// FT
else if ( GlobalConfiguration::BASIS_FACTORIZATION_TYPE ==
GlobalConfiguration::FORREST_TOMLIN_FACTORIZATION )
return new ForrestTomlinFactorization( basisSize, basisColumnOracle );

// Sparse FT
else if ( GlobalConfiguration::BASIS_FACTORIZATION_TYPE ==
GlobalConfiguration::SPARSE_FORREST_TOMLIN_FACTORIZATION )
return new SparseFTFactorization( basisSize, basisColumnOracle );

throw BasisFactorizationError( BasisFactorizationError::UNKNOWN_BASIS_FACTORIZATION_TYPE );
}

Expand Down
2 changes: 2 additions & 0 deletions src/basis_factorization/CSRMatrix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,8 @@ void CSRMatrix::storeIntoOther( SparseMatrix *other ) const

void CSRMatrix::getRow( unsigned row, SparseVector *result ) const
{
ASSERT( row < _m );

/*
Elements of row j are stored in _A and _JA between
indices _IA[j] and _IA[j+1] - 1.
Expand Down
3 changes: 2 additions & 1 deletion src/basis_factorization/EtaMatrix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,9 @@ void EtaMatrix::dump() const
printf( "\n" );
}

void EtaMatrix::toMatrix( double *A )
void EtaMatrix::toMatrix( double *A ) const
{
std::fill_n( A, _m * _m, 0.0 );
for ( unsigned i = 0; i < _m; ++i )
{
A[i * _m + i] = 1.;
Expand Down
2 changes: 1 addition & 1 deletion src/basis_factorization/EtaMatrix.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class EtaMatrix

~EtaMatrix();
void dump() const;
void toMatrix( double *A );
void toMatrix( double *A ) const;

void resetToIdentity();

Expand Down
6 changes: 4 additions & 2 deletions src/basis_factorization/ForrestTomlinFactorization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,9 @@ ForrestTomlinFactorization::~ForrestTomlinFactorization()
_A.clear();
}

void ForrestTomlinFactorization::pushEtaMatrix( unsigned columnIndex, const double *column )
void ForrestTomlinFactorization::updateToAdjacentBasis( unsigned columnIndex,
const double *changeColumn,
const double */* newColumn */ )
{
// Pushing an eta matrix invalidates the explicit basis
_explicitBasisAvailable = false;
Expand All @@ -164,7 +166,7 @@ void ForrestTomlinFactorization::pushEtaMatrix( unsigned columnIndex, const doub
it is not upper triangular.
*/
for ( unsigned i = 0; i < _m; ++i )
_workVector[i] = column[_invQ._rowOrdering[i]];
_workVector[i] = changeColumn[_invQ._rowOrdering[i]];

for ( unsigned i = 0; i < _m; ++i )
{
Expand Down
15 changes: 11 additions & 4 deletions src/basis_factorization/ForrestTomlinFactorization.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,18 @@ class ForrestTomlinFactorization : public IBasisFactorization

/*
Inform the basis factorization that the basis has been changed
by a pivot step. This results is an eta matrix by which the
basis is multiplied on the right. This eta matrix is represented
by the column index and column vector.
by a pivot step. The parameters are:
1. The index of the column in question
2. The changeColumn -- this is the so called Eta matrix column
3. The new explicit column that is being added to the basis
A basis factorization may make use of just one of the two last
parameters.
*/
void pushEtaMatrix( unsigned columnIndex, const double *column );
void updateToAdjacentBasis( unsigned columnIndex,
const double *changeColumn,
const double */* newColumn */ );

/*
Perform a forward transformation, i.e. find x such that Bx = y.
Expand Down
38 changes: 12 additions & 26 deletions src/basis_factorization/IBasisFactorization.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,26 @@ class IBasisFactorization
};

IBasisFactorization( const BasisColumnOracle &basisColumnOracle )
: _factorizationEnabled( true )
, _basisColumnOracle( &basisColumnOracle )
: _basisColumnOracle( &basisColumnOracle )
{
}

virtual ~IBasisFactorization() {}

/*
Inform the basis factorization that the basis has been changed
by a pivot step. This results is an eta matrix by which the
basis is multiplied on the right. This eta matrix is represented
by the column index and column vector.
by a pivot step. The parameters are:
1. The index of the column in question
2. The changeColumn -- this is the so called Eta matrix column
3. The new explicit column that is being added to the basis
A basis factorization may make use of just one of the two last
parameters.
*/
virtual void pushEtaMatrix( unsigned columnIndex, const double *column ) = 0;
virtual void updateToAdjacentBasis( unsigned columnIndex,
const double *changeColumn,
const double *newColumn ) = 0;

/*
Perform a forward transformation, i.e. find x such that Bx = y.
Expand All @@ -74,19 +80,6 @@ class IBasisFactorization
virtual void setBasis( const double *B ) = 0;
virtual void obtainFreshBasis() = 0;

/*
Control/check whether factorization is enabled.
*/
bool factorizationEnabled() const
{
return _factorizationEnabled;
}

void toggleFactorization( bool value )
{
_factorizationEnabled = value;
}

/*
Return true iff the basis matrix B is explicitly available.
*/
Expand All @@ -113,13 +106,6 @@ class IBasisFactorization
*/
virtual void dump() const {};

private:
/*
A flag that controls whether factorization is enabled or
disabled.
*/
bool _factorizationEnabled;

protected:
const BasisColumnOracle *_basisColumnOracle;
};
Expand Down
8 changes: 5 additions & 3 deletions src/basis_factorization/LUFactorization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,14 @@ const List<EtaMatrix *> LUFactorization::getEtas() const
return _etas;
}

void LUFactorization::pushEtaMatrix( unsigned columnIndex, const double *column )
void LUFactorization::updateToAdjacentBasis( unsigned columnIndex,
const double *changeColumn,
const double */* newColumn */ )
{
EtaMatrix *matrix = new EtaMatrix( _m, columnIndex, column );
EtaMatrix *matrix = new EtaMatrix( _m, columnIndex, changeColumn );
_etas.append( matrix );

if ( ( _etas.size() > GlobalConfiguration::REFACTORIZATION_THRESHOLD ) && factorizationEnabled() )
if ( _etas.size() > GlobalConfiguration::REFACTORIZATION_THRESHOLD )
{
log( "Number of etas exceeds threshold. Refactoring basis\n" );
obtainFreshBasis();
Expand Down
17 changes: 12 additions & 5 deletions src/basis_factorization/LUFactorization.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,19 @@ class LUFactorization : public IBasisFactorization
void freeIfNeeded();

/*
Adds a new eta matrix to the basis factorization. The matrix is
the identity matrix with the specified column replaced by the one
provided. If the number of stored eta matrices exceeds a certain
threshold, re-factorization may occur.
Inform the basis factorization that the basis has been changed
by a pivot step. The parameters are:
1. The index of the column in question
2. The changeColumn -- this is the so called Eta matrix column
3. The new explicit column that is being added to the basis
A basis factorization may make use of just one of the two last
parameters.
*/
void pushEtaMatrix( unsigned columnIndex, const double *column );
void updateToAdjacentBasis( unsigned columnIndex,
const double *changeColumn,
const double */* newColumn */ );

/*
Perform a forward transformation, i.e. find x such that x = inv(B) * y,
Expand Down
2 changes: 2 additions & 0 deletions src/basis_factorization/Sources.mk
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ SOURCES += \
LUFactorization.cpp \
LUFactors.cpp \
PermutationMatrix.cpp \
SparseEtaMatrix.cpp \
SparseFTFactorization.cpp \
SparseGaussianEliminator.cpp \
SparseLUFactorization.cpp \
SparseLUFactors.cpp \
Expand Down
147 changes: 147 additions & 0 deletions src/basis_factorization/SparseEtaMatrix.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/******************** */
/*! \file SparseEtaMatrix.cpp
** \verbatim
** Top contributors (to current version):
** Guy Katz
** This file is part of the Marabou project.
** Copyright (c) 2016-2017 by the authors listed in the file AUTHORS
** in the top-level source directory) and their institutional affiliations.
** All rights reserved. See the file COPYING in the top-level source
** directory for licensing information.\endverbatim
**/

#include "BasisFactorizationError.h"
#include "SparseEtaMatrix.h"
#include "FloatUtils.h"

#include <cstdio>
#include <cstdlib>
#include <cstring>

SparseEtaMatrix::SparseEtaMatrix( unsigned m, unsigned index, const double *column )
: _m( m )
, _columnIndex( index )
, _sparseColumn( column, m )
{
_diagonalElement = column[index];
}

SparseEtaMatrix::SparseEtaMatrix( unsigned m, unsigned index )
: _m( m )
, _columnIndex( index )
, _sparseColumn( m )
{
_sparseColumn.commitChange( index, 1 );
_sparseColumn.executeChanges();
_diagonalElement = 1;
}

SparseEtaMatrix::SparseEtaMatrix( const SparseEtaMatrix &other )
: _m( other._m )
, _columnIndex( other._columnIndex )
, _sparseColumn( other._sparseColumn )
, _diagonalElement( other._diagonalElement )
{
}

SparseEtaMatrix &SparseEtaMatrix::operator=( const SparseEtaMatrix &other )
{
_m = other._m;
_columnIndex = other._columnIndex;
_sparseColumn = other._sparseColumn;
_diagonalElement = other._diagonalElement;

return *this;
}

SparseEtaMatrix::~SparseEtaMatrix()
{
}

void SparseEtaMatrix::dump() const
{
printf( "Dumping eta matrix\n" );
printf( "\tm = %u. column index = %u\n", _m, _columnIndex );
printf( "\tcolumn: " );
for ( unsigned i = 0; i < _sparseColumn.getNnz(); ++i )
printf( "\t\tEntry %u: %lf", _sparseColumn.getIndexOfEntry( i ), _sparseColumn.getValueOfEntry( i ) );
printf( "\n" );
}

bool SparseEtaMatrix::operator==( const SparseEtaMatrix &other ) const
{
if ( _m != other._m )
return false;

if ( _columnIndex != other._columnIndex )
return false;

printf( "Error! SparseEtaMatrix::operator== not yet supported!\n" );
exit( 1 );

return true;
}

void SparseEtaMatrix::resetToIdentity()
{
_sparseColumn.clear();
_sparseColumn.commitChange( _columnIndex, 1 );
_sparseColumn.executeChanges();
_diagonalElement = 1;
}

void SparseEtaMatrix::commitChange( unsigned index, double newValue )
{
_sparseColumn.commitChange( index, newValue );
}

void SparseEtaMatrix::executeChanges()
{
_sparseColumn.executeChanges();
_diagonalElement = _sparseColumn.get( _columnIndex );
}

void SparseEtaMatrix::dumpDenseTransposed() const
{
printf( "Dumping transposed eta matrix:\n" );
for ( unsigned i = 0; i < _m; ++i )
{
printf( "\t" );
if ( i != _columnIndex )
{
// Print identity row
for ( unsigned j = 0; j < _m; ++j )
{
printf( "%5u ", j == i ? 1 : 0 );
}
}
else
{
for ( unsigned j = 0; j < _m; ++j )
{
printf( "%5.2lf ", _sparseColumn.get( j ) );
}
}
printf( "\n" );
}
printf( "\n" );
}

void SparseEtaMatrix::toMatrix( double *A ) const
{
std::fill_n( A, _m * _m, 0.0 );

for ( unsigned i = 0; i < _m; ++i )
A[i * _m + i] = 1;

for ( unsigned i = 0; i < _m; ++i )
A[i*_m + _columnIndex] = _sparseColumn.get( i );
}

//
// Local Variables:
// compile-command: "make -C ../.. "
// tags-file-name: "../../TAGS"
// c-basic-offset: 4
// End:
//
Loading

0 comments on commit 1055801

Please sign in to comment.