wrote multi-matcher with inefficient base case

This commit is contained in:
Bill March
2010-06-07 19:56:02 +00:00
parent 208feb44f0
commit 5d12924758
9 changed files with 737 additions and 140 deletions
+14
View File
@@ -12,6 +12,20 @@ librule(
deplibs = ["fastlib:fastlib", ":n_point_impl"]
)
librule(
name = "n_point_multi",
sources = ["n_point_multi.cc", "results_tensor.cc", "multi_matcher.cc", "n_point_nodes.cc"],
headers = ["n_point_multi.h", "results_tensor.h", "multi_matcher.h", "n_point_nodes.h"],
deplibs = ["fastlib:fastlib", ":n_point_impl"]
)
binrule(
name = "n_point_multi_main",
sources = ["n_point_multi_main.cc"],
headers = [],
deplibs = ["fastlib:fastlib", ":n_point_multi"]
)
binrule(
name = "n_point_testing",
sources = ["n_point_testing.cc"],
@@ -9,19 +9,53 @@
#include "multi_matcher.h"
// fills in the ranges of indices in the bandwidth
void MultiMatcher::FindBandwidths_(double min_dist_sq, double max_dist_sq,
double* max_subsume, double* min_exclude) {
bool MultiMatcher::TestPointPair(double dist_sq, index_t tuple_index_1,
index_t tuple_index_2,
ArrayList<bool>& permutation_ok,
ArrayList<GenMatrix<index_t> >& permutation_ranges) {
bool this_point_works = false;
DEBUG_ASSERT(tuple_index_1 < tuple_index_2);
for (index_t perm_ind = 0; perm_ind < num_permutations_; perm_ind++) {
// this permutation is already bad
if (! permutation_ok[perm_ind]) {
continue;
}
if (dist_sq >= distances_[num_bins_ - 1]) {
// this permutation is bad
permutation_ok[perm_ind] = false;
continue;
}
// figure out what the largest index that works is here
//permutation_ranges[perm_ind].set(tuple_index_1, tuple_index_2, dist_sq);
// TODO: do I need to set the other side of the diagonal?
// TODO: double check this
double* ind_ptr = std::upper_bound(distances_.begin(), distances_.end(),
dist_sq);
int ind = (int)(ind_ptr - distances_.begin());
permutation_ranges[perm_ind].set(tuple_index_1, tuple_index_2, ind);
this_point_works = true;
} // loop over permutations
return this_point_works;
} // FindBandwidths_()
} // TestPointPair
// this needs to return the correct range of inconclusive bandwidths for the
// pair of nodes (i.e. everything inside is subsumed, everything outside is
// excluded)
// PROBLEM: the range for one permutation and that for another need not overlap
/*
void MultiMatcher::TestNodes_(const DHrectBound<2>& box1,
const DHrectBound<2>& box2,
index_t tuple_index_1, index_t tuple_index_2,
@@ -40,5 +74,5 @@ void MultiMatcher::TestNodes_(const DHrectBound<2>& box1,
range_out.Init(max_subsume, min_exclude);
} // TestNodes_
*/
@@ -10,8 +10,8 @@
#ifndef MULTI_MATCHER_H
#define MULTI_MATCHER_H
#include "n_point_results.h"
#include "fastlib/fastlib.h"
#include "n_point_impl.h"
class MultiMatcher {
@@ -20,16 +20,57 @@ private:
////////// variables /////////////
ArrayList<double> ranges_;
ArrayList<double> distances_;
int num_bins_;
Permutations perms_;
int num_permutations_;
int tuple_size_;
public:
index_t GetPermutationIndex_(index_t perm_index, index_t pt_index) {
// these needed to be swapped to match matcher code
return perms_.GetPermutation(perm_index, pt_index);
} // GetPermutation
int num_permutations() {
return num_permutations_;
}
void TestNodes_(const DHrectBound<2>& box1, const DHrectBound<2>& box2,
ResultsTensor& results);
int num_bins() {
return num_bins_;
}
double max_dist() {
return distances_[num_bins_ - 1];
}
ArrayList<double>& distances() {
return distances_;
}
bool TestPointPair(double dist_sq, index_t tuple_index_1,
index_t tuple_index_2,
ArrayList<bool>& permutation_ok,
ArrayList<GenMatrix<index_t> >& permutation_ranges);
void Init(ArrayList<double>& dists, int n) {
tuple_size_ = n;
// TODO: are these squared?
distances_.InitCopy(dists);
num_bins_ = distances_.size();
perms_.Init(tuple_size_);
num_permutations_ = perms_.num_perms();
} // Init()
}; // class MultiMatcher
+276 -72
View File
@@ -10,7 +10,7 @@
#include "n_point_multi.h"
bool SymmetryCorrect_(ArrayList<NPointNode*>& nodes) {
bool NPointMulti::SymmetryCorrect_(ArrayList<NPointNode*>& nodes) {
for (index_t i = 0; i < tuple_size_; i++) {
@@ -31,7 +31,46 @@ bool SymmetryCorrect_(ArrayList<NPointNode*>& nodes) {
} // SymmetryCorrect_
index_t CheckBaseCase_(ArrayList<NPointNode*>& nodes) {
// fills inds with the indices in the range list that need to be recomputed
void NPointMulti::FindInvalidIndices_() {
invalid_indices_.Init(tuple_size_);
for (index_t split_ind = 0; split_ind < tuple_size_; split_ind++) {
invalid_indices_[split_ind].Init();
// inserted this easy fix, not sure if the rest is right yet
if (tuple_size_ == 2) {
invalid_indices_[split_ind].PushBackCopy(0);
}
else {
index_t bad_ind = split_ind - 1;
index_t bad_ind2 = 0;
for (index_t i = 0; i < split_ind; i++) {
invalid_indices_[split_ind].PushBackCopy(bad_ind);
bad_ind += tuple_size_ - 1 - (i+1);
bad_ind2 += tuple_size_ - i - 1;
} // horizontal
for (index_t i = split_ind+1; i < tuple_size_; i++) {
invalid_indices_[split_ind].PushBackCopy(bad_ind2);
bad_ind2++;
}
} // n > 2
} // for split_ind
} // FindInvalidIndices_()
index_t NPointMulti::CheckBaseCase_(ArrayList<NPointNode*>& nodes) {
index_t split_ind = -1;
int split_size = 0;
@@ -55,7 +94,7 @@ index_t CheckBaseCase_(ArrayList<NPointNode*>& nodes) {
// needs to find the right index among (n choose 2) quantities, where i is
// less than j
index_t FindInd_(index_t i, index_t j) {
index_t NPointMulti::FindInd_(index_t i, index_t j) {
DEBUG_ASSERT(i < j);
@@ -63,88 +102,253 @@ index_t FindInd_(index_t i, index_t j) {
} // FindInd_()
void BaseCase_(ArrayList<NPointNode*>& nodes, ResultsTensor& tuple_status,
ResultsTensor& results) {
// returns true if the indices violate the symmetry requirement
bool NPointMulti::PointsViolateSymmetry_(index_t ind1, index_t ind2) {
DEBUG_ASSERT(ind1 >= 0);
DEBUG_ASSERT(ind2 >= 0);
return (ind2 <= ind1);
} // PointsViolateSymmetry_()
void NPointMulti::BaseCaseHelper_(ArrayList<ArrayList<index_t> >& point_sets,
ArrayList<bool>& permutation_ok,
ArrayList<index_t>& points_in_tuple,
int k,
ArrayList<GenMatrix<index_t> >& permutation_ranges) {
// iterate over status tensor, skip things that are excluded
ArrayList<bool> permutation_ok_copy;
permutation_ok_copy.InitCopy(permutation_ok);
for (int i = 0; i < tensor_size; i++) {
ArrayList<GenMatrix<index_t> > permutation_ranges_copy;
permutation_ranges_copy.InitCopy(permutation_ranges);
ArrayList<index_t> k_rows;
k_rows.InitAlias(point_sets[k]);
bool bad_symmetry = false;
// loop over possible points for the kth member of the tuple
//for (index_t i = 0; !bad_symmetry && i < k_rows.size(); i++) {
// IMPORTANT: can't exit here for bad symmetry, it can get better as
// i increases
for (index_t i = 0; i < k_rows.size(); i++) {
if (! exclude) {
matcher_.TestPointSets();
index_t point_index_i = k_rows[i];
bool this_point_works = true;
Vector point_i;
data_points_.MakeColumnVector(point_index_i, &point_i);
// TODO: is this too inefficient?
permutation_ok_copy.Clear();
permutation_ok_copy.AppendCopy(permutation_ok);
permutation_ranges_copy.Clear();
permutation_ranges_copy.AppendCopy(permutation_ranges);
// TODO: figure out a way to handle the bad symmetry more elegantly
// I should be able to avoid a bit more work
for (index_t j = 0; this_point_works && j < k; j++) {
}
index_t point_index_j = points_in_tuple[j];
// j should come before i since j comes first
bad_symmetry = PointsViolateSymmetry_(point_index_j, point_index_i);
//printf("point_j: %d, point_i: %d, bad_symmetry: %d\n", point_index_j,
// point_index_i, bad_symmetry);
// don't compute the distances if we don't have to
if (!bad_symmetry) {
Vector point_j;
data_points_.MakeColumnVector(point_index_j, &point_j);
double point_dist_sq = la::DistanceSqEuclidean(point_i, point_j);
//printf("Testing point pair (%d, %d)\n", j, k);
// This needs to fill in the permutation_ok_copy for each matcher
this_point_works = matcher_.TestPointPair(point_dist_sq, j, k,
permutation_ok_copy,
permutation_ranges_copy);
//printf("this_point_works: %d\n", this_point_works);
} // compute the distances and check the matcher
} // for j
}
/*
printf("Considering point %d in position %d. bad_symmetry: %d, works: %d\n",
point_index_i, k, bad_symmetry, this_point_works);
*/
// now, if the point passed, we put it in place and recurse
if (this_point_works && !bad_symmetry) {
points_in_tuple[k] = point_index_i;
// base case of the recursion
if (k == tuple_size_ - 1) {
results_.ClearFilledResults();
for (index_t perm_index = 0; perm_index < matcher_.num_permutations();
perm_index++) {
// this one won't fit anywhere anyway
if (! permutation_ok_copy[perm_index]) {
continue;
}
results_.IncrementRange(permutation_ranges[perm_index]);
} // iterate over permutations
} // base case
else {
BaseCaseHelper_(point_sets, permutation_ok_copy,
points_in_tuple, k+1, permutation_ranges_copy);
} // recurse
//DEBUG_ONLY(points_in_tuple[k] = -1);
} // did the point work
} // for i
} // BaseCaseHelper_()
// Collect the indices of the valid matchers, check against each one?
// How to re-use info?
void NPointMulti::BaseCase_(NodeTuple& nodes,
ArrayList<std::pair<double, double> >& valid_ranges) {
// Create the lists of points
ArrayList<ArrayList<index_t> > point_sets;
point_sets.Init(tuple_size_);
for (index_t i = 0; i < tuple_size_; i++) {
point_sets[i].Init(nodes.node_list(i)->count());
for (index_t j = 0; j < nodes.node_list(i)->count(); j++) {
point_sets[i][j] = j + nodes.node_list(i)->begin();
} // for j
} // for i
ArrayList<GenMatrix<index_t> > permutation_ranges;
permutation_ranges.Init(matcher_.num_permutations());
for (int i = 0; i < permutation_ranges.size(); i++) {
permutation_ranges[i].Init(tuple_size_, tuple_size_);
// TODO: do I need to initialize it to some safe value?
} // fill in permutation matrices
ArrayList<bool> permutation_ok;
permutation_ok.InitRepeat(true, matcher_.num_permutations());
ArrayList<index_t> points_in_tuple;
points_in_tuple.InitRepeat(-1, tuple_size_);
// TODO: figure out which matchers we need to worry about here
BaseCaseHelper_(point_sets, permutation_ok, points_in_tuple, 0,
permutation_ranges);
} // BaseCase_()
void DepthFirstRecursion_(ArrayList<NPointNode*>& nodes,
StatusTensor& status,
ResultsTensor& results) {
// valid_ranges are the ranges of indices in the distances_ array in the matcher
// it has length (n choose 2), the lower ends should be strictly non-decreasing
void NPointMulti::DepthFirstRecursion_(NodeTuple& nodes,
ArrayList<std::pair<double, double> >& valid_ranges) {
bool can_prune = false;
// update valid_ranges
// valid_ranges holds the range of distances that WON'T prune
// i.e. the only matchers that can't be pruned are ones that have a non-empty
// overlap with valid_ranges[i] for all i
for (index_t i = 0; i < valid_ranges.size(); i++) {
// check symmetry
if (!SymmetryCorrect_(nodes)) {
// IMPORTANT: first is lo, second is hi
// TODO: how to account for upper and lower bounds in the matcher?
valid_ranges[i].second = min(valid_ranges[i].second, nodes.upper_bound(i));
valid_ranges[i].first = max(valid_ranges[i].first, nodes.lower_bound(i));
if (valid_ranges[i].first >= valid_ranges[i].second) {
can_prune = true;
break;
} // check if the range is empty
// TODO: make sure that it's not too small or large for any matcher
if (valid_ranges[i].first > matcher_.max_dist()) {
can_prune = true;
break;
} // too large
// add lower bounds here later
} // update ranges
// check prune - i.e. check if it's still possible to contribute to anything
if (can_prune) {
num_total_prunes_++;
return;
}
index_t split_ind = CheckBaseCase_(nodes);
if (split_ind < 0) {
BaseCase_(nodes, status, results);
}
} // check prune
else if (nodes.all_leaves()) {
BaseCase_(nodes, valid_ranges);
} // base case
else {
NodeTuple left_node;
NodeTuple* left_node_ptr = &left_node;
NodeTuple right_node;
NodeTuple* right_node_ptr = &right_node;
// just pass in the invalid indices here
nodes.PerformSplit(left_node_ptr, right_node_ptr, invalid_indices_);
// check if the list of bandwidths is still sorted here
if (left_node_ptr) {
//printf("Left node\n");
//left_node.Print();
ArrayList<std::pair<double, double> > left_ranges;
left_ranges.InitCopy(valid_ranges);
DEBUG_ASSERT(left_node.node_list(0));
DepthFirstRecursion_(left_node, left_ranges);
}
if (right_node_ptr) {
ArrayList<std::pair<double, double> > right_ranges;
right_ranges.InitCopy(valid_ranges);
//printf("Right node\n");
//right_node.Print();
DEBUG_ASSERT(right_node.node_list(0));
DepthFirstRecursion_(right_node, right_ranges);
}
} // recurse
for (int perm_ind = 0; perm_ind < matcher_.num_permutations(); perm_ind++) {
ArrayList<DRange> ranges;
ranges.Init(n_point_impl::NChooseR(tuple_size_, 2));
for (index_t i = 0; i < tuple_size_; i++) {
NPointNode* node_i = nodes[i];
for (index_t j = i+1; j < tuple_size_; j++) {
NPointNode* node_j = nodes[j];
DRange& range_ij = ranges[FindInd_(i, j)];
matcher_.TestNodes_(node_i->bound(), node_j->bound(), i, j, perm_ind,
range_ij);
} // for j
} // for i
// now, we have the ranges for this permutation, fill in the results status
status.FillResults(ranges);
} // for permutations
// TODO: need to be able to tell if something subsumes, and perform it here
// now, split and recurse
NPointNode* split_node = nodes[split_ind];
ResultsTensor right_status;
right_status.Copy(status);
nodes[split_ind] = split_node->left();
DepthFirstRecursion_(nodes, status, results);
nodes[split_ind] = split_node->right();
DepthFirstRecursion_(nodes, right_status, results);
nodes[split_ind] = split_node;
} // not a base case
} // DepthFirstRecursion
} // DepthFirstRecursion_()
@@ -14,6 +14,7 @@
#include "fastlib/fastlib.h"
#include "n_point_impl.h"
#include "results_tensor.h"
#include "n_point_nodes.h"
class NPointMulti {
@@ -24,18 +25,134 @@ private:
MultiMatcher matcher_;
ResultsTensor results_;
fx_module* mod_;
Matrix data_points_;
int leaf_size_;
NPointNode* tree_;
int tuple_size_;
int num_total_prunes_;
ArrayList<ArrayList<index_t> > invalid_indices_;
///////////////// functions ////////////////////
bool SymmetryCorrect_(ArrayList<NPointNode*>& nodes);
index_t CheckBaseCase_(ArrayList<NPointNode*>& nodes);
index_t FindInd_(index_t i, index_t j);
void BaseCaseHelper_(ArrayList<ArrayList<index_t> >& point_sets,
ArrayList<bool>& permutations_ok,
ArrayList<index_t>& points_in_tuple,
int k,
ArrayList<GenMatrix<index_t> >& permutation_ranges);
void BaseCase_(NodeTuple& nodes,
ArrayList<std::pair<double, double> >& valid_ranges);
void DepthFirstRecursion_(NodeTuple& nodes,
ArrayList<std::pair<double, double> >& valid_ranges);
bool PointsViolateSymmetry_(index_t ind1, index_t ind2);
void FindInvalidIndices_();
public:
void Init(const Matrix& data, double band_min, double band_max,
int num_bands, int n, fx_module* mod) {
mod_ = mod;
data_points_.Copy(data);
tuple_size_ = n;
leaf_size_ = fx_param_int(mod_, "leaf_size", 1);
// initialize results tensor
results_.Init(tuple_size_, num_bands);
// initialize matcher
ArrayList<double> dists_sq;
dists_sq.Init(num_bands);
double this_dist = band_min;
double dist_step = (band_max - band_min) / (double)num_bands;
// TODO: double check this
for (index_t i = 0; i < num_bands; i++) {
dists_sq[i] = this_dist * this_dist;
this_dist += dist_step;
}
matcher_.Init(dists_sq, tuple_size_);
ArrayList<index_t> old_from_new;
tree_ = tree::MakeKdTreeMidpoint<NPointNode> (data_points_, leaf_size_,
&old_from_new, NULL);
num_total_prunes_ = 0;
FindInvalidIndices_();
} // Init()
void Compute() {
fx_timer_start(mod_, "n_point_time");
NodeTuple nodes;
ArrayList<NPointNode*> node_list;
node_list.Init(tuple_size_);
for (index_t i = 0; i < tuple_size_; i++) {
node_list[i] = tree_;
} // for i
nodes.Init(node_list);
ArrayList<std::pair<double, double> > valid_ranges;
valid_ranges.Init(n_point_impl::NChooseR(tuple_size_, 2));
for (index_t i = 0; i < valid_ranges.size(); i++) {
valid_ranges[i].first = 0.0;
valid_ranges[i].second = DBL_MAX;
}
DepthFirstRecursion_(nodes, valid_ranges);
fx_timer_stop(mod_, "n_point_time");
const char* filename = fx_param_str(mod_, "output_file", "output.txt");
FILE* fp;
fp = fopen(filename, "w");
results_.Output(matcher_.distances(), fp);
fclose(fp);
} // Compute
}; // NPointMulti
@@ -0,0 +1,40 @@
/*
* n_point_multi_main.cc
*
*
* Created by William March on 6/7/10.
* Copyright 2010 __MyCompanyName__. All rights reserved.
*
*/
#include "fastlib/fastlib.h"
#include "n_point_multi.h"
int main(int argc, char* argv[]) {
fx_init(argc, argv, NULL);
Matrix data;
const char* data_file = fx_param_str_req(NULL, "data");
data::Load(data_file, &data);
double min_band, max_band;
min_band = fx_param_double_req(NULL, "min_band");
max_band = fx_param_double_req(NULL, "max_band");
int num_bands = fx_param_int_req(NULL, "num_bands");
int n = fx_param_int_req(NULL, "n");
fx_module* mod = fx_submodule(NULL, "n_point_multi");
NPointMulti alg;
alg.Init(data, min_band, max_band, num_bands, n, mod);
alg.Compute();
fx_done(NULL);
return 0;
} // main()
@@ -152,7 +152,7 @@ int NPointPermFree::BaseCaseHelper_(ArrayList<ArrayList<index_t> >& point_sets,
DEBUG_ONLY(points_in_tuple[k] = -1);
points_in_tuple[k] = -1;
//points_in_tuple[k] = -1;
} // did the point work
@@ -7,17 +7,15 @@
*
*/
#include "n_point_results.h"
#include "results_tensor.h"
// TODO: test me!
// This is the strictly upper triangular version
/*
index_t ResultsTensor::FindIndex_(const ArrayList<index_t>& indices) {
ArrayList<index_t> sort_ind;
sort_ind.InitCopy(indices);
// TODO: double check that this is correct
std::sort(sort_ind.begin(), sort_ind.end());
// This should be unnecessary
// assuming the smallest index is first
index_t return_ind = 0;
for (index_t i = 1; i <= tensor_rank_; i++) {
@@ -40,14 +38,94 @@ index_t ResultsTensor::FindIndex_(const ArrayList<index_t>& indices) {
} // FindIndex_
*/
// There is a range for each of the n! permutations
void ResultsTensor::FillRanges(ArrayList<DRange>& ranges) {
// Full tensor version
index_t ResultsTensor::FindIndex_(const ArrayList<index_t>& indices) {
index_t result = indices[0];
index_t power = tensor_rank_;
for (index_t i = 1; i < indices.size(); i++) {
result += indices[i] * power;
power = power * tensor_rank_;
} // for i
return result;
} // FindIndex_()
// TODO: test me!
bool ResultsTensor::IncrementIndex_(ArrayList<index_t>& new_ind,
const ArrayList<index_t>& orig_ind,
index_t k) {
if (k >= tensor_rank_) {
return true;
}
new_ind[k]++;
if (new_ind[k] >= lengths_) {
new_ind[k] = orig_ind[k];
return IncrementIndex_(new_ind, orig_ind, k+1);
}
else {
return false;
}
} // IncrementIndex
void ResultsTensor::IncrementRange(const GenMatrix<index_t>& lower_inds) {
// map row major into the index array
// TODO: would column major be more efficient?
} // FillRanges
ArrayList<index_t> this_result;
this_result.Init(lengths_);
index_t row_ind = 0;
index_t col_ind = 1;
for (index_t i = 0; i < this_result.size(); i++) {
this_result[i] = lower_inds.get(row_ind, col_ind);
DEBUG_ASSERT(this_result[i] < lengths_ && this_result[i] >= 0);
col_ind++;
if (col_ind >= lengths_) {
row_ind++;
col_ind = row_ind+1;
} // are we at the end of the row?
} // for i
ArrayList<index_t> this_result_orig;
this_result_orig.InitCopy(this_result);
bool done = false;
while (!done) {
// fill in the entry
index_t this_ind = FindIndex_(this_result);
if (!filled_results_[this_ind]) {
filled_results_[this_ind] = true;
results_[this_ind]++;
}
// increment the array
done = IncrementIndex_(this_result, this_result_orig, 0);
} // while
} // IncrementRange()
+111 -42
View File
@@ -22,41 +22,43 @@ class ResultsTensor {
private:
int tensor_rank_;
int tuple_size_;
int num_bandwidths_;
int lengths_;
ArrayList<double> bandwidths_;
// TODO: how is this organized?
ArrayList<int> results_;
int num_results_;
ArrayList<bool> filled_results_;
//////////// functions //////////////////////
index_t FindIndex_(const ArrayList<index_t>& indices);
bool IncrementIndex_(ArrayList<index_t>& new_ind,
const ArrayList<index_t>& orig_ind,
index_t k);
public:
void Init(int n, double min_band, double max_band, int num_bands) {
DEBUG_ASSERT(max_band > min_band);
DEBUG_ASSERT(num_bands > 0);
void Init(int n, int length) {
tuple_size_ = n;
tensor_rank_ = n_point_impl::NChooseR(n, 2);
num_bandwidths_ = num_bands;
lengths_ = length;
bandwidths_.Init(num_bandwidths_);
num_results_ = 1;
for (index_t i = 0; i < tensor_rank_; i++) {
num_results_ *= lengths_;
}
double bandwidth_step = (max_band - min_band) / (double)num_bandwidths_;
for (index_t i = 0; i < num_bandwidths_; i++) {
bandwidths_[i] = min_band + (double)i * bandwidth_step;
} // fill in bandwidths
results_.Init(n_point_impl::NChooseR(num_bandwidths_ + tuple_size_ + 1,
tuple_size_));
// The strictly upper triangular version
//results_.InitRepeat(initial_result,
// n_point_impl::NChooseR(lengths_ + tuple_size_ + 1,
// tuple_size_));
results_.InitRepeat(0, num_results_);
filled_results_.InitRepeat(false, num_results_);
} // Init()
@@ -75,39 +77,106 @@ public:
results_[ind] = val;
} // set()
void SetAll(int val) {
results_.Clear();
results_.InitRepeat(val, num_results_);
}
void AddTo(const ArrayList<index_t>& indices, int val) {
index_t ind = FindIndex_(indices);
results_[ind] += val;
} // AddTo()
/*
ArrayList<int>& results() const {
return results_;
}
ArrayList<bool>& filled_results() const {
return filled_results_;
}
*/
int tensor_rank() {
return tensor_rank_;
}
int lengths() {
return lengths_;
}
void ClearFilledResults() {
for (index_t i = 0; i < num_results_; i++) {
filled_results_[i] = false;
}
}
void IncrementRange(const GenMatrix<index_t>& lower_inds);
/*
void SetRange(const ArrayList<index_t>& lower_ind,
const ArrayList<index_t>& upper_ind, int val);
void AddToRange(const ArrayList<index_t>& lower_ind,
const ArrayList<index_t>& upper_ind, int val);
void Print() {
*/
// ArrayList<index_t> indices;
// indices.InitRepeat(0, tuple_size_);
/*
void Copy(ResultsTensor& other) {
results_.InitCopy(other.results());
filled_results_.InitCopy(other.filled_results());
tensor_rank_ = other.tensor_rank();
lengths_ = other.lengths();
} // Copy()
*/
// TODO: Make this format better
for (index_t i = 0; i < results_.size(); i++) {
printf("%d\n", results_[i]);
void Output(ArrayList<double>& distances_, FILE* fp) {
ArrayList<index_t> indices;
indices.InitRepeat(0, tensor_rank_);
ArrayList<index_t> indices_copy;
indices_copy.InitCopy(indices);
bool done = false;
while(!done) {
} // initialize
Matrix this_matcher;
this_matcher.Init(tuple_size_, tuple_size_);
index_t row_ind = 0;
index_t col_ind = 1;
for (index_t i = 0; i < indices.size(); i++) {
this_matcher.set(row_ind, col_ind, distances_[indices_copy[i]]);
row_ind++;
if (row_ind >= lengths_) {
row_ind = 0;
col_ind = row_ind + 1;
}
} // fill in the matcher's matrix
index_t ind = FindIndex_(indices_copy);
int this_result = results_[ind];
// now do the printing
this_matcher.PrintDebug("Matcher", fp);
fprintf(fp, "==Result: %d==\n\n", this_result);
done = IncrementIndex_(indices_copy, indices, 0);
} // while
} // Print()
} // Output()
}; // NPointResults