Skip to content

Commit 5d86cc8

Browse files
rafaelhlimaquikee
authored andcommitted
tdf#38948 Save solver settings to file
This patch implements the mechanism to save solver settings in LO Calc as well as export/import them from XLSX files. In MS Excel solver settings are saved as hidden named ranges, so in this patch I used the same strategy to save solver settings in Calc, i.e. by creating named ranges to store the solver settings using the same terminology used in Excel. With this we gain the ability to save solver settings by tab, as well as export/import since we already have "named ranges/expressions" import/export implemented in LO. Change-Id: Id41bca261dc3cd8e6888643f0ed6a97b26097876 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/148112 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <[email protected]>
1 parent 9a762f9 commit 5d86cc8

13 files changed

+1063
-124
lines changed

sc/CppunitTest_sc_ucalc_solver.mk

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
2+
#*************************************************************************
3+
#
4+
# This file is part of the LibreOffice project.
5+
#
6+
# This Source Code Form is subject to the terms of the Mozilla Public
7+
# License, v. 2.0. If a copy of the MPL was not distributed with this
8+
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
9+
#
10+
#*************************************************************************
11+
12+
$(eval $(call gb_CppunitTest_CppunitTest,sc_ucalc_solver))
13+
14+
$(eval $(call gb_CppunitTest_use_common_precompiled_header,sc_ucalc_solver))
15+
16+
$(eval $(call gb_CppunitTest_add_exception_objects,sc_ucalc_solver, \
17+
sc/qa/unit/ucalc_solver \
18+
))
19+
20+
$(eval $(call gb_CppunitTest_use_externals,sc_ucalc_solver, \
21+
boost_headers \
22+
mdds_headers \
23+
libxml2 \
24+
))
25+
26+
$(eval $(call gb_CppunitTest_use_libraries,sc_ucalc_solver, \
27+
basegfx \
28+
comphelper \
29+
cppu \
30+
cppuhelper \
31+
i18nlangtag \
32+
sal \
33+
sax \
34+
sc \
35+
scqahelper \
36+
sfx \
37+
subsequenttest \
38+
svl \
39+
svx \
40+
svxcore \
41+
test \
42+
tl \
43+
unotest \
44+
utl \
45+
vcl \
46+
))
47+
48+
$(eval $(call gb_CppunitTest_set_include,sc_ucalc_solver,\
49+
-I$(SRCDIR)/sc/source/ui/inc \
50+
-I$(SRCDIR)/sc/inc \
51+
$$(INCLUDE) \
52+
))
53+
54+
$(eval $(call gb_CppunitTest_use_api,sc_ucalc_solver,\
55+
offapi \
56+
udkapi \
57+
))
58+
59+
$(eval $(call gb_CppunitTest_use_sdk_api,sc_ucalc_solver))
60+
61+
$(eval $(call gb_CppunitTest_use_ure,sc_ucalc_solver))
62+
63+
$(eval $(call gb_CppunitTest_use_vcl,sc_ucalc_solver))
64+
65+
$(eval $(call gb_CppunitTest_use_rdb,sc_ucalc_solver,services))
66+
67+
$(eval $(call gb_CppunitTest_use_components,sc_ucalc_solver))
68+
69+
$(eval $(call gb_CppunitTest_use_configuration,sc_ucalc_solver))
70+
71+
$(eval $(call gb_CppunitTest_add_arguments,sc_ucalc_solver, \
72+
-env:arg-env=$(gb_Helper_LIBRARY_PATH_VAR)"$$$${$(gb_Helper_LIBRARY_PATH_VAR)+=$$$$$(gb_Helper_LIBRARY_PATH_VAR)}" \
73+
))
74+
75+
# vim: set noet sw=4 ts=4:

sc/Library_sc.mk

+1
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
186186
sc/source/core/data/segmenttree \
187187
sc/source/core/data/sheetevents \
188188
sc/source/core/data/simpleformulacalc \
189+
sc/source/core/data/SolverSettings \
189190
sc/source/core/data/sortparam \
190191
sc/source/core/data/stlpool \
191192
sc/source/core/data/stlsheet \

