251 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
		
		
			
		
	
	
			251 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @file testConditioning.cpp
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @brief Experiments using backsubstitution for conditioning (not summarization, it turns out)
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @date Sep 3, 2012
							 | 
						||
| 
								 | 
							
								 * @author Alex Cunningham
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <CppUnitLite/TestHarness.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <gtsam/base/TestableAssertions.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <boost/assign/std/set.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <gtsam_unstable/linear/conditioning.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								using namespace std;
							 | 
						||
| 
								 | 
							
								using namespace boost::assign;
							 | 
						||
| 
								 | 
							
								using namespace gtsam;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const double tol = 1e-5;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Simple example
							 | 
						||
| 
								 | 
							
								Matrix R = Matrix_(3,3,
							 | 
						||
| 
								 | 
							
								    1.0,-2.0,-3.0,
							 | 
						||
| 
								 | 
							
								    0.0, 3.0,-5.0,
							 | 
						||
| 
								 | 
							
								    0.0, 0.0, 6.0);
							 | 
						||
| 
								 | 
							
								Vector d = Vector_(3,
							 | 
						||
| 
								 | 
							
								    0.1, 0.2, 0.3);
							 | 
						||
| 
								 | 
							
								Vector x = Vector_(3,
							 | 
						||
| 
								 | 
							
								    0.55,
							 | 
						||
| 
								 | 
							
								    0.15,
							 | 
						||
| 
								 | 
							
								    0.05);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* ************************************************************************* */
							 | 
						||
