View | Details | Raw Unified | Return to issue 118160
Collapse All | Expand All

(-)a/sccomp/source/solver/makefile.mk (-1 / +1 lines)
Lines 56-62 Link Here
56
                $(CPPULIB)          \
56
                $(CPPULIB)          \
57
                $(SALLIB)           \
57
                $(SALLIB)           \
58
                $(TOOLSLIB)         \
58
                $(TOOLSLIB)         \
59
                $(LPSOLVELIB)
59
                CoinMP.lib
60
60
61
SHL1DEPN=       makefile.mk
61
SHL1DEPN=       makefile.mk
62
SHL1DEF=        $(MISC)$/$(SHL1TARGET).def
62
SHL1DEF=        $(MISC)$/$(SHL1TARGET).def
(-)a/sccomp/source/solver/solver.cxx (-71 / +107 lines)
Lines 25-36 Link Here
25
 *
25
 *
26
 ************************************************************************/
26
 ************************************************************************/
27
27
28
#undef LANGUAGE_NONE
28
#include <coinmp/CoinMP.h>
29
#define WINAPI __stdcall
30
#define LoadInverseLib FALSE
31
#define LoadLanguageLib FALSE
32
#include <lpsolve/lp_lib.h>
33
#undef LANGUAGE_NONE
34
29
35
#include "solver.hxx"
30
#include "solver.hxx"
36
#include "solver.hrc"
31
#include "solver.hrc"
Lines 314-325 Link Here
314
    maStatus = OUString();
309
    maStatus = OUString();
315
    mbSuccess = false;
310
    mbSuccess = false;
316
311
317
    if ( mnEpsilonLevel < EPS_TIGHT || mnEpsilonLevel > EPS_BAGGY )
318
    {
319
        maStatus = lcl_GetResourceString( RID_ERROR_EPSILONLEVEL );
320
        return;
321
    }
322
323
    xModel->lockControllers();
312
    xModel->lockControllers();
324
313
325
    // collect variables in vector (?)
314
    // collect variables in vector (?)
Lines 398-426 Link Here
398
        return;
387
        return;
399
388
400
    //
389
    //
401
    // build lp_solve model
390
    // build parameter arrays for CoinMP
402
    //
391
    //
403
392
404
    lprec* lp = make_lp( 0, nVariables );
405
    if ( !lp )
406
        return;
407
408
    set_outputfile( lp, const_cast<char*>( "" ) );  // no output
409
410
    // set objective function
393
    // set objective function
411
394
412
    const std::vector<double>& rObjCoeff = aCellsHash[maObjective];
395
    const std::vector<double>& rObjCoeff = aCellsHash[maObjective];
413
    REAL* pObjVal = new REAL[nVariables+1];
396
    double* pObjectCoeffs = new double[nVariables];
414
    pObjVal[0] = 0.0;                           // ignored
415
    for (nVar=0; nVar<nVariables; nVar++)
397
    for (nVar=0; nVar<nVariables; nVar++)
416
        pObjVal[nVar+1] = rObjCoeff[nVar+1];
398
        pObjectCoeffs[nVar] = rObjCoeff[nVar+1];
417
    set_obj_fn( lp, pObjVal );
399
    double nObjectConst = rObjCoeff[0];             // constant term of objective
418
    delete[] pObjVal;
419
    set_rh( lp, 0, rObjCoeff[0] );              // constant term of objective
420
400
421
    // add rows
401
    // add rows
422
402
423
    set_add_rowmode(lp, TRUE);
403
    size_t nRows = maConstraints.getLength();
404
    size_t nCompSize = nVariables * nRows;
405
    double* pCompMatrix = new double[nCompSize];    // first collect all coefficients, row-wise
406
    for (size_t i=0; i<nCompSize; i++)
407
        pCompMatrix[i] = 0.0;
408
409
    double* pRHS = new double[nRows];
410
    char* pRowType = new char[nRows];
411
    for (size_t i=0; i<nRows; i++)
412
    {
413
        pRHS[i] = 0.0;
414
        pRowType[i] = 'N';
415
    }
424
416
425
    for (sal_Int32 nConstrPos = 0; nConstrPos < maConstraints.getLength(); ++nConstrPos)
417
    for (sal_Int32 nConstrPos = 0; nConstrPos < maConstraints.getLength(); ++nConstrPos)
