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/calc_unoapi_test.hxx>
23 class SwarmSolverTest
: public CalcUnoApiTest
25 uno::Reference
<lang::XComponent
> mxComponent
;
26 void testUnconstrained();
27 void testVariableBounded();
28 void testVariableConstrained();
29 void testTwoVariables();
30 void testMultipleVariables();
34 : CalcUnoApiTest("sccomp/qa/unit/data")
38 virtual void tearDown() override
;
40 CPPUNIT_TEST_SUITE(SwarmSolverTest
);
41 CPPUNIT_TEST(testUnconstrained
);
42 CPPUNIT_TEST(testVariableBounded
);
43 CPPUNIT_TEST(testVariableConstrained
);
44 CPPUNIT_TEST(testMultipleVariables
);
45 CPPUNIT_TEST(testTwoVariables
);
46 CPPUNIT_TEST_SUITE_END();
49 void SwarmSolverTest::tearDown()
52 closeDocument(mxComponent
);
55 void SwarmSolverTest::testUnconstrained()
57 CPPUNIT_ASSERT(!mxComponent
.is());
60 createFileURL("Simple.ods", aFileURL
);
61 mxComponent
= loadFromDesktop(aFileURL
);
63 CPPUNIT_ASSERT_MESSAGE("Component not loaded", mxComponent
.is());
65 uno::Reference
<sheet::XSpreadsheetDocument
> xDocument(mxComponent
, uno::UNO_QUERY_THROW
);
66 uno::Reference
<container::XIndexAccess
> xIndex(xDocument
->getSheets(), uno::UNO_QUERY_THROW
);
67 uno::Reference
<sheet::XSpreadsheet
> xSheet(xIndex
->getByIndex(0), uno::UNO_QUERY_THROW
);
69 uno::Reference
<sheet::XSolver
> xSolver
;
71 xSolver
.set(m_xContext
->getServiceManager()->createInstanceWithContext(
72 "com.sun.star.comp.Calc.SwarmSolver", m_xContext
),
73 uno::UNO_QUERY_THROW
);
75 table::CellAddress
aObjective(0, 1, 1);
77 // "changing cells" - unknown variables
78 uno::Sequence
<table::CellAddress
> aVariables(1);
79 aVariables
[0] = table::CellAddress(0, 1, 0);
82 uno::Sequence
<sheet::SolverConstraint
> aConstraints
;
85 xSolver
->setDocument(xDocument
);
86 xSolver
->setObjective(aObjective
);
87 xSolver
->setVariables(aVariables
);
88 xSolver
->setConstraints(aConstraints
);
89 xSolver
->setMaximize(false);
93 CPPUNIT_ASSERT(xSolver
->getSuccess());
94 uno::Sequence
<double> aSolution
= xSolver
->getSolution();
96 CPPUNIT_ASSERT_EQUAL(aVariables
.getLength(), aSolution
.getLength());
97 // It happens that the unconstrained test does not find a solution in the
98 // timeframe or number of generations it has available as the search space is
99 // too big and the values might not converge to solution. So for now just run
100 // the test so we know for sure the algorithm is guaranteed to finish
101 // and doesn't cause any seg faults.
102 //CPPUNIT_ASSERT_DOUBLES_EQUAL(3.0, aSolution[0], .9);
105 void SwarmSolverTest::testVariableBounded()
107 CPPUNIT_ASSERT(!mxComponent
.is());
110 createFileURL("Simple.ods", aFileURL
);
111 mxComponent
= loadFromDesktop(aFileURL
);
113 CPPUNIT_ASSERT_MESSAGE("Component not loaded", mxComponent
.is());
115 uno::Reference
<sheet::XSpreadsheetDocument
> xDocument(mxComponent
, uno::UNO_QUERY_THROW
);
116 uno::Reference
<container::XIndexAccess
> xIndex(xDocument
->getSheets(), uno::UNO_QUERY_THROW
);
117 uno::Reference
<sheet::XSpreadsheet
> xSheet(xIndex
->getByIndex(0), uno::UNO_QUERY_THROW
);
119 uno::Reference
<sheet::XSolver
> xSolver
;
121 xSolver
.set(m_xContext
->getServiceManager()->createInstanceWithContext(
122 "com.sun.star.comp.Calc.SwarmSolver", m_xContext
),
123 uno::UNO_QUERY_THROW
);
125 table::CellAddress
aObjective(0, 1, 1);
127 // "changing cells" - unknown variables
128 uno::Sequence
<table::CellAddress
> aVariables(1);
129 aVariables
[0] = table::CellAddress(0, 1, 0);
132 uno::Sequence
<sheet::SolverConstraint
> aConstraints(2);
133 aConstraints
[0].Left
= table::CellAddress(0, 1, 0);
134 aConstraints
[0].Operator
= sheet::SolverConstraintOperator_LESS_EQUAL
;
135 aConstraints
[0].Right
<<= 100.0;
137 aConstraints
[1].Left
= table::CellAddress(0, 1, 0);
138 aConstraints
[1].Operator
= sheet::SolverConstraintOperator_GREATER_EQUAL
;
139 aConstraints
[1].Right
<<= -100.0;
142 xSolver
->setDocument(xDocument
);
143 xSolver
->setObjective(aObjective
);
144 xSolver
->setVariables(aVariables
);
145 xSolver
->setConstraints(aConstraints
);
146 xSolver
->setMaximize(false);
150 CPPUNIT_ASSERT(xSolver
->getSuccess());
151 uno::Sequence
<double> aSolution
= xSolver
->getSolution();
153 CPPUNIT_ASSERT_EQUAL(aVariables
.getLength(), aSolution
.getLength());
154 CPPUNIT_ASSERT_DOUBLES_EQUAL(3.0, aSolution
[0], 1E-5);
157 void SwarmSolverTest::testVariableConstrained()
159 CPPUNIT_ASSERT(!mxComponent
.is());
162 createFileURL("Simple.ods", aFileURL
);
163 mxComponent
= loadFromDesktop(aFileURL
);
165 CPPUNIT_ASSERT_MESSAGE("Component not loaded", mxComponent
.is());
167 uno::Reference
<sheet::XSpreadsheetDocument
> xDocument(mxComponent
, uno::UNO_QUERY_THROW
);
168 uno::Reference
<container::XIndexAccess
> xIndex(xDocument
->getSheets(), uno::UNO_QUERY_THROW
);
169 uno::Reference
<sheet::XSpreadsheet
> xSheet(xIndex
->getByIndex(0), uno::UNO_QUERY_THROW
);
171 uno::Reference
<sheet::XSolver
> xSolver
;
173 xSolver
.set(m_xContext
->getServiceManager()->createInstanceWithContext(
174 "com.sun.star.comp.Calc.SwarmSolver", m_xContext
),
175 uno::UNO_QUERY_THROW
);
177 table::CellAddress
aObjective(0, 1, 1);
179 // "changing cells" - unknown variables
180 uno::Sequence
<table::CellAddress
> aVariables(1);
181 aVariables
[0] = table::CellAddress(0, 1, 0);
184 uno::Sequence
<sheet::SolverConstraint
> aConstraints(3);
185 aConstraints
[0].Left
= table::CellAddress(0, 1, 0);
186 aConstraints
[0].Operator
= sheet::SolverConstraintOperator_GREATER_EQUAL
;
187 aConstraints
[0].Right
<<= -50000.0;
189 aConstraints
[1].Left
= table::CellAddress(0, 1, 0);
190 aConstraints
[1].Operator
= sheet::SolverConstraintOperator_LESS_EQUAL
;
191 aConstraints
[1].Right
<<= 0.0;
193 aConstraints
[2].Left
= table::CellAddress(0, 1, 1);
194 aConstraints
[2].Operator
= sheet::SolverConstraintOperator_GREATER_EQUAL
;
195 aConstraints
[2].Right
<<= 10.0;
198 xSolver
->setDocument(xDocument
);
199 xSolver
->setObjective(aObjective
);
200 xSolver
->setVariables(aVariables
);
201 xSolver
->setConstraints(aConstraints
);
202 xSolver
->setMaximize(false);
206 CPPUNIT_ASSERT(xSolver
->getSuccess());
207 uno::Sequence
<double> aSolution
= xSolver
->getSolution();
209 CPPUNIT_ASSERT_EQUAL(aVariables
.getLength(), aSolution
.getLength());
210 CPPUNIT_ASSERT_DOUBLES_EQUAL(-0.741657, aSolution
[0], 1E-5);
213 void SwarmSolverTest::testTwoVariables()
215 CPPUNIT_ASSERT(!mxComponent
.is());
218 createFileURL("TwoVariables.ods", aFileURL
);
219 mxComponent
= loadFromDesktop(aFileURL
);
221 CPPUNIT_ASSERT_MESSAGE("Component not loaded", mxComponent
.is());
223 uno::Reference
<sheet::XSpreadsheetDocument
> xDocument(mxComponent
, uno::UNO_QUERY_THROW
);
224 uno::Reference
<container::XIndexAccess
> xIndex(xDocument
->getSheets(), uno::UNO_QUERY_THROW
);
225 uno::Reference
<sheet::XSpreadsheet
> xSheet(xIndex
->getByIndex(0), uno::UNO_QUERY_THROW
);
227 uno::Reference
<sheet::XSolver
> xSolver
;
229 xSolver
.set(m_xContext
->getServiceManager()->createInstanceWithContext(
230 "com.sun.star.comp.Calc.SwarmSolver", m_xContext
),
231 uno::UNO_QUERY_THROW
);
233 table::CellAddress
aObjective(0, 1, 5);
235 // "changing cells" - unknown variables
236 uno::Sequence
<table::CellAddress
> aVariables(2);
237 aVariables
[0] = table::CellAddress(0, 1, 2);
238 aVariables
[1] = table::CellAddress(0, 1, 3);
241 uno::Sequence
<sheet::SolverConstraint
> aConstraints(4);
243 aConstraints
[0].Left
= table::CellAddress(0, 1, 2);
244 aConstraints
[0].Operator
= sheet::SolverConstraintOperator_GREATER_EQUAL
;
245 aConstraints
[0].Right
<<= -100.0;
247 aConstraints
[1].Left
= table::CellAddress(0, 1, 3);
248 aConstraints
[1].Operator
= sheet::SolverConstraintOperator_GREATER_EQUAL
;
249 aConstraints
[1].Right
<<= -100.0;
251 aConstraints
[2].Left
= table::CellAddress(0, 1, 2);
252 aConstraints
[2].Operator
= sheet::SolverConstraintOperator_LESS_EQUAL
;
253 aConstraints
[2].Right
<<= 100.0;
255 aConstraints
[3].Left
= table::CellAddress(0, 1, 3);
256 aConstraints
[3].Operator
= sheet::SolverConstraintOperator_LESS_EQUAL
;
257 aConstraints
[3].Right
<<= 100.0;
260 xSolver
->setDocument(xDocument
);
261 xSolver
->setObjective(aObjective
);
262 xSolver
->setVariables(aVariables
);
263 xSolver
->setConstraints(aConstraints
);
264 xSolver
->setMaximize(true);
268 CPPUNIT_ASSERT(xSolver
->getSuccess());
269 uno::Sequence
<double> aSolution
= xSolver
->getSolution();
271 CPPUNIT_ASSERT_EQUAL(aVariables
.getLength(), aSolution
.getLength());
272 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.666667, aSolution
[0], 1E-5);
273 CPPUNIT_ASSERT_DOUBLES_EQUAL(-1.666667, aSolution
[1], 1E-5);
276 void SwarmSolverTest::testMultipleVariables()
278 CPPUNIT_ASSERT(!mxComponent
.is());
281 createFileURL("MultiVariable.ods", aFileURL
);
282 mxComponent
= loadFromDesktop(aFileURL
);
284 CPPUNIT_ASSERT_MESSAGE("Component not loaded", mxComponent
.is());
286 uno::Reference
<sheet::XSpreadsheetDocument
> xDocument(mxComponent
, uno::UNO_QUERY_THROW
);
287 uno::Reference
<container::XIndexAccess
> xIndex(xDocument
->getSheets(), uno::UNO_QUERY_THROW
);
288 uno::Reference
<sheet::XSpreadsheet
> xSheet(xIndex
->getByIndex(0), uno::UNO_QUERY_THROW
);
290 uno::Reference
<sheet::XSolver
> xSolver
;
292 xSolver
.set(m_xContext
->getServiceManager()->createInstanceWithContext(
293 "com.sun.star.comp.Calc.SwarmSolver", m_xContext
),
294 uno::UNO_QUERY_THROW
);
296 uno::Reference
<beans::XPropertySet
> xPropSet(xSolver
, uno::UNO_QUERY_THROW
);
297 xPropSet
->setPropertyValue("Integer", uno::makeAny(true));
299 table::CellAddress
aObjective(0, 5, 7);
301 // "changing cells" - unknown variables
302 uno::Sequence
<table::CellAddress
> aVariables(4);
303 aVariables
[0] = table::CellAddress(0, 6, 1);
304 aVariables
[1] = table::CellAddress(0, 6, 2);
305 aVariables
[2] = table::CellAddress(0, 6, 3);
306 aVariables
[3] = table::CellAddress(0, 6, 4);
309 uno::Sequence
<sheet::SolverConstraint
> aConstraints(12);
311 aConstraints
[0].Left
= table::CellAddress(0, 1, 5);
312 aConstraints
[0].Operator
= sheet::SolverConstraintOperator_GREATER_EQUAL
;
313 aConstraints
[0].Right
<<= table::CellAddress(0, 1, 6);
315 aConstraints
[1].Left
= table::CellAddress(0, 2, 5);
316 aConstraints
[1].Operator
= sheet::SolverConstraintOperator_GREATER_EQUAL
;
317 aConstraints
[1].Right
<<= table::CellAddress(0, 2, 6);
319 aConstraints
[2].Left
= table::CellAddress(0, 3, 5);
320 aConstraints
[2].Operator
= sheet::SolverConstraintOperator_GREATER_EQUAL
;
321 aConstraints
[2].Right
<<= table::CellAddress(0, 3, 6);
323 aConstraints
[3].Left
= table::CellAddress(0, 4, 5);
324 aConstraints
[3].Operator
= sheet::SolverConstraintOperator_GREATER_EQUAL
;
325 aConstraints
[3].Right
<<= table::CellAddress(0, 4, 6);
327 aConstraints
[4].Left
= table::CellAddress(0, 6, 1);
328 aConstraints
[4].Operator
= sheet::SolverConstraintOperator_GREATER_EQUAL
;
329 aConstraints
[4].Right
<<= 0.0;
331 aConstraints
[5].Left
= table::CellAddress(0, 6, 2);
332 aConstraints
[5].Operator
= sheet::SolverConstraintOperator_GREATER_EQUAL
;
333 aConstraints
[5].Right
<<= 0.0;
335 aConstraints
[6].Left
= table::CellAddress(0, 6, 3);
336 aConstraints
[6].Operator
= sheet::SolverConstraintOperator_GREATER_EQUAL
;
337 aConstraints
[6].Right
<<= 0.0;
339 aConstraints
[7].Left
= table::CellAddress(0, 6, 4);
340 aConstraints
[7].Operator
= sheet::SolverConstraintOperator_GREATER_EQUAL
;
341 aConstraints
[7].Right
<<= 0.0;
343 aConstraints
[8].Left
= table::CellAddress(0, 6, 1);
344 aConstraints
[8].Operator
= sheet::SolverConstraintOperator_LESS_EQUAL
;
345 aConstraints
[8].Right
<<= 10000.0;
347 aConstraints
[9].Left
= table::CellAddress(0, 6, 2);
348 aConstraints
[9].Operator
= sheet::SolverConstraintOperator_LESS_EQUAL
;
349 aConstraints
[9].Right
<<= 10000.0;
351 aConstraints
[10].Left
= table::CellAddress(0, 6, 3);
352 aConstraints
[10].Operator
= sheet::SolverConstraintOperator_LESS_EQUAL
;
353 aConstraints
[10].Right
<<= 10000.0;
355 aConstraints
[11].Left
= table::CellAddress(0, 6, 4);
356 aConstraints
[11].Operator
= sheet::SolverConstraintOperator_LESS_EQUAL
;
357 aConstraints
[11].Right
<<= 10000.0;
360 xSolver
->setDocument(xDocument
);
361 xSolver
->setObjective(aObjective
);
362 xSolver
->setVariables(aVariables
);
363 xSolver
->setConstraints(aConstraints
);
364 xSolver
->setMaximize(false);
368 CPPUNIT_ASSERT(xSolver
->getSuccess());
369 uno::Sequence
<double> aSolution
= xSolver
->getSolution();
371 CPPUNIT_ASSERT_EQUAL(aVariables
.getLength(), aSolution
.getLength());
373 // Disable for now, needs algorithm stability improvements
374 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aSolution
[0], 1E-5);
375 CPPUNIT_ASSERT_DOUBLES_EQUAL(3.0, aSolution
[1], 1E-5);
376 CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, aSolution
[2], 1E-5);
377 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aSolution
[3], 1E-5);
381 CPPUNIT_TEST_SUITE_REGISTRATION(SwarmSolverTest
);
384 CPPUNIT_PLUGIN_IMPLEMENT();
386 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */