Skip to content

Commit

Permalink
Split method implementations into multiple files
Browse files Browse the repository at this point in the history
  • Loading branch information
lisitsyn committed May 5, 2024
1 parent 9577132 commit fd30df3
Show file tree
Hide file tree
Showing 21 changed files with 735 additions and 356 deletions.
378 changes: 22 additions & 356 deletions include/tapkee/methods/all.hpp

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions include/tapkee/methods/base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,5 +87,16 @@ class ImplementationBase

};

#define __TAPKEE_IMPLEMENTATION(Method) \
template <class RandomAccessIterator, class KernelCallback, class DistanceCallback, class FeaturesCallback> \
class Method ## Implementation : public ImplementationBase<RandomAccessIterator, KernelCallback, DistanceCallback, FeaturesCallback> \
{ \
public: \
Method ## Implementation(const ImplementationBase<RandomAccessIterator, KernelCallback, DistanceCallback, FeaturesCallback>& other) : \
ImplementationBase<RandomAccessIterator, KernelCallback, DistanceCallback, FeaturesCallback>(other) \
{ \
}
#define __TAPKEE_END_IMPLEMENTATION() };

} // End of namespace tapkee_internal
} // End of namespace tapkee
44 changes: 44 additions & 0 deletions include/tapkee/methods/diffusion_map.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/* This software is distributed under BSD 3-clause license (see LICENSE file).
*
* Copyright (c) 2024 Sergey Lisitsyn, Fernando Iglesias
*/
#pragma once

/* Tapkee includes */
#include <tapkee/methods/base.hpp>
#include <tapkee/routines/diffusion_maps.hpp>
#include <tapkee/routines/eigendecomposition.hpp>
/* End of Tapkee includes */

namespace tapkee
{
namespace tapkee_internal
{

__TAPKEE_IMPLEMENTATION(DiffusionMap)
TapkeeOutput embed()
{
this->parameters[diffusion_map_timesteps].checked().satisfies(Positivity<IndexType>()).orThrow();
this->parameters[gaussian_kernel_width].checked().satisfies(Positivity<ScalarType>()).orThrow();

IndexType target_dimension_value = static_cast<IndexType>(this->parameters[target_dimension]);
Parameter target_dimension_add = Parameter::create("target_dimension", target_dimension_value + 1);
DenseSymmetricMatrix diffusion_matrix =
compute_diffusion_matrix(this->begin, this->end, this->distance, this->parameters[gaussian_kernel_width]);
EigendecompositionResult decomposition_result =
eigendecomposition(this->parameters[eigen_method], this->parameters[computation_strategy], LargestEigenvalues,
diffusion_matrix, target_dimension_add);
DenseMatrix embedding = (decomposition_result.first).leftCols(target_dimension_value);
// scaling with lambda_i^t
for (IndexType i = 0; i < target_dimension_value; i++)
embedding.col(i).array() *=
pow(decomposition_result.second(i), static_cast<IndexType>(this->parameters[diffusion_map_timesteps]));
// scaling by eigenvector to largest eigenvalue 1
for (IndexType i = 0; i < target_dimension_value; i++)
embedding.col(i).array() /= decomposition_result.first.col(target_dimension_value).array();
return TapkeeOutput(embedding, unimplementedProjectingFunction());
}
__TAPKEE_END_IMPLEMENTATION()

} // End of namespace tapkee_internal
} // End of namespace tapkee
30 changes: 30 additions & 0 deletions include/tapkee/methods/factor_analysis.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/* This software is distributed under BSD 3-clause license (see LICENSE file).
*
* Copyright (c) 2024 Sergey Lisitsyn, Fernando Iglesias
*/
#pragma once

/* Tapkee includes */
#include <tapkee/methods/base.hpp>
#include <tapkee/routines/fa.hpp>
/* End of Tapkee includes */

namespace tapkee
{
namespace tapkee_internal
{

__TAPKEE_IMPLEMENTATION(FactorAnalysis)
TapkeeOutput embed()
{
this->parameters[fa_epsilon].checked().satisfies(NonNegativity<ScalarType>()).orThrow();

DenseVector mean_vector = compute_mean(this->begin, this->end, this->features, this->current_dimension);
return TapkeeOutput(project(this->begin, this->end, this->features, this->current_dimension, this->parameters[max_iteration],
this->parameters[fa_epsilon], this->parameters[target_dimension], mean_vector),
unimplementedProjectingFunction());
}
__TAPKEE_END_IMPLEMENTATION()

} // End of namespace tapkee_internal
} // End of namespace tapkee
31 changes: 31 additions & 0 deletions include/tapkee/methods/hessian_locally_linear_embedding.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* This software is distributed under BSD 3-clause license (see LICENSE file).
*
* Copyright (c) 2024 Sergey Lisitsyn, Fernando Iglesias
*/
#pragma once

/* Tapkee includes */
#include <tapkee/methods/base.hpp>
#include <tapkee/routines/eigendecomposition.hpp>
#include <tapkee/routines/locally_linear.hpp>
/* End of Tapkee includes */

namespace tapkee
{
namespace tapkee_internal
{

__TAPKEE_IMPLEMENTATION(HessianLocallyLinearEmbedding)
TapkeeOutput embed()
{
Neighbors neighbors = this->findNeighborsWith(this->kernel_distance);
SparseWeightMatrix weight_matrix =
hessian_weight_matrix(this->begin, this->end, neighbors, this->kernel, this->parameters[target_dimension]);
return TapkeeOutput(eigendecomposition(this->parameters[eigen_method], this->parameters[computation_strategy],
SmallestEigenvalues, weight_matrix, this->parameters[target_dimension]).first,
unimplementedProjectingFunction());
}
__TAPKEE_END_IMPLEMENTATION()

} // End of namespace tapkee_internal
} // End of namespace tapkee
41 changes: 41 additions & 0 deletions include/tapkee/methods/isomap.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/* This software is distributed under BSD 3-clause license (see LICENSE file).
*
* Copyright (c) 2024 Sergey Lisitsyn, Fernando Iglesias
*/
#pragma once

/* Tapkee includes */
#include <tapkee/methods/base.hpp>
#include <tapkee/routines/eigendecomposition.hpp>
#include <tapkee/routines/isomap.hpp>
#include <tapkee/routines/multidimensional_scaling.hpp>
/* End of Tapkee includes */

namespace tapkee
{
namespace tapkee_internal
{

__TAPKEE_IMPLEMENTATION(Isomap)
TapkeeOutput embed()
{
Neighbors neighbors = this->findNeighborsWith(this->plain_distance);
DenseSymmetricMatrix shortest_distances_matrix =
compute_shortest_distances_matrix(this->begin, this->end, neighbors, this->distance);
shortest_distances_matrix = shortest_distances_matrix.array().square();
centerMatrix(shortest_distances_matrix);
shortest_distances_matrix.array() *= -0.5;

EigendecompositionResult embedding =
eigendecomposition(this->parameters[eigen_method], this->parameters[computation_strategy], LargestEigenvalues,
shortest_distances_matrix, this->parameters[target_dimension]);

for (IndexType i = 0; i < static_cast<IndexType>(this->parameters[target_dimension]); i++)
embedding.first.col(i).array() *= sqrt(embedding.second(i));

return TapkeeOutput(embedding.first, unimplementedProjectingFunction());
}
__TAPKEE_END_IMPLEMENTATION()

} // End of namespace tapkee_internal
} // End of namespace tapkee
32 changes: 32 additions & 0 deletions include/tapkee/methods/kernel_local_tangent_space_alignment.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* This software is distributed under BSD 3-clause license (see LICENSE file).
*
* Copyright (c) 2024 Sergey Lisitsyn, Fernando Iglesias
*/
#pragma once

/* Tapkee includes */
#include <tapkee/methods/base.hpp>
#include <tapkee/routines/eigendecomposition.hpp>
#include <tapkee/routines/locally_linear.hpp>
/* End of Tapkee includes */

