Skip to content

Commit

Permalink
Move methods implementations into separate files (#93)
Browse files Browse the repository at this point in the history
  • Loading branch information
lisitsyn authored May 6, 2024
1 parent 6306c1c commit a7044a6
Show file tree
Hide file tree
Showing 25 changed files with 872 additions and 385 deletions.
397 changes: 13 additions & 384 deletions include/tapkee/methods.hpp

Large diffs are not rendered by default.

44 changes: 44 additions & 0 deletions include/tapkee/methods/all.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/methods/kernel_locally_linear_embedding.hpp>
#include <tapkee/methods/kernel_local_tangent_space_alignment.hpp>
#include <tapkee/methods/diffusion_map.hpp>
#include <tapkee/methods/multidimensional_scaling.hpp>
#include <tapkee/methods/landmark_multidimensional_scaling.hpp>
#include <tapkee/methods/isomap.hpp>
#include <tapkee/methods/landmark_isomap.hpp>
#include <tapkee/methods/neighborhood_preserving_embedding.hpp>
#include <tapkee/methods/hessian_locally_linear_embedding.hpp>
#include <tapkee/methods/laplacian_eigenmaps.hpp>
#include <tapkee/methods/locality_preserving_projections.hpp>
#include <tapkee/methods/pca.hpp>
#include <tapkee/methods/random_projection.hpp>
#include <tapkee/methods/kernel_pca.hpp>
#include <tapkee/methods/linear_local_tangent_space_alignment.hpp>
#include <tapkee/methods/stochastic_proximity_embedding.hpp>
#include <tapkee/methods/factor_analysis.hpp>
#include <tapkee/methods/manifold_sculpting.hpp>
#include <tapkee/methods/tsne.hpp>
/* End of Tapkee includes */

namespace tapkee
{
namespace tapkee_internal
{

__TAPKEE_IMPLEMENTATION(PassThru)
TapkeeOutput embed()
{
DenseMatrix feature_matrix = dense_matrix_from_features(this->features, this->current_dimension, this->begin, this->end);
return TapkeeOutput(feature_matrix.transpose(), unimplementedProjectingFunction());
}
__TAPKEE_END_IMPLEMENTATION()

} // End of namespace tapkee_internal
} // End of namespace tapkee
102 changes: 102 additions & 0 deletions include/tapkee/methods/base.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@

/* This software is distributed under BSD 3-clause license (see LICENSE file).
*
* Copyright (c) 2012-2013 Sergey Lisitsyn, Fernando Iglesias
*/
#pragma once

/* Tapkee includes */
#include <tapkee/defines.hpp>
#include <tapkee/neighbors/neighbors.hpp>
#include <tapkee/parameters/context.hpp>
#include <tapkee/parameters/defaults.hpp>
#include <tapkee/predicates.hpp>
#include <tapkee/projection.hpp>
#include <tapkee/utils/features.hpp>
#include <tapkee/utils/logging.hpp>
#include <tapkee/utils/naming.hpp>
#include <tapkee/utils/time.hpp>
/* End of Tapkee includes */

namespace tapkee
{
namespace tapkee_internal
{

template <class RandomAccessIterator, class KernelCallback, class DistanceCallback, class FeaturesCallback>
class ImplementationBase
{
public:
ImplementationBase(RandomAccessIterator b, RandomAccessIterator e, KernelCallback k, DistanceCallback d,
FeaturesCallback f, ParametersSet& pmap, const Context& ctx)
: parameters(pmap), context(ctx), kernel(k), distance(d), features(f),
plain_distance(PlainDistance<RandomAccessIterator, DistanceCallback>(distance)),
kernel_distance(KernelDistance<RandomAccessIterator, KernelCallback>(kernel)), begin(b), end(e), n_vectors(0),
current_dimension(0)
{
n_vectors = (end - begin);

if (n_vectors == 0)
throw no_data_error();

parameters[target_dimension].checked().satisfies(InRange<IndexType>(1, n_vectors)).orThrow();

if (!is_dummy<FeaturesCallback>::value)
current_dimension = features.dimension();
else
current_dimension = 0;
}
ImplementationBase(const ImplementationBase<RandomAccessIterator, KernelCallback, DistanceCallback, FeaturesCallback>& other)
: parameters(other.parameters)
, context(other.context)
, kernel(other.kernel)
, distance(other.distance)
, features(other.features)
, plain_distance(other.plain_distance)
, kernel_distance(other.kernel_distance)
, begin(other.begin)
, end(other.end)
, n_vectors(other.n_vectors)
, current_dimension(other.current_dimension)
{

}

public:
ParametersSet parameters;
Context context;
KernelCallback kernel;
DistanceCallback distance;
FeaturesCallback features;
PlainDistance<RandomAccessIterator, DistanceCallback> plain_distance;
KernelDistance<RandomAccessIterator, KernelCallback> kernel_distance;

RandomAccessIterator begin;
RandomAccessIterator end;

IndexType n_vectors;
IndexType current_dimension;

protected:
template <class Distance> Neighbors findNeighborsWith(Distance d)
{
parameters[num_neighbors].checked().satisfies(InRange<IndexType>(3, n_vectors)).orThrow();
return find_neighbors(parameters[neighbors_method], begin, end, d, parameters[num_neighbors],
parameters[check_connectivity]);
}

};

#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
Loading

0 comments on commit a7044a6

Please sign in to comment.