Skip to content

Commit 52f7407

Browse files
authored
Proof Minimization (#890)
1 parent adc5b55 commit 52f7407

14 files changed

+625
-131
lines changed

src/configuration/GlobalConfiguration.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,8 @@ const bool GlobalConfiguration::WRITE_JSON_PROOF = false;
119119
const unsigned GlobalConfiguration::BACKWARD_BOUND_PROPAGATION_DEPTH = 3;
120120
const unsigned GlobalConfiguration::MAX_ROUNDS_OF_BACKWARD_ANALYSIS = 10;
121121

122-
const bool GlobalConfiguration::ANALYZE_PROOF_DEPENDENCIES = false;
123-
const bool GlobalConfiguration::MINIMIZE_PROOF_DEPENDENCIES = false;
122+
const bool GlobalConfiguration::ANALYZE_PROOF_DEPENDENCIES = true;
123+
const bool GlobalConfiguration::MINIMIZE_PROOF_DEPENDENCIES = true;
124124

125125
#ifdef ENABLE_GUROBI
126126
const unsigned GlobalConfiguration::GUROBI_NUMBER_OF_THREADS = 1;

src/engine/BoundManager.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ bool BoundManager::addLemmaExplanationAndTightenBound( unsigned var,
417417
const List<unsigned> &causingVars,
418418
Tightening::BoundType causingVarBound,
419419
PiecewiseLinearConstraint &constraint,
420-
bool /*isPhaseFixing*/,
420+
bool isPhaseFixing,
421421
double minTargetBound )
422422
{
423423
if ( !shouldProduceProofs() )
@@ -475,14 +475,18 @@ bool BoundManager::addLemmaExplanationAndTightenBound( unsigned var,
475475

476476

477477
_engine->getUNSATCertificateCurrentPointer()->addPLCLemma( PLCExpl );
478-
affectedVarBound == Tightening::UB ? _engine->updateGroundUpperBound( var, value )
479-
: _engine->updateGroundLowerBound( var, value );
480-
481-
PLCExpl->setToCheck();
482478

483479
// Add ground bound entry to the GroundBoundManager
480+
std::shared_ptr<GroundBoundManager::GroundBoundEntry> phaseFixingEntry =
481+
_engine->setGroundBoundFromLemma( PLCExpl, isPhaseFixing );
484482
resetExplanation( var, affectedVarBound );
485483

484+
if ( isPhaseFixing )
485+
{
486+
ASSERT( constraint.getPhaseFixingEntry() == nullptr );
487+
constraint.setPhaseFixingEntry( phaseFixingEntry );
488+
}
489+
486490
_engine->incNumOfLemmas();
487491
}
488492

src/engine/Engine.cpp

Lines changed: 216 additions & 48 deletions
Large diffs are not rendered by default.

src/engine/Engine.h

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "DegradationChecker.h"
2828
#include "DivideStrategy.h"
2929
#include "GlobalConfiguration.h"
30+
#include "GroundBoundManager.h"
3031
#include "GurobiWrapper.h"
3132
#include "IEngine.h"
3233
#include "IQuery.h"
@@ -254,16 +255,12 @@ class Engine
254255
*/
255256
bool shouldProduceProofs() const override;
256257

257-
/*
258-
Update the ground bounds
259-
*/
260-
void updateGroundUpperBound( unsigned var, double value ) override;
261-
void updateGroundLowerBound( unsigned var, double value ) override;
262-
263258
/*
264259
Return all ground bounds as a vector
265260
*/
266261
double getGroundBound( unsigned var, bool isUpper ) const override;
262+
std::shared_ptr<GroundBoundManager::GroundBoundEntry>
263+
getGroundBoundEntry( unsigned var, bool isUpper ) const override;
267264

268265
/*
269266
Get the current pointer of the UNSAT certificate
@@ -305,6 +302,12 @@ class Engine
305302
*/
306303
void incNumOfLemmas() override;
307304

305+
/*
306+
Add ground bound entry using a lemma
307+
*/
308+
std::shared_ptr<GroundBoundManager::GroundBoundEntry>
309+
setGroundBoundFromLemma( const std::shared_ptr<PLCLemma> lemma, bool isPhaseFixing ) override;
310+
308311
/*
309312
For debugging purpose
310313
*/
@@ -843,7 +846,7 @@ class Engine
843846
*/
844847

845848
bool _produceUNSATProofs;
846-
BoundManager _groundBoundManager;
849+
GroundBoundManager _groundBoundManager;
847850
UnsatCertificateNode *_UNSATCertificate;
848851
CVC4::context::CDO<UnsatCertificateNode *> *_UNSATCertificateCurrentPointer;
849852

@@ -911,6 +914,17 @@ class Engine
911914
*/
912915
void writeContradictionToCertificate( const Vector<double> &contradiction,
913916
unsigned infeasibleVar ) const;
917+
918+
919+
/*
920+
Analyse dependencies of an explanation vector, resulting in a list of necessary ground bounds
921+
*/
922+
Set<std::shared_ptr<GroundBoundManager::GroundBoundEntry>>
923+
analyseExplanationDependencies( const SparseUnsortedList &explanation,
924+
unsigned id,
925+
int explainedVar,
926+
bool isUpper,
927+
double targetBound );
914928
};
915929

916930
#endif // __Engine_h__

src/engine/GroundBoundManager.cpp

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
/********************* */
2+
/*! \file GroundBoundManager.cpp
3+
** \verbatim
4+
** Top contributors (to current version):
5+
** Idan Refaeli, Omri Isac
6+
** This file is part of the Marabou project.
7+
** Copyright (c) 2017-2025 by the authors listed in the file AUTHORS
8+
** in the top-level source directory) and their institutional affiliations.
9+
** All rights reserved. See the file COPYING in the top-level source
10+
** directory for licensing information.\endverbatim
11+
**
12+
** [[ Add lengthier description here ]]
13+
14+
**/
15+
16+
#include "GroundBoundManager.h"
17+
18+
#include "FloatUtils.h"
19+
20+
21+
GroundBoundManager::GroundBoundManager( CVC4::context::Context &ctx )
22+
: _context( ctx )
23+
, _size( 0 )
24+
, _upperGroundBounds( 0 )
25+
, _lowerGroundBounds( 0 )
26+
{
27+
_counter = new ( true ) CVC4::context::CDO<unsigned>( &_context, 0 );
28+
}
29+
30+
GroundBoundManager::~GroundBoundManager()
31+
{
32+
_counter->deleteSelf();
33+
for ( unsigned i = 0; i < _size; ++i )
34+
{
35+
_upperGroundBounds[i]->deleteSelf();
36+
_lowerGroundBounds[i]->deleteSelf();
37+
}
38+
}
39+
40+
void GroundBoundManager::initialize( unsigned size )
41+
{
42+
_counter->set( 0 );
43+
_size = size;
44+
45+
for ( unsigned i = 0; i < size; ++i )
46+
{
47+
_upperGroundBounds.append(
48+
new ( true ) CVC4::context::CDList<std::shared_ptr<GroundBoundEntry>>( &_context ) );
49+
_lowerGroundBounds.append(
50+
new ( true ) CVC4::context::CDList<std::shared_ptr<GroundBoundEntry>>( &_context ) );
51+
}
52+
}
53+
54+
std::shared_ptr<GroundBoundManager::GroundBoundEntry>
55+
GroundBoundManager::addGroundBound( unsigned index,
56+
double value,
57+
Tightening::BoundType boundType,
58+
bool isPhaseFixing )
59+
{
60+
const Vector<CVC4::context::CDList<std::shared_ptr<GroundBoundEntry>> *> &temp =
61+
boundType == Tightening::UB ? _upperGroundBounds : _lowerGroundBounds;
62+
63+
std::shared_ptr<GroundBoundEntry> groundBoundEntry(
64+
new GroundBoundEntry( _counter->get(), value, nullptr, isPhaseFixing ) );
65+
66+
if ( !temp[index]->empty() )
67+
{
68+
ASSERT( boundType == Tightening::UB ? FloatUtils::lte( value, temp[index]->back()->val )
69+
: FloatUtils::gte( value, temp[index]->back()->val ) )
70+
}
71+
72+
temp[index]->push_back( groundBoundEntry );
73+
_counter->set( _counter->get() + 1 );
74+
75+
return temp[index]->back();
76+
}
77+
78+
std::shared_ptr<GroundBoundManager::GroundBoundEntry>
79+
GroundBoundManager::addGroundBound( const std::shared_ptr<PLCLemma> &lemma, bool isPhaseFixing )
80+
{
81+
Tightening::BoundType isUpper = lemma->getAffectedVarBound();
82+
unsigned index = lemma->getAffectedVar();
83+
84+
const Vector<CVC4::context::CDList<std::shared_ptr<GroundBoundEntry>> *> &temp =
85+
isUpper == Tightening::UB ? _upperGroundBounds : _lowerGroundBounds;
86+
87+
std::shared_ptr<GroundBoundEntry> groundBoundEntry(
88+
new GroundBoundEntry( _counter->get(), lemma->getBound(), lemma, isPhaseFixing ) );
89+
90+
if ( !temp[index]->empty() )
91+
{
92+
ASSERT( isUpper == Tightening::UB
93+
? FloatUtils::lte( lemma->getBound(), temp[index]->back()->val )
94+
: FloatUtils::gte( lemma->getBound(), temp[index]->back()->val ) )
95+
}
96+
97+
temp[index]->push_back( groundBoundEntry );
98+
_counter->set( _counter->get() + 1 );
99+
100+
return temp[index]->back();
101+
}
102+
103+
double GroundBoundManager::getGroundBound( unsigned index, Tightening::BoundType boundType ) const
104+
{
105+
const Vector<CVC4::context::CDList<std::shared_ptr<GroundBoundEntry>> *> &temp =
106+
boundType == Tightening::UB ? _upperGroundBounds : _lowerGroundBounds;
107+
return temp[index]->back()->val;
108+
}
109+
110+
std::shared_ptr<GroundBoundManager::GroundBoundEntry>
111+
GroundBoundManager::getGroundBoundEntry( unsigned int index, Tightening::BoundType boundType ) const
112+
{
113+
const Vector<CVC4::context::CDList<std::shared_ptr<GroundBoundEntry>> *> &temp =
114+
boundType == Tightening::UB ? _upperGroundBounds : _lowerGroundBounds;
115+
return temp[index]->back();
116+
}
117+
118+
std::shared_ptr<GroundBoundManager::GroundBoundEntry>
119+
GroundBoundManager::getGroundBoundEntryUpToId( unsigned index,
120+
Tightening::BoundType boundType,
121+
unsigned id ) const
122+
{
123+
const Vector<CVC4::context::CDList<std::shared_ptr<GroundBoundEntry>> *> &temp =
124+
boundType == Tightening::UB ? _upperGroundBounds : _lowerGroundBounds;
125+
126+
if ( id == 0 )
127+
return ( *temp[index] )[0];
128+
129+
for ( int i = temp[index]->size() - 1; i >= 0; --i )
130+
{
131+
const std::shared_ptr<GroundBoundEntry> entry = ( *temp[index] )[i];
132+
if ( entry->id < id )
133+
return entry;
134+
}
135+
ASSERT( id <= 2 * temp.size() );
136+
return ( *temp[index] )[0];
137+
}
138+
139+
double GroundBoundManager::getGroundBoundUpToId( unsigned index,
140+
Tightening::BoundType boundType,
141+
unsigned id ) const
142+
{
143+
return getGroundBoundEntryUpToId( index, boundType, id )->val;
144+
}
145+
146+
Vector<double> GroundBoundManager::getAllGroundBounds( Tightening::BoundType boundType ) const
147+
{
148+
const Vector<CVC4::context::CDList<std::shared_ptr<GroundBoundEntry>> *> &temp =
149+
boundType == Tightening::UB ? _upperGroundBounds : _lowerGroundBounds;
150+
Vector<double> tops = Vector<double>( 0 );
151+
152+
for ( const auto &GBList : temp )
153+
tops.append( GBList->back()->val );
154+
155+
return tops;
156+
}
157+
158+
unsigned GroundBoundManager::getCounter() const
159+
{
160+
return _counter->get();
161+
}

src/engine/GroundBoundManager.h

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/********************* */
2+
/*! \file GroundBoundManager.h
3+
** \verbatim
4+
** Top contributors (to current version):
5+
** Idan Refaeli, Omri Isac
6+
** This file is part of the Marabou project.
7+
** Copyright (c) 2017-2025 by the authors listed in the file AUTHORS
8+
** in the top-level source directory) and their institutional affiliations.
9+
** All rights reserved. See the file COPYING in the top-level source
10+
** directory for licensing information.\endverbatim
11+
**
12+
** [[ Add lengthier description here ]]
13+
14+
**/
15+
16+
#ifndef __GroundBoundManager_h__
17+
#define __GroundBoundManager_h__
18+
19+
#include "PlcLemma.h"
20+
#include "Set.h"
21+
#include "Tightening.h"
22+
#include "Vector.h"
23+
#include "context/cdlist.h"
24+
#include "context/cdo.h"
25+
#include "context/context.h"
26+
27+
/*
28+
A class to manage all ground bounds updates
29+
*/
30+
class GroundBoundManager
31+
{
32+
public:
33+
/*
34+
A struct representing ground bounds, whose derivation cannot be explained using a single Farkas
35+
vector. Entries include bookkeeping of data used for proof minimization, such as a unique id
36+
and the lemma used for derivation
37+
*/
38+
struct GroundBoundEntry
39+
{
40+
GroundBoundEntry( unsigned id,
41+
double val,
42+
const std::shared_ptr<PLCLemma> &lemma,
43+
bool isPhaseFixing )
44+
: id( id )
45+
, val( val )
46+
, lemma( lemma )
47+
, isPhaseFixing( isPhaseFixing )
48+
{
49+
}
50+
unsigned id;
51+
double val;
52+
const std::shared_ptr<PLCLemma> lemma;
53+
bool isPhaseFixing; // Preparation for CDCL-based solving
54+
Set<std::shared_ptr<GroundBoundManager::GroundBoundEntry>> depList;
55+
};
56+
57+
GroundBoundManager( CVC4::context::Context &ctx );
58+
~GroundBoundManager();
59+
60+
/*
61+
Initialize internal data structures
62+
*/
63+
void initialize( unsigned size );
64+
65+
/*
66+
Update the ground bounds, manually or by learning a lemma
67+
*/
68+
std::shared_ptr<GroundBoundManager::GroundBoundEntry>
69+
addGroundBound( unsigned index,
70+
double value,
71+
Tightening::BoundType boundType,
72+
bool isPhaseFixing );
73+
74+
std::shared_ptr<GroundBoundManager::GroundBoundEntry>
75+
addGroundBound( const std::shared_ptr<PLCLemma> &lemma, bool isPhaseFixing );
76+
77+
/*
78+
Getters for ground bounds
79+
*/
80+
double getGroundBound( unsigned index, Tightening::BoundType boundType ) const;
81+
82+
std::shared_ptr<GroundBoundManager::GroundBoundEntry>
83+
getGroundBoundEntry( unsigned index, Tightening::BoundType boundType ) const;
84+
85+
std::shared_ptr<GroundBoundManager::GroundBoundEntry>
86+
getGroundBoundEntryUpToId( unsigned index, Tightening::BoundType boundType, unsigned id ) const;
87+
88+
double
89+
getGroundBoundUpToId( unsigned index, Tightening::BoundType boundType, unsigned id ) const;
90+
91+
Vector<double> getAllGroundBounds( Tightening::BoundType boundType ) const;
92+
93+
/*
94+
Get the current value of the unique id counter
95+
*/
96+
unsigned getCounter() const;
97+
98+
private:
99+
CVC4::context::CDO<unsigned> *_counter;
100+
101+
CVC4::context::Context &_context;
102+
unsigned _size;
103+
104+
Vector<CVC4::context::CDList<std::shared_ptr<GroundBoundEntry>> *> _upperGroundBounds;
105+
Vector<CVC4::context::CDList<std::shared_ptr<GroundBoundEntry>> *> _lowerGroundBounds;
106+
};
107+
108+
109+
#endif // __GroundBoundManager_h__

0 commit comments

Comments
 (0)