/src/libreoffice/sc/inc/SolverSettings.hxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
5 | | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | | * |
9 | | */ |
10 | | |
11 | | #pragma once |
12 | | |
13 | | #include <utility> |
14 | | #include <variant> |
15 | | #include <rtl/ustring.hxx> |
16 | | #include <com/sun/star/beans/PropertyValue.hpp> |
17 | | |
18 | | #include "document.hxx" |
19 | | #include <docsh.hxx> |
20 | | |
21 | | namespace sc |
22 | | { |
23 | | // These values are MS compatible |
24 | | enum ObjectiveType |
25 | | { |
26 | | OT_MAXIMIZE = 1, |
27 | | OT_MINIMIZE = 2, |
28 | | OT_VALUE = 3 |
29 | | }; |
30 | | |
31 | | enum SolverParameter |
32 | | { |
33 | | SP_OBJ_CELL, // Objective cell |
34 | | SP_OBJ_TYPE, // Objective type (max, min, value) |
35 | | SP_OBJ_VAL, // Value (used when objective is of type "value") |
36 | | SP_VAR_CELLS, // Variable cells |
37 | | SP_CONSTR_COUNT, // Number of constraints (MSO only) |
38 | | SP_LO_ENGINE, // Engine name used in LO |
39 | | SP_MS_ENGINE, // Engine ID used in MSO |
40 | | SP_INTEGER, // Assume all variables are integer (0: no, 1: yes) |
41 | | // LpSolve, CoinMP and SwarmSolver |
42 | | SP_NON_NEGATIVE, // Assume non negativity (1: yes, 2: no) |
43 | | SP_EPSILON_LEVEL, // Epsilon level |
44 | | SP_LIMIT_BBDEPTH, // Branch and bound depth |
45 | | SP_TIMEOUT, // Time limit to return a solution |
46 | | SP_ALGORITHM, // Algorithm used by the SwarmSolver (1, 2 or 3) |
47 | | // Engine options common for DEPS and SCO |
48 | | SP_SWARM_SIZE, // Size of Swarm |
49 | | SP_LEARNING_CYCLES, // Learning Cycles |
50 | | SP_GUESS_VARIABLE_RANGE, // Variable Bounds Guessing |
51 | | SP_VARIABLE_RANGE_THRESHOLD, // Variable Bounds Threshold (when guessing) |
52 | | SP_ACR_COMPARATOR, // Use ACR Comparator (instead of BCH) |
53 | | SP_RND_STARTING_POINT, // Use Random starting point |
54 | | SP_STRONGER_PRNG, // Use a stronger random generator (slower) |
55 | | SP_STAGNATION_LIMIT, // Stagnation Limit |
56 | | SP_STAGNATION_TOLERANCE, // Stagnation Tolerance |
57 | | SP_ENHANCED_STATUS, // Show enhanced solver status |
58 | | // DEPS Options |
59 | | SP_AGENT_SWITCH_RATE, // Agent Switch Rate (DE Probability) |
60 | | SP_SCALING_MIN, // DE: Min Scaling Factor (0-1.2) |
61 | | SP_SCALING_MAX, // DE: Max Scaling Factor (0-1.2) |
62 | | SP_CROSSOVER_PROB, // DE: Crossover Probability (0-1) |
63 | | SP_COGNITIVE_CONST, // Cognitive Constant |
64 | | SP_SOCIAL_CONST, // Social Constant |
65 | | SP_CONSTRICTION_COEFF, // PS: Constriction Coefficient |
66 | | SP_MUTATION_PROB, // Mutation Probability (0-0.005) |
67 | | // SCO Options |
68 | | SP_LIBRARY_SIZE, // Size of library |
69 | | }; |
70 | | |
71 | | // Starts at 1 to maintain MS compatibility |
72 | | enum ConstraintOperator |
73 | | { |
74 | | CO_LESS_EQUAL = 1, |
75 | | CO_EQUAL = 2, |
76 | | CO_GREATER_EQUAL = 3, |
77 | | CO_INTEGER = 4, |
78 | | CO_BINARY = 5 |
79 | | }; |
80 | | |
81 | | // Parts of a constraint |
82 | | enum ConstraintPart |
83 | | { |
84 | | CP_LEFT_HAND_SIDE, |
85 | | CP_OPERATOR, |
86 | | CP_RIGHT_HAND_SIDE |
87 | | }; |
88 | | |
89 | | // Stores the information of a single constraint (condition) |
90 | | struct ModelConstraint |
91 | | { |
92 | | OUString aLeftStr; |
93 | | ConstraintOperator nOperator; |
94 | | OUString aRightStr; |
95 | | |
96 | | ModelConstraint() |
97 | 0 | : nOperator(CO_LESS_EQUAL) |
98 | 0 | { |
99 | 0 | } |
100 | | bool IsDefault() const |
101 | 0 | { |
102 | 0 | return aLeftStr.isEmpty() && aRightStr.isEmpty() && nOperator == CO_LESS_EQUAL; |
103 | 0 | } |
104 | | }; |
105 | | |
106 | | /* Class SolverSettings |
107 | | * |
108 | | * This class is used to load/save and manipulate solver settings in a Calc tab. |
109 | | * |
110 | | * During initialization, (see Initialize() method) all settings stored in the tab are loaded onto |
111 | | * the object. Settings that are not defined use default values. |
112 | | * |
113 | | * Read/Write methods are private and are used internally to load/write solver settings from |
114 | | * named ranges associated with the sheet. |
115 | | * |
116 | | * Get/Set methods are public methods used to change object properties (they do not save data |
117 | | * to the file). |
118 | | * |
119 | | * The method SaveSolverSettings() is used to create the named ranges containing the current |
120 | | * property values into the file. |
121 | | * |
122 | | */ |
123 | | |
124 | | class SolverSettings |
125 | | { |
126 | | private: |
127 | | ScTable& m_rTable; |
128 | | ScDocument& m_rDoc; |
129 | | ScDocShell* m_pDocShell; |
130 | | |
131 | | // Used to read/write the named ranges in the tab |
132 | | ScRangeName* m_pRangeName; |
133 | | |
134 | | OUString m_sObjCell; |
135 | | ObjectiveType m_eObjType; |
136 | | OUString m_sObjVal; |
137 | | OUString m_sVariableCells; |
138 | | OUString m_sLOEngineName; |
139 | | OUString m_sMSEngineId; |
140 | | |
141 | | // Solver engine options |
142 | | OUString m_sInteger; |
143 | | OUString m_sNonNegative; |
144 | | OUString m_sEpsilonLevel; |
145 | | OUString m_sLimitBBDepth; |
146 | | OUString m_sTimeout; |
147 | | OUString m_sAlgorithm; |
148 | | // DEPS and SCO |
149 | | OUString m_sSwarmSize; |
150 | | OUString m_sLearningCycles; |
151 | | OUString m_sGuessVariableRange; |
152 | | OUString m_sVariableRangeThreshold; |
153 | | OUString m_sUseACRComparator; |
154 | | OUString m_sUseRandomStartingPoint; |
155 | | OUString m_sUseStrongerPRNG; |
156 | | OUString m_sStagnationLimit; |
157 | | OUString m_sTolerance; |
158 | | OUString m_sEnhancedSolverStatus; |
159 | | // DEPS only |
160 | | OUString m_sAgentSwitchRate; |
161 | | OUString m_sScalingFactorMin; |
162 | | OUString m_sScalingFactorMax; |
163 | | OUString m_sCrossoverProbability; |
164 | | OUString m_sCognitiveConstant; |
165 | | OUString m_sSocialConstant; |
166 | | OUString m_sConstrictionCoeff; |
167 | | OUString m_sMutationProbability; |
168 | | // SCO only |
169 | | OUString m_sLibrarySize; |
170 | | |
171 | | std::vector<ModelConstraint> m_aConstraints; |
172 | | |
173 | | void Initialize(); |
174 | | |
175 | | // Used to create or read a single solver parameter based on its named range |
176 | | bool ReadParamValue(SolverParameter eParam, OUString& rValue, bool bRemoveQuotes = false); |
177 | | bool ReadDoubleParamValue(SolverParameter eParam, OUString& rValue); |
178 | | void WriteParamValue(SolverParameter eParam, OUString sValue, bool bQuoted = false); |
179 | | void WriteDoubleParamValue(SolverParameter eParam, std::u16string_view sValue); |
180 | | |
181 | | // Creates or reads all constraints stored in named ranges |
182 | | void ReadConstraints(); |
183 | | void WriteConstraints(); |
184 | | |
185 | | // Used to create or get a single constraint part |
186 | | bool ReadConstraintPart(ConstraintPart ePart, tools::Long nIndex, OUString& rValue); |
187 | | void WriteConstraintPart(ConstraintPart ePart, tools::Long nIndex, const OUString& sValue); |
188 | | |
189 | | // Creates or reads all named ranges associated with solver engine options |
190 | | void ReadEngine(); |
191 | | void WriteEngine(); |
192 | | |
193 | | void DeleteAllNamedRanges(); |
194 | | |
195 | | // Maps solver parameters to named ranges |
196 | | std::map<SolverParameter, OUString> m_mNamedRanges |
197 | | = { { SP_OBJ_CELL, "solver_opt" }, |
198 | | { SP_OBJ_TYPE, "solver_typ" }, |
199 | | { SP_OBJ_VAL, "solver_val" }, |
200 | | { SP_VAR_CELLS, "solver_adj" }, |
201 | | { SP_CONSTR_COUNT, "solver_num" }, |
202 | | { SP_LO_ENGINE, "solver_lo_eng" }, |
203 | | { SP_MS_ENGINE, "solver_eng" }, |
204 | | { SP_INTEGER, "solver_int" }, |
205 | | { SP_NON_NEGATIVE, "solver_neg" }, |
206 | | { SP_EPSILON_LEVEL, "solver_eps" }, |
207 | | { SP_LIMIT_BBDEPTH, "solver_bbd" }, |
208 | | { SP_TIMEOUT, "solver_tim" }, |
209 | | { SP_ALGORITHM, "solver_alg" }, |
210 | | { SP_SWARM_SIZE, "solver_ssz" }, |
211 | | { SP_LEARNING_CYCLES, "solver_lcy" }, |
212 | | { SP_GUESS_VARIABLE_RANGE, "solver_gvr" }, |
213 | | { SP_VARIABLE_RANGE_THRESHOLD, "solver_vrt" }, |
214 | | { SP_ACR_COMPARATOR, "solver_acr" }, |
215 | | { SP_RND_STARTING_POINT, "solver_rsp" }, |
216 | | { SP_STRONGER_PRNG, "solver_prng" }, |
217 | | { SP_STAGNATION_LIMIT, "solver_slim" }, |
218 | | { SP_STAGNATION_TOLERANCE, "solver_stol" }, |
219 | | { SP_ENHANCED_STATUS, "solver_enst" }, |
220 | | { SP_AGENT_SWITCH_RATE, "solver_asr" }, |
221 | | { SP_SCALING_MIN, "solver_smin" }, |
222 | | { SP_SCALING_MAX, "solver_smax" }, |
223 | | { SP_CROSSOVER_PROB, "solver_crpb" }, |
224 | | { SP_COGNITIVE_CONST, "solver_cog" }, |
225 | | { SP_SOCIAL_CONST, "solver_soc" }, |
226 | | { SP_CONSTRICTION_COEFF, "solver_ccoeff" }, |
227 | | { SP_MUTATION_PROB, "solver_mtpb" }, |
228 | | { SP_LIBRARY_SIZE, "solver_lbsz" } }; |
229 | | |
230 | | // Maps LO solver implementation names to MS engine codes |
231 | | std::map<OUString, OUString> SolverNamesToExcelEngines = { |
232 | | { "com.sun.star.comp.Calc.CoinMPSolver", "2" }, // Simplex LP |
233 | | { "com.sun.star.comp.Calc.LpsolveSolver", "2" }, // Simplex LP |
234 | | { "com.sun.star.comp.Calc.SwarmSolver", "1" }, // GRG Nonlinear |
235 | | { "com.sun.star.comp.Calc.NLPSolver.DEPSSolverImpl", "3" }, // DEPS |
236 | | { "com.sun.star.comp.Calc.NLPSolver.SCOSolverImpl", "3" } // SCO |
237 | | }; |
238 | | |
239 | | // Maps MS solver engine codes to LO solver implementation names |
240 | | std::map<OUString, OUString> SolverCodesToLOEngines = { |
241 | | { "1", "com.sun.star.comp.Calc.SwarmSolver" }, // GRG Nonlinear |
242 | | { "2", "com.sun.star.comp.Calc.CoinMPSolver" }, // Simplex LP |
243 | | { "3", "com.sun.star.comp.Calc.SwarmSolver" } // Evolutionary |
244 | | }; |
245 | | |
246 | | // Maps LO solver parameters to named ranges to be used |
247 | | // NonNegative: for MS compatibility, use 1 for selected and 2 for not selected |
248 | | typedef std::vector<std::variant<OUString, SolverParameter>> TParamInfo; |
249 | | std::map<OUString, TParamInfo> SolverParamNames |
250 | | = { { u"Integer"_ustr, { SP_INTEGER, "solver_int", "bool" } }, |
251 | | { u"NonNegative"_ustr, { SP_NON_NEGATIVE, "solver_neg", "bool" } }, |
252 | | { u"EpsilonLevel"_ustr, { SP_EPSILON_LEVEL, "solver_eps", "int" } }, |
253 | | { u"LimitBBDepth"_ustr, { SP_LIMIT_BBDEPTH, "solver_bbd", "bool" } }, |
254 | | { u"Timeout"_ustr, { SP_TIMEOUT, "solver_tim", "int" } }, |
255 | | { u"Algorithm"_ustr, { SP_ALGORITHM, "solver_alg", "int" } }, |
256 | | // SCO and DEPS |
257 | | { u"AssumeNonNegative"_ustr, { SP_NON_NEGATIVE, "solver_neg", "bool" } }, |
258 | | { u"SwarmSize"_ustr, { SP_SWARM_SIZE, "solver_ssz", "int" } }, |
259 | | { u"LearningCycles"_ustr, { SP_LEARNING_CYCLES, "solver_lcy", "int" } }, |
260 | | { u"GuessVariableRange"_ustr, { SP_GUESS_VARIABLE_RANGE, "solver_gvr", "bool" } }, |
261 | | { u"VariableRangeThreshold"_ustr, |
262 | | { SP_VARIABLE_RANGE_THRESHOLD, "solver_vrt", "double" } }, |
263 | | { u"UseACRComparator"_ustr, { SP_ACR_COMPARATOR, "solver_acr", "bool" } }, |
264 | | { u"UseRandomStartingPoint"_ustr, { SP_RND_STARTING_POINT, "solver_rsp", "bool" } }, |
265 | | { u"UseStrongerPRNG"_ustr, { SP_STRONGER_PRNG, "solver_prng", "bool" } }, |
266 | | { u"StagnationLimit"_ustr, { SP_STAGNATION_LIMIT, "solver_slim", "int" } }, |
267 | | { u"Tolerance"_ustr, { SP_STAGNATION_TOLERANCE, "solver_stol", "double" } }, |
268 | | { u"EnhancedSolverStatus"_ustr, { SP_ENHANCED_STATUS, "solver_enst", "bool" } }, |
269 | | // DEPS only |
270 | | { u"AgentSwitchRate"_ustr, { SP_AGENT_SWITCH_RATE, "solver_asr", "double" } }, |
271 | | { u"DEFactorMin"_ustr, { SP_SCALING_MIN, "solver_smin", "double" } }, |
272 | | { u"DEFactorMax"_ustr, { SP_SCALING_MAX, "solver_smax", "double" } }, |
273 | | { u"DECR"_ustr, { SP_CROSSOVER_PROB, "solver_crpb", "double" } }, |
274 | | { u"PSC1"_ustr, { SP_COGNITIVE_CONST, "solver_cog", "double" } }, |
275 | | { u"PSC2"_ustr, { SP_SOCIAL_CONST, "solver_soc", "double" } }, |
276 | | { u"PSWeight"_ustr, { SP_CONSTRICTION_COEFF, "solver_ccoeff", "double" } }, |
277 | | { u"PSCL"_ustr, { SP_MUTATION_PROB, "solver_mtpb", "double" } }, |
278 | | // SCO only |
279 | | { u"LibrarySize"_ustr, { SP_LIBRARY_SIZE, "solver_lbsz", "int" } } }; |
280 | | |
281 | | // Stores the roots used for named ranges of constraint parts |
282 | | // Items here must be in the same order as in ConstraintPart enum |
283 | | std::vector<OUString> m_aConstraintParts{ u"solver_lhs"_ustr, u"solver_rel"_ustr, |
284 | | u"solver_rhs"_ustr }; |
285 | | |
286 | | public: |
287 | | /* A SolverSettings object is linked to the ScTable where solver parameters |
288 | | * are located and saved to */ |
289 | | SolverSettings(ScTable& pTable); |
290 | | |
291 | | SC_DLLPUBLIC OUString GetParameter(SolverParameter eParam); |
292 | | SC_DLLPUBLIC void SetParameter(SolverParameter eParam, const OUString& sValue); |
293 | 0 | SC_DLLPUBLIC ObjectiveType GetObjectiveType() { return m_eObjType; } |
294 | | SC_DLLPUBLIC void SetObjectiveType(ObjectiveType eType); |
295 | | SC_DLLPUBLIC void GetEngineOptions(css::uno::Sequence<css::beans::PropertyValue>& aOptions); |
296 | | SC_DLLPUBLIC void |
297 | | SetEngineOptions(const css::uno::Sequence<css::beans::PropertyValue>& aOptions); |
298 | 0 | SC_DLLPUBLIC const std::vector<ModelConstraint>& GetConstraints() { return m_aConstraints; } |
299 | | SC_DLLPUBLIC void SetConstraints(std::vector<ModelConstraint> aConstraints); |
300 | | |
301 | | SC_DLLPUBLIC void SaveSolverSettings(); |
302 | | SC_DLLPUBLIC void ResetToDefaults(); |
303 | | SC_DLLPUBLIC bool TabHasSolverModel(); |
304 | | }; |
305 | | |
306 | | } // namespace sc |
307 | | |
308 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |