#include "NsSystem.hh" #include "NsUnit.hh" #include "MathUtil.hh" NsUnit::NsUnit(const NsLayer *layer, uint index) : layer(layer), id(layer->id + "." + fmt::format("{:02}", index)), actFuncK(props.getDouble("actFuncK")), actThreshold(props.getDouble("actThreshold")), isFrozen(false), isActive(false), newIsActive(false), lastNetInput(0.0) {} /** * Probability of activation is a sigmoid function of net input * @param netInput Net input */ bool NsUnit::activationFunction(double netInput) { if (netInput <= actThreshold) return false; double probOfActivation = MathUtil::asigmoid(netInput, actFuncK, layer->inhibition); //infoTrace("XXX {}\n", netInput); double ret = Util::randDouble(0.0, 1.0) < probOfActivation; //fmt::print("activationFunction: {} {}\n", // netInput - layer->inhibition, ret); return ret; } /** * Calculate net input as sum of the weights of those inbound connection * whose sending units are active, i.e. count "true" activity level as 1 and * "false" as zero. Then use activationFunction to determine the unit's new * activation state and store it in newIsActive. */ void NsUnit::computeNewActivation() { if (isFrozen) { newIsActive = false; } else { // Calculate net input // double netInput = 0.0; uint numActiveInputs = 0; for (auto c : inConnections) { if (c->fromUnit->isActive && c->getStrength() > 0.0) { netInput += c->getStrength(); numActiveInputs++; } } #if 0 // TODO: this didn't work, because it kills everything when there // are many connections. -- It would be nice to find another way to // handle different system sizes without twiddling parameters. // Normalize the input to the [0, 1] range. (This reflects the idea // of homeostatic synaptic plasticity, a.k.a. synaptic scaling) // netInput *= (double) numActiveInputs / inConnections.size(); #endif // Use the activation function to decide whether to become/remain // active // newIsActive = activationFunction(netInput); lastNetInput = netInput; } } void NsUnit::applyNewActivation() { isActive = newIsActive; } void NsUnit::setFrozen(bool state) { isFrozen = state; if (isFrozen) { isActive = false; } } void NsUnit::maintain() { } void NsUnit::printStateHdr() { infoTrace("time unit ID ACTIVE\n"); } void NsUnit::printState() const { infoTrace("{} unit {} {}\n", simTime / 24., id, isActive ? 'a' : 'i'); } string NsUnit::toStr(uint iLvl, const string &iStr) const { return fmt::format("{}[{} {}]", Util::repeatStr(iStr, iLvl), id, isActive ? 'a' : 'i'); }