The Lpsolve solver and the CoinMP solver are both used for the same thing: a linear model, with optional integer variables by branch and bound. CoinMP (CLP plus CBC) is the more capable and better maintained of the two, so the lp_solve one adds a second bundled dependency and a parallel copy of the solver code for no capability the other lacks. Remove the LpsolveSolver component, the bundled lp_solve external (and its colamd dependency, which only lp_solve used), and all the build, configure, packaging and license references to them. A document may still name com.sun.star.comp.Calc.LpsolveSolver as its engine. SolverSettings now reads that name as the CoinMP solver, which solves the same model, so such documents keep working. The Calc solver test that exercised the engine now uses CoinMP. Its knapsack model has a single optimal total value of 6987, which fills the weight capacity of 1000 exactly and which CoinMP finds. The lp_solve run had returned a suboptimal 6981, so the test now expects the true optimum. The build setup changes only take effect after re-running autogen. Signed-off-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> Change-Id: Ia14d8c491779873da6b0157aa524056275adf8f5 Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/3810 Reviewed-by: Miklos Vajna <vmiklos@collabora.com> Tested-by: Jenkins CPCI <releng@collaboraoffice.com> (cherry picked from commit e77738a7ca7d44fd9d1f852e26d46e3a6d60467b) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/208038 Tested-by: Jenkins Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
308 lines
12 KiB
C++
308 lines
12 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <utility>
|
|
#include <variant>
|
|
#include <rtl/ustring.hxx>
|
|
#include <com/sun/star/beans/PropertyValue.hpp>
|
|
|
|
#include "document.hxx"
|
|
#include <docsh.hxx>
|
|
|
|
namespace sc
|
|
{
|
|
// These values are MS compatible
|
|
enum ObjectiveType
|
|
{
|
|
OT_MAXIMIZE = 1,
|
|
OT_MINIMIZE = 2,
|
|
OT_VALUE = 3
|
|
};
|
|
|
|
enum SolverParameter
|
|
{
|
|
SP_OBJ_CELL, // Objective cell
|
|
SP_OBJ_TYPE, // Objective type (max, min, value)
|
|
SP_OBJ_VAL, // Value (used when objective is of type "value")
|
|
SP_VAR_CELLS, // Variable cells
|
|
SP_CONSTR_COUNT, // Number of constraints (MSO only)
|
|
SP_LO_ENGINE, // Engine name used in LO
|
|
SP_MS_ENGINE, // Engine ID used in MSO
|
|
SP_INTEGER, // Assume all variables are integer (0: no, 1: yes)
|
|
// CoinMP and SwarmSolver
|
|
SP_NON_NEGATIVE, // Assume non negativity (1: yes, 2: no)
|
|
SP_EPSILON_LEVEL, // Epsilon level
|
|
SP_LIMIT_BBDEPTH, // Branch and bound depth
|
|
SP_TIMEOUT, // Time limit to return a solution
|
|
SP_ALGORITHM, // Algorithm used by the SwarmSolver (1, 2 or 3)
|
|
// Engine options common for DEPS and SCO
|
|
SP_SWARM_SIZE, // Size of Swarm
|
|
SP_LEARNING_CYCLES, // Learning Cycles
|
|
SP_GUESS_VARIABLE_RANGE, // Variable Bounds Guessing
|
|
SP_VARIABLE_RANGE_THRESHOLD, // Variable Bounds Threshold (when guessing)
|
|
SP_ACR_COMPARATOR, // Use ACR Comparator (instead of BCH)
|
|
SP_RND_STARTING_POINT, // Use Random starting point
|
|
SP_STRONGER_PRNG, // Use a stronger random generator (slower)
|
|
SP_STAGNATION_LIMIT, // Stagnation Limit
|
|
SP_STAGNATION_TOLERANCE, // Stagnation Tolerance
|
|
SP_ENHANCED_STATUS, // Show enhanced solver status
|
|
// DEPS Options
|
|
SP_AGENT_SWITCH_RATE, // Agent Switch Rate (DE Probability)
|
|
SP_SCALING_MIN, // DE: Min Scaling Factor (0-1.2)
|
|
SP_SCALING_MAX, // DE: Max Scaling Factor (0-1.2)
|
|
SP_CROSSOVER_PROB, // DE: Crossover Probability (0-1)
|
|
SP_COGNITIVE_CONST, // Cognitive Constant
|
|
SP_SOCIAL_CONST, // Social Constant
|
|
SP_CONSTRICTION_COEFF, // PS: Constriction Coefficient
|
|
SP_MUTATION_PROB, // Mutation Probability (0-0.005)
|
|
// SCO Options
|
|
SP_LIBRARY_SIZE, // Size of library
|
|
};
|
|
|
|
// Starts at 1 to maintain MS compatibility
|
|
enum ConstraintOperator
|
|
{
|
|
CO_LESS_EQUAL = 1,
|
|
CO_EQUAL = 2,
|
|
CO_GREATER_EQUAL = 3,
|
|
CO_INTEGER = 4,
|
|
CO_BINARY = 5
|
|
};
|
|
|
|
// Parts of a constraint
|
|
enum ConstraintPart
|
|
{
|
|
CP_LEFT_HAND_SIDE,
|
|
CP_OPERATOR,
|
|
CP_RIGHT_HAND_SIDE
|
|
};
|
|
|
|
// Stores the information of a single constraint (condition)
|
|
struct ModelConstraint
|
|
{
|
|
OUString aLeftStr;
|
|
ConstraintOperator nOperator;
|
|
OUString aRightStr;
|
|
|
|
ModelConstraint()
|
|
: nOperator(CO_LESS_EQUAL)
|
|
{
|
|
}
|
|
bool IsDefault() const
|
|
{
|
|
return aLeftStr.isEmpty() && aRightStr.isEmpty() && nOperator == CO_LESS_EQUAL;
|
|
}
|
|
};
|
|
|
|
/* Class SolverSettings
|
|
*
|
|
* This class is used to load/save and manipulate solver settings in a Calc tab.
|
|
*
|
|
* During initialization, (see Initialize() method) all settings stored in the tab are loaded onto
|
|
* the object. Settings that are not defined use default values.
|
|
*
|
|
* Read/Write methods are private and are used internally to load/write solver settings from
|
|
* named ranges associated with the sheet.
|
|
*
|
|
* Get/Set methods are public methods used to change object properties (they do not save data
|
|
* to the file).
|
|
*
|
|
* The method SaveSolverSettings() is used to create the named ranges containing the current
|
|
* property values into the file.
|
|
*
|
|
*/
|
|
|
|
class SolverSettings
|
|
{
|
|
private:
|
|
ScTable& m_rTable;
|
|
ScDocument& m_rDoc;
|
|
ScDocShell* m_pDocShell;
|
|
|
|
// Used to read/write the named ranges in the tab
|
|
ScRangeName* m_pRangeName;
|
|
|
|
OUString m_sObjCell;
|
|
ObjectiveType m_eObjType;
|
|
OUString m_sObjVal;
|
|
OUString m_sVariableCells;
|
|
OUString m_sLOEngineName;
|
|
OUString m_sMSEngineId;
|
|
|
|
// Solver engine options
|
|
OUString m_sInteger;
|
|
OUString m_sNonNegative;
|
|
OUString m_sEpsilonLevel;
|
|
OUString m_sLimitBBDepth;
|
|
OUString m_sTimeout;
|
|
OUString m_sAlgorithm;
|
|
// DEPS and SCO
|
|
OUString m_sSwarmSize;
|
|
OUString m_sLearningCycles;
|
|
OUString m_sGuessVariableRange;
|
|
OUString m_sVariableRangeThreshold;
|
|
OUString m_sUseACRComparator;
|
|
OUString m_sUseRandomStartingPoint;
|
|
OUString m_sUseStrongerPRNG;
|
|
OUString m_sStagnationLimit;
|
|
OUString m_sTolerance;
|
|
OUString m_sEnhancedSolverStatus;
|
|
// DEPS only
|
|
OUString m_sAgentSwitchRate;
|
|
OUString m_sScalingFactorMin;
|
|
OUString m_sScalingFactorMax;
|
|
OUString m_sCrossoverProbability;
|
|
OUString m_sCognitiveConstant;
|
|
OUString m_sSocialConstant;
|
|
OUString m_sConstrictionCoeff;
|
|
OUString m_sMutationProbability;
|
|
// SCO only
|
|
OUString m_sLibrarySize;
|
|
|
|
std::vector<ModelConstraint> m_aConstraints;
|
|
|
|
void Initialize();
|
|
|
|
// Used to create or read a single solver parameter based on its named range
|
|
bool ReadParamValue(SolverParameter eParam, OUString& rValue, bool bRemoveQuotes = false);
|
|
bool ReadDoubleParamValue(SolverParameter eParam, OUString& rValue);
|
|
void WriteParamValue(SolverParameter eParam, OUString sValue, bool bQuoted = false);
|
|
void WriteDoubleParamValue(SolverParameter eParam, std::u16string_view sValue);
|
|
|
|
// Creates or reads all constraints stored in named ranges
|
|
void ReadConstraints();
|
|
void WriteConstraints();
|
|
|
|
// Used to create or get a single constraint part
|
|
bool ReadConstraintPart(ConstraintPart ePart, tools::Long nIndex, OUString& rValue);
|
|
void WriteConstraintPart(ConstraintPart ePart, tools::Long nIndex, const OUString& sValue);
|
|
|
|
// Creates or reads all named ranges associated with solver engine options
|
|
void ReadEngine();
|
|
void WriteEngine();
|
|
|
|
void DeleteAllNamedRanges();
|
|
|
|
// Maps solver parameters to named ranges
|
|
std::map<SolverParameter, OUString> m_mNamedRanges
|
|
= { { SP_OBJ_CELL, "solver_opt" },
|
|
{ SP_OBJ_TYPE, "solver_typ" },
|
|
{ SP_OBJ_VAL, "solver_val" },
|
|
{ SP_VAR_CELLS, "solver_adj" },
|
|
{ SP_CONSTR_COUNT, "solver_num" },
|
|
{ SP_LO_ENGINE, "solver_lo_eng" },
|
|
{ SP_MS_ENGINE, "solver_eng" },
|
|
{ SP_INTEGER, "solver_int" },
|
|
{ SP_NON_NEGATIVE, "solver_neg" },
|
|
{ SP_EPSILON_LEVEL, "solver_eps" },
|
|
{ SP_LIMIT_BBDEPTH, "solver_bbd" },
|
|
{ SP_TIMEOUT, "solver_tim" },
|
|
{ SP_ALGORITHM, "solver_alg" },
|
|
{ SP_SWARM_SIZE, "solver_ssz" },
|
|
{ SP_LEARNING_CYCLES, "solver_lcy" },
|
|
{ SP_GUESS_VARIABLE_RANGE, "solver_gvr" },
|
|
{ SP_VARIABLE_RANGE_THRESHOLD, "solver_vrt" },
|
|
{ SP_ACR_COMPARATOR, "solver_acr" },
|
|
{ SP_RND_STARTING_POINT, "solver_rsp" },
|
|
{ SP_STRONGER_PRNG, "solver_prng" },
|
|
{ SP_STAGNATION_LIMIT, "solver_slim" },
|
|
{ SP_STAGNATION_TOLERANCE, "solver_stol" },
|
|
{ SP_ENHANCED_STATUS, "solver_enst" },
|
|
{ SP_AGENT_SWITCH_RATE, "solver_asr" },
|
|
{ SP_SCALING_MIN, "solver_smin" },
|
|
{ SP_SCALING_MAX, "solver_smax" },
|
|
{ SP_CROSSOVER_PROB, "solver_crpb" },
|
|
{ SP_COGNITIVE_CONST, "solver_cog" },
|
|
{ SP_SOCIAL_CONST, "solver_soc" },
|
|
{ SP_CONSTRICTION_COEFF, "solver_ccoeff" },
|
|
{ SP_MUTATION_PROB, "solver_mtpb" },
|
|
{ SP_LIBRARY_SIZE, "solver_lbsz" } };
|
|
|
|
// Maps LO solver implementation names to MS engine codes
|
|
std::map<OUString, OUString> SolverNamesToExcelEngines = {
|
|
{ "com.sun.star.comp.Calc.CoinMPSolver", "2" }, // Simplex LP
|
|
{ "com.sun.star.comp.Calc.SwarmSolver", "1" }, // GRG Nonlinear
|
|
{ "com.sun.star.comp.Calc.NLPSolver.DEPSSolverImpl", "3" }, // DEPS
|
|
{ "com.sun.star.comp.Calc.NLPSolver.SCOSolverImpl", "3" } // SCO
|
|
};
|
|
|
|
// Maps MS solver engine codes to LO solver implementation names
|
|
std::map<OUString, OUString> SolverCodesToLOEngines = {
|
|
{ "1", "com.sun.star.comp.Calc.SwarmSolver" }, // GRG Nonlinear
|
|
{ "2", "com.sun.star.comp.Calc.CoinMPSolver" }, // Simplex LP
|
|
{ "3", "com.sun.star.comp.Calc.SwarmSolver" } // Evolutionary
|
|
};
|
|
|
|
// Maps LO solver parameters to named ranges to be used
|
|
// NonNegative: for MS compatibility, use 1 for selected and 2 for not selected
|
|
typedef std::vector<std::variant<OUString, SolverParameter>> TParamInfo;
|
|
std::map<OUString, TParamInfo> SolverParamNames
|
|
= { { u"Integer"_ustr, { SP_INTEGER, "solver_int", "bool" } },
|
|
{ u"NonNegative"_ustr, { SP_NON_NEGATIVE, "solver_neg", "bool" } },
|
|
{ u"EpsilonLevel"_ustr, { SP_EPSILON_LEVEL, "solver_eps", "int" } },
|
|
{ u"LimitBBDepth"_ustr, { SP_LIMIT_BBDEPTH, "solver_bbd", "bool" } },
|
|
{ u"Timeout"_ustr, { SP_TIMEOUT, "solver_tim", "int" } },
|
|
{ u"Algorithm"_ustr, { SP_ALGORITHM, "solver_alg", "int" } },
|
|
// SCO and DEPS
|
|
{ u"AssumeNonNegative"_ustr, { SP_NON_NEGATIVE, "solver_neg", "bool" } },
|
|
{ u"SwarmSize"_ustr, { SP_SWARM_SIZE, "solver_ssz", "int" } },
|
|
{ u"LearningCycles"_ustr, { SP_LEARNING_CYCLES, "solver_lcy", "int" } },
|
|
{ u"GuessVariableRange"_ustr, { SP_GUESS_VARIABLE_RANGE, "solver_gvr", "bool" } },
|
|
{ u"VariableRangeThreshold"_ustr,
|
|
{ SP_VARIABLE_RANGE_THRESHOLD, "solver_vrt", "double" } },
|
|
{ u"UseACRComparator"_ustr, { SP_ACR_COMPARATOR, "solver_acr", "bool" } },
|
|
{ u"UseRandomStartingPoint"_ustr, { SP_RND_STARTING_POINT, "solver_rsp", "bool" } },
|
|
{ u"UseStrongerPRNG"_ustr, { SP_STRONGER_PRNG, "solver_prng", "bool" } },
|
|
{ u"StagnationLimit"_ustr, { SP_STAGNATION_LIMIT, "solver_slim", "int" } },
|
|
{ u"Tolerance"_ustr, { SP_STAGNATION_TOLERANCE, "solver_stol", "double" } },
|
|
{ u"EnhancedSolverStatus"_ustr, { SP_ENHANCED_STATUS, "solver_enst", "bool" } },
|
|
// DEPS only
|
|
{ u"AgentSwitchRate"_ustr, { SP_AGENT_SWITCH_RATE, "solver_asr", "double" } },
|
|
{ u"DEFactorMin"_ustr, { SP_SCALING_MIN, "solver_smin", "double" } },
|
|
{ u"DEFactorMax"_ustr, { SP_SCALING_MAX, "solver_smax", "double" } },
|
|
{ u"DECR"_ustr, { SP_CROSSOVER_PROB, "solver_crpb", "double" } },
|
|
{ u"PSC1"_ustr, { SP_COGNITIVE_CONST, "solver_cog", "double" } },
|
|
{ u"PSC2"_ustr, { SP_SOCIAL_CONST, "solver_soc", "double" } },
|
|
{ u"PSWeight"_ustr, { SP_CONSTRICTION_COEFF, "solver_ccoeff", "double" } },
|
|
{ u"PSCL"_ustr, { SP_MUTATION_PROB, "solver_mtpb", "double" } },
|
|
// SCO only
|
|
{ u"LibrarySize"_ustr, { SP_LIBRARY_SIZE, "solver_lbsz", "int" } } };
|
|
|
|
// Stores the roots used for named ranges of constraint parts
|
|
// Items here must be in the same order as in ConstraintPart enum
|
|
std::vector<OUString> m_aConstraintParts{ u"solver_lhs"_ustr, u"solver_rel"_ustr,
|
|
u"solver_rhs"_ustr };
|
|
|
|
public:
|
|
/* A SolverSettings object is linked to the ScTable where solver parameters
|
|
* are located and saved to */
|
|
SolverSettings(ScTable& pTable);
|
|
|
|
SC_DLLPUBLIC OUString GetParameter(SolverParameter eParam);
|
|
SC_DLLPUBLIC void SetParameter(SolverParameter eParam, const OUString& sValue);
|
|
SC_DLLPUBLIC ObjectiveType GetObjectiveType() { return m_eObjType; }
|
|
SC_DLLPUBLIC void SetObjectiveType(ObjectiveType eType);
|
|
SC_DLLPUBLIC void GetEngineOptions(css::uno::Sequence<css::beans::PropertyValue>& aOptions);
|
|
SC_DLLPUBLIC void
|
|
SetEngineOptions(const css::uno::Sequence<css::beans::PropertyValue>& aOptions);
|
|
SC_DLLPUBLIC const std::vector<ModelConstraint>& GetConstraints() { return m_aConstraints; }
|
|
SC_DLLPUBLIC void SetConstraints(std::vector<ModelConstraint> aConstraints);
|
|
|
|
SC_DLLPUBLIC void SaveSolverSettings();
|
|
SC_DLLPUBLIC void ResetToDefaults();
|
|
SC_DLLPUBLIC bool TabHasSolverModel();
|
|
};
|
|
|
|
} // namespace sc
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|