1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
10 #include <sal/config.h>
12 #include <com/sun/star/sheet/XSolver.hpp>
13 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
14 #include <com/sun/star/sheet/XSpreadsheet.hpp>
15 #include <com/sun/star/beans/XPropertySet.hpp>
17 #include <test/unoapi_test.hxx>
23 class SwarmSolverTest
: public UnoApiTest
25 void testUnconstrained();
26 void testVariableBounded();
27 void testVariableConstrained();
28 void testTwoVariables();
29 void testMultipleVariables();
33 : UnoApiTest(u
"sccomp/qa/unit/data"_ustr
)
37 CPPUNIT_TEST_SUITE(SwarmSolverTest
);
38 CPPUNIT_TEST(testUnconstrained
);
39 CPPUNIT_TEST(testVariableBounded
);
40 CPPUNIT_TEST(testVariableConstrained
);
41 CPPUNIT_TEST(testMultipleVariables
);
42 CPPUNIT_TEST(testTwoVariables
);
43 CPPUNIT_TEST_SUITE_END();
46 void SwarmSolverTest::testUnconstrained()
48 loadFromFile(u
"Simple.ods");
50 uno::Reference
<sheet::XSpreadsheetDocument
> xDocument(mxComponent
, uno::UNO_QUERY_THROW
);
51 uno::Reference
<container::XIndexAccess
> xIndex(xDocument
->getSheets(), uno::UNO_QUERY_THROW
);
52 uno::Reference
<sheet::XSpreadsheet
> xSheet(xIndex
->getByIndex(0), uno::UNO_QUERY_THROW
);
54 uno::Reference
<sheet::XSolver
> xSolver
;
56 xSolver
.set(m_xContext
->getServiceManager()->createInstanceWithContext(
57 u
"com.sun.star.comp.Calc.SwarmSolver"_ustr
, m_xContext
),
58 uno::UNO_QUERY_THROW
);
60 table::CellAddress
aObjective(0, 1, 1);
62 // "changing cells" - unknown variables
63 uno::Sequence
<table::CellAddress
> aVariables
{ { 0, 1, 0 } };
66 uno::Sequence
<sheet::SolverConstraint
> aConstraints
;
69 xSolver
->setDocument(xDocument
);
70 xSolver
->setObjective(aObjective
);
71 xSolver
->setVariables(aVariables
);
72 xSolver
->setConstraints(aConstraints
);
73 xSolver
->setMaximize(false);
77 CPPUNIT_ASSERT(xSolver
->getSuccess());
78 uno::Sequence
<double> aSolution
= xSolver
->getSolution();
80 CPPUNIT_ASSERT_EQUAL(aVariables
.getLength(), aSolution
.getLength());
81 // It happens that the unconstrained test does not find a solution in the
82 // timeframe or number of generations it has available as the search space is
83 // too big and the values might not converge to solution. So for now just run
84 // the test so we know for sure the algorithm is guaranteed to finish
85 // and doesn't cause any seg faults.
86 //CPPUNIT_ASSERT_DOUBLES_EQUAL(3.0, aSolution[0], .9);
89 void SwarmSolverTest::testVariableBounded()
91 loadFromFile(u
"Simple.ods");
93 uno::Reference
<sheet::XSpreadsheetDocument
> xDocument(mxComponent
, uno::UNO_QUERY_THROW
);
94 uno::Reference
<container::XIndexAccess
> xIndex(xDocument
->getSheets(), uno::UNO_QUERY_THROW
);
95 uno::Reference
<sheet::XSpreadsheet
> xSheet(xIndex
->getByIndex(0), uno::UNO_QUERY_THROW
);
97 uno::Reference
<sheet::XSolver
> xSolver
;
99 xSolver
.set(m_xContext
->getServiceManager()->createInstanceWithContext(
100 u
"com.sun.star.comp.Calc.SwarmSolver"_ustr
, m_xContext
),
101 uno::UNO_QUERY_THROW
);
103 table::CellAddress
aObjective(0, 1, 1);
105 // "changing cells" - unknown variables
106 uno::Sequence
<table::CellAddress
> aVariables
{ { 0, 1, 0 } };
109 uno::Sequence
<sheet::SolverConstraint
> aConstraints
{
110 { /* [0] Left */ table::CellAddress(0, 1, 0),
111 /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL
,
112 /* Right */ uno::Any(100.0) },
113 { /* [1] Left */ table::CellAddress(0, 1, 0),
114 /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL
,
115 /* Right */ uno::Any(-100.0) }
119 xSolver
->setDocument(xDocument
);
120 xSolver
->setObjective(aObjective
);
121 xSolver
->setVariables(aVariables
);
122 xSolver
->setConstraints(aConstraints
);
123 xSolver
->setMaximize(false);
127 CPPUNIT_ASSERT(xSolver
->getSuccess());
128 uno::Sequence
<double> aSolution
= xSolver
->getSolution();
130 CPPUNIT_ASSERT_EQUAL(aVariables
.getLength(), aSolution
.getLength());
131 CPPUNIT_ASSERT_DOUBLES_EQUAL(3.0, aSolution
[0], 1E-5);
134 void SwarmSolverTest::testVariableConstrained()
136 loadFromFile(u
"Simple.ods");
138 uno::Reference
<sheet::XSpreadsheetDocument
> xDocument(mxComponent
, uno::UNO_QUERY_THROW
);
139 uno::Reference
<container::XIndexAccess
> xIndex(xDocument
->getSheets(), uno::UNO_QUERY_THROW
);
140 uno::Reference
<sheet::XSpreadsheet
> xSheet(xIndex
->getByIndex(0), uno::UNO_QUERY_THROW
);
142 uno::Reference
<sheet::XSolver
> xSolver
;
144 xSolver
.set(m_xContext
->getServiceManager()->createInstanceWithContext(
145 u
"com.sun.star.comp.Calc.SwarmSolver"_ustr
, m_xContext
),
146 uno::UNO_QUERY_THROW
);
148 table::CellAddress
aObjective(0, 1, 1);
150 // "changing cells" - unknown variables
151 uno::Sequence
<table::CellAddress
> aVariables
{ { 0, 1, 0 } };
154 uno::Sequence
<sheet::SolverConstraint
> aConstraints
{
155 { /* [0] Left */ table::CellAddress(0, 1, 0),
156 /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL
,
157 /* Right */ uno::Any(-50000.0) },
158 { /* [1] Left */ table::CellAddress(0, 1, 0),
159 /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL
,
160 /* Right */ uno::Any(0.0) },
161 { /* [2] Left */ table::CellAddress(0, 1, 1),
162 /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL
,
163 /* Right */ uno::Any(10.0) }
167 xSolver
->setDocument(xDocument
);
168 xSolver
->setObjective(aObjective
);
169 xSolver
->setVariables(aVariables
);
170 xSolver
->setConstraints(aConstraints
);
171 xSolver
->setMaximize(false);
175 CPPUNIT_ASSERT(xSolver
->getSuccess());
176 uno::Sequence
<double> aSolution
= xSolver
->getSolution();
178 CPPUNIT_ASSERT_EQUAL(aVariables
.getLength(), aSolution
.getLength());
179 CPPUNIT_ASSERT_DOUBLES_EQUAL(-0.741657, aSolution
[0], 1E-5);
182 void SwarmSolverTest::testTwoVariables()
184 loadFromFile(u
"TwoVariables.ods");
186 uno::Reference
<sheet::XSpreadsheetDocument
> xDocument(mxComponent
, uno::UNO_QUERY_THROW
);
187 uno::Reference
<container::XIndexAccess
> xIndex(xDocument
->getSheets(), uno::UNO_QUERY_THROW
);
188 uno::Reference
<sheet::XSpreadsheet
> xSheet(xIndex
->getByIndex(0), uno::UNO_QUERY_THROW
);
190 uno::Reference
<sheet::XSolver
> xSolver
;
192 xSolver
.set(m_xContext
->getServiceManager()->createInstanceWithContext(
193 u
"com.sun.star.comp.Calc.SwarmSolver"_ustr
, m_xContext
),
194 uno::UNO_QUERY_THROW
);
196 table::CellAddress
aObjective(0, 1, 5);
198 // "changing cells" - unknown variables
199 uno::Sequence
<table::CellAddress
> aVariables
{ { 0, 1, 2 }, { 0, 1, 3 } };
202 uno::Sequence
<sheet::SolverConstraint
> aConstraints
{
203 { /* [0] Left */ table::CellAddress(0, 1, 2),
204 /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL
,
205 /* Right */ uno::Any(-100.0) },
206 { /* [1] Left */ table::CellAddress(0, 1, 3),
207 /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL
,
208 /* Right */ uno::Any(-100.0) },
209 { /* [2] Left */ table::CellAddress(0, 1, 2),
210 /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL
,
211 /* Right */ uno::Any(100.0) },
212 { /* [3] Left */ table::CellAddress(0, 1, 3),
213 /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL
,
214 /* Right */ uno::Any(100.0) }
218 xSolver
->setDocument(xDocument
);
219 xSolver
->setObjective(aObjective
);
220 xSolver
->setVariables(aVariables
);
221 xSolver
->setConstraints(aConstraints
);
222 xSolver
->setMaximize(true);
226 CPPUNIT_ASSERT(xSolver
->getSuccess());
227 uno::Sequence
<double> aSolution
= xSolver
->getSolution();
229 CPPUNIT_ASSERT_EQUAL(aVariables
.getLength(), aSolution
.getLength());
230 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.666667, aSolution
[0], 1E-5);
231 CPPUNIT_ASSERT_DOUBLES_EQUAL(-1.666667, aSolution
[1], 1E-5);
234 void SwarmSolverTest::testMultipleVariables()
236 loadFromFile(u
"MultiVariable.ods");
238 uno::Reference
<sheet::XSpreadsheetDocument
> xDocument(mxComponent
, uno::UNO_QUERY_THROW
);
239 uno::Reference
<container::XIndexAccess
> xIndex(xDocument
->getSheets(), uno::UNO_QUERY_THROW
);
240 uno::Reference
<sheet::XSpreadsheet
> xSheet(xIndex
->getByIndex(0), uno::UNO_QUERY_THROW
);
242 uno::Reference
<sheet::XSolver
> xSolver
;
244 xSolver
.set(m_xContext
->getServiceManager()->createInstanceWithContext(
245 u
"com.sun.star.comp.Calc.SwarmSolver"_ustr
, m_xContext
),
246 uno::UNO_QUERY_THROW
);
248 uno::Reference
<beans::XPropertySet
> xPropSet(xSolver
, uno::UNO_QUERY_THROW
);
249 xPropSet
->setPropertyValue(u
"Integer"_ustr
, uno::Any(true));
251 table::CellAddress
aObjective(0, 5, 7);
253 // "changing cells" - unknown variables
254 uno::Sequence
<table::CellAddress
> aVariables
{
255 { 0, 6, 1 }, { 0, 6, 2 }, { 0, 6, 3 }, { 0, 6, 4 }
259 uno::Sequence
<sheet::SolverConstraint
> aConstraints
{
260 { /* [ 0] Left */ table::CellAddress(0, 1, 5),
261 /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL
,
262 /* Right */ uno::Any(table::CellAddress(0, 1, 6)) },
263 { /* [ 1] Left */ table::CellAddress(0, 2, 5),
264 /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL
,
265 /* Right */ uno::Any(table::CellAddress(0, 2, 6)) },
266 { /* [ 2] Left */ table::CellAddress(0, 3, 5),
267 /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL
,
268 /* Right */ uno::Any(table::CellAddress(0, 3, 6)) },
269 { /* [ 3] Left */ table::CellAddress(0, 4, 5),
270 /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL
,
271 /* Right */ uno::Any(table::CellAddress(0, 4, 6)) },
272 { /* [ 4] Left */ table::CellAddress(0, 6, 1),
273 /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL
,
274 /* Right */ uno::Any(0.0) },
275 { /* [ 5] Left */ table::CellAddress(0, 6, 2),
276 /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL
,
277 /* Right */ uno::Any(0.0) },
278 { /* [ 6] Left */ table::CellAddress(0, 6, 3),
279 /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL
,
280 /* Right */ uno::Any(0.0) },
281 { /* [ 7] Left */ table::CellAddress(0, 6, 4),
282 /* Operator */ sheet::SolverConstraintOperator_GREATER_EQUAL
,
283 /* Right */ uno::Any(0.0) },
284 { /* [ 8] Left */ table::CellAddress(0, 6, 1),
285 /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL
,
286 /* Right */ uno::Any(10000.0) },
287 { /* [ 9] Left */ table::CellAddress(0, 6, 2),
288 /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL
,
289 /* Right */ uno::Any(10000.0) },
290 { /* [10] Left */ table::CellAddress(0, 6, 3),
291 /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL
,
292 /* Right */ uno::Any(10000.0) },
293 { /* [11] Left */ table::CellAddress(0, 6, 4),
294 /* Operator */ sheet::SolverConstraintOperator_LESS_EQUAL
,
295 /* Right */ uno::Any(10000.0) }
299 xSolver
->setDocument(xDocument
);
300 xSolver
->setObjective(aObjective
);
301 xSolver
->setVariables(aVariables
);
302 xSolver
->setConstraints(aConstraints
);
303 xSolver
->setMaximize(false);
307 CPPUNIT_ASSERT(xSolver
->getSuccess());
308 uno::Sequence
<double> aSolution
= xSolver
->getSolution();
310 CPPUNIT_ASSERT_EQUAL(aVariables
.getLength(), aSolution
.getLength());
312 // Disable for now, needs algorithm stability improvements
313 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aSolution
[0], 1E-5);
314 CPPUNIT_ASSERT_DOUBLES_EQUAL(3.0, aSolution
[1], 1E-5);
315 CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, aSolution
[2], 1E-5);
316 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aSolution
[3], 1E-5);
320 CPPUNIT_TEST_SUITE_REGISTRATION(SwarmSolverTest
);
323 CPPUNIT_PLUGIN_IMPLEMENT();
325 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */