source: src/unittests/SubspaceFactorizerUnitTest.cpp@ 1f91f4

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults AddingActions_SaveParseParticleParameters Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_ParticleName_to_Atom Adding_StructOpt_integration_tests AtomFragments Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator CombiningParticlePotentialParsing Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_BoundInBox_CenterInBox_MoleculeActions Fix_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions Fix_PopActions Fix_QtFragmentList_sorted_selection Fix_Restrictedkeyset_FragmentMolecule Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns Fix_fitting_potentials Fixes ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion FragmentAction_writes_AtomFragments FragmentMolecule_checks_bonddegrees GeometryObjects Gui_Fixes Gui_displays_atomic_force_velocity ImplicitCharges IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix MoreRobust_FragmentAutomation ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PdbParser_setsAtomName PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks Rewrite_FitPartialCharges RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg Switchable_LogView ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps TremoloParser_setsAtomName Ubuntu_1604_changes stable
Last change on this file since 1f91f4 was ad011c, checked in by Frederik Heber <heber@…>, 14 years ago

CodePatterns places all includes now in subfolder CodePatterns/.

  • change all includes accordingly.
  • this was necessary as Helpers and Patterns are not very distinctive names for include folders. Already now, we had a conflict between Helpers from CodePatterns and Helpers from this project.
  • changed compilation test in ax_codepatterns.m4 when changing CodePatterns includes.
  • Property mode set to 100644
