inline void swapBytes(T *pxOut, nta::Size n, const T *pxIn) { NTA_ASSERT(pxOut != pxIn) << "Use swapBytesInPlace() instead."; NTA_ASSERT(!(((pxOut > pxIn) && (pxOut < (pxIn+n))) || ((pxIn > pxOut) && (pxIn < (pxOut+n))))) << "Overlapping ranges not supported."; union SwapType { T x; unsigned char b[sizeof(T)]; }; const SwapType *px0 = reinterpret_cast<SwapType *>(pxIn); const SwapType *pxend = px0 + n; SwapType *px1 = reinterpret_cast<SwapType *>(pxOut); for(; px0!=pxend; ++px0, ++px1) { for(int j=0; j<sizeof(T); ++j) px1->b[j] = px0->b[sizeof(T)-j-1]; } }
void FlatSpatialPoolerTest::testSerialize() { string filename = "FlatSpatialPoolerSerialization.tmp"; FlatSpatialPooler sp_orig; UInt numInputs = 5; UInt numColumns = 10; FlatSpatialPooler fsp_orig = FlatSpatialPooler(); fsp_orig.initializeFlat(numInputs, numColumns); fsp_orig.setRandomSP(true); fsp_orig.setMinDistance(0.3); ofstream outfile; outfile.open (filename.c_str()); fsp_orig.save(outfile); outfile.close(); FlatSpatialPooler fsp_dest; ifstream infile (filename.c_str()); fsp_dest.load(infile); infile.close(); NTA_CHECK(fsp_orig.getMinDistance() == fsp_dest.getMinDistance()); NTA_CHECK(fsp_orig.getRandomSP() == fsp_dest.getRandomSP()); string command = string("rm -f ") + filename; int ret = system(command.c_str()); NTA_ASSERT(ret == 0); // << " FlatSpatialPooler.serialization failed. " << std::endl; }
/** * This can be used to truncate an array to a smaller size. * Not usable with an SDR. */ void ArrayBase::setCount(size_t count) { NTA_CHECK(type_ != NTA_BasicType_SDR) << "Operation not valid for SDR"; NTA_ASSERT(count <= getMaxElementsCount()) << "Cannot set the array count (" << count << ") greater than the capacity (" << getMaxElementsCount() << ")."; count_ = count; }
inline void set_from_sparse(It begin, It end) { NTA_ASSERT(begin <= end); this->clear(); while (begin != end) this->set(*begin++); }
inline std::binder2nd<nupic::Divides<T> > DividesByVal(const T& v) { NTA_ASSERT(!nupic::nearlyZero(v)) << "dividesByVal: " << "Division by zero"; return std::bind2nd(nupic::Divides<T>(), v); }
/** * Returns list of segments that are not empty. */ std::vector<UInt> getNonEmptySegList() const { std::vector<UInt> non_empties; for (UInt i = 0; i != _segments.size(); ++i) if (!_segments[i].empty()) non_empties.push_back(i); NTA_ASSERT(non_empties.size() == nSegments()); return non_empties; }
/** * Release a segment by putting it on the list of "freed" segments. We keep the * memory instead of deallocating it each time, so that's it's fast to "allocate" * a new segment next time. * * Assumes outSynapses has already been updated. * TODO: a call to releaseSegment should delete any pending * update for that segment in the update list. The * cheapest way to do this is to maintain segment updates on a * per cell basis. Currently there is a check in * Cells4::adaptSegment for this case but that may be insufficient. */ void releaseSegment(UInt segIdx) { NTA_ASSERT(segIdx < _segments.size()); // TODO: check this if (is_in(segIdx, _freeSegments)) { return; } // TODO: check this NTA_ASSERT(not_in(segIdx, _freeSegments)); _segments[segIdx].clear(); // important in case we push_back later _freeSegments.push_back(segIdx); _segments[segIdx]._totalActivations = 0; _segments[segIdx]._positiveActivations = 0; NTA_ASSERT(_segments[segIdx].empty()); NTA_ASSERT(is_in(segIdx, _freeSegments)); }
//-------------------------------------------------------------------------------- double binomial(unsigned long n, unsigned long k) { { NTA_ASSERT(k <= n) << "binomial: Wrong arguments: n= " << n << " k= " << k; } if (n < 171) return floor(0.5 + fact(n) / (fact(k) * fact(n-k))); else return floor(0.5 + exp(lfact(n) - lfact(k) - lfact(n-k))); }
void RegionImpl::setParameterArray(const std::string& name, Int64 index,const Array & array) { WriteBuffer wb; size_t count = array.getCount(); void *buffer = array.getBuffer(); for (size_t i = 0; i < count; i++) { int rc; switch (array.getType()) { case NTA_BasicType_Byte: rc = wb.write(((Byte*)buffer)[i]); break; case NTA_BasicType_Int32: rc = wb.write(((Int32*)buffer)[i]); break; case NTA_BasicType_UInt32: rc = wb.write(((UInt32*)buffer)[i]); break; case NTA_BasicType_Int64: rc = wb.write(((Int64*)buffer)[i]); break; case NTA_BasicType_UInt64: rc = wb.write(((UInt64*)buffer)[i]); break; case NTA_BasicType_Real32: rc = wb.write(((Real32*)buffer)[i]); break; case NTA_BasicType_Real64: rc = wb.write(((Real64*)buffer)[i]); break; default: NTA_THROW << "Unsupported basic type " << BasicType::getName(array.getType()) << " in setParameterArray for parameter " << name; break; } NTA_ASSERT(rc == 0) << "getParameterArray - failure to get parameter '" << name << "' on node of type " << getType(); } ReadBuffer rb(wb.getData(), wb.getSize(), false); setParameterFromBuffer(name, index, rb); }
Int32 ReadBuffer::readString( NTA_Byte * &value, NTA_UInt32 &size, fp_alloc fAlloc, fp_dealloc fDealloc ) const { NTA_ASSERT(fDealloc || !fAlloc); // Assume new/delete if unspecified. value = 0; size = 0; Int32 result = findWithLeadingWhitespace(*this, "<s", 16); if(result != 0) return result; result = findWithLeadingWhitespace(*this, "n", 16); if(result != 0) return result; result = findWithLeadingWhitespace(*this, "=", 16); if(result != 0) return result; result = read(size); if(result != 0) return result; result = findWithLeadingWhitespace(*this, '>', 16); if(result != 0) return result; if(size) { char *allocated = 0; if(fAlloc) allocated = fAlloc(size); else allocated = new char[size]; try { result = readT(allocated, size); value = allocated; } catch(...) { value = 0; size = 0; if(fDealloc) fDealloc(allocated); else if(fAlloc) { } // Leak (prevented by initial assertion). else delete[] allocated; throw; } if(result != 0) return result; } else { value = const_cast<NTA_Byte *>(reinterpret_cast<const NTA_Byte *>("")); } return findWithLeadingWhitespace(*this, "</s>", 1); }
void RegionImplFactory::cleanup() { std::map<std::string, Spec*>::iterator ns; // destroy all nodespecs for (ns = nodespecCache_.begin(); ns != nodespecCache_.end(); ns++) { assert(ns->second != nullptr); // PyNode node specs are destroyed by the C++ PyNode if (ns->first.substr(0, 3) == "py.") { std::string noClass = ""; pyLib_->destroySpec(ns->first, noClass); } else { delete ns->second; } ns->second = nullptr; } nodespecCache_.clear(); // destroy all RegisteredRegionImpls for (auto rri = cppRegions.begin(); rri != cppRegions.end(); rri++) { NTA_ASSERT(rri->second != nullptr); delete rri->second; rri->second = nullptr; } cppRegions.clear(); initializedRegions = false; // Never release the Python dynamic library! // This is due to cleanup issues of Python itself // See: http://docs.python.org/c-api/init.html#Py_Finalize //pyLib_.reset(); }
inline void set(size_type w) { NTA_ASSERT(w < board.size()); board[w] = color; }
/** * Returns number of segments that are not in the free list currently, i.e. that * have at leat 1 synapse. */ UInt nSegments() const { NTA_ASSERT(_freeSegments.size() <= _segments.size()); return _segments.size() - _freeSegments.size(); }
float Solver<TQ>::solve(int l, TQ& Q, const signed char *y_, float *alpha_, float C, float eps, int shrinking) { this->l = l; this->Q = &Q; this->QD = Q.get_QD(); this->C = C; this->eps = eps; unshrinked = false; p = new float [l]; std::fill(p, p + l, float(-1.0)); y = new signed char [l]; std::copy(y_, y_ + l, y); alpha = new float [l]; std::copy(alpha_, alpha_ + l, alpha); // initialize alpha_status { alpha_status = new int[l]; for(int i=0;i<l;i++) update_alpha_status(i); } // initialize active set (for shrinking) { active_set = new int[l]; for(int i=0;i<l;i++) active_set[i] = i; active_size = l; } // initialize gradient { G = new float[l]; G_bar = new float[l]; for(int i=0;i<l;i++) { G[i] = p[i]; G_bar[i] = 0; } for(int i=0;i<l;i++) if(!is_lower_bound(i)) { const float *Q_i = Q.get_Q(i,l); float alpha_i = alpha[i]; for(int j=0;j<l;j++) G[j] += alpha_i*Q_i[j]; if(is_upper_bound(i)) for(int j=0;j<l;j++) G_bar[j] += get_C(i) * Q_i[j]; } } // optimization step int iter = 0; int counter = std::min(l,1000)+1; while (1) { // show progress and do shrinking if(--counter == 0) { counter = std::min(l,1000); if(shrinking) do_shrinking(); } int i,j; if (select_working_set(i, j) != 0) { // reconstruct the whole gradient reconstruct_gradient(); // reset active set size and check active_size = l; if (select_working_set(i, j) != 0) break; else counter = 1; // do shrinking next iteration } ++iter; // update alpha[i] and alpha[j], handle bounds carefully const float *Q_i = Q.get_Q(i, active_size); const float *Q_j = Q.get_Q(j, active_size); NTA_ASSERT(Q_i != nullptr); NTA_ASSERT(Q_j != nullptr); float C_i = get_C(i); float C_j = get_C(j); float old_alpha_i = alpha[i]; float old_alpha_j = alpha[j]; if (y[i]!=y[j]) { float quad_coef = Q_i[i]+Q_j[j]+2*Q_i[j]; if (quad_coef <= 0) quad_coef = TAU; NTA_ASSERT(quad_coef > 0); float delta = (-G[i]-G[j])/quad_coef; float diff = alpha[i] - alpha[j]; alpha[i] += delta; alpha[j] += delta; if(diff > 0) { if(alpha[j] < 0) { alpha[j] = 0; alpha[i] = diff; } } else { if(alpha[i] < 0) { alpha[i] = 0; alpha[j] = -diff; } } if(diff > C_i - C_j) { if(alpha[i] > C_i) { alpha[i] = C_i; alpha[j] = C_i - diff; } } else { if(alpha[j] > C_j) { alpha[j] = C_j; alpha[i] = C_j + diff; } } } else { float quad_coef = Q_i[i]+Q_j[j]-2*Q_i[j]; if (quad_coef <= 0) quad_coef = TAU; NTA_ASSERT(quad_coef > 0); float delta = (G[i]-G[j])/quad_coef; float sum = alpha[i] + alpha[j]; alpha[i] -= delta; alpha[j] += delta; if(sum > C_i) { if(alpha[i] > C_i) { alpha[i] = C_i; alpha[j] = sum - C_i; } } else { if(alpha[j] < 0) { alpha[j] = 0; alpha[i] = sum; } } if(sum > C_j) { if(alpha[j] > C_j) { alpha[j] = C_j; alpha[i] = sum - C_j; } } else { if(alpha[i] < 0) { alpha[i] = 0; alpha[j] = sum; } } } // update G float delta_alpha_i = alpha[i] - old_alpha_i; float delta_alpha_j = alpha[j] - old_alpha_j; for(int k=0;k<active_size;k++) { G[k] += Q_i[k]*delta_alpha_i + Q_j[k]*delta_alpha_j; NTA_ASSERT(-HUGE_VAL <= G[k] && G[k] <= HUGE_VAL); } // update alpha_status and G_bar { bool ui = is_upper_bound(i); bool uj = is_upper_bound(j); update_alpha_status(i); update_alpha_status(j); if(ui != is_upper_bound(i)) { Q_i = Q.get_Q(i,l); if(ui) for(int k=0;k<l;k++) G_bar[k] -= C_i * Q_i[k]; else for(int k=0;k<l;k++) G_bar[k] += C_i * Q_i[k]; } if(uj != is_upper_bound(j)) { Q_j = Q.get_Q(j,l); if(uj) for(int k=0;k<l;k++) G_bar[k] -= C_j * Q_j[k]; else for(int k=0;k<l;k++) G_bar[k] += C_j * Q_j[k]; } } } float rho = calculate_rho(); // put back the solution for(int i=0;i<l;i++) alpha_[active_set[i]] = alpha[i]; delete[] p; delete[] y; delete[] alpha; delete[] alpha_status; delete[] active_set; delete[] G; delete[] G_bar; return rho; }
void ASSERT_VALID_RANGE(It begin, It end, const char *message) { NTA_ASSERT(begin <= end) << "Invalid iterators: " << message; }
inline bool is_on(size_type w) const { NTA_ASSERT(w < board.size()); return board[w] == color; }
inline bool operator[](size_type w) const { NTA_ASSERT(w < board.size()); return is_on(w); }
//-------------------------------------------------------------------------------- const Segment& operator[](UInt segIdx) const { NTA_ASSERT(segIdx < _segments.size()); return _segments[segIdx]; }
//-------------------------------------------------------------------------------- Segment& getSegment(UInt segIdx) { NTA_ASSERT(segIdx < _segments.size()); return _segments[segIdx]; }
int Solver<TQ>::select_working_set(int &out_i, int &out_j) { // return i,j such that // i: maximizes -y_i * grad(f)_i, i in I_up(\alpha) // j: minimizes the decrease of obj value // (if quadratic coefficeint <= 0, replace it with tau) // -y_j*grad(f)_j < -y_i*grad(f)_i, j in I_low(\alpha) float Gmax = -HUGE_VAL; //std::numeric_limits<float>::max(); float Gmax2 = -HUGE_VAL; //std::numeric_limits<float>::max(); int Gmax_idx = -1; int Gmin_idx = -1; float obj_diff_min = HUGE_VAL; //std::numeric_limits<float>::max(); for (int t=0;t<active_size;t++) { if (y[t] == +1) { if (!is_upper_bound(t)) if (-G[t] >= Gmax) { Gmax = -G[t]; Gmax_idx = t; } } else { if (!is_lower_bound(t)) if (G[t] >= Gmax) { Gmax = G[t]; Gmax_idx = t; } } } int i = Gmax_idx; const float *Q_i = nullptr; if (i != -1) // NULL Q_i not accessed: Gmax=-INF if i=-1 Q_i = Q->get_Q(i,active_size); NTA_ASSERT(0 <= i); for(int j=0;j<active_size;j++) { if (y[j] == +1) { if (!is_lower_bound(j)) { float grad_diff=Gmax+G[j]; if (G[j] >= Gmax2) Gmax2 = G[j]; if (grad_diff > 0) { float obj_diff; float quad_coef=Q_i[i]+QD[j]-2*y[i]*Q_i[j]; if (quad_coef > 0) obj_diff = -(grad_diff*grad_diff)/quad_coef; else obj_diff = -(grad_diff*grad_diff)/TAU; if (obj_diff <= obj_diff_min) { Gmin_idx=j; obj_diff_min = obj_diff; } } } } else { if (!is_upper_bound(j)) { float grad_diff= Gmax - G[j]; if (-G[j] >= Gmax2) Gmax2 = -G[j]; if (grad_diff > 0) { float obj_diff; float quad_coef = Q_i[i]+QD[j]+2*y[i]*Q_i[j]; if (quad_coef > 0) obj_diff = -(grad_diff*grad_diff)/quad_coef; else obj_diff = -(grad_diff*grad_diff)/TAU; if (obj_diff <= obj_diff_min) { Gmin_idx = j; obj_diff_min = obj_diff; } } } } } if (Gmax + Gmax2 < eps) return 1; out_i = Gmax_idx; out_j = Gmin_idx; NTA_ASSERT(0 <= out_i); NTA_ASSERT(0 <= out_j); return 0; }