This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
0, 0, 0
|
||||
0, 0, 0
|
||||
0, 0, 0
|
||||
0, 1, 3
|
||||
1, 0, 2
|
||||
3, 2, 0
|
||||
0, 10, 30
|
||||
10, 0, 20
|
||||
30, 20, 0
|
||||
|
||||
@@ -33,9 +33,17 @@ librule(
|
||||
deplibs = ["fastlib:fastlib",":datapack",":metrics",":matcher"]
|
||||
)
|
||||
|
||||
librule(
|
||||
name = "unit_test",
|
||||
sources = ["tests.cc"],
|
||||
headers = ["tests.h"],
|
||||
deplibs =
|
||||
["fastlib:fastlib",":datapack",":metrics",":matcher",":naive",":multi_matcher"]
|
||||
)
|
||||
|
||||
binrule(
|
||||
name = "npoint",
|
||||
sources = ["main.cc"],
|
||||
headers = ["globals.h"],
|
||||
deplibs = ["fastlib:fastlib",":datapack",":metrics",":matcher",":naive"]
|
||||
deplibs = ["fastlib:fastlib",":datapack",":metrics",":matcher",":naive",":unit_test"]
|
||||
)
|
||||
|
||||
@@ -13,9 +13,10 @@
|
||||
#define RECURSE 0
|
||||
|
||||
#define LEAF_SIZE 20
|
||||
#define MAX_N 25
|
||||
#define MAX_N 10
|
||||
|
||||
extern FILE *output;
|
||||
extern int count_all_permutations;
|
||||
extern char *unit_test;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
* --n=[size of n-tuple (default 2)]
|
||||
* --nweights=[number of weights (default 0)]
|
||||
* --metric=[csv file containing the desired metric]
|
||||
* --test=[test name]
|
||||
* etc.
|
||||
*/
|
||||
|
||||
@@ -24,8 +25,10 @@
|
||||
#include "matcher.h"
|
||||
#include "datapack.h"
|
||||
#include "naive.h"
|
||||
#include "tests.h"
|
||||
|
||||
/* Initialize any global variables here. */
|
||||
/* Note: Probably useless. */
|
||||
|
||||
FILE *output = stderr;
|
||||
int count_all_permutations = 0;
|
||||
@@ -37,6 +40,29 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
fx_init(argc,argv);
|
||||
|
||||
/* First we check if we want to run a test */
|
||||
const char *test = fx_param_str(NULL,"test","none");
|
||||
String tmp;
|
||||
|
||||
tmp.Copy(test);
|
||||
if ( tmp.CompareTo("none") ) {
|
||||
if ( !tmp.CompareTo("permutations") ) {
|
||||
const int n = fx_param_int(NULL,"n",2);
|
||||
|
||||
if ( !PASSED(test_permutation_generator(n)) ) {
|
||||
fprintf(output,"\n\nPermutation generator failed for n = %d.\n\n",n);
|
||||
}
|
||||
else {
|
||||
fprintf(output,"\n\nPermutation generator worked for n = %d.\n\n",n);
|
||||
}
|
||||
}
|
||||
|
||||
fx_done();
|
||||
exit(1);
|
||||
}
|
||||
tmp.Destruct();
|
||||
|
||||
/* After the tests are done get the parameters and run the actual program */
|
||||
const char *data_file = fx_param_str_req(NULL,"data");
|
||||
const char *matcher_file = fx_param_str_req(NULL,"matcher");
|
||||
const char *metric_file = fx_param_str(NULL,"metric","default");
|
||||
@@ -50,7 +76,6 @@ int main(int argc, char *argv[])
|
||||
Matcher matcher;
|
||||
Metric metric;
|
||||
Vector count;
|
||||
String tmp;
|
||||
int i;
|
||||
|
||||
tmp.Copy(output_file);
|
||||
|
||||
@@ -215,6 +215,7 @@ success_t Matcher::AnyMatch(const DataPack data, const Vector index, const Metri
|
||||
}
|
||||
else {
|
||||
int ready = 0;
|
||||
index_t i;
|
||||
success_t match = SUCCESS_PASS;
|
||||
Vector tau;
|
||||
tau.Init(n);
|
||||
@@ -223,15 +224,11 @@ success_t Matcher::AnyMatch(const DataPack data, const Vector index, const Metri
|
||||
fprintf(output,"Fatal error: could not generate the first permutation\n");
|
||||
exit(1);
|
||||
}
|
||||
/*
|
||||
for (i=0;i<n;i++) {
|
||||
tau[i] = i;
|
||||
}
|
||||
*/
|
||||
|
||||
do {
|
||||
index_t i,j;
|
||||
index_t j;
|
||||
ready = 1; // be optimistic about the current permutation
|
||||
|
||||
|
||||
for (i=0;i<n;i++) {
|
||||
for (j=i+1;j<n && PASSED(match);j++) {
|
||||
index_t index_i = index[tau[i]], index_j = index[tau[j]];
|
||||
@@ -253,6 +250,7 @@ success_t Matcher::AnyMatch(const DataPack data, const Vector index, const Metri
|
||||
success_t can_make_new_permutation = generate_next_permutation(tau);
|
||||
ready = 0;
|
||||
if ( !PASSED(can_make_new_permutation) ) { // we're out of permutations
|
||||
fprintf(output,"No new permutation avaliable\n\n");
|
||||
return SUCCESS_FAIL; // report that no match could be found
|
||||
}
|
||||
}
|
||||
@@ -278,11 +276,7 @@ success_t Matcher::AnyMatch(const Matrix data, const Vector index, const Metric
|
||||
fprintf(output,"Fatal error: could not generate the first permutation\n");
|
||||
exit(1);
|
||||
}
|
||||
/*
|
||||
for (i=0;i<n;i++) {
|
||||
tau[i] = i;
|
||||
}
|
||||
*/
|
||||
|
||||
do {
|
||||
index_t i,j;
|
||||
ready = 1; // be optimistic about the current permutation
|
||||
@@ -335,9 +329,10 @@ success_t Matcher::AnyMatch(const Matrix distances) const {
|
||||
fprintf(output,"Fatal error: could not generate the first permutation\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
do {
|
||||
index_t i,j;
|
||||
ready = 1; // be optimistic about the current permutation
|
||||
ready = 1;
|
||||
|
||||
for (i=0;i<n;i++) {
|
||||
for (j=i+1;j<n && PASSED(match);j++) {
|
||||
@@ -350,13 +345,13 @@ success_t Matcher::AnyMatch(const Matrix distances) const {
|
||||
}
|
||||
}
|
||||
|
||||
if ( PASSED(match) ) { // we got a match... yupii
|
||||
if ( PASSED(match) ) {
|
||||
return SUCCESS_PASS;
|
||||
}
|
||||
else { // gotta try something new
|
||||
else {
|
||||
ready = 0;
|
||||
if ( !PASSED(generate_next_permutation(distances,tau,dist) ) ) { // out of permutations
|
||||
return SUCCESS_FAIL; // report that no match was found
|
||||
if ( !PASSED(generate_next_permutation(distances,tau,dist) ) ) {
|
||||
return SUCCESS_FAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -436,32 +431,32 @@ success_t generate_first_permutation(Vector &tau) {
|
||||
success_t generate_next_permutation(Vector &tau) {
|
||||
index_t i;
|
||||
index_t n = tau.length();
|
||||
index_t top = n - 1;
|
||||
int is_valid = 1;
|
||||
index_t top = n-1;
|
||||
int ok_so_far = 0;
|
||||
|
||||
do {
|
||||
if ( is_valid && top < (n-1) ) {
|
||||
if (ok_so_far) {
|
||||
top += 1;
|
||||
tau[top] = -1;
|
||||
}
|
||||
|
||||
is_valid = 1;
|
||||
tau[top] += 1;
|
||||
ok_so_far = 1;
|
||||
|
||||
if ( tau[top] > (n-1) ) {
|
||||
if (tau[top] > n-1) {
|
||||
ok_so_far = 0;
|
||||
tau[top] = -1;
|
||||
top -= 1;
|
||||
if (top < 0) {
|
||||
return SUCCESS_FAIL;
|
||||
}
|
||||
}
|
||||
if (top < 0) {
|
||||
return SUCCESS_FAIL;
|
||||
}
|
||||
|
||||
for (i=0;i<top;i++) {
|
||||
if (tau[i] == tau[top]) {
|
||||
is_valid = 0;
|
||||
for (i=0;i<top;i++) {
|
||||
if (tau[top] == tau[i]) {
|
||||
ok_so_far = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
while ( top < (n-1) && !is_valid );
|
||||
while (top < (n-1) || !ok_so_far);
|
||||
|
||||
return SUCCESS_PASS;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @author Angela N. Grigoroaia
|
||||
* @file metrics.h
|
||||
* @author: Angela N. Grigoroaia
|
||||
* @file: metrics.h
|
||||
*
|
||||
* @description: Stuff that takes care of distance computations.
|
||||
**/
|
||||
|
||||
@@ -16,7 +16,7 @@ void estimate_multi_matcher_list(const Matrix data, const Metric metric) {
|
||||
}
|
||||
|
||||
|
||||
double estimate_diameter(const Matrix data, const Metric metric) const {
|
||||
double estimate_diameter(const Matrix data, const Metric metric) {
|
||||
double diam = -1;
|
||||
index_t x,y,z;
|
||||
|
||||
@@ -31,7 +31,7 @@ double estimate_diameter(const Matrix data, const Metric metric) const {
|
||||
|
||||
|
||||
index_t find_farthest_neighbor(const Matrix data, const index_t x,
|
||||
const Metric metric) const {
|
||||
const Metric metric) {
|
||||
double max_dist_so_far = -1;
|
||||
index_t result = -1, i;
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
* matchers over which we wil run naive or single tree n-point. We can also use
|
||||
* it for a divide & conquer approach (dual-tree, multi-matcher n-point).
|
||||
*/
|
||||
void estimate_multi_matcher_list(const Matrix data, const Metric metric) const;
|
||||
void estimate_multi_matcher_list(const Matrix data, const Metric metric);
|
||||
|
||||
/**
|
||||
* Estimate the largest distance between any two points. This should be useful
|
||||
@@ -31,7 +31,7 @@ void estimate_multi_matcher_list(const Matrix data, const Metric metric) const;
|
||||
* 3. Find z such that dist(y,z) is maximized
|
||||
* 4. Return dist (y,z)
|
||||
*/
|
||||
double estimate_diameter(const Matrix data, const Metric metric) const;
|
||||
double estimate_diameter(const Matrix data, const Metric metric);
|
||||
|
||||
/**
|
||||
* Given x, find y such that dist(x,y) is maximum.
|
||||
@@ -40,7 +40,7 @@ double estimate_diameter(const Matrix data, const Metric metric) const;
|
||||
* the index of y.
|
||||
*/
|
||||
index_t find_farthest_neighbor(const Matrix data, const index_t x,
|
||||
const Metric metric) const;
|
||||
const Metric metric);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -13,14 +13,14 @@
|
||||
|
||||
|
||||
Vector naive_npoint(DataPack data, Matcher matcher, Metric metric) {
|
||||
if ( count_all_permutations && matcher.is_simple() ) {
|
||||
if (count_all_permutations && matcher.is_simple()) {
|
||||
Vector tmp;
|
||||
tmp.Copy(symmetric_naive_npoint(data,matcher,metric));
|
||||
la::Scale(math::Factorial(matcher.size()),&tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
if ( count_all_permutations ) {
|
||||
if (count_all_permutations) {
|
||||
return asymmetric_naive_npoint(data,matcher,metric);
|
||||
}
|
||||
|
||||
@@ -52,13 +52,6 @@ Vector symmetric_naive_npoint(DataPack data, Matcher matcher, Metric metric)
|
||||
/* Running the actual naive loop */
|
||||
do {
|
||||
if (PASSED(matcher.Matches(data, index, metric))) {
|
||||
/*
|
||||
fprintf(output,"Found a match for indexes:");
|
||||
for (i = 0; i < n; i++) {
|
||||
fprintf(output," %3.0f", index[i]);
|
||||
}
|
||||
fprintf(output,"\n");
|
||||
*/
|
||||
results[0] += 1.0;
|
||||
|
||||
/* Updating the weighted count(s) if needed. */
|
||||
@@ -130,13 +123,6 @@ Vector asymmetric_naive_npoint(DataPack data, Matcher matcher, Metric metric)
|
||||
do {
|
||||
int is_valid = 1;
|
||||
if (PASSED(matcher.Matches(data, index, metric))) {
|
||||
/*
|
||||
fprintf(output,"Found a match for indexes:");
|
||||
for (i = 0; i < n; i++) {
|
||||
fprintf(output," %3.0f", index[i]);
|
||||
}
|
||||
fprintf(output,"\n");
|
||||
*/
|
||||
results[0] += 1.0;
|
||||
|
||||
/* Updating the weighted count(s) if needed. */
|
||||
|
||||
@@ -2,6 +2,11 @@ main.cc
|
||||
- figure out the arguments and call appropriate part of the code
|
||||
+ depends on: all
|
||||
|
||||
tests.c
|
||||
tests.cc
|
||||
- unit tests to ensure proper behavior of all code
|
||||
+ depends on: all
|
||||
|
||||
globals.h
|
||||
- define global variables and handy constants
|
||||
+ depends on: none
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* @author: Angela Grigoroaia
|
||||
* @file: tests.cc
|
||||
*
|
||||
* @description: Simple unit tests for npoint.
|
||||
*/
|
||||
|
||||
#include "fastlib/fastlib.h"
|
||||
#include "globals.h"
|
||||
#include "datapack.h"
|
||||
#include "metrics.h"
|
||||
#include "matcher.h"
|
||||
#include "naive.h"
|
||||
|
||||
#include "tests.h"
|
||||
|
||||
success_t test_permutation_generator(int n) {
|
||||
DEBUG_ASSERT (n > 0);
|
||||
Vector tau;
|
||||
double count = 0.0;
|
||||
|
||||
tau.Init(n);
|
||||
if ( !PASSED(generate_first_permutation(tau)) ) {
|
||||
return SUCCESS_FAIL;
|
||||
}
|
||||
count += 1.0;
|
||||
while ( PASSED(generate_next_permutation(tau)) ) {
|
||||
count += 1.0;
|
||||
}
|
||||
|
||||
if ( count != math::Factorial(n) ) {
|
||||
return SUCCESS_FAIL;
|
||||
}
|
||||
|
||||
return SUCCESS_PASS;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* @author: Angela Grigoroaia
|
||||
* @file: tests.h
|
||||
*
|
||||
* @description: Simple unit tests for npoint.
|
||||
*/
|
||||
|
||||
#ifndef TESTS_H
|
||||
#define TEST_H
|
||||
|
||||
/**
|
||||
* This can be used to test if we are properly generating all the possible
|
||||
* permutations of size n. It counts all the permutations that we generate and
|
||||
* checks if the final value is n!.
|
||||
*/
|
||||
success_t test_permutation_generator(int n);
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user