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/container/XContentEnumerationAccess.hpp>
13 #include <com/sun/star/frame/Desktop.hpp>
14 #include <com/sun/star/lang/XServiceInfo.hpp>
15 #include <com/sun/star/sheet/XSolver.hpp>
16 #include <com/sun/star/sheet/XSolverDescription.hpp>
17 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
18 #include <com/sun/star/sheet/XSpreadsheet.hpp>
19 #include <com/sun/star/text/XTextRange.hpp>
20 #include <com/sun/star/beans/XPropertySet.hpp>
22 #include <test/calc_unoapi_test.hxx>
24 #include <address.hxx>
30 class SwarmSolverTest
: public CalcUnoApiTest
32 uno::Reference
<lang::XComponent
> mxComponent
;
33 void testUnconstrained();
34 void testVariableBounded();
35 void testVariableConstrained();
36 void testTwoVariables();
37 void testMultipleVariables();
41 : CalcUnoApiTest("sccomp/qa/unit/data")
45 virtual void tearDown() override
;
47 CPPUNIT_TEST_SUITE(SwarmSolverTest
);
48 CPPUNIT_TEST(testUnconstrained
);
49 CPPUNIT_TEST(testVariableBounded
);
50 CPPUNIT_TEST(testVariableConstrained
);
51 CPPUNIT_TEST(testMultipleVariables
);
52 CPPUNIT_TEST(testTwoVariables
);
53 CPPUNIT_TEST_SUITE_END();
56 void SwarmSolverTest::tearDown()
59 closeDocument(mxComponent
);
62 void SwarmSolverTest::testUnconstrained()
64 CPPUNIT_ASSERT(!mxComponent
.is());
67 createFileURL("Simple.ods", aFileURL
);
68 mxComponent
= loadFromDesktop(aFileURL
);
70 CPPUNIT_ASSERT_MESSAGE("Component not loaded", mxComponent
.is());
72 uno::Reference
<sheet::XSpreadsheetDocument
> xDocument(mxComponent
, uno::UNO_QUERY_THROW
);
73 uno::Reference
<container::XIndexAccess
> xIndex(xDocument
->getSheets(), uno::UNO_QUERY_THROW
);
74 uno::Reference
<sheet::XSpreadsheet
> xSheet(xIndex
->getByIndex(0), uno::UNO_QUERY_THROW
);
76 uno::Reference
<table::XCell
> xCell
;
78 uno::Reference
<sheet::XSolver
> xSolver
;
79 OUString
sSolverName("com.sun.star.comp.Calc.SwarmSolver");
81 xSolver
.set(m_xContext
->getServiceManager()->createInstanceWithContext(sSolverName
, m_xContext
),
82 uno::UNO_QUERY_THROW
);
84 table::CellAddress
aObjective(0, 1, 1);
86 // "changing cells" - unknown variables
87 uno::Sequence
<table::CellAddress
> aVariables(1);
88 aVariables
[0] = table::CellAddress(0, 1, 0);
91 uno::Sequence
<sheet::SolverConstraint
> aConstraints
;
94 xSolver
->setDocument(xDocument
);
95 xSolver
->setObjective(aObjective
);
96 xSolver
->setVariables(aVariables
);
97 xSolver
->setConstraints(aConstraints
);
98 xSolver
->setMaximize(false);
102 CPPUNIT_ASSERT(xSolver
->getSuccess());
103 uno::Sequence
<double> aSolution
= xSolver
->getSolution();
105 CPPUNIT_ASSERT_EQUAL(aSolution
.getLength(), aVariables
.getLength());
106 // It happens that the unconstrained test does not find a solution in the
107 // timeframe or number of generations it has available as the search space is
108 // too big and the values might not converge to solution. So for now just run
109 // the test so we know for sure the algorithm is guaranteed to finish
110 // and doesn't cause any seg faults.
111 //CPPUNIT_ASSERT_DOUBLES_EQUAL(3.0, aSolution[0], .9);
114 void SwarmSolverTest::testVariableBounded()
116 CPPUNIT_ASSERT(!mxComponent
.is());
119 createFileURL("Simple.ods", aFileURL
);
120 mxComponent
= loadFromDesktop(aFileURL
);
122 CPPUNIT_ASSERT_MESSAGE("Component not loaded", mxComponent
.is());
124 uno::Reference
<sheet::XSpreadsheetDocument
> xDocument(mxComponent
, uno::UNO_QUERY_THROW
);
125 uno::Reference
<container::XIndexAccess
> xIndex(xDocument
->getSheets(), uno::UNO_QUERY_THROW
);
126 uno::Reference
<sheet::XSpreadsheet
> xSheet(xIndex
->getByIndex(0), uno::UNO_QUERY_THROW
);
128 uno::Reference
<table::XCell
> xCell
;
130 uno::Reference
<sheet::XSolver
> xSolver
;
131 OUString
sSolverName("com.sun.star.comp.Calc.SwarmSolver");
133 xSolver
.set(m_xContext
->getServiceManager()->createInstanceWithContext(sSolverName
, m_xContext
),
134 uno::UNO_QUERY_THROW
);
136 table::CellAddress
aObjective(0, 1, 1);
138 // "changing cells" - unknown variables
139 uno::Sequence
<table::CellAddress
> aVariables(1);
140 aVariables
[0] = table::CellAddress(0, 1, 0);
143 uno::Sequence
<sheet::SolverConstraint
> aConstraints(2);
144 aConstraints
[0].Left
= table::CellAddress(0, 1, 0);
145 aConstraints
[0].Operator
= sheet::SolverConstraintOperator_LESS_EQUAL
;
146 aConstraints
[0].Right
<<= 100.0;
148 aConstraints
[1].Left
= table::CellAddress(0, 1, 0);
149 aConstraints
[1].Operator
= sheet::SolverConstraintOperator_GREATER_EQUAL
;
150 aConstraints
[1].Right
<<= -100.0;
153 xSolver
->setDocument(xDocument
);
154 xSolver
->setObjective(aObjective
);
155 xSolver
->setVariables(aVariables
);
156 xSolver
->setConstraints(aConstraints
);
157 xSolver
->setMaximize(false);
161 CPPUNIT_ASSERT(xSolver
->getSuccess());
162 uno::Sequence
<double> aSolution
= xSolver
->getSolution();
164 CPPUNIT_ASSERT_EQUAL(aSolution
.getLength(), aVariables
.getLength());
165 CPPUNIT_ASSERT_DOUBLES_EQUAL(3.0, aSolution
[0], 1E-5);
168 void SwarmSolverTest::testVariableConstrained()
170 CPPUNIT_ASSERT(!mxComponent
.is());
173 createFileURL("Simple.ods", aFileURL
);
174 mxComponent
= loadFromDesktop(aFileURL
);
176 CPPUNIT_ASSERT_MESSAGE("Component not loaded", mxComponent
.is());
178 uno::Reference
<sheet::XSpreadsheetDocument
> xDocument(mxComponent
, uno::UNO_QUERY_THROW
);
179 uno::Reference
<container::XIndexAccess
> xIndex(xDocument
->getSheets(), uno::UNO_QUERY_THROW
);
180 uno::Reference
<sheet::XSpreadsheet
> xSheet(xIndex
->getByIndex(0), uno::UNO_QUERY_THROW
);
182 uno::Reference
<table::XCell
> xCell
;
184 uno::Reference
<sheet::XSolver
> xSolver
;
185 OUString
sSolverName("com.sun.star.comp.Calc.SwarmSolver");
187 xSolver
.set(m_xContext
->getServiceManager()->createInstanceWithContext(sSolverName
, m_xContext
),
188 uno::UNO_QUERY_THROW
);
190 table::CellAddress
aObjective(0, 1, 1);
192 // "changing cells" - unknown variables
193 uno::Sequence
<table::CellAddress
> aVariables(1);
194 aVariables
[0] = table::CellAddress(0, 1, 0);
197 uno::Sequence
<sheet::SolverConstraint
> aConstraints(3);
198 aConstraints
[0].Left
= table::CellAddress(0, 1, 0);
199 aConstraints
[0].Operator
= sheet::SolverConstraintOperator_GREATER_EQUAL
;
200 aConstraints
[0].Right
<<= -50000.0;
202 aConstraints
[1].Left
= table::CellAddress(0, 1, 0);
203 aConstraints
[1].Operator
= sheet::SolverConstraintOperator_LESS_EQUAL
;
204 aConstraints
[1].Right
<<= 0.0;
206 aConstraints
[2].Left
= table::CellAddress(0, 1, 1);
207 aConstraints
[2].Operator
= sheet::SolverConstraintOperator_GREATER_EQUAL
;
208 aConstraints
[2].Right
<<= 10.0;
211 xSolver
->setDocument(xDocument
);
212 xSolver
->setObjective(aObjective
);
213 xSolver
->setVariables(aVariables
);
214 xSolver
->setConstraints(aConstraints
);
215 xSolver
->setMaximize(false);
219 CPPUNIT_ASSERT(xSolver
->getSuccess());
220 uno::Sequence
<double> aSolution
= xSolver
->getSolution();
222 CPPUNIT_ASSERT_EQUAL(aSolution
.getLength(), aVariables
.getLength());
223 CPPUNIT_ASSERT_DOUBLES_EQUAL(-0.741657, aSolution
[0], 1E-5);
226 void SwarmSolverTest::testTwoVariables()
228 CPPUNIT_ASSERT(!mxComponent
.is());
231 createFileURL("TwoVariables.ods", aFileURL
);
232 mxComponent
= loadFromDesktop(aFileURL
);
234 CPPUNIT_ASSERT_MESSAGE("Component not loaded", mxComponent
.is());
236 uno::Reference
<sheet::XSpreadsheetDocument
> xDocument(mxComponent
, uno::UNO_QUERY_THROW
);
237 uno::Reference
<container::XIndexAccess
> xIndex(xDocument
->getSheets(), uno::UNO_QUERY_THROW
);
238 uno::Reference
<sheet::XSpreadsheet
> xSheet(xIndex
->getByIndex(0), uno::UNO_QUERY_THROW
);
240 uno::Reference
<table::XCell
> xCell
;
242 uno::Reference
<sheet::XSolver
> xSolver
;
243 OUString
sSolverName("com.sun.star.comp.Calc.SwarmSolver");
245 xSolver
.set(m_xContext
->getServiceManager()->createInstanceWithContext(sSolverName
, m_xContext
),
246 uno::UNO_QUERY_THROW
);
248 table::CellAddress
aObjective(0, 1, 5);
250 // "changing cells" - unknown variables
251 uno::Sequence
<table::CellAddress
> aVariables(2);
252 aVariables
[0] = table::CellAddress(0, 1, 2);
253 aVariables
[1] = table::CellAddress(0, 1, 3);
256 uno::Sequence
<sheet::SolverConstraint
> aConstraints(4);
258 aConstraints
[0].Left
= table::CellAddress(0, 1, 2);
259 aConstraints
[0].Operator
= sheet::SolverConstraintOperator_GREATER_EQUAL
;
260 aConstraints
[0].Right
<<= -100.0;
262 aConstraints
[1].Left
= table::CellAddress(0, 1, 3);
263 aConstraints
[1].Operator
= sheet::SolverConstraintOperator_GREATER_EQUAL
;
264 aConstraints
[1].Right
<<= -100.0;
266 aConstraints
[2].Left
= table::CellAddress(0, 1, 2);
267 aConstraints
[2].Operator
= sheet::SolverConstraintOperator_LESS_EQUAL
;
268 aConstraints
[2].Right
<<= 100.0;
270 aConstraints
[3].Left
= table::CellAddress(0, 1, 3);
271 aConstraints
[3].Operator
= sheet::SolverConstraintOperator_LESS_EQUAL
;
272 aConstraints
[3].Right
<<= 100.0;
275 xSolver
->setDocument(xDocument
);
276 xSolver
->setObjective(aObjective
);
277 xSolver
->setVariables(aVariables
);
278 xSolver
->setConstraints(aConstraints
);
279 xSolver
->setMaximize(true);
283 CPPUNIT_ASSERT(xSolver
->getSuccess());
284 uno::Sequence
<double> aSolution
= xSolver
->getSolution();
286 CPPUNIT_ASSERT_EQUAL(aVariables
.getLength(), aSolution
.getLength());
287 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.666667, aSolution
[0], 1E-5);
288 CPPUNIT_ASSERT_DOUBLES_EQUAL(-1.666667, aSolution
[1], 1E-5);
291 void SwarmSolverTest::testMultipleVariables()
293 CPPUNIT_ASSERT(!mxComponent
.is());
296 createFileURL("MultiVariable.ods", aFileURL
);
297 mxComponent
= loadFromDesktop(aFileURL
);
299 CPPUNIT_ASSERT_MESSAGE("Component not loaded", mxComponent
.is());
301 uno::Reference
<sheet::XSpreadsheetDocument
> xDocument(mxComponent
, uno::UNO_QUERY_THROW
);
302 uno::Reference
<container::XIndexAccess
> xIndex(xDocument
->getSheets(), uno::UNO_QUERY_THROW
);
303 uno::Reference
<sheet::XSpreadsheet
> xSheet(xIndex
->getByIndex(0), uno::UNO_QUERY_THROW
);
305 uno::Reference
<table::XCell
> xCell
;
307 uno::Reference
<sheet::XSolver
> xSolver
;
308 OUString
sSolverName("com.sun.star.comp.Calc.SwarmSolver");
310 xSolver
.set(m_xContext
->getServiceManager()->createInstanceWithContext(sSolverName
, m_xContext
),
311 uno::UNO_QUERY_THROW
);
313 uno::Reference
<beans::XPropertySet
> xPropSet(xSolver
, uno::UNO_QUERY_THROW
);
314 xPropSet
->setPropertyValue("Integer", uno::makeAny(true));
316 table::CellAddress
aObjective(0, 5, 7);
318 // "changing cells" - unknown variables
319 uno::Sequence
<table::CellAddress
> aVariables(4);
320 aVariables
[0] = table::CellAddress(0, 6, 1);
321 aVariables
[1] = table::CellAddress(0, 6, 2);
322 aVariables
[2] = table::CellAddress(0, 6, 3);
323 aVariables
[3] = table::CellAddress(0, 6, 4);
326 uno::Sequence
<sheet::SolverConstraint
> aConstraints(12);
328 aConstraints
[0].Left
= table::CellAddress(0, 1, 5);
329 aConstraints
[0].Operator
= sheet::SolverConstraintOperator_GREATER_EQUAL
;
330 aConstraints
[0].Right
<<= table::CellAddress(0, 1, 6);
332 aConstraints
[1].Left
= table::CellAddress(0, 2, 5);
333 aConstraints
[1].Operator
= sheet::SolverConstraintOperator_GREATER_EQUAL
;
334 aConstraints
[1].Right
<<= table::CellAddress(0, 2, 6);
336 aConstraints
[2].Left
= table::CellAddress(0, 3, 5);
337 aConstraints
[2].Operator
= sheet::SolverConstraintOperator_GREATER_EQUAL
;
338 aConstraints
[2].Right
<<= table::CellAddress(0, 3, 6);
340 aConstraints
[3].Left
= table::CellAddress(0, 4, 5);
341 aConstraints
[3].Operator
= sheet::SolverConstraintOperator_GREATER_EQUAL
;
342 aConstraints
[3].Right
<<= table::CellAddress(0, 4, 6);
344 aConstraints
[4].Left
= table::CellAddress(0, 6, 1);
345 aConstraints
[4].Operator
= sheet::SolverConstraintOperator_GREATER_EQUAL
;
346 aConstraints
[4].Right
<<= 0.0;
348 aConstraints
[5].Left
= table::CellAddress(0, 6, 2);
349 aConstraints
[5].Operator
= sheet::SolverConstraintOperator_GREATER_EQUAL
;
350 aConstraints
[5].Right
<<= 0.0;
352 aConstraints
[6].Left
= table::CellAddress(0, 6, 3);
353 aConstraints
[6].Operator
= sheet::SolverConstraintOperator_GREATER_EQUAL
;
354 aConstraints
[6].Right
<<= 0.0;
356 aConstraints
[7].Left
= table::CellAddress(0, 6, 4);
357 aConstraints
[7].Operator
= sheet::SolverConstraintOperator_GREATER_EQUAL
;
358 aConstraints
[7].Right
<<= 0.0;
360 aConstraints
[8].Left
= table::CellAddress(0, 6, 1);
361 aConstraints
[8].Operator
= sheet::SolverConstraintOperator_LESS_EQUAL
;
362 aConstraints
[8].Right
<<= 10000.0;
364 aConstraints
[9].Left
= table::CellAddress(0, 6, 2);
365 aConstraints
[9].Operator
= sheet::SolverConstraintOperator_LESS_EQUAL
;
366 aConstraints
[9].Right
<<= 10000.0;
368 aConstraints
[10].Left
= table::CellAddress(0, 6, 3);
369 aConstraints
[10].Operator
= sheet::SolverConstraintOperator_LESS_EQUAL
;
370 aConstraints
[10].Right
<<= 10000.0;
372 aConstraints
[11].Left
= table::CellAddress(0, 6, 4);
373 aConstraints
[11].Operator
= sheet::SolverConstraintOperator_LESS_EQUAL
;
374 aConstraints
[11].Right
<<= 10000.0;
377 xSolver
->setDocument(xDocument
);
378 xSolver
->setObjective(aObjective
);
379 xSolver
->setVariables(aVariables
);
380 xSolver
->setConstraints(aConstraints
);
381 xSolver
->setMaximize(false);
385 CPPUNIT_ASSERT(xSolver
->getSuccess());
386 uno::Sequence
<double> aSolution
= xSolver
->getSolution();
388 CPPUNIT_ASSERT_EQUAL(aVariables
.getLength(), aSolution
.getLength());
390 // Disable for now, needs algorithm stability improvements
391 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aSolution
[0], 1E-5);
392 CPPUNIT_ASSERT_DOUBLES_EQUAL(3.0, aSolution
[1], 1E-5);
393 CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, aSolution
[2], 1E-5);
394 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aSolution
[3], 1E-5);
398 CPPUNIT_TEST_SUITE_REGISTRATION(SwarmSolverTest
);
401 CPPUNIT_PLUGIN_IMPLEMENT();
403 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */