| 690 | } |
| 691 | |
| 692 | void MILPEncoder::encodeBilinearConstraint( GurobiWrapper &gurobi, |
| 693 | BilinearConstraint *bilinear, |
| 694 | bool relax ) |
| 695 | { |
| 696 | if ( relax ) |
| 697 | { |
| 698 | // Encode the DeepPoly abstraction |
| 699 | auto sourceVariables = bilinear->getBs(); |
| 700 | unsigned sourceVariable1 = sourceVariables[0]; |
| 701 | unsigned sourceVariable2 = sourceVariables[1]; |
| 702 | unsigned targetVariable = bilinear->getF(); |
| 703 | double sourceLb1 = _tableau.getLowerBound( sourceVariable1 ); |
| 704 | double sourceLb2 = _tableau.getLowerBound( sourceVariable2 ); |
| 705 | double sourceUb2 = _tableau.getUpperBound( sourceVariable2 ); |
| 706 | |
| 707 | List<GurobiWrapper::Term> terms; |
| 708 | terms.append( GurobiWrapper::Term( 1, Stringf( "x%u", targetVariable ) ) ); |
| 709 | terms.append( GurobiWrapper::Term( -sourceLb2, Stringf( "x%u", sourceVariable1 ) ) ); |
| 710 | terms.append( GurobiWrapper::Term( -sourceLb1, Stringf( "x%u", sourceVariable2 ) ) ); |
| 711 | gurobi.addGeqConstraint( terms, -sourceLb1 * sourceLb2 ); |
| 712 | |
| 713 | terms.clear(); |
| 714 | terms.append( GurobiWrapper::Term( 1, Stringf( "x%u", targetVariable ) ) ); |
| 715 | terms.append( GurobiWrapper::Term( -sourceUb2, Stringf( "x%u", sourceVariable1 ) ) ); |
| 716 | terms.append( GurobiWrapper::Term( -sourceLb1, Stringf( "x%u", sourceVariable2 ) ) ); |
| 717 | gurobi.addLeqConstraint( terms, -sourceLb1 * sourceUb2 ); |
| 718 | } |
| 719 | else |
| 720 | { |
| 721 | gurobi.nonConvex(); |
| 722 | auto bs = bilinear->getBs(); |
| 723 | ASSERT( bs.size() == 2 ); |
| 724 | auto f = bilinear->getF(); |
| 725 | gurobi.addBilinearConstraint( |
| 726 | Stringf( "x%u", bs[0] ), Stringf( "x%u", bs[1] ), Stringf( "x%u", f ) ); |
| 727 | return; |
| 728 | } |
| 729 | } |
| 730 | |
| 731 | void MILPEncoder::encodeRoundConstraint( GurobiWrapper &gurobi, RoundConstraint *round, bool relax ) |
| 732 | { |
nothing calls this directly
no test coverage detected