Brief description of class still missing. More...
#include <Neighborhood.h>
Public Member Functions | |
int | activeModelCount () const |
double | bestIterationMisfit () const |
int | bestModelCount () const |
int | bestModelIndex () const |
uint | checksum () const |
void | clear () |
AbstractForward * | forward () |
const AbstractForward * | forward () const |
int | giveUpCount () const |
bool | importModels (QString fileName, bool strict=true) |
void | lock () const |
double | misfit (int modelIndex) const |
const int * | model (int modelIndex) const |
Neighborhood () | |
bool | openReport (const QString &fileName) |
bool | operator== (const Neighborhood &o) const |
bool | optimization (int ns=50, int nw=2) |
bool | random (int ns=50, int nw=2) |
int | rejectedCount () const |
void | setForward (AbstractForward *forward) |
void | setGiveUp (double giveUp) |
void | setMaximumSavedMisfit (double m) |
void | setNr (int nr) |
void | setSeed (int seed) |
void | setStorage () |
bool | setThreadCount (int nThreads) |
bool | setVolumes () |
void | sleep () |
void | start (int itmax=50, int ns0=50, int ns=50, int nr=50) |
void | terminate (bool t=true) |
void | timeReport () const |
void | unlock () const |
int | validModelCount () const |
const Parameter * | variableParameter (int paramIndex) const |
int | variableParameterCount () const |
double | variableParameterValue (int modelIndex, int paramIndex) const |
int | visitedModelCount () const |
void | wake () |
~Neighborhood () |
Brief description of class still missing.
Full description of class still missing
Description of constructor still missing
References TRACE.
{ TRACE; _allModels=0; _activeModels=0; _bestModels=0; _originalBestModels=0; _generator=new UniqueRandom(0); _report=0; _parameterSpaceChecksum=0; _giveUp=0.9; _deadCount=0; _giveUpCount=0; _rejectedCount=0; _maxModelCount=0; _maximumSavedMisfit=1e99; // by default no limit }
int DinverCore::Neighborhood::activeModelCount | ( | ) | const |
References DinverCore::ActiveModels::count().
{ return _activeModels ? _activeModels->count() : 0; }
double DinverCore::Neighborhood::bestIterationMisfit | ( | ) | const [inline] |
{return _iterationMinimumMisfit;}
int DinverCore::Neighborhood::bestModelCount | ( | ) | const |
References DinverCore::BestModels::count().
{ return _bestModels ? _bestModels->count() : 0; }
int DinverCore::Neighborhood::bestModelIndex | ( | ) | const |
References DinverCore::ModelSet::bestModel().
Referenced by main(), and ToolNR::optimizeStack().
{ // TODO: multi-dimensional misfit return _allModels->bestModel(); }
uint DinverCore::Neighborhood::checksum | ( | ) | const [inline] |
{return _parameterSpaceChecksum;}
void DinverCore::Neighborhood::clear | ( | ) |
AbstractForward* DinverCore::Neighborhood::forward | ( | ) | [inline] |
{return _forwards.isEmpty() ? 0 : _forwards.first();}
const AbstractForward* DinverCore::Neighborhood::forward | ( | ) | const [inline] |
{return _forwards.isEmpty() ? 0 : _forwards.first();}
int DinverCore::Neighborhood::giveUpCount | ( | ) | const [inline] |
{return _giveUpCount;}
bool DinverCore::Neighborhood::importModels | ( | QString | fileName, |
bool | strict = true |
||
) |
void DinverCore::Neighborhood::lock | ( | ) | const |
Used only by external objects to acces generated models (read only)
References DinverCore::ModelSet::lock().
{ if(_allModels) { _allModels->lock(); } }
double DinverCore::Neighborhood::misfit | ( | int | modelIndex | ) | const |
References DinverCore::ModelSet::misfit().
Referenced by main(), and ToolNR::optimizeStack().
{ // TODO: multi-dimensional misfit return _allModels ? _allModels->misfit(modelIndex)[0] : 0; }
const int * DinverCore::Neighborhood::model | ( | int | modelIndex | ) | const |
References DinverCore::ModelSet::model().
Referenced by ToolNR::optimizeStack(), and setThreadCount().
{ return _allModels->model(modelIndex); }
bool DinverCore::Neighborhood::openReport | ( | const QString & | fileName | ) |
Initialize report. Can be called at any time.
References QGpCoreTools::endl(), DinverCore::ReportWriter::open(), and QGpCoreTools::tr().
Referenced by main().
bool DinverCore::Neighborhood::operator== | ( | const Neighborhood & | o | ) | const |
{
return _forwards.first()->parameterSpace()==o._forwards.first()->parameterSpace();
}
bool DinverCore::Neighborhood::optimization | ( | int | ns = 50 , |
int | nw = 2 |
||
) |
Generates ns new samples with a Neighborhood Algorithm. Returns false if the inversion stops for an error
References DinverCore::ActiveModels::count(), DinverCore::BestModels::count(), QGpCoreTools::endl(), DinverCore::AbstractForward::generate(), DinverCore::AbstractForward::initGenerate(), DinverCore::ActiveModels::model(), DinverCore::BestModels::modelIndex(), DinverCore::ModelSet::parameterCount(), DinverCore::AbstractForward::parameterSpace(), DinverCore::ActiveModels::reserve(), DinverCore::BestModels::reserve(), DinverCore::ModelSet::reserve(), DinverCore::Parameter::setGridValue(), QGpCoreTools::tr(), TRACE, DinverCore::UniqueRandom::uniform(), DinverCore::AbstractForward::unlock(), DinverCore::BestModels::update(), and DinverCore::RealSpace::variableParameter().
Referenced by start().
{ TRACE; QTime chrono; chrono.start(); _iterationMinimumMisfit=1e99; if(_bestModels->count()==0) { // Still no best model ... something wrong App::stream() << tr("No model in parameter space, cannot run iteration. Generate random models or import models.") << endl; return true; } // Complete if possible best models list to its maximum item count _bestModels->update(); /* Reserve space for new models that will be generated to avoid locking for capacity increases. For _allmodels there might be much more than ns models added during this iteration hence locking is still necessary. */ _bestModels->reserve(ns); // in the extreme case all generated models will be added to best models // in a minimum misfit inversion, increasing the total number of best // models by ns. _activeModels->reserve(ns); _allModels->reserve(2*ns); int ndVar=_allModels->parameterCount(); int effectiveNr=_bestModels->count(); enum Distribution {Ordered, Random}; Distribution sampleDistribution=(effectiveNr>ns) ? Random : Ordered; int curCell=-1; ScaledModels scaledModels(_activeModels, scales()); // Initialize the forward threads foreach(AbstractForward * f, _forwards) { f->initGenerate(&scaledModels, nw); } // Make a copy of _bestModels to avoid its modification while generating new cells _originalBestModels=new BestModels( *_bestModels); int timeStart=chrono.elapsed(); _timeStartEnd+=timeStart; _maxModelCount=_activeModels->count() + ns; while(_activeModels->count()<_maxModelCount) { AbstractForward * forward=nextForward(); if(terminated()) { if(forward) { // In case of unthreaded forward, the state is currently running forward->unlock(); } return optimizationEnd(false); } ASSERT(forward); // Check if there are still enough best models, some of them might be lost if models // are rejected or in case of atomic cells if(_originalBestModels->count() < effectiveNr) { _originalBestModels->update(); } switch(sampleDistribution) { case Ordered: curCell++; if(curCell>=effectiveNr) curCell=0; break; case Random: curCell=_generator->uniform(0, effectiveNr-1); break; } int modelIndex=_originalBestModels->modelIndex(curCell); // Copy model to param structure to enable condition testing const int * v=_activeModels->model(modelIndex); RealSpace& parameterSpace=forward->parameterSpace(); for(int ip=0;ip < ndVar;ip++ ) { parameterSpace.variableParameter(ip)->setGridValue(v[ip] ); } if(!forward->generate(modelIndex)) { break; } } int timeEnd=chrono.elapsed(); _deadCount += removeDeadModels(); _timeStartEnd+=chrono.elapsed()-timeEnd; _timeTotal+=chrono.elapsed(); return optimizationEnd(true); }
bool DinverCore::Neighborhood::random | ( | int | ns = 50 , |
int | nw = 2 |
||
) |
Generate ns random models
References DinverCore::ActiveModels::count(), DinverCore::AbstractForward::generate(), DinverCore::AbstractForward::initGenerate(), and TRACE.
Referenced by start().
{ TRACE; QTime chrono; chrono.start(); _iterationMinimumMisfit=1e99; _maxModelCount=_activeModels->count() + ns; // Initialize the forward threads foreach(AbstractForward * f, _forwards) { f->initGenerate(0, nw); } while(_activeModels->count()<_maxModelCount) { if(terminated()) { stopForwards(); return false; } AbstractForward * f=nextForward(); if(f) { if(!f->generate()) { break; } } } stopForwards(); _timeTotal+=chrono.elapsed(); return true; }
int DinverCore::Neighborhood::rejectedCount | ( | ) | const [inline] |
{return _rejectedCount;}
void DinverCore::Neighborhood::setForward | ( | AbstractForward * | forward | ) |
Set the forward object in charge of forward computation. Can be called only once. forward can be uninitialized (number of variable parameters).
References TRACE.
Referenced by main(), and ToolNR::optimizeStack().
void DinverCore::Neighborhood::setGiveUp | ( | double | giveUp | ) | [inline] |
{_giveUp=giveUp;}
void DinverCore::Neighborhood::setMaximumSavedMisfit | ( | double | m | ) | [inline] |
{_maximumSavedMisfit=m;}
void DinverCore::Neighborhood::setNr | ( | int | nr | ) |
References QGpCoreTools::endl(), DinverCore::BestModels::setNr(), and QGpCoreTools::tr().
Referenced by start().
void DinverCore::Neighborhood::setSeed | ( | int | seed | ) |
If seed is null, a random number is calculated from current time.
References QGpCoreTools::endl(), and QGpCoreTools::tr().
{ if(_forwards.isEmpty() || _forwards.first()->isSleeping()) { delete _generator; _generator=new UniqueRandom(seed); if( !_forwards.isEmpty()) _forwards.first()->setGenerator(_generator); } else { App::stream() << tr("Cannot change the random seed of a running inversion, first terminate it.") << endl; } }
void DinverCore::Neighborhood::setStorage | ( | ) |
Initialize the model list, random generator, list of best models. The forward object must be initialized (number of variable parameters). Can be called only once.
Referenced by start().
{ ASSERT(_forwards.count()==1); ASSERT( !_allModels && !_activeModels && !_bestModels); int ndVar=_forwards.first()->parameterSpace().variableParameterCount(); // TODO: generalized multi-dimensional misfit _allModels=new ModelSet(ndVar, 1); _activeModels=new ActiveModels(_allModels); _bestModels=new BestModels (_activeModels); }
bool DinverCore::Neighborhood::setThreadCount | ( | int | nThreads | ) |
If there is no model currently in list, it generates a random model without checking conditions between parameters limits. In a second step, the model is adjusted until matching all conditions of the parameter space.
References DinverCore::RealSpace::adjustRanges(), DinverCore::AbstractForward::clone(), DinverCore::AbstractForward::copyValues(), DinverCore::ActiveModels::count(), DinverCore::BestModels::count(), DinverCore::RealSpace::isOkDebug(), DinverCore::BestModels::model(), model(), DinverCore::AbstractForward::parameterSpace(), DinverCore::AbstractForward::setAllModels(), DinverCore::AbstractForward::setFinishSignal(), DinverCore::AbstractForward::setGenerator(), DinverCore::Parameter::setGridValue(), DinverCore::RealSpace::setVariableParameters(), TRACE, DinverCore::UniqueRandom::uniform(), DinverCore::RealSpace::variableParameter(), DinverCore::RealSpace::variableParameterCount(), and DinverCore::AbstractForward::wake().
Referenced by start().
{ TRACE; QTime chrono; chrono.start(); ASSERT(_forwards.count()==1); AbstractForward * refForward=_forwards.first(); if(nThreads>CoreApplication::instance()->maximumThreadCount()) { nThreads=CoreApplication::instance()->maximumThreadCount(); } if(nThreads>refForward->maximumThreadCount()) { nThreads=refForward->maximumThreadCount(); } if(nThreads<1) nThreads=1; // Get the checksum of the parameterization _parameterSpaceChecksum=refForward->parameterSpace().checksum(); refForward->setFinishSignal(&_forwardSignal); refForward->setGenerator(_generator); refForward->setAllModels(_allModels); if(_activeModels->count()==0) { if( ! refForward->firstModel()) { return false; } } else { // Load one of the best models into refForward RealSpace& parameterSpace=refForward->parameterSpace(); int ndVar=parameterSpace.variableParameterCount(); const int * model=_bestModels->model(_generator->uniform(0, _bestModels->count()-1) ); for(int ip=0;ip < ndVar;ip++ ) { parameterSpace.variableParameter(ip)->setGridValue(model[ip] ); } // Some parametrizations may need some updates before proceeding refForward->valueChanged(); // Check validity of exisiting best models if( !parameterSpace.isOkDebug()) { return false; } } // Init all forwards with this first model //refForward->redirectStream(); for(int i=1;i<nThreads; i++) { AbstractForward * f=refForward->clone(); //f->redirectStream(); f->setFinishSignal(&_forwardSignal); f->setGenerator(_generator); f->setAllModels(_allModels); RealSpace& parameterSpace=f->parameterSpace(); parameterSpace.setVariableParameters(); parameterSpace.adjustRanges(); // Assumed to be ok, because checked before for the first one _forwards.append(f); // Init first model for f f->copyValues( *refForward); // Activate this new forward thread f->wake(); } _timeTotal+=chrono.elapsed(); return true; }
bool DinverCore::Neighborhood::setVolumes | ( | ) |
Initialize the volumes of all active models. It must be called before first optimization. Currenly not used.
References QGpCoreTools::abs(), DinverCore::VoronoiNavigator::cellLimits(), DinverCore::ActiveModels::count(), DinverCore::VoronoiNavigator::currentAxis(), DinverCore::Parameter::getGridLimits(), iModel, DinverCore::VoronoiNavigator::incrementAxis(), DinverCore::VoronoiNavigator::setCurrentAxis(), DinverCore::VoronoiNavigator::setCurrentPoint(), TRACE, DinverCore::RealSpace::variableParameter(), and DinverCore::RealSpace::variableParameterCount().
Referenced by start().
{ TRACE; RealSpace& parameterSpace=_forwards.first()->parameterSpace(); int ndVar=parameterSpace.variableParameterCount(); ScaledModels scaledModels(_activeModels, scales()); VoronoiNavigator nav(&scaledModels); int nModels=_activeModels->count(); int xMin, xMax, iMin, iMax; for(int iModel=0;iModel<nModels; iModel++) { if(terminated()) { return false; } double volume=1.0; nav.setCurrentPoint(iModel); nav.setCurrentAxis(ndVar-1); for(int id=0; id<ndVar; id++) { nav.incrementAxis(); Parameter * p=parameterSpace.variableParameter(nav.currentAxis()); p->getGridLimits(xMin, xMax); nav.cellLimits(xMin, xMax, iMin, iMax); volume*=abs(xMax-xMin)+1; } //_allModels->setVolume(_activeModels->at(iModel).modelIndex(), volume); } return true; }
void DinverCore::Neighborhood::sleep | ( | ) |
References DinverCore::AbstractForward::sleep(), and TRACE.
Referenced by start().
{ TRACE; // Remove all but one forward thread while(_forwards.count()>1) { AbstractForward * f=_forwards.last(); f->sleep(); delete f; _forwards.pop_back(); } _forwards.first()->sleep(); }
void DinverCore::Neighborhood::start | ( | int | itmax = 50 , |
int | ns0 = 50 , |
||
int | ns = 50 , |
||
int | nr = 50 |
||
) |
For convenience, starts the inversion in current thread with the number of available threads. It does not return before the end. For specific applications, use the general interface.
References DinverCore::RealSpace::adjustRanges(), QGpCoreTools::endl(), DinverCore::RealSpace::humanInfo(), optimization(), random(), setNr(), setStorage(), setThreadCount(), DinverCore::RealSpace::setVariableParameters(), setVolumes(), sleep(), QGpCoreTools::tr(), TRACE, and wake().
Referenced by main(), and ToolNR::optimizeStack().
{ TRACE; RealSpace& ps=_forwards.first()->parameterSpace(); ps.setVariableParameters(); if(!ps.adjustRanges()) { App::stream() << tr("Error adjusting ranges") << endl; return; } ps.humanInfo(); App::stream() << tr("\nStarting %1 iterations\n").arg(itmax) << endl; if( !_allModels) { setStorage(); } setNr(nr); wake(); setThreadCount(Thread::idealThreadCount()); random(ns0); setVolumes(); for(int i=0; i< itmax; i++) { App::stream() << tr("Iteration %1").arg(i) << endl; optimization(ns); } sleep(); }
void DinverCore::Neighborhood::terminate | ( | bool | t = true | ) |
References DinverCore::AbstractForward::abort(), and DinverCore::ForwardSignal::finished().
{ _terminated.fetchAndStoreOrdered(t); if(t) { foreach(AbstractForward * f, _forwards) { f->abort(); } _forwardSignal.finished(0); } }
void DinverCore::Neighborhood::timeReport | ( | ) | const |
Report timing (must be called before sleep() to get reports about forward threads)
References QGpCoreTools::endl(), QGpCoreTools::tr(), and TRACE.
{ TRACE; App::stream() << tr("\nTiming report\n" "--------------\n") << endl; App::stream() << tr("Waiting for forward threads: %1 ms").arg(_timeMainWait) << endl; App::stream() << tr("Adding new models: %1 ms").arg(_timeAdd) << endl; App::stream() << tr("Iteration init&cleanup: %1 ms").arg(_timeStartEnd) << endl; int n=_forwards.count(); for(int i=0; i<n; i++) { App::stream() << tr("Foward computations[thread %1]:\n").arg(i+1); _forwards[i]->timeReport(" "); } App::stream() << tr("Total: %1 ms").arg(_timeTotal) << endl; }
void DinverCore::Neighborhood::unlock | ( | ) | const |
Used only by external objects to acces generated models (read only)
References DinverCore::ModelSet::unlock().
{ if(_allModels) { _allModels->unlock(); } }
int DinverCore::Neighborhood::validModelCount | ( | ) | const |
References DinverCore::ActiveModels::count().
Referenced by main().
{ return (_activeModels ? _activeModels->count() : 0) + _deadCount; }
const Parameter * DinverCore::Neighborhood::variableParameter | ( | int | paramIndex | ) | const |
References DinverCore::RealSpace::variableParameter().
Referenced by variableParameterValue().
{ const RealSpace& parameterSpace=_forwards.first()->parameterSpace(); return parameterSpace.variableParameter(paramIndex); }
int DinverCore::Neighborhood::variableParameterCount | ( | ) | const |
References DinverCore::ModelSet::parameterCount().
{ return _allModels ? _allModels->parameterCount() : 0; }
double DinverCore::Neighborhood::variableParameterValue | ( | int | modelIndex, |
int | paramIndex | ||
) | const |
References DinverCore::ModelSet::model(), DinverCore::Parameter::realValue(), and variableParameter().
Referenced by main().
{ return variableParameter(paramIndex)->realValue(_allModels->model(modelIndex)[paramIndex] ); }
int DinverCore::Neighborhood::visitedModelCount | ( | ) | const |
References DinverCore::ModelSet::count().
{ return _allModels ? _allModels->count() : 0; }
void DinverCore::Neighborhood::wake | ( | ) |