Skip to content

Commit

Permalink
Fix streaming EM-tree const correctness.
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris De Vries committed May 17, 2015
1 parent b360b60 commit 235bce2
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 77 deletions.
48 changes: 32 additions & 16 deletions src/lmw/Node.h
Expand Up @@ -9,45 +9,57 @@ template <typename T>
class Node {
public:
Node() : _isLeaf(true), _ownsKeys(false) { }

~Node() {
for (size_t i = 0; i < size(); i++) {
remove(i);
}
}

bool isEmpty() {
bool isEmpty() const {
return _keys.empty();
}

bool isLeaf() {
bool isLeaf() const {
return _isLeaf;
}

int size() {
int size() const {
return _keys.size();
}
bool getOwnsKeys() {

bool getOwnsKeys() const {
return _ownsKeys;
}
void setOwnsKeys(bool ownsKeys) {

void setOwnsKeys(const bool ownsKeys) {
_ownsKeys = ownsKeys;
}

T* getKey(int i) {
T* getKey(const int i) {
return _keys[i];
}

const T* getKey(const int i) const {
return _keys[i];
}

vector<T*>& getKeys() {
return _keys;
}

const vector<T*>& getKeys() const {
return _keys;
}

/**
* pre: !isLeaf()
*/
Node* getChild(int i) {
Node* getChild(const int i) {
return _children[i];
}

const Node* getChild(const int i) const {
return _children[i];
}

Expand All @@ -58,6 +70,10 @@ class Node {
return _children;
}

const vector<Node*>& getChildren() const {
return _children;
}

void clearKeysAndChildren() {
_children.clear();
_keys.clear();
Expand Down Expand Up @@ -97,11 +113,11 @@ class Node {
_isLeaf = true;
}

void remove(int i) {
void remove(const int i) {
if (_ownsKeys) {
// Free the memory for the centroid key
delete _keys[i];
_keys[i] = NULL;
_keys[i] = NULL;
}
if (!_isLeaf) {
// Delete associated child node
Expand All @@ -122,7 +138,7 @@ class Node {
if (_keys[i] == NULL) {
toRemove++;
} else {
// Shuffle keys down
// Shuffle keys down
_keys[i - toRemove] = _keys[i];

// Shuffle children down
Expand All @@ -141,7 +157,7 @@ class Node {
}
}
}

private:
// In Leaf nodes the keys are the data.
vector<T*> _keys;
Expand All @@ -151,11 +167,11 @@ class Node {

// Does this node have any children?
bool _isLeaf;

// Will the keys be deleted?
bool _ownsKeys;
};

} // namespace lmw

#endif /* NODE_H */
#endif /* NODE_H */
47 changes: 25 additions & 22 deletions src/lmw/Optimizer.h
Expand Up @@ -2,9 +2,9 @@
* The OPTIMIZER concept chooses how to optimize a given distance function.
* Typically this is minimizing or maximizing the function. However, other
* types of optimizers may be used.
*
*
* TODO(cdevries): finish description of concept
*
*
* For example,
* Optimizer<SVector<bool>, hammingDistance, Minimize> optimizer;
* SVector<bool>* centroid = ...;
Expand All @@ -20,13 +20,13 @@
namespace lmw {

struct Minimize {
bool operator()(double currentDistance, double nearestDistance) {
bool operator()(double currentDistance, double nearestDistance) const {
return currentDistance < nearestDistance;
}
};

struct Maximize {
bool operator()(double currentDistance, double nearestDistance) {
bool operator()(double currentDistance, double nearestDistance) const {
return currentDistance > nearestDistance;
}
};
Expand All @@ -37,37 +37,39 @@ struct Nearest {
size_t index;
double distance;
};

template <typename T, typename DISTANCE, typename COMPARATOR, typename PROTOTYPE>
class Optimizer {
public:

void updatePrototype(T* prototype, vector<T*>& neighbours, vector<int>& weights) {

void updatePrototype(T* prototype, const vector<T*>& neighbours,
const vector<int>& weights) const {
_prototype(prototype, neighbours, weights);
}
Nearest<T> nearest(T* object, vector<T*>& others) {

Nearest<T> nearest(const T* object, const vector<T*>& others) const {
return nearestAccessor(object, others, _defaultAccessor);
}
}

/**
* This function provides access to a more complex KEY via used of an
* ACCESSOR functor that implements T* operator()(KEY* key).
*
*
* For example, this is used in StreamingEMTree where ACCUMULATORs are also
* stored in the key. It avoids having to unpack all they T* from the
* stored in the key. It avoids having to unpack all they T* from the
* more complex key type.
*/
template <typename KEY, typename ACCESSOR>
Nearest<KEY> nearest(T* object, vector<KEY*>& others, ACCESSOR& accessor) {
Nearest<KEY> nearest(const T* object, const vector<KEY*>& others,
const ACCESSOR& accessor) const {
return nearestAccessor(object, others, accessor);
}
double squaredDistance(T* object1, T* object2) {

double squaredDistance(const T* object1, const T* object2) const {
return _distance.squared(object1, object2);
}
double sumSquaredError(T* object, vector<T*>& others) {

double sumSquaredError(const T* object, const vector<T*>& others) const {
double SSE = 0;
for (auto otherObject : others) {
SSE += _distance.squared(object, otherObject);
Expand All @@ -81,13 +83,14 @@ class Optimizer {
* other objects match the object.
*/
struct DefaultAccessor {
T* operator()(T* key) {
T* operator()(T* key) const {
return key;
}
};

template <typename KEY, typename ACCESSOR>
Nearest<KEY> nearestAccessor(T* object, vector<KEY*>& others, ACCESSOR& accessor) {
Nearest<KEY> nearestAccessor(const T* object, const vector<KEY*>& others,
const ACCESSOR& accessor) const {
size_t nearestIndex = 0;
double nearestDistance = _distance(object, accessor(others[0]));
for (size_t i = 1; i < others.size(); ++i) {
Expand All @@ -98,8 +101,8 @@ class Optimizer {
}
}
return {others[nearestIndex], nearestIndex, nearestDistance};
}
}

COMPARATOR _comp;
DISTANCE _distance;
PROTOTYPE _prototype;
Expand All @@ -108,4 +111,4 @@ class Optimizer {

} // namespace lmw

#endif /* OPTIMIZER_H */
#endif /* OPTIMIZER_H */
39 changes: 18 additions & 21 deletions src/lmw/Prototype.h
@@ -1,24 +1,24 @@
/**
* This file contains PROTOTYPE functions. It summarizes a list of objects into
* a single object. It also takes weights for each object into account.
*
*
* It works on objects of type T.
*
*
* The PROTOTYPE function is called with a pointer to the result, a list of
* object and a list of weights.
*
*
* The only required operation is,
* void operator()(T* result, vector<T*> objects, vector<int> weights)
*
*
* A PROTOTYPE function MUST be thread safe. Multiple calls to operator() can
* happen concurrently.
*
* Note that weights can be empty if no weights are present, otherwise the
*
* Note that weights can be empty if no weights are present, otherwise the
* number of objects must match the number of weights,
* assert(objects.size() == weight.size())
*
*
* For example, floating point vectors can use the mean or median, and bit
* vectors use a specialized prototype optimized for speed.
* vectors use a specialized prototype optimized for speed.
*/

#ifndef PROTOTYPE_H
Expand All @@ -33,8 +33,7 @@ namespace lmw {

template <typename T>
struct meanPrototype {

void operator()(T *t1, vector<T*> &objs, vector<int> &weights) const {
void operator()(T* t1, const vector<T*>& objs, const vector<int>& weights) const {
float total = 0.0f;
t1->setAll(0);
if (weights.size() != 0) {
Expand All @@ -57,12 +56,10 @@ struct meanBitPrototype {
/**
* We assume that the length of bit vectors is less than 65536 and greater than 0.
*/
void operator()(SVector<bool> *t1, vector<SVector<bool>*> &objs,
vector<int> &weights) const {

void operator()(SVector<bool>* t1, const vector<SVector<bool>*>& objs,
const vector<int>& weights) const {
int bitCountPerDimension[65536];
block_type *data = t1->getData();
;
int vecSize = t1->size();
int dataSize = sizeof (data[0]) * 8;
int numBlocks = t1->getNumBlocks();
Expand Down Expand Up @@ -118,8 +115,8 @@ struct meanBitPrototype2 {
/**
* We assume that the length of bit vectors is less than 65536 and greater than 0.
*/
void operator()(SVector<bool> *t1, vector<SVector<bool>*> &objs,
vector<int> &weights) const {
void operator()(SVector<bool>* t1, const vector<SVector<bool>*>& objs,
const vector<int>& weights) const {
int bitCountPerDimension[65536];
unsigned short val;
block_type *data = t1->getData();
Expand Down Expand Up @@ -147,7 +144,7 @@ struct meanBitPrototype2 {
//std::cout << "\n .. " << (data[i] >> 48);
val = data[i];
for (int j = 0; j < dataSize; j += 16) {
//std::cout << "\n ''" << ((data[i] >> j) & 65535) << "\n";
//std::cout << "\n ''" << ((data[i] >> j) & 65535) << "\n";
val = (data[i] >> j) & 65535;
//std::cout << "\n" << j << " " << val;
//std::cout << "\n" << val;
Expand Down Expand Up @@ -211,8 +208,8 @@ struct meanBitPrototype8 {
/**
* We assume that the length of bit vectors is less than 65536 and greater than 0.
*/
void operator()(SVector<bool> *t1, vector<SVector<bool>*> &objs,
vector<int> &weights) const {
void operator()(SVector<bool>* t1, const vector<SVector<bool>*>& objs,
const vector<int>& weights) const {

int bitCountPerDimension[65536];
unsigned short val;
Expand Down Expand Up @@ -242,7 +239,7 @@ struct meanBitPrototype8 {
//std::cout << "\n .. " << (data[i] >> 48);
val = data[i];
for (int j = 0; j < dataSize; j += 8) {
//std::cout << "\n ''" << ((data[i] >> j) & 65535) << "\n";
//std::cout << "\n ''" << ((data[i] >> j) & 65535) << "\n";
val = (data[i] >> j) & 255LL;
//std::cout << "\n" << j << " " << val;
//std::cout << "\n" << val;
Expand Down Expand Up @@ -315,4 +312,4 @@ struct meanBitPrototype8 {

} // namespace lmw

#endif /* PROTOTYPE_H */
#endif /* PROTOTYPE_H */

0 comments on commit 235bce2

Please sign in to comment.