/** * Test a value against the trigger. * * Note that this function will call the registered handler function synchronously. The handler function * is called only once, when the trigger is released. Subsequent calls to this function will not call * the handler function again (until triggerReset() or triggerActivate() has been called to reset the * trigger). * * This function will continue to return a value of true as long as the condition for the trigger release * has been met (or exceeds the triggerCount value). * * This function will increment the testCounter until it reaches triggerCount. * * @param trigger The trigger object. * @param testValue The test value to compare against the threshold with the trigger function. * * @return True when the trigger has been released. */ bool triggerTestValue(trigger_t *trigger, float testValue) { assert_param(trigger != NULL); /* Do not do anything if the trigger has been deactivated. */ if(!trigger->active) { return false; } switch(trigger->func) { case triggerFuncIsLE: { if(testValue <= trigger->threshold) { triggerIncTestCounter(trigger); break; } else { /* Reset the trigger if the test failed. */ triggerReset(trigger); return false; } } case triggerFuncIsGE: { if(testValue >= trigger->threshold) { triggerIncTestCounter(trigger); break; } else { /* Reset the trigger if the test failed. */ triggerReset(trigger); return false; } } case triggerFuncNone: { /* No action, included to avoid compiler warnings. */ break; } } /* Check if the triggerCount has been reached. */ trigger->released = (trigger->testCounter >= trigger->triggerCount); /* If the trigger has not been release, exit immediately. */ if(!trigger->released) { return false; } /* The trigger object may be reset by the handler, thus make an internal copy of the released flag. */ bool iReleased = trigger->released; if(trigger->released && (trigger->handler != NULL) && (!trigger->handlerCalled)) { /* Set the handlerCalled = true before calling, since the handler may choose to reset the object. */ trigger->handlerCalled = true; trigger->handler(trigger->handlerArg); } /* Return the release flag. This may return the value true more than once. */ return iReleased; }
/** * Activate or deactivate a trigger object. * * This function does not influence the attributes of the trigger object as initialized by * triggerInitialize() or triggerRegisterHandler() functions. * * Calling this function will reset all counters and flags, in addition to activating or * deactivating the trigger. * * @param trigger The trigger object. * @param active Set the trigger active (true) or deactive (false). */ void triggerActivate(trigger_t *trigger, bool active) { assert_param(trigger != NULL); triggerReset(trigger); trigger->active = active; }
/** * DeInitialize a trigger object. * * @param trigger The trigger object. */ void triggerDeInit(trigger_t *trigger) { assert_param(trigger != NULL); triggerInit(trigger, triggerFuncNone, 0, 0); triggerRegisterHandler(trigger, NULL, NULL); triggerReset(trigger); }
/** * Initialize a trigger object. * * Note that to activate the trigger, the triggerActivate() function must be called after * calling triggerInit(). * * @param trigger The trigger object. * @param func The trigger function type. * @param threshold The threshold to use with the trigger function. * @param triggerCount When testCounter reaches this value, a trigger is reported. */ void triggerInit(trigger_t *trigger, triggerFunc_t func, float threshold, uint32_t triggerCount) { assert_param(trigger != NULL); assert_param(func != triggerFuncNone); trigger->active = false; trigger->func = func; trigger->threshold = threshold; trigger->triggerCount = triggerCount; triggerReset(trigger); }
void BasinPlotter::calculateData() { // get program core Core *core = Core::getInstance(); // get network ModularNeuralNetwork *network = getCurrentNetwork(); if(network == 0) { Core::log("BasinPlotter: Could not find a neural network to work with! Aborting.", true); return; } QList<NeuralNetworkElement*> networkElements; network->getNetworkElements(networkElements); QList<DoubleValue*> networkValues = DynamicsPlotterUtil::getNetworkValues(networkElements); // Get parameters for varied elements QString variedX = mVariedX->get(); QString variedY = mVariedY->get(); if(variedX.isEmpty() || variedY.isEmpty()) { reportProblem("BasinPlotter: No elements to vary."); return; } DoubleValue *variedValX = DynamicsPlotterUtil::getElementValue( variedX, networkElements, &mNeuronsWithActivationsToTransfer); DoubleValue *variedValY = DynamicsPlotterUtil::getElementValue( variedY, networkElements, &mNeuronsWithActivationsToTransfer); if(variedValX == 0 || variedValY == 0) { reportProblem("BasinPlotter: NULL pointer for varied element. Aborting."); return; } QList<double> variedRangeX = DynamicsPlotterUtil::getDoublesFromString(mVariedRangeX->get()); QList<double> variedRangeY = DynamicsPlotterUtil::getDoublesFromString(mVariedRangeY->get()); if(variedRangeX.size() != 2 || variedRangeY.size() != 2) { reportProblem("BasinPlotter: Not a valid range given."); return; } int resolutionX = mResolutionX->get(); int resolutionY = mResolutionY->get(); //avoid division by zero! if(resolutionX < 2 || resolutionY < 2) { reportProblem("BasinPlotter: Invalid resolution given."); return; } // projected elements int nrProjections = 0; QString projectionsX = mProjectionsX->get(); QString projectionsY = mProjectionsY->get(); QList< QList<DoubleValue*> > projectionValuesX; QList< QList<DoubleValue*> > projectionValuesY; QList<double> projectionRangesX; QList<double> projectionRangesY; if(projectionsX != "0" && projectionsY != "0") { QList<QStringList> projectionListX = DynamicsPlotterUtil::parseElementString(projectionsX); QList<QStringList> projectionListY = DynamicsPlotterUtil::parseElementString(projectionsY); projectionValuesX = DynamicsPlotterUtil::getElementValues(projectionListX, networkElements); projectionValuesY = DynamicsPlotterUtil::getElementValues(projectionListY, networkElements); if(projectionValuesX.isEmpty() || projectionValuesY.isEmpty()) { reportProblem("BasinPlotter: Could not find specified elements to project onto."); return; } if(projectionValuesX.size() != projectionValuesY.size()) { reportProblem("BasinPlotter: Mismatching number of projected elements for the two axes."); return; } projectionRangesX = DynamicsPlotterUtil::getDoublesFromString(mProjectionRangesX->get()); projectionRangesY = DynamicsPlotterUtil::getDoublesFromString(mProjectionRangesY->get()); if(projectionRangesX.size() != 2*projectionValuesX.size() || projectionRangesY.size() != 2*projectionValuesY.size()) { reportProblem("BasinPlotter: Given ranges for projection don't match number of elements."); return; } nrProjections = projectionValuesX.size(); } // save original values for clean-up QList<double> variedValuesOrig; variedValuesOrig.append(QList<double>() << variedValX->get() << variedValY->get()); bool resetNetworkActivation = mResetNetworkActivation->get(); storeCurrentNetworkActivities(); /* store network configuration (bias terms, synapse weights, observable parameters of TFs, AFs, SFs. */ bool restoreNetConfiguration = mRestoreNetworkConfiguration->get(); storeNetworkConfiguration(); //This is important when the physical simulator is activated! bool resetSimulation = mResetSimulator->get(); triggerReset(); // PREPARE data matrix double xStart = variedRangeX.first(); double xEnd = variedRangeX.last(); double xStepSize = (xEnd - xStart) / (double) (resolutionX - 1); int roundDigits = mRoundDigits->get(); double xVal; QList<double> xValues; double yStart = variedRangeY.first(); double yEnd = variedRangeY.last(); double yStepSize = (yEnd - yStart) / (double) (resolutionY - 1); double yVal; QList<double> yValues; { //Thread safety of matrix. QMutexLocker guard(mDynamicsPlotManager->getMatrixLocker()); mData->clear(); mData->resize(resolutionX + 1, resolutionY + 1, 3 + nrProjections); mData->fill(0); // calculate values and draw axes for(int x = 1; x <= resolutionX; ++x) { xVal = xStart + (x - 1) * xStepSize; mData->set(Math::round(xVal, 5), x, 0, 0); mData->set(Math::round(xVal, 5), x, 0, 1); mData->set(Math::round(xVal, 5), x, 0, 2); if(roundDigits >= 0) { xVal = Math::round(xVal, roundDigits); } xValues.append(xVal); } for(int y = 1; y <= resolutionY; ++y) { yVal = yStart + (y - 1) * yStepSize; mData->set(Math::round(yVal, 5), 0, y, 0); mData->set(Math::round(yVal, 5), 0, y, 1); mData->set(Math::round(yVal, 5), 0, y, 2); if(roundDigits >= 0) { yVal = Math::round(yVal, roundDigits); } yValues.append(yVal); } // same for additional projections for(int currProj = 0; currProj < nrProjections; ++currProj) { double pStartX = projectionRangesX.at(currProj * 2); double pEndX = projectionRangesX.at(currProj * 2 + 1); double pStepX = (pEndX - pStartX) / (double) (resolutionX - 1); for(int x = 1; x <= resolutionX; ++x) { mData->set(Math::round((pStartX + (x - 1) * pStepX), 5), x, 0, 3 + currProj); } double pStartY = projectionRangesY.at(currProj * 2); double pEndY = projectionRangesY.at(currProj * 2 + 1); double pStepY = (pEndY - pStartY) / (double) (resolutionY - 1); for(int y = 1; y <= resolutionY; ++y) { mData->set(Math::round((pStartY + (y - 1) * pStepY), 5), 0, y, 3 + currProj); } } } // MAIN LOOP over x parameter points int stepsRun = mStepsToRun->get(); int stepsCheck = mStepsToCheck->get(); double accuracy = mAccuracy->get(); QList< QList<double> > attractors; for(int x = 1; x <= resolutionX && mActiveValue->get(); ++x) { mProgressPercentage->set((double)(100 * x / resolutionX)); // INNER LOOP over y parameter points for(int y = 1; y <= resolutionY && mActiveValue->get(); ++y) { if(resetSimulation) { triggerReset(); } if(restoreNetConfiguration) { restoreNetworkConfiguration(); } if(resetNetworkActivation) { restoreCurrentNetworkActivites(); } // set x parameter variedValX->set(xValues.at(x - 1)); // set y parameter variedValY->set(yValues.at(y - 1)); if(!notifyNetworkParametersChanged(network)) { return; } for(int runStep = 0; runStep < stepsRun && mActiveValue->get(); ++runStep) { // let the network run for 1 timestep triggerNetworkStep(); } QList< QList<double> > networkStates; QList<double> networkState; QList< QPair<double,double> > variedPositions; QList< QPair< QList<double>, QList<double> > > projectionPositions; bool foundMatch = false; int attrPeriod = 0; for(int checkStep = 0; checkStep <= stepsCheck && !foundMatch && mActiveValue->get(); ++checkStep) { triggerNetworkStep(); // get current network state networkState = DynamicsPlotterUtil::getNetworkState(networkValues); // abort on empty state if(networkState.isEmpty()) { reportProblem("BasinPlotter: Encountered empty network state."); return; } // compare states to find attractors for(int period = 1; period <= checkStep && !foundMatch; ++period) { foundMatch = DynamicsPlotterUtil::compareNetworkStates( networkStates.at(checkStep-period), networkState, accuracy); attrPeriod = period; } // save current state as last one networkStates.append(networkState); variedPositions.append(QPair<double,double>(variedValX->get(), variedValY->get())); if(nrProjections > 0) { QPair< QList<double>, QList<double> > currentPositions; currentPositions.first = DynamicsPlotterUtil::getMeanValues(projectionValuesX); currentPositions.second = DynamicsPlotterUtil::getMeanValues(projectionValuesY); projectionPositions.append(currentPositions); } } // at this point, either an attractor has been found if(foundMatch && mActiveValue->get()) { // check for past attractors bool attrMatch = false; int attrNo = 1; while(attrNo <= attractors.size() && !attrMatch) { for(int state = 1; state <= attrPeriod && !attrMatch; ++state) { attrMatch = DynamicsPlotterUtil::compareNetworkStates( attractors.at(attrNo-1), networkStates.at(networkStates.size()-state), // was: size()-1-state accuracy); } attrNo++; } //Thread safety of matrix. QMutexLocker guard(mDynamicsPlotManager->getMatrixLocker()); // write matrix mData->set(attrNo, x, y, 0); mData->set(attrPeriod, x, y, 1); // calculate and plot attractor position int nrPositions = variedPositions.size(); for(int periodPos = 1; periodPos <= attrPeriod; ++periodPos) { int currPosition = nrPositions - periodPos; double currValX = variedPositions.at(currPosition).first; double currValY = variedPositions.at(currPosition).second; int attrPosX = ceil((currValX - xStart) / xStepSize + 1); int attrPosY = ceil((currValY - yStart) / yStepSize + 1); mData->set(attrNo, attrPosX, attrPosY, 2); for(int currProj = 0; currProj < nrProjections; ++currProj) { double xVal = projectionPositions.at(currPosition).first.at(currProj); double yVal = projectionPositions.at(currPosition).second.at(currProj); double pStartX = projectionRangesX.at(currProj * 2); double pEndX = projectionRangesX.at(currProj * 2 + 1); double pStepX = (pEndX - pStartX) / (double) (resolutionX - 1); double pStartY = projectionRangesY.at(currProj * 2); double pEndY = projectionRangesY.at(currProj * 2 + 1); double pStepY = (pEndY - pStartY) / (double) (resolutionY - 1); int xPos = floor((xVal - pStartX) / pStepX + 1); int yPos = floor((yVal - pStartY) / pStepY + 1); mData->set(attrNo, xPos, yPos, 3 + currProj); } } if(!attrMatch) { attractors.append(networkStates.last()); } } // or not, but then there's nothing to do :D // runtime maintencance if(core->isShuttingDown()) { return; } core->executePendingTasks(); } } // CLEAN UP variedValX->set(variedValuesOrig.at(0)); variedValY->set(variedValuesOrig.at(1)); notifyNetworkParametersChanged(network); triggerReset(); restoreNetworkConfiguration(); restoreCurrentNetworkActivites(); }
void LyapunovExponent::calculateData() { // get program core Core *core = Core::getInstance(); // get network ModularNeuralNetwork *network = getCurrentNetwork(); QList<NeuralNetworkElement*> networkElements; network->getNetworkElements(networkElements); QList<DoubleValue*> networkValues = DynamicsPlotterUtil::getNetworkValues(networkElements); // Get parameters for varied element QString variedElement = mVariedElement->get(); if(variedElement.isEmpty()) { reportProblem("LyapunovExponent: No element to vary."); return; } DoubleValue *variedValue = DynamicsPlotterUtil::getElementValue(variedElement, networkElements); if(variedValue == 0) { reportProblem("LyapunovExponent: Invalid value or specifier."); return; } QList<double> variedRange = DynamicsPlotterUtil::getDoublesFromString(mVariedRange->get()); if(variedRange.size() != 2) { reportProblem("LyapunovExponent: Invalid parameter range."); return; } int resolutionX = mResolutionX->get(); int resolutionY = mResolutionY->get(); //avoid division by zero! if(resolutionX < 2 || resolutionY < 2) { reportProblem("LyapunovExponent: Invalid resolution given."); return; } // Let costraint resolver run properly (order matters!) storeNetworkConfiguration(); storeCurrentNetworkActivities(); triggerReset(); restoreCurrentNetworkActivites(); restoreNetworkConfiguration(); notifyNetworkParametersChanged(network); // save original value double originalValue = variedValue->get(); double valStep = (variedRange.at(1) - variedRange.at(0)) / (double) (resolutionX - 1); QList<double> variedValues; // prepare data matrix { //Thread safety of matrix. QMutexLocker guard(mDynamicsPlotManager->getMatrixLocker()); mData->clear(); mData->resize(resolutionX + 1, resolutionY + 1, 1); mData->fill(0); for(int x = 1; x <= resolutionX; ++x) { double val = variedRange.at(0) + (x-1) * valStep; variedValues.append(val); mData->set(val, x, 0, 0); } } int stepsPrePlot = mStepsPrePlot->get(); int stepsToPlot = mStepsToPlot->get(); bool drawNL = mDrawNL->get(); QList<double> ynum; double eps = pow(10,-9); for(int x = 0; x < variedValues.size(); ++x) { // set initial conditions of this run/trajectory variedValue->set(variedValues.at(x)); notifyNetworkParametersChanged(network); // calculate activation after X PrePlot-Steps for(int s = 0; s < stepsPrePlot && mActiveValue->get(); ++s) { triggerNetworkStep(); } // list for states QList< QList<double> > networkStates; for(int s = 0; s < stepsToPlot && mActiveValue->get(); ++s) { triggerNetworkStep(); // get current state of the network QList<double> networkState = DynamicsPlotterUtil::getNetworkState(networkValues); // save to list networkStates.append(networkState); } double ljanum = 0; int c = 0; for(int i = 0; i < networkStates.size() - 1; ++i) { double dy = 10000000, df = 100000000; bool found = false; for(int j = 0; j < networkStates.size() - 1; ++j) { double d = DynamicsPlotterUtil::getDistance( networkStates.at(i), networkStates.at(j)); if(d < dy && d > eps) { dy = d; df = DynamicsPlotterUtil::getDistance( networkStates.at(i + 1), networkStates.at(j + 1)); found = true; } } if(found && dy != 0 && df != 0) { ljanum += log(df / dy); c++; } } // save current hightest exponent ynum.append(ljanum / c); // find smallest and biggest exponent double ymin = ynum.first(); double ymax = ynum.first(); for(int i = 1; i < ynum.size(); ++i) { double y = ynum.at(i); if(y < ymin) { ymin = y; } if(y > ymax) { ymax = y; } } double ystep = (ymax - ymin) / (double)(resolutionY - 1); if(ystep == 0) { reportProblem("LyapunovExponent: No suitable data found."); ymin = 1; ymax = 1; } { //Thread safety of matrix. QMutexLocker guard(mDynamicsPlotManager->getMatrixLocker()); // clear data matrix mData->fill(0); // rescale for(int y = 1; y <= resolutionY; ++y) { double v = ymin + (y-1) * ystep; mData->set(Math::round(v, 5), 0, y, 0); } // fill rescaled matrix again for(int x = 1; x <= ynum.size(); ++x) { double v = min(max(ymin, ynum.at(x - 1)), ymax); int y = ceil(((v - ymin) / ystep) + 1); mData->set(1, x, y, 0); } // find null position (if any) int ny = ceil(((-ymin)/ystep)+1); // and draw red line indicating y=0 if(drawNL && ny < resolutionY && ny > 0) { for(int x = 0; x < resolutionX; ++x) { if(mData->get(x, ny, 0) == 0) { mData->set(2, x, ny, 0); } } } } // runtime maintencance if(core->isShuttingDown()) { return; } core->executePendingTasks(); } // re-set original parameter value variedValue->set(originalValue); // CLEAN UP notifyNetworkParametersChanged(network); triggerReset(); restoreNetworkConfiguration(); restoreCurrentNetworkActivites(); }
void DummyPlotter::calculateData() { if(mExecutionLoop == 0) { mExecutionLoop = dynamic_cast<PlotterExecutionLoop*>(Core::getInstance()->getGlobalObject( DynamicsPlotConstants::OBJECT_PLOTTER_EXECUTION_LOOP)); } // get program core Core *core = Core::getInstance(); // get network //ModularNeuralNetwork *network = getCurrentNetwork(); { //Thread safety of matrix. QMutexLocker guard(mDynamicsPlotManager->getMatrixLocker()); // PREPARE data matrix mData->clear(); mData->resize(0, 0, 0); } int numberSteps = mNumberSteps->get(); int step = 0; //make sure that the constraint resolver is run also after the activations have been restored //so that an optional randomization constraint can alter the activations if required. //notifyNetworkParametersChanged(getCurrentNetwork()); storeNetworkConfiguration(); storeCurrentNetworkActivities(); triggerReset(); restoreNetworkConfiguration(); restoreCurrentNetworkActivites(); notifyNetworkParametersChanged(getCurrentNetwork()); while(mActiveValue->get()) { // let the network run for 1 timestep triggerNetworkStep(); mCurrentStep->set(++step); if(numberSteps > 0 && step >= numberSteps) { break; } int msToWait = mMicrosecondsToWait->get(); do { // runtime maintencance if(core->isShuttingDown()) { return; } core->executePendingTasks(); if(msToWait > 0 && mExecutionLoop != 0) { mExecutionLoop->performUSleep(Math::min(100000, msToWait)); } msToWait -= 100000; } while(msToWait > 0); } restoreNetworkConfiguration(); restoreCurrentNetworkActivites(); }