| 
								 | 
							
								TEST( testConditioning, directed_elimination_example ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // create a 3-variable system from which to eliminate variables
							 | 
						||
| 
								 | 
							
								  // Scalar variables, pre-factorized into R,d system
							 | 
						||
| 
								 | 
							
								  // Use multifrontal representation
							 | 
						||
| 
								 | 
							
								  // Variables 0, 1, 2 - want to summarize out 1
							 | 
						||
| 
								 | 
							
								  Vector expx = R.triangularView<Eigen::Upper>().solve(d);
							 | 
						||
| 
								 | 
							
								  EXPECT(assert_equal(x, expx, tol));
							 | 
						||
| 
								 | 
							
								  EXPECT(assert_equal(Vector(R*x), d, tol));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // backsub-summarized version
							 | 
						||
| 
								 | 
							
								  Matrix Rprime = Matrix_(2,2,
							 | 
						||
| 
								 | 
							
								      1.0,-3.0,
							 | 
						||
| 
								 | 
							
								      0.0, 6.0);
							 | 
						||
| 
								 | 
							
								  Vector dprime = Vector_(2,
							 | 
						||
| 
								 | 
							
								      d(0) - R(0,1)*x(1),
							 | 
						||
| 
								 | 
							
								      d(2));
							 | 
						||
| 
								 | 
							
								  Vector xprime = Vector_(2,
							 | 
						||
| 
								 | 
							
								      x(0), // Same solution, just smaller
							 | 
						||
| 
								 | 
							
								      x(2));
							 | 
						||
| 
								 | 
							
								  EXPECT(assert_equal(Vector(Rprime*xprime), dprime, tol));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* ************************************************************************* */
							 | 
						||
| 
								 | 
							
								TEST( testConditioning, directed_elimination_singlefrontal ) {
							 | 
						||
| 
								 | 
							
								  // Gaussian conditional with a single frontal variable, parent is to be removed
							 | 
						||
| 
								 | 
							
								  // Top row from above example
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Index root_key = 0, removed_key = 1, remaining_parent = 2;
							 | 
						||
| 
								 | 
							
								  Matrix R11 = Matrix_(1,1, 1.0), R22 = Matrix_(1,1, 3.0), S = Matrix_(1,1,-2.0), T = Matrix_(1,1,-3.0);
							 | 
						||
| 
								 | 
							
								  Vector d0 = d.segment(0,1), d1 = d.segment(1,1), sigmas = Vector_(1, 1.0);
							 | 
						||
| 
								 | 
							
								  GaussianConditional::shared_ptr initConditional(new
							 | 
						||
| 
								 | 
							
								      GaussianConditional(root_key, d0, R11, removed_key, S, remaining_parent, T, sigmas));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  VectorValues solution;
							 | 
						||
| 
								 | 
							
								  solution.insert(0, x.segment(0,1));
							 | 
						||
| 
								 | 
							
								  solution.insert(1, x.segment(1,1));
							 | 
						||
| 
								 | 
							
								  solution.insert(2, x.segment(2,1));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  std::set<Index> saved_indices;
							 | 
						||
| 
								 | 
							
								  saved_indices += root_key, remaining_parent;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  GaussianConditional::shared_ptr actSummarized = conditionDensity(initConditional, saved_indices, solution);
							 | 
						||
| 
								 | 
							
								  GaussianConditional::shared_ptr expSummarized(new
							 | 
						||
| 
								 | 
							
								      GaussianConditional(root_key, d0 - S*x(1), R11, remaining_parent, T, sigmas));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  CHECK(actSummarized);
							 | 
						||
| 
								 | 
							
								  EXPECT(assert_equal(*expSummarized, *actSummarized, tol));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Simple test of base case: if target index isn't present, return clone
							 | 
						||
| 
								 | 
							
								  GaussianConditional::shared_ptr actSummarizedSimple = conditionDensity(expSummarized, saved_indices, solution);
							 | 
						||
| 
								 | 
							
								  CHECK(actSummarizedSimple);
							 | 
						||
| 
								 | 
							
								  EXPECT(assert_equal(*expSummarized, *actSummarizedSimple, tol));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // case where frontal variable is to be eliminated - return null
							 | 
						||
| 
								 | 
							
								  GaussianConditional::shared_ptr removeFrontalInit(new
							 | 
						||
| 
								 | 
							
								        GaussianConditional(removed_key, d1, R22, remaining_parent, T, sigmas));
							 | 
						||
| 
								 | 
							
								  GaussianConditional::shared_ptr actRemoveFrontal = conditionDensity(removeFrontalInit, saved_indices, solution);
							 | 
						||
| 
								 | 
							
								  EXPECT(!actRemoveFrontal);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* ************************************************************************* */
							 | 
						||
| 
								 | 
							
								TEST( testConditioning, directed_elimination_multifrontal ) {
							 | 
						||
| 
								 | 
							
								  // Use top two rows from the previous example
							 | 
						||
| 
								 | 
							
								  Index root_key = 0, removed_key = 1, remaining_parent = 2;
							 | 
						||
| 
								 | 
							
								  Matrix R11 = R.topLeftCorner(2,2), S = R.block(0,2,2,1),
							 | 
						||
| 
								 | 
							
								      Sprime = Matrix_(1,1,-2.0), R11prime = Matrix_(1,1, 1.0);
							 | 
						||
| 
								 | 
							
								  Vector d1 = d.segment(0,2), sigmas1 = Vector_(1, 1.0), sigmas2 = Vector_(2, 1.0, 1.0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  std::list<std::pair<Index, Matrix> > terms;
							 | 
						||
| 
								 | 
							
								  terms += make_pair(root_key, Matrix(R11.col(0)));
							 | 
						||
| 
								 | 
							
								  terms += make_pair(removed_key, Matrix(R11.col(1)));
							 | 
						||
| 
								 | 
							
								  terms += make_pair(remaining_parent, S);
							 | 
						||
| 
								 | 
							
								  GaussianConditional::shared_ptr initConditional(new GaussianConditional(terms, 2, d1, sigmas2));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  VectorValues solution;
							 | 
						||
| 
								 | 
							
								  solution.insert(0, x.segment(0,1));
							 | 
						||
| 
								 | 
							
								  solution.insert(1, x.segment(1,1));
							 | 
						||
| 
								 | 
							
								  solution.insert(2, x.segment(2,1));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  std::set<Index> saved_indices;
							 | 
						||
| 
								 | 
							
								  saved_indices += root_key, remaining_parent;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  GaussianConditional::shared_ptr actSummarized = conditionDensity(initConditional, saved_indices, solution);
							 | 
						||
| 
								 | 
							
								  GaussianConditional::shared_ptr expSummarized(new
							 | 
						||
| 
								 | 
							
								      GaussianConditional(root_key, d.segment(0,1) - Sprime*x(1), R11prime, remaining_parent, R.block(0,2,1,1), sigmas1));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  CHECK(actSummarized);
							 | 
						||
| 
								 | 
							
								  EXPECT(assert_equal(*expSummarized, *actSummarized, tol));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* ************************************************************************* */
							 | 
						||
| 
								 | 
							
								TEST( testConditioning, directed_elimination_multifrontal_multidim ) {
							 | 
						||
| 
								 | 
							
								  // use larger example, three frontal variables, dim = 2 each, two parents (one removed)
							 | 
						||
| 
								 | 
							
								  // Vars: 0, 1, 2, 3, 4; frontal: 0, 1, 2. parents: 3, 4;
							 | 
						||
| 
								 | 
							
								  // Remove 1, 3
							 | 
						||
| 
								 | 
							
								  Matrix Rinit = Matrix_(6, 11,
							 | 
						||
| 
								 | 
							
								      1.0, 0.0,  2.0, 0.0,  3.0, 0.0,  1.0, 0.0, -1.0, 0.0,  0.1,
							 | 
						||
| 
								 | 
							
								      0.0, 1.0,  0.0, 2.0,  0.0, 3.0,  0.0, 1.0,  0.0, 1.0,  0.2,
							 | 
						||
| 
								 | 
							
								      0.0, 0.0,  3.0, 0.0,  4.0, 0.0,  0.0,-1.0,  1.0, 0.0,  0.3,
							 | 
						||
| 
								 | 
							
								      0.0, 0.0,  0.0, 4.0,  0.0, 4.0,  3.0, 2.0,  0.0, 9.0,  0.4,
							 | 
						||
| 
								 | 
							
								      0.0, 0.0,  0.0, 0.0,  5.0, 0.0,  7.0, 0.0,  3.0, 0.0,  0.5,
							 | 
						||
| 
								 | 
							
								      0.0, 0.0,  0.0, 0.0,  0.0, 4.0,  0.0, 8.0,  0.0, 6.0,  0.6);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  vector<size_t> init_dims; init_dims += 2, 2, 2, 2, 2, 1;
							 | 
						||
| 
								 | 
							
								  GaussianConditional::rsd_type init_matrices(Rinit, init_dims.begin(), init_dims.end());
							 | 
						||
| 
								 | 
							
								  Vector sigmas = ones(6);
							 | 
						||
| 
								 | 
							
								  vector<size_t> init_keys; init_keys += 0, 1, 2, 3, 4;
							 | 
						||
| 
								 | 
							
								  GaussianConditional::shared_ptr initConditional(new
							 | 
						||
| 
								 | 
							
								      GaussianConditional(init_keys.begin(), init_keys.end(), 3, init_matrices, sigmas));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Construct a solution vector
							 | 
						||
| 
								 | 
							
								  VectorValues solution;
							 | 
						||
| 
								 | 
							
								  solution.insert(0, zero(2));
							 | 
						||
| 
								 | 
							
								  solution.insert(1, zero(2));
							 | 
						||
| 
								 | 
							
								  solution.insert(2, zero(2));
							 | 
						||
| 
								 | 
							
								  solution.insert(3, Vector_(2, 1.0, 2.0));
							 | 
						||
| 
								 | 
							
								  solution.insert(4, Vector_(2, 3.0, 4.0));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  initConditional->solveInPlace(solution);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  std::set<Index> saved_indices;
							 | 
						||
| 
								 | 
							
								  saved_indices += 0, 2, 4;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  GaussianConditional::shared_ptr actSummarized = conditionDensity(initConditional, saved_indices, solution);
							 | 
						||
| 
								 | 
							
								  CHECK(actSummarized);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Matrix Rexp = Matrix_(4, 7,
							 | 
						||
| 
								 | 
							
								      1.0, 0.0,  3.0, 0.0,  -1.0, 0.0,  0.1,
							 | 
						||
| 
								 | 
							
								      0.0, 1.0,  0.0, 3.0,   0.0, 1.0,  0.2,
							 | 
						||
| 
								 | 
							
								      0.0, 0.0,  5.0, 0.0,   3.0, 0.0,  0.5,
							 | 
						||
| 
								 | 
							
								      0.0, 0.0,  0.0, 4.0,   0.0, 6.0,  0.6);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Update rhs
							 | 
						||
| 
								 | 
							
								  Rexp.block(0, 6, 2, 1) -= Rinit.block(0, 2, 2, 2) * solution.at(1) + Rinit.block(0, 6, 2, 2) * solution.at(3);
							 | 
						||
| 
								 | 
							
								  Rexp.block(2, 6, 2, 1) -= Rinit.block(4, 6, 2, 2) * solution.at(3);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  vector<size_t> exp_dims; exp_dims += 2, 2, 2, 1;
							 | 
						||
| 
								 | 
							
								  GaussianConditional::rsd_type exp_matrices(Rexp, exp_dims.begin(), exp_dims.end());
							 | 
						||
| 
								 | 
							
								  Vector exp_sigmas = ones(4);
							 | 
						||
| 
								 | 
							
								  vector<size_t> exp_keys; exp_keys += 0, 2, 4;
							 | 
						||
| 
								 | 
							
								  GaussianConditional expSummarized(exp_keys.begin(), exp_keys.end(), 2, exp_matrices, exp_sigmas);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  EXPECT(assert_equal(expSummarized, *actSummarized, tol));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* ************************************************************************* */
							 | 
						||
| 
								 | 
							
								TEST( testConditioning, directed_elimination_multifrontal_multidim2 ) {
							 | 
						||
| 
								 | 
							
								  // Example from LinearAugmentedSystem
							 | 
						||
| 
								 | 
							
								  // 4 variables, last two in ordering kept - should be able to do this with no computation.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  vector<size_t> init_dims; init_dims += 3, 3, 2, 2, 1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  //Full initial conditional: density on [3] [4] [5] [6]
							 | 
						||
| 
								 | 
							
								  Matrix Rinit = Matrix_(10, 11,
							 | 
						||
| 
								 | 
							
								      8.78422312,  -0.0375455118,  -0.0387376278,     -5.059576,           0.0,           0.0,  -0.0887200041,  0.00429643583,  -0.130078263,  0.0193260727,  0.0,
							 | 
						||
| 
								 | 
							
								      0.0,    8.46951839,    9.51456887,  -0.0224291821,   -5.24757636,           0.0,  0.0586258904,  -0.173455825,    0.11090295,  -0.330696013,        0.0,
							 | 
						||
| 
								 | 
							
								      0.0,           0.0,    16.5539485,  0.00105159359,   -2.35354497,   -6.04085484,  -0.0212095105,  0.0978729072,  0.00471054272,  0.0694956367,    0.0,
							 | 
						||
| 
								 | 
							
								      0.0,           0.0,           0.0,    10.9015885,  -0.0105694572,  0.000582715469,  -0.0410535006,  0.00162772139,  -0.0601433772,  0.0082824087,0.0,
							 | 
						||
| 
								 | 
							
								      0.0,           0.0,           0.0,           0.0,    10.5531086,   -1.34722553,    0.02438072,  -0.0644224578,  0.0561372492,  -0.148932792,        0.0,
							 | 
						||
| 
								 | 
							
								      0.0,           0.0,           0.0,           0.0,           0.0,    21.4870439,  -0.00443305851,  0.0234766354,  0.00484572411,  0.0101997356,      0.0,
							 | 
						||
| 
								 | 
							
								      0.0,           0.0,           0.0,           0.0,           0.0,           0.0,    2.73892865,  0.0242046766,  -0.0459727048,  0.0445071938,        0.0,
							 | 
						||
| 
								 | 
							
								      0.0,           0.0,           0.0,           0.0,           0.0,           0.0,           0.0,    2.61246954,    0.02287419,  -0.102870789,          0.0,
							 | 
						||
| 
								 | 
							
								      0.0,           0.0,           0.0,           0.0,           0.0,           0.0,           0.0,           0.0,    2.04823446,  -0.302033014,          0.0,
							 | 
						||
| 
								 | 
							
								      0.0,           0.0,           0.0,           0.0,           0.0,           0.0,           0.0,           0.0,           0.0,    2.24068986,          0.0);
							 | 
						||
| 
								 | 
							
								  Vector dinit = Vector_(10,
							 | 
						||
| 
								 | 
							
								      -0.00186915, 0.00318554, 0.000592421, -0.000861, 0.00171528, 0.000274123, -0.0284011, 0.0275465, 0.0439795, -0.0222134);
							 | 
						||
| 
								 | 
							
								  Rinit.rightCols(1) = dinit;
							 | 
						||
| 
								 | 
							
								  Vector sigmas = ones(10);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  GaussianConditional::rsd_type init_matrices(Rinit, init_dims.begin(), init_dims.end());
							 | 
						||
| 
								 | 
							
								  vector<size_t> init_keys; init_keys += 3, 4, 5, 6;
							 | 
						||
| 
								 | 
							
								  GaussianConditional::shared_ptr initConditional(new
							 | 
						||
| 
								 | 
							
								      GaussianConditional(init_keys.begin(), init_keys.end(), 4, init_matrices, sigmas));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Calculate a solution
							 | 
						||
| 
								 | 
							
								  VectorValues solution;
							 | 
						||
| 
								 | 
							
								  solution.insert(0, zero(3));
							 | 
						||
| 
								 | 
							
								  solution.insert(1, zero(3));
							 | 
						||
| 
								 | 
							
								  solution.insert(2, zero(3));
							 | 
						||
| 
								 | 
							
								  solution.insert(3, zero(3));
							 | 
						||
| 
								 | 
							
								  solution.insert(4, zero(3));
							 | 
						||
| 
								 | 
							
								  solution.insert(5, zero(2));
							 | 
						||
| 
								 | 
							
								  solution.insert(6, zero(2));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  initConditional->solveInPlace(solution);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Perform summarization
							 | 
						||
| 
								 | 
							
								  std::set<Index> saved_indices;
							 | 
						||
| 
								 | 
							
								  saved_indices += 5, 6;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  GaussianConditional::shared_ptr actSummarized = conditionDensity(initConditional, saved_indices, solution);
							 | 
						||
| 
								 | 
							
								  CHECK(actSummarized);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Create expected value on [5], [6]
							 | 
						||
| 
								 | 
							
								  Matrix Rexp = Matrix_(4, 5,
							 | 
						||
| 
								 | 
							
								      2.73892865,  0.0242046766,  -0.0459727048,  0.0445071938,  -0.0284011,
							 | 
						||
| 
								 | 
							
								             0.0,    2.61246954,    0.02287419,  -0.102870789,     0.0275465,
							 | 
						||
| 
								 | 
							
								             0.0,           0.0,    2.04823446,  -0.302033014,     0.0439795,
							 | 
						||
| 
								 | 
							
								             0.0,           0.0,           0.0,    2.24068986,    -0.0222134);
							 | 
						||
| 
								 | 
							
								  Vector expsigmas = ones(4);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  vector<size_t> exp_dims; exp_dims += 2, 2, 1;
							 | 
						||
| 
								 | 
							
								  GaussianConditional::rsd_type exp_matrices(Rexp, exp_dims.begin(), exp_dims.end());
							 | 
						||
| 
								 | 
							
								  vector<size_t> exp_keys; exp_keys += 5, 6;
							 | 
						||
| 
								 | 
							
								  GaussianConditional expConditional(exp_keys.begin(), exp_keys.end(), 2, exp_matrices, expsigmas);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  EXPECT(assert_equal(expConditional, *actSummarized, tol));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* ************************************************************************* */
							 | 
						||
| 
								 | 
							
								int main() { TestResult tr; return TestRegistry::runAllTests(tr); }
							 | 
						||
| 
								 | 
							
								/* ************************************************************************* */
							 |