@@ -26,6 +26,7 @@ AletheProofWriter::AletheProofWriter( unsigned explanationSize,
2626 , _n( upperBounds.size() )
2727 , _m( explanationSize )
2828 , _stepCounter( 1 )
29+ , _varToPLC()
2930{
3031 for ( unsigned i = 0 ; i < _n; ++i )
3132 {
@@ -36,6 +37,10 @@ AletheProofWriter::AletheProofWriter( unsigned explanationSize,
3637 _currentUpperBounds[i].push ( std::tuple<int , double >( 0 , upperBounds[i] ) );
3738 }
3839
40+ for ( const auto &plc : problemConstraints )
41+ for ( const auto var : plc->getParticipatingVariables () )
42+ _varToPLC.insert ( var, plc );
43+
3944 // Write only necessary lines upon initialization
4045 writeTableauAssumptions ();
4146}
@@ -295,9 +300,9 @@ void AletheProofWriter::applyContradiction( const UnsatCertificateNode *node )
295300 " :rule la_generic :args " + farkasArgs;
296301
297302 String res = String ( " ( step res" + std::to_string ( node->getId () ) ) + " (cl " +
298- getPathClause ( node ) + " ) :rule resolution :premises (" +
299- getPathResSteps ( node ) + " t " + std::to_string ( node-> getId ( ) ) + " " +
300- farkasParticipants + " ) ) \n " ;
303+ getNegatedSplitsClause ( getPathSplits ( node ) ) + " ) :rule resolution :premises (" +
304+ getSplitsResSteps ( getPathSplits ( node ) ) + " t " +
305+ std::to_string ( node-> getId () ) + " " + farkasParticipants + " ) ) \n " ;
301306
302307
303308 _proof.append ( { laGeneric, res } );
@@ -334,34 +339,33 @@ void AletheProofWriter::concludeChildrenUnsat( const UnsatCertificateNode *node,
334339 ASSERT ( childrenIndices.size () == 2 )
335340 PiecewiseLinearCaseSplit firstChildSplit = node->getChildren ().front ()->getSplit ();
336341 String resLine = String ( " ( step res" + std::to_string ( node->getId () ) + " (cl " ) +
337- getPathClause ( node ) + " ) :rule resolution :premises ( split" +
342+ getNegatedSplitsClause ( getPathSplits ( node ) ) +
343+ " ) :rule resolution :premises ( split" +
338344 std::to_string ( node->getChildren ().front ()->getSplitNum () ) + " res" +
339345 std::to_string ( childrenIndices.front () ) + " res" +
340346 std::to_string ( childrenIndices.back () ) + " ) )\n " ;
341347
342348 _proof.append ( resLine );
343349}
344350
345- String AletheProofWriter::getPathClause ( const UnsatCertificateNode *node )
351+ String
352+ AletheProofWriter::getNegatedSplitsClause ( const List<PiecewiseLinearCaseSplit> &splits ) const
346353{
347- if ( !node-> getParent () )
354+ if ( splits. empty () )
348355 return " " ;
349356
350357 String clause = " " ;
351- const UnsatCertificateNode *cur = node;
352- while ( !cur->getSplit ().getBoundTightenings ().empty () )
358+ for ( const auto &split : splits )
353359 {
354360 clause += " ( not ( and " ;
355- const PiecewiseLinearCaseSplit &headSplit = cur->getSplit ();
356- for ( const auto bound : headSplit.getBoundTightenings () )
361+ for ( const auto bound : split.getBoundTightenings () )
357362 clause += getBoundAsClause ( bound );
358- cur = cur->getParent ();
359363 clause += " ) )" ;
360364 }
361365 return clause;
362366}
363367
364- String AletheProofWriter::getBoundAsClause ( const Tightening &bound )
368+ String AletheProofWriter::getBoundAsClause ( const Tightening &bound ) const
365369{
366370 if ( bound._type == Tightening::UB )
367371 return String ( " ( <= x" + std::to_string ( bound._variable ) + " " ) +
@@ -372,7 +376,7 @@ String AletheProofWriter::getBoundAsClause( const Tightening &bound )
372376}
373377
374378
375- String AletheProofWriter::getSplitAsClause ( const PiecewiseLinearCaseSplit &split )
379+ String AletheProofWriter::getSplitAsClause ( const PiecewiseLinearCaseSplit &split ) const
376380{
377381 ASSERT ( split.getEquations ().empty () );
378382 String clause = " ( and " ;
@@ -383,38 +387,51 @@ String AletheProofWriter::getSplitAsClause( const PiecewiseLinearCaseSplit &spli
383387 return clause;
384388}
385389
386- String AletheProofWriter::getSplitsAsClause ( const List<PiecewiseLinearCaseSplit> &splits )
390+ String AletheProofWriter::getSplitsAsClause ( const List<PiecewiseLinearCaseSplit> &splits ) const
387391{
388392 String clause = " " ;
389393 for ( const auto &split : splits )
390394 clause += getSplitAsClause ( split );
391395 return clause;
392396}
393397
394- bool AletheProofWriter::isSplitActive ( const PiecewiseLinearCaseSplit &split )
398+ bool AletheProofWriter::isSplitActive ( const PiecewiseLinearCaseSplit &split ) const
395399{
396400 ASSERT ( split.getEquations ().empty () )
397401 return split.getBoundTightenings ().back ()._type == Tightening::LB ||
398402 split.getBoundTightenings ().front ()._type == Tightening::LB;
399403}
400404
401- String AletheProofWriter::getPathResSteps ( const UnsatCertificateNode *node )
405+ List<PiecewiseLinearCaseSplit>
406+ AletheProofWriter::getPathSplits ( const UnsatCertificateNode *node ) const
402407{
403- if ( !node->getParent () )
408+ List<PiecewiseLinearCaseSplit> pathSplits = List<PiecewiseLinearCaseSplit>();
409+ const UnsatCertificateNode *cur = node;
410+ while ( cur && !cur->getSplit ().getBoundTightenings ().empty () )
411+ {
412+ pathSplits.append ( cur->getSplit () );
413+ cur = cur->getParent ();
414+ }
415+
416+ return pathSplits;
417+ }
418+
419+ String AletheProofWriter::getSplitsResSteps ( const List<PiecewiseLinearCaseSplit> &splits ) const
420+ {
421+ if ( splits.empty () )
404422 return " " ;
405423
406424 String resSteps = " " ;
407- const UnsatCertificateNode *cur = node;
408- while ( !cur->getSplit ().getBoundTightenings ().empty () )
425+ for ( const auto &split : splits )
409426 {
410- String currentStep = " split " + std::to_string ( cur-> getSplitNum () );
411- const PiecewiseLinearCaseSplit &headSplit = cur-> getSplit ();
412- String isActive = isSplitActive ( headSplit ) ? " a " : " i " ;
413-
414- for ( unsigned i = 0 ; i < headSplit. getBoundTightenings (). size (); ++i )
415- currentStep += String ( " split " + std::to_string ( cur-> getSplitNum () ) + " _ " ) +
416- isActive + std::to_string ( i );
417- cur = cur-> getParent ( );
427+ unsigned splitNum =
428+ _varToPLC[split. getBoundTightenings (). front (). _variable ]-> getTableauAuxVars (). front ();
429+ String currentStep = " split " + std::to_string ( splitNum ) ;
430+ String isActive = isSplitActive ( split ) ? " a " : " i " ;
431+
432+ for ( unsigned i = 0 ; i < split. getBoundTightenings (). size (); ++i )
433+ currentStep += String ( " split " + std::to_string ( splitNum ) + " _ " ) + isActive +
434+ std::to_string ( i );
418435 // Add steps to the left
419436 resSteps = currentStep + resSteps;
420437 }
@@ -489,11 +506,10 @@ List<String> AletheProofWriter::applyReluLemma( const UnsatCertificateNode *node
489506 String laGeneric = String ( " ( step farkasLem" ) + id + " " + farkasClause +
490507 " :rule la_generic :args " + farkasArgs;
491508
492- String res = String ( " ( step causResLem" ) + id + " (cl " + getPathClause ( node ) + causeBound +
493- " ) :rule resolution :premises (" + getPathResSteps ( node ) + " farkasLem" + id +
494- " " + farkasParticipants + " ) ) \n " ;
495-
496- // TODO consider writing the causing var ground bound
509+ String res = String ( " ( step causResLem" ) + id + " (cl " +
510+ getNegatedSplitsClause ( getPathSplits ( node ) ) + causeBound +
511+ " ) :rule resolution :premises (" + getSplitsResSteps ( getPathSplits ( node ) ) +
512+ " farkasLem" + id + " " + farkasParticipants + " ) ) \n " ;
497513
498514 unsigned b = plc->getB ();
499515 unsigned f = plc->getF ();
@@ -527,29 +543,31 @@ List<String> AletheProofWriter::applyReluLemma( const UnsatCertificateNode *node
527543 {
528544 matched = true ;
529545 String splitrule = causingVar == f ? " _i1" : " _i0" ;
530- proofRuleRes = String ( " ( step resLem" ) + id + " ( cl " + getPathClause ( node ) +
531- conclusion + " ) :rule resolution :premises ( causResLem" + id +
532- " tautSplit" + id + " split" + identifier + splitrule + " split" +
533- identifier + " split" + identifier + " _a1 ) ) \n " ;
546+ proofRuleRes = String ( " ( step resLem" ) + id + " ( cl " +
547+ getNegatedSplitsClause ( getPathSplits ( node ) ) + conclusion +
548+ " ) :rule resolution :premises ( causResLem" + id + " tautSplit" + id +
549+ " split" + identifier + splitrule + " split" + identifier + " split" +
550+ identifier + " _a1 ) ) \n " ;
534551 }
535552 else if ( causingVar == b && causingVarBound == Tightening::LB && affectedVar == aux &&
536553 affectedVarBound == Tightening::UB && targetBound == 0 )
537554 {
538555 matched = true ;
539- proofRuleRes = String ( " ( step resLem" ) + id + " ( cl " + getPathClause ( node ) +
540- conclusion + " ) :rule resolution :premises ( causResLem" + id + " equiv" +
541- identifier + " _a0) ) \n " ;
556+ proofRuleRes = String ( " ( step resLem" ) + id + " ( cl " +
557+ getNegatedSplitsClause ( getPathSplits ( node ) ) + conclusion +
558+ " ) :rule resolution :premises ( causResLem" + id + " equiv" + identifier +
559+ " _a0) ) \n " ;
542560 }
543561 // If lb of aux is positive, then ub of f is 0
544562 else if ( causingVar == aux && causingVarBound == Tightening::LB && affectedVar == f &&
545563 affectedVarBound == Tightening::UB && targetBound > 0 )
546564 {
547565 matched = true ;
548566
549- proofRuleRes = String ( " ( step resLem " ) + id + " ( cl " + getPathClause ( node ) +
550- conclusion + " ) :rule resolution :premises ( causResLem " + id +
551- " tautSplit " + id + " split " + identifier + " _a1 split " + identifier +
552- " split" + identifier + " _i1 ) ) \n " ;
567+ proofRuleRes =
568+ String ( " ( step resLem " ) + id + " ( cl " + getNegatedSplitsClause ( getPathSplits ( node ) ) +
569+ conclusion + " ) :rule resolution :premises ( causResLem " + id + " tautSplit " + id +
570+ " split " + identifier + " _a1 split " + identifier + " split" + identifier + " _i1 ) ) \n " ;
553571 }
554572
555573 // If ub of b is non positive, then ub of f is 0
@@ -558,37 +576,40 @@ List<String> AletheProofWriter::applyReluLemma( const UnsatCertificateNode *node
558576 {
559577 matched = true ;
560578
561- proofRuleRes = String ( " ( step resLem " ) + id + " ( cl " + getPathClause ( node ) +
562- conclusion + " ) :rule resolution :premises ( causResLem " + id +
563- " tautSplit " + id + " split " + identifier + " _a0 split " + identifier +
564- " split" + identifier + " _i1 ) ) \n " ;
579+ proofRuleRes =
580+ String ( " ( step resLem " ) + id + " ( cl " + getNegatedSplitsClause ( getPathSplits ( node ) ) +
581+ conclusion + " ) :rule resolution :premises ( causResLem " + id + " tautSplit " + id +
582+ " split " + identifier + " _a0 split " + identifier + " split" + identifier + " _i1 ) ) \n " ;
565583 }
566584 // Propagate 0 ub from f to b
567585 else if ( causingVar == f && causingVarBound == Tightening::UB && affectedVar == b &&
568586 affectedVarBound == Tightening::UB && targetBound == 0 )
569587 {
570588 matched = true ;
571- getPathClause ( node ) + conclusion + proofRuleRes =
572- String ( " ( step resLem" ) + id + " ( cl " +
573- " ) :rule resolution :premises ( causResLem" + id + " equiv" + identifier + " _i1) ) \n " ;
589+ proofRuleRes = String ( " ( step resLem" ) + id + " ( cl " +
590+ getNegatedSplitsClause ( getPathSplits ( node ) ) + conclusion +
591+ " ) :rule resolution :premises ( causResLem" + id + " equiv" + identifier +
592+ " _i1) ) \n " ;
574593 }
575594 else if ( causingVar == b && causingVarBound == Tightening::UB && affectedVar == f &&
576595 affectedVarBound == Tightening::UB && targetBound == 0 )
577596 {
578597 matched = true ;
579- proofRuleRes = String ( " ( step resLem" ) + id + " ( cl " + getPathClause ( node ) +
580- conclusion + " ) :rule resolution :premises ( causResLem" + id + " equiv" +
581- identifier + " _i0) ) \n " ;
598+ proofRuleRes = String ( " ( step resLem" ) + id + " ( cl " +
599+ getNegatedSplitsClause ( getPathSplits ( node ) ) + conclusion +
600+ " ) :rule resolution :premises ( causResLem" + id + " equiv" + identifier +
601+ " _i0) ) \n " ;
582602 }
583603 // If ub of aux is 0, then lb of b is 0
584604 else if ( causingVar == aux && causingVarBound == Tightening::UB && affectedVar == b &&
585605 affectedVarBound == Tightening::LB && targetBound == 0 )
586606
587607 {
588608 matched = true ;
589- proofRuleRes = String ( " ( step resLem" ) + id + " ( cl " + getPathClause ( node ) +
590- conclusion + " ) :rule resolution :premises ( causResLem" + id + " equiv" +
591- identifier + " _a1) ) \n " ;
609+ proofRuleRes = String ( " ( step resLem" ) + id + " ( cl " +
610+ getNegatedSplitsClause ( getPathSplits ( node ) ) + conclusion +
611+ " ) :rule resolution :premises ( causResLem" + id + " equiv" + identifier +
612+ " _a1) ) \n " ;
592613 }
593614 // If lb of b is negative x, then ub of aux is -x
594615 else if ( causingVar == b && causingVarBound == Tightening::LB && affectedVar == aux &&
@@ -618,8 +639,9 @@ List<String> AletheProofWriter::applyReluLemma( const UnsatCertificateNode *node
618639 proofRule += String ( " ( step aFarkasLem" ) + id + " " + subFarkasClause +
619640 " ) :rule la_generic :args (1 1 -1 1 -1) )\n " ;
620641
621- proofRuleRes += String ( " ( step resLem" ) + id + " ( cl " + getPathClause ( node ) +
622- conclusion + " ) :rule resolution :premises ( causResLem" + id + " e" +
642+ proofRuleRes += String ( " ( step resLem" ) + id + " ( cl " +
643+ getNegatedSplitsClause ( getPathSplits ( node ) ) + conclusion +
644+ " ) :rule resolution :premises ( causResLem" + id + " e" +
623645 std::to_string ( identifierInt - ( _n - _m ) ) + " l" + identifier +
624646 " aFarkasLem" + id + " tautSplit" + id + " split" + identifier +
625647 " _a1 split" + identifier + " split" + identifier + " _i1 ) ) \n " ;
@@ -652,8 +674,9 @@ List<String> AletheProofWriter::applyReluLemma( const UnsatCertificateNode *node
652674 proofRule += String ( " ( step aFarkasLem" ) + id + " " + subFarkasClause +
653675 " ) :rule la_generic :args (1 1 -1 1 1) )\n " ;
654676
655- proofRuleRes += String ( " ( step resLem" ) + id + " ( cl " + getPathClause ( node ) +
656- conclusion + " ) :rule resolution :premises ( causResLem" + id + " e" +
677+ proofRuleRes += String ( " ( step resLem" ) + id + " ( cl " +
678+ getNegatedSplitsClause ( getPathSplits ( node ) ) + conclusion +
679+ " ) :rule resolution :premises ( causResLem" + id + " e" +
657680 std::to_string ( identifierInt - ( _n - _m ) ) + " u" + identifier +
658681 " aFarkasLem" + id + " tautSplit" + id + " split" + identifier +
659682 " _a1 split" + identifier + " split" + identifier + " _i1 ) ) \n " ;
@@ -679,7 +702,7 @@ List<String> AletheProofWriter::applyReluLemma( const UnsatCertificateNode *node
679702}
680703
681704void AletheProofWriter::linearCombinationMpq ( const std::vector<mpq_t > &explainedRow,
682- const SparseUnsortedList &expl )
705+ const SparseUnsortedList &expl ) const
683706{
684707 SparseUnsortedList tableauRow ( _n );
685708 for ( const auto &entry : expl )
@@ -789,7 +812,7 @@ void AletheProofWriter::farkasStrings( const SparseUnsortedList &expl,
789812}
790813
791814
792- String AletheProofWriter::convertTableauAssumptionToClause ( unsigned index )
815+ String AletheProofWriter::convertTableauAssumptionToClause ( unsigned index ) const
793816{
794817 String assumption ( _tableauAssumptions[index] );
795818 unsigned begin = assumption.find ( " =" );
@@ -800,7 +823,7 @@ String AletheProofWriter::convertTableauAssumptionToClause( unsigned index )
800823void AletheProofWriter::writeDelegatedLeaf ( const UnsatCertificateNode *node )
801824{
802825 String proofHole = String ( " ( step res" + std::to_string ( node->getId () ) ) + " (cl " +
803- getPathClause ( node ) + " ) :rule hole ) \n " ;
826+ getNegatedSplitsClause ( getPathSplits ( node ) ) + " ) :rule hole ) \n " ;
804827 _proof.append ( proofHole );
805828}
806829
0 commit comments