Files
mlpack/fastlib/branches/fastlib-old/thor/allnn.cc
T
Ryan Curtin f6864dd435 Move fastlib-old (originally 'fastlib') to fastlib/branches/fastlib-old where it
will sit until the end of time and nobody will touch it because it's old
2010-01-31 22:31:55 +00:00

244 lines
6.3 KiB
C++

/**
* @file allnn.cc
*
* A multithreaded and cluster-parallel nearest neighbors finder.
*
* TODO: Currently doesn't output anything.
*/
#include "thor/thor.h"
#include "fastlib/fastlib.h"
/**
* An N-Body-Reduce problem.
*/
class Allnn {
public:
/**
* All parameters required by the execution of the algorithm.
*
* Required by THOR.
*/
struct Param {
public:
/** The dimensionality of the data sets. */
index_t dim;
OT_DEF_BASIC(Param) {
OT_MY_OBJECT(dim);
}
public:
/**
* Initialize parameters from a data node (Req THOR).
*/
void Init(datanode *datanode) {
dim = -1;
}
void SetDimensions(index_t vector_dimension, index_t n_points) {
dim = vector_dimension;
}
};
/** The bounding type. Required by THOR. */
typedef DHrectBound<2> Bound;
/** The type of point in use. Required by THOR. */
typedef ThorVectorPoint QPoint;
typedef ThorVectorPoint RPoint;
typedef BlankStat QStat;
typedef BlankStat RStat;
typedef ThorNode<Bound, BlankStat> RNode;
typedef ThorNode<Bound, BlankStat> QNode;
typedef BlankQPostponed QPostponed;
typedef BlankDelta Delta;
typedef BlankGlobalResult GlobalResult;
// rho
struct QResult {
public:
double distance_sq;
index_t neighbor_i;
OT_DEF_BASIC(QResult) {
OT_MY_OBJECT(distance_sq);
OT_MY_OBJECT(neighbor_i);
}
public:
void Init(const Param& param) {
distance_sq = DBL_MAX;
neighbor_i = -1;
}
void Postprocess(const Param& param,
const QPoint& q_point, index_t q_index,
const RNode& r_root) {}
void ApplyPostponed(const Param& param,
const QPostponed& postponed,
const QPoint& q_point,
index_t q_index) {}
};
struct QSummaryResult {
public:
MinMaxVal<double> distance_sq_hi;
OT_DEF_BASIC(QSummaryResult) {
OT_MY_OBJECT(distance_sq_hi);
}
public:
void Init(const Param& param) {
distance_sq_hi = DBL_MAX;
}
void ApplyDelta(const Param& param, const Delta& delta) {}
void ApplyPostponed(const Param& param,
const QPostponed& postponed, const QNode& q_node) {}
void ApplySummaryResult(const Param& param, const QSummaryResult& summary_result) {
distance_sq_hi.MinWith(summary_result.distance_sq_hi);
}
void StartReaccumulate(const Param& param, const QNode& q_node) {
distance_sq_hi = 0;
}
void Accumulate(const Param& param, const QResult& result) {
distance_sq_hi.MaxWith(result.distance_sq);
}
void Accumulate(const Param& param,
const QSummaryResult& result, index_t n_points) {
distance_sq_hi.MaxWith(result.distance_sq_hi);
}
void FinishReaccumulate(const Param& param, const QNode& q_node) {}
};
/**
* Abstract out the inner loop in a way that allows temporary variables
* to be register-allocated.
*/
struct PairVisitor {
public:
double distance_sq;
index_t neighbor_i;
public:
void Init(const Param& param) {}
bool StartVisitingQueryPoint(const Param& param,
const QPoint& q_point,
index_t q_index,
const RNode& r_node,
const QSummaryResult& unapplied_summary_results,
QResult* q_result,
GlobalResult* global_result) {
/* ignore horizontal join operator */
distance_sq = q_result->distance_sq;
neighbor_i = q_result->neighbor_i;
return r_node.bound().MinDistanceSq(q_point.vec()) <= distance_sq;
}
bool StartVisitingQueryPoint(const Param& param,
const QPoint& q_point,
index_t q_index,
const RNode& r_node,
QResult* q_result,
GlobalResult* global_result) {
distance_sq = q_result->distance_sq;
neighbor_i = q_result->neighbor_i;
return true;
}
void VisitPair(const Param& param,
const QPoint& q_point, index_t q_index,
const RPoint& r_point, index_t r_index) {
double trial_distance_sq = la::DistanceSqEuclidean(
q_point.vec(), r_point.vec());
if (unlikely(trial_distance_sq <= distance_sq)) {
// TODO: Is this really indicative of q != r?
if (likely(trial_distance_sq != 0)) {
neighbor_i = r_index;
distance_sq = trial_distance_sq;
}
}
}
void FinishVisitingQueryPoint(const Param& param,
const QPoint& q_point, index_t q_index,
const RNode& r_node, const QSummaryResult& unapplied_summary_results,
QResult* q_result, GlobalResult* global_result) {
q_result->distance_sq = distance_sq;
q_result->neighbor_i = neighbor_i;
}
void FinishVisitingQueryPoint(const Param& param,
const QPoint& q_point, index_t q_index,
const RNode& r_node,
QResult* q_result, GlobalResult* global_result) {
q_result->distance_sq = distance_sq;
q_result->neighbor_i = neighbor_i;
}
};
class Algorithm {
public:
/**
* Calculates a delta and intrinsic pruning.
*/
static bool ConsiderPairIntrinsic(const Param& param,
const QNode& q_node, const RNode& r_node,
Delta* delta,
GlobalResult* global_result, QPostponed* q_postponed) {
return true;
}
/**
* Attempts extrinsic pruning.
*/
static bool ConsiderPairExtrinsic(const Param& param,
const QNode& q_node, const RNode& r_node, const Delta& delta,
const QSummaryResult& q_summary_result, const GlobalResult& global_result,
QPostponed* q_postponed) {
double distance_sq_lo = q_node.bound().MinDistanceSq(r_node.bound());
return distance_sq_lo <= q_summary_result.distance_sq_hi;
}
/**
* Attempts termination pruning.
*/
static bool ConsiderQueryTermination(const Param& param,
const QNode& q_node,
const QSummaryResult& q_summary_result, const GlobalResult& global_result,
QPostponed* q_postponed) {
return true;
}
/**
* Computes a heuristic for how early a computation should occur -- smaller
* values are earlier.
*/
static double Heuristic(const Param& param,
const QNode& q_node, const RNode& r_node, const Delta& delta) {
return r_node.bound().MinToMidSq(q_node.bound());
}
};
};
int main(int argc, char *argv[]) {
fx_init(argc, argv);
thor::MonochromaticDualTreeMain<Allnn, DualTreeDepthFirst<Allnn> >(
fx_root, "allnn");
fx_done();
}