namespace tapkee
{
namespace tapkee_internal
{

__TAPKEE_IMPLEMENTATION(KernelLocalTangentSpaceAlignment)
TapkeeOutput embed()
{
Neighbors neighbors = this->findNeighborsWith(this->kernel_distance);
SparseWeightMatrix weight_matrix = tangent_weight_matrix(
this->begin, this->end, neighbors, this->kernel, this->parameters[target_dimension], this->parameters[nullspace_shift]);
DenseMatrix embedding = eigendecomposition(this->parameters[eigen_method], this->parameters[computation_strategy],
SmallestEigenvalues, weight_matrix, this->parameters[target_dimension]).first;

return TapkeeOutput(embedding, unimplementedProjectingFunction());
}
__TAPKEE_END_IMPLEMENTATION()

} // End of namespace tapkee_internal
} // End of namespace tapkee
32 changes: 32 additions & 0 deletions include/tapkee/methods/kernel_locally_linear_embedding.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* This software is distributed under BSD 3-clause license (see LICENSE file).
*
* Copyright (c) 2024 Sergey Lisitsyn, Fernando Iglesias
*/
#pragma once

/* Tapkee includes */
#include <tapkee/methods/base.hpp>
#include <tapkee/routines/eigendecomposition.hpp>
#include <tapkee/routines/locally_linear.hpp>
/* End of Tapkee includes */

namespace tapkee
{
namespace tapkee_internal
{

__TAPKEE_IMPLEMENTATION(KernelLocallyLinearEmbedding)
TapkeeOutput embed()
{
Neighbors neighbors = this->findNeighborsWith(this->kernel_distance);
SparseWeightMatrix weight_matrix =
linear_weight_matrix(this->begin, this->end, neighbors, this->kernel, this->parameters[nullspace_shift], this->parameters[klle_shift]);
DenseMatrix embedding = eigendecomposition(this->parameters[eigen_method], this->parameters[computation_strategy],
SmallestEigenvalues, weight_matrix, this->parameters[target_dimension]).first;

return TapkeeOutput(embedding, unimplementedProjectingFunction());
}
__TAPKEE_END_IMPLEMENTATION()

} // End of namespace tapkee_internal
} // End of namespace tapkee
32 changes: 32 additions & 0 deletions include/tapkee/methods/kernel_pca.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* This software is distributed under BSD 3-clause license (see LICENSE file).
*
* Copyright (c) 2024 Sergey Lisitsyn, Fernando Iglesias
*/
#pragma once

/* Tapkee includes */
#include <tapkee/methods/base.hpp>
#include <tapkee/routines/eigendecomposition.hpp>
#include <tapkee/routines/pca.hpp>
/* End of Tapkee includes */

namespace tapkee
{
namespace tapkee_internal
{

__TAPKEE_IMPLEMENTATION(KernelPCA)
TapkeeOutput embed()
{
DenseSymmetricMatrix centered_kernel_matrix = compute_centered_kernel_matrix(this->begin, this->end, this->kernel);
EigendecompositionResult embedding =
eigendecomposition(this->parameters[eigen_method], this->parameters[computation_strategy], LargestEigenvalues,
centered_kernel_matrix, this->parameters[target_dimension]);
for (IndexType i = 0; i < static_cast<IndexType>(this->parameters[target_dimension]); i++)
embedding.first.col(i).array() *= sqrt(embedding.second(i));
return TapkeeOutput(embedding.first, unimplementedProjectingFunction());
}
__TAPKEE_END_IMPLEMENTATION()

} // End of namespace tapkee_internal
} // End of namespace tapkee
62 changes: 62 additions & 0 deletions include/tapkee/methods/landmark_isomap.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/* This software is distributed under BSD 3-clause license (see LICENSE file).
*
* Copyright (c) 2024 Sergey Lisitsyn, Fernando Iglesias
*/
#pragma once

/* Tapkee includes */
#include <tapkee/methods/base.hpp>
#include <tapkee/routines/eigendecomposition.hpp>
#include <tapkee/routines/isomap.hpp>
#include <tapkee/routines/multidimensional_scaling.hpp>
/* End of Tapkee includes */

