// Store all RHS values
sal_uInt32 nConstraints = maConstraints.size();
m_aConstrRHS.realloc(nConstraints);
// collect all dependent cells
ScSolverCellHashMap aCellsHash;
aCellsHash[maObjective].reserve( nVariables + 1 ); // objective function
for (constauto& rConstr : maConstraints)
{
table::CellAddress aCellAddr = rConstr.Left;
aCellsHash[aCellAddr].reserve( nVariables + 1 ); // constraints: left hand side
if ( rConstr.Right >>= aCellAddr )
aCellsHash[aCellAddr].reserve( nVariables + 1 ); // constraints: right hand side
}
// set all variables to zero //! store old values? //! use old values as initial values? for ( constauto& rVarCell : aVariableCells )
{
SolverComponent::SetValue( mxDoc, rVarCell, 0.0 );
}
// read initial values from all dependent cells for ( auto& rEntry : aCellsHash )
{ double fValue = SolverComponent::GetValue( mxDoc, rEntry.first );
rEntry.second.push_back( fValue ); // store as first element, as-is
}
// loop through variables for ( constauto& rVarCell : aVariableCells )
{
SolverComponent::SetValue( mxDoc, rVarCell, 1.0 ); // set to 1 to examine influence
// read value change from all dependent cells for ( auto& rEntry : aCellsHash )
{ double fChanged = SolverComponent::GetValue( mxDoc, rEntry.first ); double fInitial = rEntry.second.front();
rEntry.second.push_back( fChanged - fInitial );
}
SolverComponent::SetValue( mxDoc, rVarCell, 2.0 ); // minimal test for linearity
for ( constauto& rEntry : aCellsHash )
{ double fInitial = rEntry.second.front(); double fCoeff = rEntry.second.back(); // last appended: coefficient for this variable double fTwo = SolverComponent::GetValue( mxDoc, rEntry.first );
bool bLinear = rtl::math::approxEqual( fTwo, fInitial + 2.0 * fCoeff ) ||
rtl::math::approxEqual( fInitial, fTwo - 2.0 * fCoeff ); // second comparison is needed in case fTwo is zero if ( !bLinear )
maStatus = SolverComponent::GetResourceString( RID_ERROR_NONLINEAR );
}
SolverComponent::SetValue( mxDoc, rVarCell, 0.0 ); // set back to zero for examining next variable
}
// Initially set to false because getting the report might fail
m_aSensitivityReport.HasReport = false;
// Get sensitivity report if the user set SensitivityReport parameter to true if (mbGenSensitivity)
{ // Get sensitivity data about the objective function // LpSolve returns an interval for the coefficients of the objective function // instead of returning an allowable increase/decrease (which is what we want to show // in the sensitivity report; so we these from/till values are converted into increase // and decrease values later)
REAL* pObjFrom = nullptr;
REAL* pObjTill = nullptr; bool bHasObjReport = false;
bHasObjReport = get_ptr_sensitivity_obj(lp, &pObjFrom, &pObjTill);
// Get sensitivity data about constraints // Similarly to the objective function, the sensitivity values returned for the // constraints are in the form from/till and are later converted to increase and // decrease values later
REAL* pConstrValue = nullptr;
REAL* pConstrDual = nullptr;
REAL* pConstrFrom = nullptr;
REAL* pConstrTill = nullptr; bool bHasConstrReport = false;
bHasConstrReport = get_ptr_sensitivity_rhs(lp, &pConstrDual, &pConstrFrom, &pConstrTill);
// When successful, store sensitivity data in the solver component if (bHasObjReport && bHasConstrReport)
{
m_aSensitivityReport.HasReport = true;
m_aObjDecrease.realloc(nVariables);
m_aObjIncrease.realloc(nVariables); double* pObjDecrease = m_aObjDecrease.getArray(); double* pObjIncrease = m_aObjIncrease.getArray(); for (size_t i = 0; i < nVariables; i++)
{ // Allowed decrease. Note that the indices of rObjCoeff are offset by 1 // because of the objective function if (static_cast<bool>(is_infinite(lp, pObjFrom[i])))
pObjDecrease[i] = get_infinite(lp); else
pObjDecrease[i] = rObjCoeff[i + 1] - pObjFrom[i];
// Save objective coefficients for the sensitivity report double* pObjCoefficients(newdouble[nVariables]); for (size_t i = 0; i < nVariables; i++)
pObjCoefficients[i] = rObjCoeff[i + 1];
m_aObjCoefficients.realloc(nVariables);
std::copy_n(pObjCoefficients, nVariables, m_aObjCoefficients.getArray());
// The reduced costs are in pConstrDual after the constraints double* pObjRedCost(newdouble[nVariables]); for (size_t i = 0; i < nVariables; i++)
pObjRedCost[i] = pConstrDual[nConstraints + i];
m_aObjRedCost.realloc(nVariables);
std::copy_n(pObjRedCost, nVariables, m_aObjRedCost.getArray());
// Final value of constraints
get_ptr_constraints(lp, &pConstrValue);
m_aConstrValue.realloc(nConstraints);
std::copy_n(pConstrValue, nConstraints, m_aConstrValue.getArray());
// The RHS contains information for each constraint
m_aConstrDual.realloc(nConstraints);
m_aConstrDecrease.realloc(nConstraints);
m_aConstrIncrease.realloc(nConstraints);
std::copy_n(pConstrDual, nConstraints, m_aConstrDual.getArray()); double* pConstrDecrease = m_aConstrDecrease.getArray(); double* pConstrIncrease = m_aConstrIncrease.getArray();
for (sal_uInt32 i = 0; i < nConstraints; i++)
{ // Allowed decrease
pConstrDecrease[i] = m_aConstrRHS[i] - pConstrFrom[i]; if (static_cast<bool>(is_infinite(lp, pConstrFrom[i]))
&& maConstraints[i].Operator == sheet::SolverConstraintOperator_LESS_EQUAL)
pConstrDecrease[i] = m_aConstrRHS[i] - m_aConstrValue[i];
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.15Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-09-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.