File size: 31.7 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010 University of Bonn. All rights reserved.
5 * Please see the LICENSE file or "Copyright notice" in builder.cpp for details.
6 */
7
8/*
9 * SubspaceFactorizerUnitTest.cpp
10 *
11 * Created on: Nov 13, 2010
12 * Author: heber
13 */
14
15// include config.h
16#ifdef HAVE_CONFIG_H
17#include <config.h>
18#endif
19
20#include <cppunit/CompilerOutputter.h>
21#include <cppunit/extensions/TestFactoryRegistry.h>
22#include <cppunit/ui/text/TestRunner.h>
23
24#include <cmath>
25
26#include <gsl/gsl_vector.h>
27#include <boost/foreach.hpp>
28#include <boost/shared_ptr.hpp>
29#include <boost/timer.hpp>
30
31#include "CodePatterns/Assert.hpp"
32#include "Helpers/defs.hpp"
33#include "CodePatterns/Log.hpp"
34#include "CodePatterns/toString.hpp"
35#include "CodePatterns/Verbose.hpp"
36#include "LinearAlgebra/Eigenspace.hpp"
37#include "LinearAlgebra/MatrixContent.hpp"
38#include "LinearAlgebra/Subspace.hpp"
39#include "LinearAlgebra/VectorContent.hpp"
40
41#include "SubspaceFactorizerUnitTest.hpp"
42
43#ifdef HAVE_TESTRUNNER
44#include "UnitTestMain.hpp"
45#endif /*HAVE_TESTRUNNER*/
46
47// Registers the fixture into the 'registry'
48CPPUNIT_TEST_SUITE_REGISTRATION( SubspaceFactorizerUnittest );
49
50void SubspaceFactorizerUnittest::setUp(){
51 matrix = new MatrixContent(matrixdimension,matrixdimension);
52 matrix->setZero();
53 for (size_t i=0; i<matrixdimension ; i++) {
54 for (size_t j=0; j<= i; ++j) {
55 //const double value = 10. * rand() / (double)RAND_MAX;
56 //const double value = i==j ? 2. : 1.;
57 if (i==j)
58 matrix->set(i,i, 2.);
59 else if (j+1 == i) {
60 matrix->set(i,j, 1.);
61 matrix->set(j,i, 1.);
62 } else {
63 matrix->set(i,j, 0.);
64 matrix->set(j,i, 0.);
65 }
66 }
67 }
68}
69
70void SubspaceFactorizerUnittest::tearDown(){
71 // delete test matrix
72 delete matrix;
73}
74
75void SubspaceFactorizerUnittest::BlockTest()
76{
77 MatrixContent *transformation = new MatrixContent(matrixdimension,matrixdimension);
78 transformation->setZero();
79 for (size_t j=0; j<1; ++j)
80 transformation->set(j,j, 1.);
81
82 MatrixContent temp((*matrix)&(*transformation));
83 std::cout << "Our matrix is " << *matrix << "." << std::endl;
84
85 std::cout << "Hadamard product of " << *matrix << " with " << *transformation << " is: " << std::endl;
86 std::cout << temp << std::endl;
87
88 gsl_vector *eigenvalues = temp.transformToEigenbasis();
89 VectorContent *eigenvaluesView = new VectorViewContent(gsl_vector_subvector(eigenvalues, 0, eigenvalues->size));
90 std::cout << "The resulting eigenbasis is " << temp
91 << "\n\t with eigenvalues " << *eigenvaluesView << std::endl;
92 delete eigenvaluesView;
93 gsl_vector_free(eigenvalues);
94 delete (transformation);
95
96
97 CPPUNIT_ASSERT_EQUAL(0,0);
98}
99
100/** For given set of row and column indices, we extract the small block matrix.
101 * @param bigmatrix big matrix to extract from
102 * @param Eigenvectors eigenvectors of the subspaces to obtain matrix in
103 * @param columnindexset index set to pick out of all indices
104 * @return small matrix with dimension equal to the number of indices for row and column.
105 */
106MatrixContent * getSubspaceMatrix(
107 MatrixContent &bigmatrix,
108 VectorArray &Eigenvectors,
109 const IndexSet &indexset)
110{
111 // check whether subsystem is big enough for both index sets
112 ASSERT(indexset.size() <= bigmatrix.getRows(),
113 "embedSubspaceMatrix() - bigmatrix has less rows "+toString(bigmatrix.getRows())
114 +" than needed by index set "
115 +toString(indexset.size())+"!");
116 ASSERT(indexset.size() <= bigmatrix.getColumns(),
117 "embedSubspaceMatrix() - bigmatrix has less columns "+toString(bigmatrix.getColumns())
118 +" than needed by index set "
119 +toString(indexset.size())+"!");
120
121 // construct small matrix
122 MatrixContent *subsystem = new MatrixContent(indexset.size(), indexset.size());
123 size_t localrow = 0; // local row indices for the subsystem
124 size_t localcolumn = 0;
125 BOOST_FOREACH( size_t rowindex, indexset) {
126 localcolumn = 0;
127 BOOST_FOREACH( size_t columnindex, indexset) {
128 ASSERT((rowindex < bigmatrix.getRows()) && (columnindex < bigmatrix.getColumns()),
129 "current index pair ("
130 +toString(rowindex)+","+toString(columnindex)
131 +") is out of bounds of bigmatrix ("
132 +toString(bigmatrix.getRows())+","+toString(bigmatrix.getColumns())
133 +")");
134 subsystem->at(localrow,localcolumn) = (*Eigenvectors[rowindex]) * (bigmatrix * (*Eigenvectors[columnindex]));
135 localcolumn++;
136 }
137 localrow++;
138 }
139 return subsystem;
140}
141
142/** For a given set of row and columns indices, we embed a small block matrix into a bigger space.
143 *
144 * @param eigenvectors current eigenvectors
145 * @param rowindexset row index set
146 * @param columnindexset column index set
147 * @return bigmatrix with eigenvectors contained
148 */
149MatrixContent * embedSubspaceMatrix(
150 VectorArray &Eigenvectors,
151 MatrixContent &subsystem,
152 const IndexSet &columnindexset)
153{
154 // check whether bigmatrix is at least as big as subsystem
155 ASSERT(Eigenvectors.size() > 0,
156 "embedSubspaceMatrix() - no Eigenvectors given!");
157 ASSERT(subsystem.getRows() <= Eigenvectors[0]->getDimension(),
158 "embedSubspaceMatrix() - subsystem has more rows "
159 +toString(subsystem.getRows())+" than eigenvectors "
160 +toString(Eigenvectors[0]->getDimension())+"!");
161 ASSERT(subsystem.getColumns() <= Eigenvectors.size(),
162 "embedSubspaceMatrix() - subsystem has more columns "
163 +toString(subsystem.getColumns())+" than eigenvectors "
164 +toString(Eigenvectors.size())+"!");
165 // check whether subsystem is big enough for both index sets
166 ASSERT(subsystem.getColumns() == subsystem.getRows(),
167 "embedSubspaceMatrix() - subsystem is not square "
168 +toString(subsystem.getRows())+" than needed by index set "
169 +toString(subsystem.getColumns())+"!");
170 ASSERT(columnindexset.size() == subsystem.getColumns(),
171 "embedSubspaceMatrix() - subsystem has not the same number of columns "
172 +toString(subsystem.getColumns())+" compared to the index set "
173 +toString(columnindexset.size())+"!");
174
175 // construct intermediate matrix
176 MatrixContent *intermediatematrix = new MatrixContent(Eigenvectors[0]->getDimension(), columnindexset.size());
177 size_t localcolumn = 0;
178 BOOST_FOREACH(size_t columnindex, columnindexset) {
179 // create two vectors from each row and copy assign them
180 boost::shared_ptr<VectorContent> srceigenvector(Eigenvectors[columnindex]);
181 boost::shared_ptr<VectorContent> desteigenvector(intermediatematrix->getColumnVector(localcolumn));
182 *desteigenvector = *srceigenvector;
183 localcolumn++;
184 }
185 // matrix product with eigenbasis subsystem matrix
186 *intermediatematrix *= subsystem;
187
188 // and place at right columns into bigmatrix
189 MatrixContent *bigmatrix = new MatrixContent(Eigenvectors[0]->getDimension(), Eigenvectors.size());
190 bigmatrix->setZero();
191 localcolumn = 0;
192 BOOST_FOREACH(size_t columnindex, columnindexset) {
193 // create two vectors from each row and copy assign them
194 boost::shared_ptr<VectorContent> srceigenvector(intermediatematrix->getColumnVector(localcolumn));
195 boost::shared_ptr<VectorContent> desteigenvector(bigmatrix->getColumnVector(columnindex));
196 *desteigenvector = *srceigenvector;
197 localcolumn++;
198 }
199
200 return bigmatrix;
201}
202
203/** Prints the scalar product of each possible pair that is not orthonormal.
204 * We use class logger for printing.
205 * @param AllIndices set of all possible indices of the eigenvectors
206 * @param CurrentEigenvectors array of eigenvectors
207 * @return true - all are orthonormal to each other,
208 * false - some are not orthogonal or not normalized.
209 */
210bool checkOrthogonality(const IndexSet &AllIndices, const VectorArray &CurrentEigenvectors)
211{
212 size_t nonnormalized = 0;
213 size_t nonorthogonal = 0;
214 // check orthogonality
215 BOOST_FOREACH( size_t firstindex, AllIndices) {
216 BOOST_FOREACH( size_t secondindex, AllIndices) {
217 const double scp = (*CurrentEigenvectors[firstindex])*(*CurrentEigenvectors[secondindex]);
218 if (firstindex == secondindex) {
219 if (fabs(scp - 1.) > MYEPSILON) {
220 nonnormalized++;
221 Log() << Verbose(2) << "Vector " << firstindex << " is not normalized, off by "
222 << fabs(1.-(*CurrentEigenvectors[firstindex])*(*CurrentEigenvectors[secondindex])) << std::endl;
223 }
224 } else {
225 if (fabs(scp) > MYEPSILON) {
226 nonorthogonal++;
227 Log() << Verbose(2) << "Scalar product between " << firstindex << " and " << secondindex
228 << " is " << (*CurrentEigenvectors[firstindex])*(*CurrentEigenvectors[secondindex]) << std::endl;
229 }
230 }
231 }
232 }
233
234 if ((nonnormalized == 0) && (nonorthogonal == 0)) {
235 DoLog(1) && (DoLog(1) && (Log() << Verbose(1) << "All vectors are orthonormal to each other." << std::endl));
236 return true;
237 }
238 if ((nonnormalized == 0) && (nonorthogonal != 0))
239 DoLog(1) && (DoLog(1) && (Log() << Verbose(1) << "All vectors are normalized." << std::endl));
240 if ((nonnormalized != 0) && (nonorthogonal == 0))
241 DoLog(1) && (DoLog(1) && (Log() << Verbose(1) << "All vectors are orthogonal to each other." << std::endl));
242 return false;
243}
244
245/** Calculate the sum of the scalar product of each possible pair.
246 * @param AllIndices set of all possible indices of the eigenvectors
247 * @param CurrentEigenvectors array of eigenvectors
248 * @return sum of scalar products between all possible pairs
249 */
250double calculateOrthogonalityThreshold(const IndexSet &AllIndices, const VectorArray &CurrentEigenvectors)
251{
252 double threshold = 0.;
253 // check orthogonality
254 BOOST_FOREACH( size_t firstindex, AllIndices) {
255 BOOST_FOREACH( size_t secondindex, AllIndices) {
256 const double scp = (*CurrentEigenvectors[firstindex])*(*CurrentEigenvectors[secondindex]);
257 if (firstindex == secondindex) {
258 threshold += fabs(scp - 1.);
259 } else {
260 threshold += fabs(scp);
261 }
262 }
263 }
264 return threshold;
265}
266
267/** Operator for output to std::ostream operator of an IndexSet.
268 * @param ost output stream
269 * @param indexset index set to output
270 * @return ost output stream
271 */
272std::ostream & operator<<(std::ostream &ost, const IndexSet &indexset)
273{
274 ost << "{ ";
275 for (IndexSet::const_iterator iter = indexset.begin();
276 iter != indexset.end();
277 ++iter)
278 ost << *iter << " ";
279 ost << "}";
280 return ost;
281}
282
283/** Assign eigenvectors of subspace to full eigenvectors.
284 * We use parallelity as relation measure.
285 * @param eigenvalue eigenvalue to assign along with
286 * @param CurrentEigenvector eigenvector to assign, is taken over within
287 * boost::shared_ptr
288 * @param CurrentEigenvectors full eigenvectors
289 * @param CorrespondenceList list to make sure that each subspace eigenvector
290 * is assigned to a unique full eigenvector
291 * @param ParallelEigenvectorList list of "similar" subspace eigenvectors per
292 * full eigenvector, allocated
293 */
294void AssignSubspaceEigenvectors(
295 double eigenvalue,
296 VectorContent *CurrentEigenvector,
297 VectorArray &CurrentEigenvectors,
298 IndexSet &CorrespondenceList,
299 VectorValueList *&ParallelEigenvectorList)
300{
301 DoLog(1) && (DoLog(1) && (Log() << Verbose(1) << "Current Eigenvector is " << *CurrentEigenvector << std::endl));
302
303 // (for now settle with the one we are most parallel to)
304 size_t mostparallel_index = SubspaceFactorizerUnittest::matrixdimension;
305 double mostparallel_scalarproduct = 0.;
306 BOOST_FOREACH( size_t indexiter, CorrespondenceList) {
307 DoLog(2) && (DoLog(2) && (Log() << Verbose(2) << "Comparing to old " << indexiter << "th eigenvector " << *(CurrentEigenvectors[indexiter]) << std::endl));
308 const double scalarproduct = (*(CurrentEigenvectors[indexiter])) * (*CurrentEigenvector);
309 DoLog(2) && (DoLog(2) && (Log() << Verbose(2) << "SKP is " << scalarproduct << std::endl));
310 if (fabs(scalarproduct) > mostparallel_scalarproduct) {
311 mostparallel_scalarproduct = fabs(scalarproduct);
312 mostparallel_index = indexiter;
313 }
314 }
315 if (mostparallel_index != SubspaceFactorizerUnittest::matrixdimension) {
316 // put into std::list for later use
317 // invert if pointing in negative direction
318 if ((*(CurrentEigenvectors[mostparallel_index])) * (*CurrentEigenvector) < 0) {
319 *CurrentEigenvector *= -1.;
320 DoLog(1) && (Log() << Verbose(1) << "Pushing (inverted) " << *CurrentEigenvector << " into parallel list [" << mostparallel_index << "]" << std::endl);
321 } else {
322 DoLog(1) && (Log() << Verbose(1) << "Pushing " << *CurrentEigenvector << " into parallel list [" << mostparallel_index << "]" << std::endl);
323 }
324 ParallelEigenvectorList[mostparallel_index].push_back(make_pair(boost::shared_ptr<VectorContent>(CurrentEigenvector), eigenvalue));
325 CorrespondenceList.erase(mostparallel_index);
326 }
327}
328
329void SubspaceFactorizerUnittest::EigenvectorTest()
330{
331 VectorArray CurrentEigenvectors;
332 ValueArray CurrentEigenvalues;
333 VectorValueList *ParallelEigenvectorList = new VectorValueList[matrixdimension];
334 IndexSet AllIndices;
335
336 // create the total index set
337 for (size_t i=0;i<matrixdimension;++i)
338 AllIndices.insert(i);
339
340 // create all consecutive index subsets for dim 1 to 3
341 IndexMap Dimension_to_Indexset;
342 for (size_t dim = 0; dim<3;++dim) {
343 for (size_t i=0;i<matrixdimension;++i) {
344 IndexSet *indexset = new IndexSet;
345 for (size_t j=0;j<dim+1;++j) {
346 const int value = (i+j) % matrixdimension;
347 //std::cout << "Putting " << value << " into " << i << "th map " << dim << std::endl;
348 CPPUNIT_ASSERT_MESSAGE("index "+toString(value)+" already present in "+toString(dim)+"-dim "+toString(i)+"th indexset.", indexset->count(value) == 0);
349 indexset->insert(value);
350 }
351 Dimension_to_Indexset.insert( make_pair(dim, boost::shared_ptr<IndexSet>(indexset)) );
352 // no need to free indexset, is stored in shared_ptr and
353 // will get released when Dimension_to_Indexset is destroyed
354 }
355 }
356
357 // set to first guess, i.e. the unit vectors of R^matrixdimension
358 BOOST_FOREACH( size_t index, AllIndices) {
359 boost::shared_ptr<VectorContent> EV(new VectorContent(matrixdimension));
360 EV->setZero();
361 EV->at(index) = 1.;
362 CurrentEigenvectors.push_back(EV);
363 CurrentEigenvalues.push_back(0.);
364 }
365
366 size_t run=1; // counting iterations
367 double threshold = 1.; // containing threshold value
368 while ((threshold > 1e-10) && (run < 10)) {
369 // for every dimension
370 for (size_t dim = 0; dim<subspacelimit;++dim) {
371 // for every index set of this dimension
372 DoLog(0) && (Log() << Verbose(0) << std::endl << std::endl);
373 DoLog(0) && (Log() << Verbose(0) << "Current dimension is " << dim << std::endl);
374 std::pair<IndexMap::const_iterator,IndexMap::const_iterator> Bounds = Dimension_to_Indexset.equal_range(dim);
375 for (IndexMap::const_iterator IndexsetIter = Bounds.first;
376 IndexsetIter != Bounds.second;
377 ++IndexsetIter) {
378 // show the index set
379 DoLog(0) && (Log() << Verbose(0) << std::endl);
380 DoLog(1) && (Log() << Verbose(1) << "Current index set is " << *(IndexsetIter->second) << std::endl);
381
382 // create transformation matrices from these
383 MatrixContent *subsystem = getSubspaceMatrix(*matrix, CurrentEigenvectors, *(IndexsetIter->second));
384 DoLog(2) && (Log() << Verbose(2) << "Subsystem matrix is " << *subsystem << std::endl);
385
386 // solve _small_ systems for eigenvalues
387 VectorContent *Eigenvalues = new VectorContent(subsystem->transformToEigenbasis());
388 DoLog(2) && (Log() << Verbose(2) << "Eigenvector matrix is " << *subsystem << std::endl);
389 DoLog(2) && (Log() << Verbose(2) << "Eigenvalues are " << *Eigenvalues << std::endl);
390
391 // blow up eigenvectors to matrixdimensiondim column vector again
392 MatrixContent *Eigenvectors = embedSubspaceMatrix(CurrentEigenvectors, *subsystem, *(IndexsetIter->second));
393 DoLog(1) && (Log() << Verbose(1) << matrixdimension << "x" << matrixdimension << " Eigenvector matrix is " << *Eigenvectors << std::endl);
394
395 // we don't need the subsystem anymore
396 delete subsystem;
397
398 // go through all eigenvectors in this subspace
399 IndexSet CorrespondenceList((*IndexsetIter->second)); // assure one-to-one and onto assignment
400 size_t localindex = 0;
401 BOOST_FOREACH( size_t iter, (*IndexsetIter->second)) {
402 // recognize eigenvectors parallel to existing ones
403 AssignSubspaceEigenvectors(
404 Eigenvalues->at(localindex),
405 new VectorContent(Eigenvectors->getColumnVector(iter)),
406 CurrentEigenvectors,
407 CorrespondenceList,
408 ParallelEigenvectorList);
409 localindex++;
410 }
411
412 // free eigenvectors
413 delete Eigenvectors;
414 delete Eigenvalues;
415 }
416 }
417
418 // print list of similar eigenvectors
419 BOOST_FOREACH( size_t index, AllIndices) {
420 DoLog(2) && (Log() << Verbose(2) << "Similar to " << index << "th current eigenvector " << *(CurrentEigenvectors[index]) << " are:" << std::endl);
421 BOOST_FOREACH( VectorValueList::value_type &iter, ParallelEigenvectorList[index] ) {
422 DoLog(2) && (Log() << Verbose(2) << *(iter.first) << std::endl);
423 }
424 DoLog(2) && (Log() << Verbose(2) << std::endl);
425 }
426
427 // create new CurrentEigenvectors from averaging parallel ones.
428 BOOST_FOREACH(size_t index, AllIndices) {
429 CurrentEigenvectors[index]->setZero();
430 CurrentEigenvalues[index] = 0.;
431 BOOST_FOREACH( VectorValueList::value_type &iter, ParallelEigenvectorList[index] ) {
432 *CurrentEigenvectors[index] += (*iter.first) * (iter.second);
433 CurrentEigenvalues[index] += (iter.second);
434 }
435 *CurrentEigenvectors[index] *= 1./CurrentEigenvalues[index];
436 CurrentEigenvalues[index] /= (double)ParallelEigenvectorList[index].size();
437 ParallelEigenvectorList[index].clear();
438 }
439
440 // check orthonormality
441 threshold = calculateOrthogonalityThreshold(AllIndices, CurrentEigenvectors);
442 bool dontOrthonormalization = checkOrthogonality(AllIndices, CurrentEigenvectors);
443
444 // orthonormalize
445 if (!dontOrthonormalization) {
446 DoLog(0) && (Log() << Verbose(0) << "Orthonormalizing ... " << std::endl);
447 for (IndexSet::const_iterator firstindex = AllIndices.begin();
448 firstindex != AllIndices.end();
449 ++firstindex) {
450 for (IndexSet::const_iterator secondindex = firstindex;
451 secondindex != AllIndices.end();
452 ++secondindex) {
453 if (*firstindex == *secondindex) {
454 (*CurrentEigenvectors[*secondindex]) *= 1./(*CurrentEigenvectors[*secondindex]).Norm();
455 } else {
456 (*CurrentEigenvectors[*secondindex]) -=
457 ((*CurrentEigenvectors[*firstindex])*(*CurrentEigenvectors[*secondindex]))
458 *(*CurrentEigenvectors[*firstindex]);
459 }
460 }
461 }
462 }
463
464// // check orthonormality again
465// checkOrthogonality(AllIndices, CurrentEigenvectors);
466
467 // show new ones
468 DoLog(0) && (Log() << Verbose(0) << "Resulting new eigenvectors and -values, run " << run << " are:" << std::endl);
469 BOOST_FOREACH( size_t index, AllIndices) {
470 DoLog(0) && (Log() << Verbose(0) << *CurrentEigenvectors[index] << " with " << CurrentEigenvalues[index] << std::endl);
471 }
472 run++;
473 }
474
475 delete[] ParallelEigenvectorList;
476
477 CPPUNIT_ASSERT_EQUAL(0,0);
478}
479
480
481/** Iterative function to generate all power sets of indices of size \a maxelements.
482 *
483 * @param SetofSets Container for all sets
484 * @param CurrentSet pointer to current set in this container
485 * @param Indices Source set of indices
486 * @param maxelements number of elements of each set in final SetofSets
487 * @return true - generation continued, false - current set already had
488 * \a maxelements elements
489 */
490bool generatePowerSet(
491 SetofIndexSets &SetofSets,
492 SetofIndexSets::iterator &CurrentSet,
493 IndexSet &Indices,
494 const size_t maxelements)
495{
496 if (CurrentSet->size() < maxelements) {
497 // allocate the needed sets
498 const size_t size = Indices.size() - CurrentSet->size();
499 std::vector<std::set<size_t> > SetExpanded;
500 SetExpanded.reserve(size);
501
502 // copy the current set into each
503 for (size_t i=0;i<size;++i)
504 SetExpanded.push_back(*CurrentSet);
505
506 // expand each set by one index
507 size_t localindex=0;
508 BOOST_FOREACH(size_t iter, Indices) {
509 if (CurrentSet->count(iter) == 0) {
510 SetExpanded[localindex].insert(iter);
511 ++localindex;
512 }
513 }
514
515 // insert set at position of CurrentSet
516 for (size_t i=0;i<size;++i) {
517 //DoLog(1) && (Log() << Verbose(1) << "Inserting set #" << i << ": " << SetExpanded[i] << std::endl);
518 SetofSets.insert(CurrentSet, SetExpanded[i]);
519 }
520 SetExpanded.clear();
521
522 // and remove the current set
523 //SetofSets.erase(CurrentSet);
524 //CurrentSet = SetofSets.begin();
525
526 // set iterator to a valid position again
527 ++CurrentSet;
528 return true;
529 } else {
530 return false;
531 }
532}
533
534void SubspaceFactorizerUnittest::generatePowerSetTest()
535{
536 IndexSet AllIndices;
537 for (size_t i=0;i<4;++i)
538 AllIndices.insert(i);
539
540 SetofIndexSets SetofSets;
541 // note that starting off empty set is unstable
542 IndexSet singleset;
543 BOOST_FOREACH(size_t iter, AllIndices) {
544 singleset.insert(iter);
545 SetofSets.insert(singleset);
546 singleset.clear();
547 }
548 SetofIndexSets::iterator CurrentSet = SetofSets.begin();
549 while (CurrentSet != SetofSets.end()) {
550 //DoLog(0) && (Log() << Verbose(0) << "Current set is " << *CurrentSet << std::endl);
551 if (!generatePowerSet(SetofSets, CurrentSet, AllIndices, 2)) {
552 // go to next set
553 ++CurrentSet;
554 }
555 }
556
557 SetofIndexSets ComparisonSet;
558 // now follows a very stupid construction
559 // because we can't use const arrays of some type meaningfully ...
560 { IndexSet tempSet; tempSet.insert(0); ComparisonSet.insert(tempSet); }
561 { IndexSet tempSet; tempSet.insert(1); ComparisonSet.insert(tempSet); }
562 { IndexSet tempSet; tempSet.insert(2); ComparisonSet.insert(tempSet); }
563 { IndexSet tempSet; tempSet.insert(3); ComparisonSet.insert(tempSet); }
564
565 { IndexSet tempSet; tempSet.insert(0); tempSet.insert(1); ComparisonSet.insert(tempSet); }
566 { IndexSet tempSet; tempSet.insert(0); tempSet.insert(2); ComparisonSet.insert(tempSet); }
567 { IndexSet tempSet; tempSet.insert(0); tempSet.insert(3); ComparisonSet.insert(tempSet); }
568
569 { IndexSet tempSet; tempSet.insert(1); tempSet.insert(2); ComparisonSet.insert(tempSet); }
570 { IndexSet tempSet; tempSet.insert(1); tempSet.insert(3); ComparisonSet.insert(tempSet); }
571
572 { IndexSet tempSet; tempSet.insert(2); tempSet.insert(3); ComparisonSet.insert(tempSet); }
573
574 CPPUNIT_ASSERT_EQUAL(SetofSets, ComparisonSet);
575}
576
577bool cmd(double a, double b)
578{
579 return a > b;
580}
581
582void SubspaceFactorizerUnittest::SubspaceTest()
583{
584 Eigenspace::eigenvectorset CurrentEigenvectors;
585 Eigenspace::eigenvalueset CurrentEigenvalues;
586
587 setVerbosity(0);
588
589 boost::timer Time_generatingfullspace;
590 DoLog(0) && (Log() << Verbose(0) << std::endl << std::endl);
591 // create the total index set
592 IndexSet AllIndices;
593 for (size_t i=0;i<matrixdimension;++i)
594 AllIndices.insert(i);
595 Eigenspace FullSpace(AllIndices, *matrix);
596 DoLog(1) && (Log() << Verbose(1) << "Generated full space: " << FullSpace << std::endl);
597 DoLog(0) && (Log() << Verbose(0) << "Full space generation took " << Time_generatingfullspace.elapsed() << " seconds." << std::endl);
598
599 // generate first set of eigenvectors
600 // set to first guess, i.e. the unit vectors of R^matrixdimension
601 BOOST_FOREACH( size_t index, AllIndices) {
602 boost::shared_ptr<VectorContent> EV(new VectorContent(matrixdimension));
603 EV->setZero();
604 EV->at(index) = 1.;
605 CurrentEigenvectors.push_back(EV);
606 CurrentEigenvalues.push_back(0.);
607 }
608
609 boost::timer Time_generatingsubsets;
610 DoLog(0) && (Log() << Verbose(0) << "Generating sub sets ..." << std::endl);
611 SetofIndexSets SetofSets;
612 // note that starting off empty set is unstable
613 IndexSet singleset;
614 BOOST_FOREACH(size_t iter, AllIndices) {
615 singleset.insert(iter);
616 SetofSets.insert(singleset);
617 singleset.clear();
618 }
619 SetofIndexSets::iterator CurrentSet = SetofSets.begin();
620 while (CurrentSet != SetofSets.end()) {
621 //DoLog(2) && (Log() << Verbose(2) << "Current set is " << *CurrentSet << std::endl);
622 if (!generatePowerSet(SetofSets, CurrentSet, AllIndices, subspacelimit)) {
623 // go to next set
624 ++CurrentSet;
625 }
626 }
627 DoLog(0) && (Log() << Verbose(0) << "Sub set generation took " << Time_generatingsubsets.elapsed() << " seconds." << std::endl);
628
629 // create a subspace to each set and and to respective level
630 boost::timer Time_generatingsubspaces;
631 DoLog(0) && (Log() << Verbose(0) << "Generating sub spaces ..." << std::endl);
632 SubspaceMap Dimension_to_Indexset;
633 BOOST_FOREACH(std::set<size_t> iter, SetofSets) {
634 boost::shared_ptr<Subspace> subspace(new Subspace(iter, FullSpace));
635 DoLog(1) && (Log() << Verbose(1) << "Current subspace is " << *subspace << std::endl);
636 Dimension_to_Indexset.insert( make_pair(iter.size(), boost::shared_ptr<Subspace>(subspace)) );
637 }
638
639 for (size_t dim = 1; dim<=subspacelimit;++dim) {
640 BOOST_FOREACH( SubspaceMap::value_type subspace, Dimension_to_Indexset.equal_range(dim)) {
641 if (dim != 0) { // from level 1 and onward
642 BOOST_FOREACH( SubspaceMap::value_type entry, Dimension_to_Indexset.equal_range(dim-1)) {
643 if (subspace.second->contains(*entry.second)) {
644 // if contained then add ...
645 subspace.second->addSubset(entry.second);
646 // ... and also its containees as they are all automatically contained as well
647 BOOST_FOREACH(boost::shared_ptr<Subspace> iter, entry.second->SubIndices) {
648 subspace.second->addSubset(iter);
649 }
650 }
651 }
652 }
653 }
654 }
655 DoLog(0) && (Log() << Verbose(0) << "Sub space generation took " << Time_generatingsubspaces.elapsed() << " seconds." << std::endl);
656
657 // create a file handle for the eigenvalues
658 std::ofstream outputvalues("eigenvalues.dat", std::ios_base::trunc);
659 ASSERT(outputvalues.good(),
660 "SubspaceFactorizerUnittest::EigenvectorTest() - failed to open eigenvalue file!");
661 outputvalues << "# iteration ";
662 BOOST_FOREACH(size_t iter, AllIndices) {
663 outputvalues << "\teigenvalue" << iter;
664 }
665 outputvalues << std::endl;
666
667 DoLog(0) && (Log() << Verbose(0) << "Solving ..." << std::endl);
668 boost::timer Time_solving;
669 size_t run=1; // counting iterations
670 double threshold = 1.; // containing threshold value
671 while ((threshold > MYEPSILON) && (run < 20)) {
672 // for every dimension
673 for (size_t dim = 1; dim <= subspacelimit;++dim) {
674 // for every index set of this dimension
675 DoLog(1) && (Log() << Verbose(1) << std::endl << std::endl);
676 DoLog(1) && (Log() << Verbose(1) << "Current dimension is " << dim << std::endl);
677 std::pair<SubspaceMap::const_iterator,SubspaceMap::const_iterator> Bounds = Dimension_to_Indexset.equal_range(dim);
678 for (SubspaceMap::const_iterator IndexsetIter = Bounds.first;
679 IndexsetIter != Bounds.second;
680 ++IndexsetIter) {
681 Subspace& subspace = *(IndexsetIter->second);
682 // show the index set
683 DoLog(2) && (Log() << Verbose(2) << std::endl);
684 DoLog(2) && (Log() << Verbose(2) << "Current subspace is " << subspace << std::endl);
685
686 // solve
687 subspace.calculateEigenSubspace();
688
689 // note that assignment to global eigenvectors all remains within subspace
690 }
691 }
692
693 // print list of similar eigenvectors
694 DoLog(2) && (Log() << Verbose(2) << std::endl);
695 BOOST_FOREACH( size_t index, AllIndices) {
696 DoLog(2) && (Log() << Verbose(2) << "Similar to " << index << "th current eigenvector " << *(CurrentEigenvectors[index]) << " are:" << std::endl);
697 BOOST_FOREACH( SubspaceMap::value_type iter, Dimension_to_Indexset) {
698 const VectorContent & CurrentEV = (iter.second)->getEigenvectorParallelToFullOne(index);
699 if (!CurrentEV.IsZero())
700 Log() << Verbose(2)
701 << "dim" << iter.first
702 << ", subspace{" << (iter.second)->getIndices()
703 << "}: "<<CurrentEV << std::endl;
704 }
705 DoLog(2) && (Log() << Verbose(2) << std::endl);
706 }
707
708 // create new CurrentEigenvectors from averaging parallel ones.
709 BOOST_FOREACH(size_t index, AllIndices) {
710 CurrentEigenvectors[index]->setZero();
711 CurrentEigenvalues[index] = 0.;
712 size_t count = 0;
713 BOOST_FOREACH( SubspaceMap::value_type iter, Dimension_to_Indexset) {
714 const VectorContent CurrentEV = (iter.second)->getEigenvectorParallelToFullOne(index);
715 *CurrentEigenvectors[index] += CurrentEV; // * (iter.second)->getEigenvalueOfEigenvectorParallelToFullOne(index);
716 CurrentEigenvalues[index] += (iter.second)->getEigenvalueOfEigenvectorParallelToFullOne(index);
717 if (!CurrentEV.IsZero())
718 count++;
719 }
720 *CurrentEigenvectors[index] *= 1./CurrentEigenvalues[index];
721 //CurrentEigenvalues[index] /= (double)count;
722 }
723
724 // check orthonormality
725 threshold = calculateOrthogonalityThreshold(AllIndices, CurrentEigenvectors);
726 bool dontOrthonormalization = checkOrthogonality(AllIndices, CurrentEigenvectors);
727
728 // orthonormalize
729 if (!dontOrthonormalization) {
730 DoLog(1) && (Log() << Verbose(1) << "Orthonormalizing ... " << std::endl);
731 for (IndexSet::const_iterator firstindex = AllIndices.begin();
732 firstindex != AllIndices.end();
733 ++firstindex) {
734 for (IndexSet::const_iterator secondindex = firstindex;
735 secondindex != AllIndices.end();
736 ++secondindex) {
737 if (*firstindex == *secondindex) {
738 (*CurrentEigenvectors[*secondindex]) *= 1./(*CurrentEigenvectors[*secondindex]).Norm();
739 } else {
740 (*CurrentEigenvectors[*secondindex]) -=
741 ((*CurrentEigenvectors[*firstindex])*(*CurrentEigenvectors[*secondindex]))
742 *(*CurrentEigenvectors[*firstindex]);
743 }
744 }
745 }
746 }
747
748// // check orthonormality again
749// checkOrthogonality(AllIndices, CurrentEigenvectors);
750
751 // put obtained eigenvectors into full space
752 FullSpace.setEigenpairs(CurrentEigenvectors, CurrentEigenvalues);
753
754 // show new ones
755 DoLog(1) && (Log() << Verbose(1) << "Resulting new eigenvectors and -values, run " << run << " are:" << std::endl);
756 outputvalues << run;
757 BOOST_FOREACH( size_t index, AllIndices) {
758 DoLog(1) && (Log() << Verbose(1) << *CurrentEigenvectors[index] << " with " << CurrentEigenvalues[index] << std::endl);
759 outputvalues << "\t" << CurrentEigenvalues[index];
760 }
761 outputvalues << std::endl;
762
763 // and next iteration
764 DoLog(0) && (Log() << Verbose(0) << "\titeration #" << run << std::endl);
765 run++;
766 }
767 DoLog(0) && (Log() << Verbose(0) << "Solving took " << Time_solving.elapsed() << " seconds." << std::endl);
768 // show final ones
769 DoLog(0) && (Log() << Verbose(0) << "Resulting new eigenvectors and -values, run " << run << " are:" << std::endl);
770 outputvalues << run;
771 BOOST_FOREACH( size_t index, AllIndices) {
772 DoLog(0) && (Log() << Verbose(0) << *CurrentEigenvectors[index] << " with " << CurrentEigenvalues[index] << std::endl);
773 outputvalues << "\t" << CurrentEigenvalues[index];
774 }
775 outputvalues << std::endl;
776 outputvalues.close();
777
778 setVerbosity(2);
779
780 DoLog(0) && (Log() << Verbose(0) << "Solving full space ..." << std::endl);
781 boost::timer Time_comparison;
782 MatrixContent tempFullspaceMatrix = FullSpace.getEigenspaceMatrix();
783 gsl_vector *eigenvalues = tempFullspaceMatrix.transformToEigenbasis();
784 tempFullspaceMatrix.sortEigenbasis(eigenvalues);
785 DoLog(0) && (Log() << Verbose(0) << "full space solution took " << Time_comparison.elapsed() << " seconds." << std::endl);
786
787 // compare all
788 sort(CurrentEigenvalues.begin(),CurrentEigenvalues.end()); //, cmd);
789 for (size_t i=0;i<eigenvalues->size; ++i) {
790 CPPUNIT_ASSERT_MESSAGE(toString(i)+"ths eigenvalue differs:"
791 +toString(CurrentEigenvalues[i])+" != "+toString(gsl_vector_get(eigenvalues,i)),
792 fabs((CurrentEigenvalues[i] - gsl_vector_get(eigenvalues,i))/CurrentEigenvalues[i]) < 1e-3);
793 }
794
795 CPPUNIT_ASSERT_EQUAL(0,0);
796}
Note: See TracBrowser for help on using the repository browser.