namespace tapkee
{
namespace tapkee_internal
{

__TAPKEE_IMPLEMENTATION(LandmarkIsomap)
TapkeeOutput embed()
{
this->parameters[landmark_ratio].checked().satisfies(InClosedRange<ScalarType>(3.0 / this->n_vectors, 1.0)).orThrow();

Neighbors neighbors = this->findNeighborsWith(this->plain_distance);
Landmarks landmarks = select_landmarks_random(this->begin, this->end, this->parameters[landmark_ratio]);
DenseMatrix distance_matrix = compute_shortest_distances_matrix(this->begin, this->end, landmarks, neighbors, this->distance);
distance_matrix = distance_matrix.array().square();

DenseVector col_means = distance_matrix.colwise().mean();
DenseVector row_means = distance_matrix.rowwise().mean();
ScalarType grand_mean = distance_matrix.mean();
distance_matrix.array() += grand_mean;
distance_matrix.colwise() -= row_means;
distance_matrix.rowwise() -= col_means.transpose();
distance_matrix.array() *= -0.5;

EigendecompositionResult landmarks_embedding;

if (this->parameters[eigen_method].is(Dense))
{
DenseMatrix distance_matrix_sym = distance_matrix * distance_matrix.transpose();
landmarks_embedding =
eigendecomposition(this->parameters[eigen_method], this->parameters[computation_strategy], LargestEigenvalues,
distance_matrix_sym, this->parameters[target_dimension]);
}
else
{
landmarks_embedding =
eigendecomposition(this->parameters[eigen_method], this->parameters[computation_strategy],
SquaredLargestEigenvalues, distance_matrix, this->parameters[target_dimension]);
}

DenseMatrix embedding = distance_matrix.transpose() * landmarks_embedding.first;

for (IndexType i = 0; i < static_cast<IndexType>(this->parameters[target_dimension]); i++)
embedding.col(i).array() /= sqrt(sqrt(landmarks_embedding.second(i)));
return TapkeeOutput(embedding, unimplementedProjectingFunction());
}
__TAPKEE_END_IMPLEMENTATION()

} // End of namespace tapkee_internal
} // End of namespace tapkee
40 changes: 40 additions & 0 deletions include/tapkee/methods/landmark_multidimensional_scaling.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/* This software is distributed under BSD 3-clause license (see LICENSE file).
*
* Copyright (c) 2024 Sergey Lisitsyn, Fernando Iglesias
*/
#pragma once

/* Tapkee includes */
#include <tapkee/methods/base.hpp>
#include <tapkee/routines/eigendecomposition.hpp>
#include <tapkee/routines/multidimensional_scaling.hpp>
/* End of Tapkee includes */

namespace tapkee
{
namespace tapkee_internal
{

__TAPKEE_IMPLEMENTATION(LandmarkMultidimensionalScaling)
TapkeeOutput embed()
{
this->parameters[landmark_ratio].checked().satisfies(InClosedRange<ScalarType>(3.0 / this->n_vectors, 1.0)).orThrow();

Landmarks landmarks = select_landmarks_random(this->begin, this->end, this->parameters[landmark_ratio]);
DenseSymmetricMatrix distance_matrix = compute_distance_matrix(this->begin, this->end, landmarks, this->distance);
DenseVector landmark_distances_squared = distance_matrix.colwise().mean();
centerMatrix(distance_matrix);
distance_matrix.array() *= -0.5;
EigendecompositionResult landmarks_embedding =
eigendecomposition(this->parameters[eigen_method], this->parameters[computation_strategy], LargestEigenvalues,
distance_matrix, this->parameters[target_dimension]);
for (IndexType i = 0; i < static_cast<IndexType>(this->parameters[target_dimension]); i++)
landmarks_embedding.first.col(i).array() *= sqrt(landmarks_embedding.second(i));
return TapkeeOutput(triangulate(this->begin, this->end, this->distance, landmarks, landmark_distances_squared,
landmarks_embedding, this->parameters[target_dimension]),
unimplementedProjectingFunction());
}
__TAPKEE_END_IMPLEMENTATION()

} // End of namespace tapkee_internal
} // End of namespace tapkee
Loading

0 comments on commit fd30df3

Please sign in to comment.