426
    {
418
    {
Lines 442-451 Link Here
442
            table::CellAddress aLeftAddr = maConstraints[nConstrPos].Left;
434
            table::CellAddress aLeftAddr = maConstraints[nConstrPos].Left;
443
435
444
            const std::vector<double>& rLeftCoeff = aCellsHash[aLeftAddr];
436
            const std::vector<double>& rLeftCoeff = aCellsHash[aLeftAddr];
445
            REAL* pValues = new REAL[nVariables+1];
437
            double* pValues = &pCompMatrix[nConstrPos * nVariables];
446
            pValues[0] = 0.0;                               // ignored?
447
            for (nVar=0; nVar<nVariables; nVar++)
438
            for (nVar=0; nVar<nVariables; nVar++)
448
                pValues[nVar+1] = rLeftCoeff[nVar+1];
439
                pValues[nVar] = rLeftCoeff[nVar+1];
449
440
450
            // if left hand cell has a constant term, put into rhs value
441
            // if left hand cell has a constant term, put into rhs value
451
            double fRightValue = -rLeftCoeff[0];
442
            double fRightValue = -rLeftCoeff[0];
Lines 455-495 Link Here
455
                const std::vector<double>& rRightCoeff = aCellsHash[aRightAddr];
446
                const std::vector<double>& rRightCoeff = aCellsHash[aRightAddr];
456
                // modify pValues with rhs coefficients
447
                // modify pValues with rhs coefficients
457
                for (nVar=0; nVar<nVariables; nVar++)
448
                for (nVar=0; nVar<nVariables; nVar++)
458
                    pValues[nVar+1] -= rRightCoeff[nVar+1];
449
                    pValues[nVar] -= rRightCoeff[nVar+1];
459
450
460
                fRightValue += rRightCoeff[0];      // constant term
451
                fRightValue += rRightCoeff[0];      // constant term
461
            }
452
            }
462
            else
453
            else
463
                fRightValue += fDirectValue;
454
                fRightValue += fDirectValue;
464
455
465
            int nConstrType = LE;
466
            switch ( eOp )
456
            switch ( eOp )
467
            {
457
            {
468
                case sheet::SolverConstraintOperator_LESS_EQUAL:    nConstrType = LE; break;
458
                case sheet::SolverConstraintOperator_LESS_EQUAL:    pRowType[nConstrPos] = 'L'; break;
469
                case sheet::SolverConstraintOperator_GREATER_EQUAL: nConstrType = GE; break;
459
                case sheet::SolverConstraintOperator_GREATER_EQUAL: pRowType[nConstrPos] = 'G'; break;
470
                case sheet::SolverConstraintOperator_EQUAL:         nConstrType = EQ; break;
460
                case sheet::SolverConstraintOperator_EQUAL:         pRowType[nConstrPos] = 'E'; break;
471
                default:
461
                default:
472
                    OSL_ENSURE( false, "unexpected enum type" );
462
                    OSL_ENSURE( false, "unexpected enum type" );
473
            }
463
            }
474
            add_constraint( lp, pValues, nConstrType, fRightValue );
464
            pRHS[nConstrPos] = fRightValue;
475
476
            delete[] pValues;
477
        }
465
        }
478
    }
466
    }
479
467
480
    set_add_rowmode(lp, FALSE);
468
    // Find non-zero coefficients, column-wise
469
470
    int* pMatrixBegin = new int[nVariables+1];
471
    int* pMatrixCount = new int[nVariables];
472
    double* pMatrix = new double[nCompSize];    // not always completely used
473
    int* pMatrixIndex = new int[nCompSize];
474
    int nMatrixPos = 0;
475
    for (nVar=0; nVar<nVariables; nVar++)
476
    {
477
        int nBegin = nMatrixPos;
478
        for (size_t nRow=0; nRow<nRows; nRow++)
479
        {
480
            double fCoeff = pCompMatrix[ nRow * nVariables + nVar ];    // row-wise
481
            if ( fCoeff != 0.0 )
482
            {
483
                pMatrix[nMatrixPos] = fCoeff;
484
                pMatrixIndex[nMatrixPos] = nRow;
485
                ++nMatrixPos;
486
            }
487
        }
488
        pMatrixBegin[nVar] = nBegin;
489
        pMatrixCount[nVar] = nMatrixPos - nBegin;
490
    }
491
    pMatrixBegin[nVariables] = nMatrixPos;
492
    delete[] pCompMatrix;
493
    pCompMatrix = NULL;
481
494
482
    // apply settings to all variables
495
    // apply settings to all variables
483
496
497
    double* pLowerBounds = new double[nVariables];
498
    double* pUpperBounds = new double[nVariables];
484
    for (nVar=0; nVar<nVariables; nVar++)
499
    for (nVar=0; nVar<nVariables; nVar++)
485
    {
500
    {
486
        if ( !mbNonNegative )
501
        pLowerBounds[nVar] = mbNonNegative ? 0.0 : -DBL_MAX;
487
            set_unbounded(lp, nVar+1);          // allow negative (default is non-negative)
502
        pUpperBounds[nVar] = DBL_MAX;
488
                                                //! collect bounds from constraints?
503
489
        if ( mbInteger )
504
        // bounds could possibly be further restricted from single-cell constraints
490
            set_int(lp, nVar+1, TRUE);
491
    }
505
    }
492
506
507
    char* pColType = new char[nVariables];
508
    for (nVar=0; nVar<nVariables; nVar++)
509
        pColType[nVar] = mbInteger ? 'I' : 'C';
510
493
    // apply single-var integer constraints
511
    // apply single-var integer constraints
494
512
495
    for (sal_Int32 nConstrPos = 0; nConstrPos < maConstraints.getLength(); ++nConstrPos)
