static void adaptSegment( Connections& connections, Segment segment, const vector<CellIdx>& prevActiveCells, Permanence permanenceIncrement, Permanence permanenceDecrement) { const vector<Synapse>& synapses = connections.synapsesForSegment(segment); for (SynapseIdx i = 0; i < synapses.size();) { const SynapseData& synapseData = connections.dataForSynapse(synapses[i]); const bool isActive = std::binary_search(prevActiveCells.begin(), prevActiveCells.end(), synapseData.presynapticCell); Permanence permanence = synapseData.permanence; if (isActive) { permanence += permanenceIncrement; } else { permanence -= permanenceDecrement; } permanence = min(permanence, (Permanence)1.0); permanence = max(permanence, (Permanence)0.0); if (permanence < EPSILON) { connections.destroySynapse(synapses[i]); // Synapses vector is modified in-place, so don't update `i`. } else { connections.updateSynapsePermanence(synapses[i], permanence); i++; } } if (synapses.size() == 0) { connections.destroySegment(segment); } }
static void growSynapses( Connections& connections, Random& rng, Segment segment, UInt32 nDesiredNewSynapses, const vector<CellIdx>& prevWinnerCells, Permanence initialPermanence) { // It's possible to optimize this, swapping candidates to the end as // they're used. But this is awkward to mimic in other // implementations, especially because it requires iterating over // the existing synapses in a particular order. vector<CellIdx> candidates(prevWinnerCells.begin(), prevWinnerCells.end()); NTA_ASSERT(std::is_sorted(candidates.begin(), candidates.end())); // Remove cells that are already synapsed on by this segment for (Synapse synapse : connections.synapsesForSegment(segment)) { CellIdx presynapticCell = connections.dataForSynapse(synapse).presynapticCell; auto ineligible = std::lower_bound(candidates.begin(), candidates.end(), presynapticCell); if (ineligible != candidates.end() && *ineligible == presynapticCell) { candidates.erase(ineligible); } } const UInt32 nActual = std::min(nDesiredNewSynapses, (UInt32)candidates.size()); // Pick nActual cells randomly. for (UInt32 c = 0; c < nActual; c++) { size_t i = rng.getUInt32(candidates.size()); connections.createSynapse(segment, candidates[i], initialPermanence); candidates.erase(candidates.begin() + i); } }