sc/Module_sc.mk

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ $(eval $(call gb_Module_add_check_targets,sc,\
5454
CppunitTest_sc_ucalc_range \
5555
CppunitTest_sc_ucalc_sharedformula \
5656
CppunitTest_sc_ucalc_sparkline \
57+
CppunitTest_sc_ucalc_solver \
5758
CppunitTest_sc_ucalc_sort \
5859
CppunitTest_sc_filters_test \
5960
CppunitTest_sc_mark_test \

sc/inc/SolverSettings.hxx

+209
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
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 <memory>
14+
#include <utility>
15+
#include <variant>
16+
#include <rtl/ustring.hxx>
17+
#include <com/sun/star/beans/PropertyValue.hpp>
18+
19+
class ScTable;
20+
class ScDocShell;
21+
22+
namespace sc
23+
{
24+
// These values are MS compatible
25+
enum ObjectiveType
26+
{
27+
OT_MAXIMIZE = 1,
28+
OT_MINIMIZE = 2,
29+
OT_VALUE = 3
30+
};
31+
32+
enum SolverParameter
33+
{
34+
SP_OBJ_CELL, // Objective cell
35+
SP_OBJ_TYPE, // Objective type (max, min, value)
36+
SP_OBJ_VAL, // Value (used when objective is of type "value")
37+
SP_VAR_CELLS, // Variable cells
38+
SP_CONSTR_COUNT, // Number of constraints (MSO only)
39+
SP_LO_ENGINE, // Engine name used in LO
40+
SP_MS_ENGINE, // Engine ID used in MSO
41+
SP_INTEGER, // Assume all variables are integer (0: no, 1: yes)
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+
};
48+
49+
// Starts at 1 to maintain MS compatibility
50+
enum ConstraintOperator
51+
{
52+
CO_LESS_EQUAL = 1,
53+
CO_EQUAL = 2,
54+
CO_GREATER_EQUAL = 3,
55+
CO_INTEGER = 4,
56+
CO_BINARY = 5
57+
};
58+
59+
// Parts of a constraint
60+
enum ConstraintPart
61+
{
62+
CP_LEFT_HAND_SIDE,
63+
CP_OPERATOR,
64+
CP_RIGHT_HAND_SIDE
65+
};
66+
67+
// Stores the information of a single constraint (condition)
68+
struct ModelConstraint
69+
{
70+
OUString aLeftStr;
71+
ConstraintOperator nOperator;
72+
OUString aRightStr;
73+
74+
ModelConstraint()
75+
: nOperator(CO_LESS_EQUAL)
76+
{
77+
}
78+
bool IsDefault() const
79+
{
80+
return aLeftStr.isEmpty() && aRightStr.isEmpty() && nOperator == CO_LESS_EQUAL;
81+
}
82+
};
83+
84+
/* Class SolverSettings
85+
*
86+
* This class is used to load/save and manipulate solver settings in a Calc tab.
87+
*
88+
* During initialization, (see Initialize() method) all settings stored in the tab are loaded onto
89+
* the object. Settings that are not defined use default values.
90+
*
91+
* Read/Write methods are private and are used internally to load/write solver settings from
92+
* named ranges associated with the sheet.
93+
*
94+
* Get/Set methods are public methods used to change object properties (they do not save data
95+
* to the file).
96+
*
97+
* The method SaveSolverSettings() is used to create the named ranges containing the current
98+
* property values into the file.
99+
*
100+
*/
101+
102+
class SolverSettings
103+
{
104+
private:
105+
ScTable& m_rTable;
106+
ScDocument& m_rDoc;
107+
ScDocShell* m_pDocShell;
108+
109+
// Used to read/write the named ranges in the tab
110+
ScRangeName* m_pRangeName;
111+
112+
OUString m_sObjCell;
113+
ObjectiveType m_eObjType;
114+
OUString m_sObjVal;
115+
OUString m_sVariableCells;
116+
OUString m_sLOEngineName;
117+
OUString m_sMSEngineId;
118+
119+
// Solver engine options
120+
OUString m_sInteger;
121+
OUString m_sNonNegative;
122+
OUString m_sEpsilonLevel;
123+
OUString m_sLimitBBDepth;
124+
OUString m_sTimeout;
125+
OUString m_sAlgorithm;
126+
css::uno::Sequence<css::beans::PropertyValue> m_aEngineOptions;
127+
128+
std::vector<ModelConstraint> m_aConstraints;
129+
130+
void Initialize();
131+
132+
// Used to create or read a single solver parameter based on its named range
133+
bool ReadParamValue(SolverParameter eParam, OUString& rValue, bool bRemoveQuotes = false);
134+
void WriteParamValue(SolverParameter eParam, OUString sValue, bool bQuoted = false);
135+
136+
// Creates or reads all constraints stored in named ranges
137+
void ReadConstraints();
138+
void WriteConstraints();
139+
140+
// Used to create or get a single constraint part
141+
bool ReadConstraintPart(ConstraintPart ePart, tools::Long nIndex, OUString& rValue);
142+
void WriteConstraintPart(ConstraintPart ePart, tools::Long nIndex, OUString sValue);
143+
144+
// Creates or reads all named ranges associated with solver engine options
145+
void ReadEngine();
146+
void WriteEngine();
147+
148+
void DeleteAllNamedRanges();
149+
150+
// Maps solver parameters to named ranges
151+
std::map<SolverParameter, OUString> m_mNamedRanges
152+
= { { SP_OBJ_CELL, "solver_opt" }, { SP_OBJ_TYPE, "solver_typ" },
153+
{ SP_OBJ_VAL, "solver_val" }, { SP_VAR_CELLS, "solver_adj" },
154+
{ SP_CONSTR_COUNT, "solver_num" }, { SP_LO_ENGINE, "solver_lo_eng" },
155+
{ SP_MS_ENGINE, "solver_eng" }, { SP_INTEGER, "solver_int" },
156+
{ SP_NON_NEGATIVE, "solver_neg" }, { SP_EPSILON_LEVEL, "solver_eps" },
157+
{ SP_LIMIT_BBDEPTH, "solver_bbd" }, { SP_TIMEOUT, "solver_tim" },
158+
{ SP_ALGORITHM, "solver_alg" } };
159+
160+
// Maps LO solver implementation names to MS engine codes
161+
std::map<OUString, OUString> SolverNamesToExcelEngines = {
162+
{ "com.sun.star.comp.Calc.CoinMPSolver", "2" }, // Simplex LP
163+
{ "com.sun.star.comp.Calc.LpsolveSolver", "2" }, // Simplex LP
164+
{ "com.sun.star.comp.Calc.SwarmSolver", "1" } // GRG Nonlinear
165+
};
166+
167+
// Maps MS solver engine codes to LO solver implementation names
168+
std::map<OUString, OUString> SolverCodesToLOEngines = {
169+
{ "1", "com.sun.star.comp.Calc.SwarmSolver" }, // GRG Nonlinear
170+
{ "2", "com.sun.star.comp.Calc.CoinMPSolver" }, // Simplex LP
171+
{ "3", "com.sun.star.comp.Calc.SwarmSolver" } // Evolutionary
172+
};
173+
174+
// Maps LO solver parameters to named ranges to be used
175+
// NonNegative: for MS compatibility, use 1 for selected and 2 for not selected
176+
typedef std::vector<std::variant<OUString, SolverParameter>> TParamInfo;
177+
std::map<OUString, TParamInfo> SolverParamNames
178+
= { { "Integer", { SP_INTEGER, "solver_int", "bool" } },
179+
{ "NonNegative", { SP_NON_NEGATIVE, "solver_neg", "bool" } },
180+
{ "EpsilonLevel", { SP_EPSILON_LEVEL, "solver_eps", "int" } },
181+
{ "LimitBBDepth", { SP_LIMIT_BBDEPTH, "solver_bbd", "bool" } },
182+
{ "Timeout", { SP_TIMEOUT, "solver_tim", "int" } },
183+
{ "Algorithm", { SP_ALGORITHM, "solver_alg", "int" } } };
184+
185+
// Stores the roots used for named ranges of constraint parts
186+
// Items here must be in the same order as in ConstraintPart enum
187+
std::vector<OUString> m_aConstraintParts{ "solver_lhs", "solver_rel", "solver_rhs" };
188+
189+
public:
190+
/* A SolverSettings object is linked to the ScTable where solver parameters
191+
* are located and saved to */
192+
SolverSettings(ScTable& pTable);
193+
194+
SC_DLLPUBLIC OUString GetParameter(SolverParameter eParam);
195+
SC_DLLPUBLIC void SetParameter(SolverParameter eParam, OUString sValue);
196+
SC_DLLPUBLIC ObjectiveType GetObjectiveType() { return m_eObjType; }
197+
SC_DLLPUBLIC void SetObjectiveType(ObjectiveType eType);
198+
SC_DLLPUBLIC void GetEngineOptions(css::uno::Sequence<css::beans::PropertyValue>& aOptions);
199+
SC_DLLPUBLIC void SetEngineOptions(css::uno::Sequence<css::beans::PropertyValue>& aOptions);
200+
SC_DLLPUBLIC std::vector<ModelConstraint> GetConstraints() { return m_aConstraints; }
201+
SC_DLLPUBLIC void SetConstraints(std::vector<ModelConstraint> aConstraints);
202+
203+
SC_DLLPUBLIC void SaveSolverSettings();
204+
SC_DLLPUBLIC void ResetToDefaults();
205+
};
206+
207+
} // namespace sc
208+
209+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

sc/inc/document.hxx

+1-1
Original file line numberDiff line numberDiff line change
@@ -2691,7 +2691,7 @@ private:
26912691
bool HasPartOfMerged( const ScRange& rRange );
26922692

26932693
public:
2694-
ScTable* FetchTable( SCTAB nTab );
2694+
SC_DLLPUBLIC ScTable* FetchTable( SCTAB nTab );
26952695
const ScTable* FetchTable( SCTAB nTab ) const;
26962696

26972697
ScRefCellValue GetRefCellValue( const ScAddress& rPos );

sc/inc/table.hxx

+6
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "document.hxx"
3434
#include "drwlayer.hxx"
3535
#include "SparklineList.hxx"
36+
#include "SolverSettings.hxx"
3637

3738
#include <algorithm>
3839
#include <atomic>
@@ -257,6 +258,9 @@ private:
257258
/** this is touched from formula group threading context */
258259
std::atomic<bool> bStreamValid;
259260

261+
// Solver settings in current tab
262+
std::shared_ptr<sc::SolverSettings> m_pSolverSettings;
263+
260264
// Default attributes for the unallocated columns.
261265
ScColumnData aDefaultColData;
262266

@@ -442,6 +446,8 @@ public:
442446
void SetFormula(
443447
SCCOL nCol, SCROW nRow, const OUString& rFormula, formula::FormulaGrammar::Grammar eGram );
444448

449+
SC_DLLPUBLIC std::shared_ptr<sc::SolverSettings> GetSolverSettings();
450+
445451
/**
446452
* Takes ownership of pCell
447453
*

0 commit comments

Comments
 (0)