513
    for (sal_Int32 nConstrPos = 0; nConstrPos < maConstraints.getLength(); ++nConstrPos)
Lines 504-554 Link Here
504
                if ( AddressEqual( aVariableCells[nVar], aLeftAddr ) )
522
                if ( AddressEqual( aVariableCells[nVar], aLeftAddr ) )
505
                {
523
                {
506
                    if ( eOp == sheet::SolverConstraintOperator_INTEGER )
524
                    if ( eOp == sheet::SolverConstraintOperator_INTEGER )
507
                        set_int(lp, nVar+1, TRUE);
525
                        pColType[nVar] = 'I';
508
                    else
526
                    else
509
                        set_binary(lp, nVar+1, TRUE);
527
                    {
528
                        pColType[nVar] = 'B';
529
                        pLowerBounds[nVar] = 0.0;
530
                        pUpperBounds[nVar] = 1.0;
531
                    }
510
                }
532
                }
511
        }
533
        }
512
    }
534
    }
513
535
514
    if ( mbMaximize )
536
    int nObjectSense = mbMaximize ? SOLV_OBJSENS_MAX : SOLV_OBJSENS_MIN;
515
        set_maxim(lp);
516
    else
517
        set_minim(lp);
518
537
519
    if ( !mbLimitBBDepth )
538
    HPROB hProb = CoinCreateProblem("");
520
        set_bb_depthlimit( lp, 0 );
539
    int nResult = CoinLoadProblem( hProb, nVariables, nRows, nMatrixPos, 0,
540
                    nObjectSense, nObjectConst, pObjectCoeffs,
541
                    pLowerBounds, pUpperBounds, pRowType, pRHS, NULL,
542
                    pMatrixBegin, pMatrixCount, pMatrixIndex, pMatrix,
543
                    NULL, NULL, NULL );
544
    nResult = CoinLoadInteger( hProb, pColType );
521
545
522
    set_epslevel( lp, mnEpsilonLevel );
546
    delete[] pColType;
523
    set_timeout( lp, mnTimeout );
547
    delete[] pMatrixIndex;
548
    delete[] pMatrix;
549
    delete[] pMatrixCount;
550
    delete[] pMatrixBegin;
551
    delete[] pUpperBounds;
552
    delete[] pLowerBounds;
553
    delete[] pRowType;
554
    delete[] pRHS;
555
    delete[] pObjectCoeffs;
556
557
    CoinSetRealOption( hProb, COIN_REAL_MAXSECONDS, mnTimeout );
558
    CoinSetRealOption( hProb, COIN_REAL_MIPMAXSEC, mnTimeout );
559
560
    // TODO: handle (or remove) settings: epsilon, B&B depth
524
561
525
    // solve model
562
    // solve model
526
563
527
    int nResult = ::solve( lp );
564
    nResult = CoinCheckProblem( hProb );
565
    nResult = CoinOptimizeProblem( hProb, 0 );
528
566
529
    mbSuccess = ( nResult == OPTIMAL );
567
    mbSuccess = ( nResult == SOLV_CALL_SUCCESS );
530
    if ( mbSuccess )
568
    if ( mbSuccess )
531
    {
569
    {
532
        // get solution
570
        // get solution
533
571
534
        maSolution.realloc( nVariables );
572
        maSolution.realloc( nVariables );
573
        CoinGetSolutionValues( hProb, maSolution.getArray(), NULL, NULL, NULL );
574
        mfResultValue = CoinGetObjectValue( hProb );
575
    }
576
    else
577
    {
578
        int nSolutionStatus = CoinGetSolutionStatus( hProb );
579
        if ( nSolutionStatus == 1 )
580
            maStatus = lcl_GetResourceString( RID_ERROR_INFEASIBLE );
581
        else if ( nSolutionStatus == 2 )
582
            maStatus = lcl_GetResourceString( RID_ERROR_UNBOUNDED );
583
        // TODO: detect timeout condition and report as RID_ERROR_TIMEOUT
584
        // (currently reported as infeasible)
585
    }
535
586
536
        REAL* pResultVar = NULL;
587
    CoinUnloadProblem( hProb );
537
        get_ptr_variables( lp, &pResultVar );
538
        for (nVar=0; nVar<nVariables; nVar++)
539
            maSolution[nVar] = pResultVar[nVar];
540
541
        mfResultValue = get_objective( lp );
542
    }
543
    else if ( nResult == INFEASIBLE )
544
        maStatus = lcl_GetResourceString( RID_ERROR_INFEASIBLE );
545
    else if ( nResult == UNBOUNDED )
546
        maStatus = lcl_GetResourceString( RID_ERROR_UNBOUNDED );
547
    else if ( nResult == TIMEOUT || nResult == SUBOPTIMAL )
548
        maStatus = lcl_GetResourceString( RID_ERROR_TIMEOUT );
549
    // SUBOPTIMAL is assumed to be caused by a timeout, and reported as an error
550
551
    delete_lp( lp );
552
}
588
}
553
589
554
// -------------------------------------------------------------------------
590
// -------------------------------------------------------------------------

Return to issue 118160