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 | ( | ) |