Logo Search packages:      
Sourcecode: kboincspy version File versions  Download package

kbsseticalibrator.cpp

/***************************************************************************
 *   Copyright (C) 2004 by Roberto Virga                                   *
 *   rvirga@users.sf.net                                                   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include <math.h>

#include <kbsboincmonitor.h>

#include <kbssetitaskmonitor.h>

#include "kbsseticalibrator.h"

KBSSETICalibrator *KBSSETICalibrator::s_self = NULL;


KBSSETICalibrator *KBSSETICalibrator::self()
{
  if(NULL == s_self)
    s_self = new KBSSETICalibrator();
    
  return s_self;
}

KBSSETICalibrator::KBSSETICalibrator(QObject *parent, const char *name)
                 : QObject(parent, name), m_auto(true)
{
  setupStandardCalibration();
  
  m_entered = standardCalibration();
  m_log.setAutoDelete(true);
}

bool KBSSETICalibrator::isAuto() const
{
  return m_auto;
}

void KBSSETICalibrator::setAuto(bool set)
{
  if(set == m_auto) return;
  
  m_auto = set;
  
  emit calibrationUpdated();
}

void KBSSETICalibrator::setCalibration(const KBSSETICalibration &calibration)
{
  m_entered = calibration;
  m_auto = false;
  
  emit calibrationUpdated();
}

const KBSSETICalibration &KBSSETICalibrator::standardCalibration() const
{
  return m_standard;
}

void KBSSETICalibrator::resetCalibration(const KURL &url)
{
  const QString id = this->id(url);
  
  m_computed.remove(id);
  for(unsigned i = LowAR; i <= HighAR; ++i)
    m_count[i].remove(id);
  
  if(m_auto) emit calibrationUpdated();
}

double KBSSETICalibrator::calibrate(const KURL &url, double ar, double prog)
{
  if(0.0 == prog) return 0.0;
  
  const unsigned group = computeGroup(ar);
  
  QMap<double,double> map = calibration(url).map[group];
  map[0.0] = 0.0; map[1.0] = 1.0;
  
  QValueList<double> reported = map.keys();
  qHeapSort(reported);
  
  QValueList<double>::iterator start;
  for(start = reported.begin(); start != reported.end(); ++start)
    if(*start >= prog) break;
  QValueList<double>::iterator end = start;
  --start;
  
  const double dx = *end - *start;
  const double dy = map[*end] - map[*start];
  
  return(map[*start] + (prog - *start) * dy / dx);
}

double KBSSETICalibrator::count(const KURL &url, unsigned group)
{
  const QString id = this->id(url);
  
  if(!m_count[group].contains(id))
    m_count[group][id] = 1;
  
  return m_count[group][id];
}

const KBSSETICalibration &KBSSETICalibrator::calibration(const KURL &url)
{
  return m_auto ? autoCalibration(id(url)) : m_entered;
}

void KBSSETICalibrator::startLog(KBSSETITaskMonitor *monitor)
{
  KBSSETICalibrationLog *logPtr = m_log.find(monitor);
  if(NULL == logPtr) {
    logPtr = new KBSSETICalibrationLog();
    m_log.insert(monitor, logPtr);
  }
  logPtr->clear();
}

void KBSSETICalibrator::logPair(KBSSETITaskMonitor *monitor, double prog, double cpu)
{
  KBSSETICalibrationLog *logPtr = m_log.find(monitor);
  if(NULL == logPtr) return;
  
  (*logPtr)[prog] = cpu;
}

void KBSSETICalibrator::endLog(KBSSETITaskMonitor *monitor, double ar)
{
  KBSSETICalibrationLog *logPtr = m_log.find(monitor);
  if(NULL == logPtr) return;
  
  QString id = this->id(monitor->boincMonitor()->url());
  
  KBSSETICalibrationLog log = *logPtr;
  m_log.remove(monitor);
  
  if(ar < 0.0) return;
  const unsigned group = computeGroup(ar);
  const double count = this->count(id, group);
  
  QValueList<double> progs = log.keys();
  qHeapSort(progs);
  
  const double first = progs.first();
  const double last = progs.last();
  if(first > 0.10 || last < 0.90) return;
  double total_cpu = log[last] / last;
  
  QMap<double,double> map;
  QValueList<double> reported = autoCalibration(id).map[group].keys();
  for(QValueList<double>::iterator it = reported.begin(); it != reported.end(); ++it)
  {
    double distance = 1.00, closest = 0.00;
    for(QValueList<double>::iterator prog = progs.begin(); prog != progs.end(); ++prog)
      if(fabs(*prog - *it) < distance) {
        closest = *prog;
        distance = fabs(*prog - *it);
      }
    
    double key, value;
    if(distance < 0.10) {
      key = ((*it) * count + closest) / (count + 1);
      value = (m_computed[id].map[group][*it] * count + log[closest] / total_cpu) / (count + 1);
    } else {
      key = *it;
      value = m_computed[id].map[group][*it];
    }
    map[key] = value; 
  }
  
  m_computed[id].map[group] = map;
  m_count[group][id]++;
  
  if(m_auto) emit calibrationUpdated();
}

void KBSSETICalibrator::readConfig(KConfig *config)
{
  config->setGroup("KBSSETICalibrator");
  
  QStringList ids = config->readListEntry("IDs");
  
  for(unsigned i = 0; i < ids.count(); ++i)
  {
    QString id = ids[i];
    
    for(unsigned group = LowAR; group <= HighAR; ++group)
    {
      QString key;
      unsigned count;
       
      key = QString("reported_%1_%2").arg(i).arg(group);
      QStringList reported = config->readListEntry(key);
      count = reported.count();
      
      key = QString("effective_%1_%2").arg(i).arg(group);
      QStringList effective = config->readListEntry(key);
      if(effective.count() < count) count = effective.count();
      
      m_computed[id].map[group].clear();    
      for(unsigned j = 0; j < count; ++j)
        m_computed[id].map[group][reported[j].toDouble()] = effective[j].toDouble();
      
      key = QString("count_%1_%2").arg(i).arg(group);
      m_count[group][id] = config->readUnsignedNumEntry(key, 1);
    }
  }
  
  if(m_auto) emit calibrationUpdated();
}

void KBSSETICalibrator::writeConfig(KConfig *config)
{
  config->setGroup("KBSSETICalibrator");
  
  QStringList ids = m_computed.keys();
  config->writeEntry("IDs", ids);
  
  for(unsigned i = 0; i < ids.count(); ++i)
  {
    QString id = ids[i];
    
    for(unsigned group = LowAR; group <= HighAR; ++group)
    {
      QString key;
      
      QStringList reported, effective;
      QMap<double,double> map = m_computed[id].map[group];
      for(QMap<double,double>::iterator it = map.begin(); it != map.end(); ++it)
      {
        reported << QString::number(it.key(), 'f', 5);
        effective << QString::number(it.data(), 'f', 5);
      }
      
      key = QString("reported_%1_%2").arg(i).arg(group);
      config->writeEntry(key, reported);
      
      key = QString("effective_%1_%2").arg(i).arg(group);
      config->writeEntry(key, effective);
      
      key = QString("count_%1_%2").arg(i).arg(group);
      config->writeEntry(key, count(id, group));
    }
  }
}

QString KBSSETICalibrator::id(const KURL &url) const
{
  return url.prettyURL(+1);
}

unsigned KBSSETICalibrator::computeGroup(double ar) const
{
  return (ar < 0.2255) ? LowAR : (ar < 1.1274) ? MediumAR : HighAR;
}

const KBSSETICalibration &KBSSETICalibrator::autoCalibration(const QString &id)
{
  if(!m_computed.contains(id)) m_computed[id] = m_standard;
  
  return m_computed[id];
}

void KBSSETICalibrator::setupStandardCalibration()
{
  m_standard.map[LowAR][0.15] = 0.15;
  m_standard.map[LowAR][0.30] = 0.30;
  m_standard.map[LowAR][0.45] = 0.45;
  m_standard.map[LowAR][0.60] = 0.60;
  m_standard.map[LowAR][0.75] = 0.75;
  m_standard.map[LowAR][0.90] = 0.90;

  m_standard.map[MediumAR][0.15] = 0.15;
  m_standard.map[MediumAR][0.30] = 0.30;
  m_standard.map[MediumAR][0.45] = 0.45;
  m_standard.map[MediumAR][0.60] = 0.60;
  m_standard.map[MediumAR][0.75] = 0.75;
  m_standard.map[MediumAR][0.90] = 0.90;

  m_standard.map[HighAR][0.15] = 0.15;
  m_standard.map[HighAR][0.30] = 0.30;
  m_standard.map[HighAR][0.45] = 0.45;
  m_standard.map[HighAR][0.60] = 0.60;
  m_standard.map[HighAR][0.75] = 0.75;
  m_standard.map[HighAR][0.90] = 0.90;
}

#include "kbsseticalibrator.moc"

Generated by  Doxygen 1.6.0   Back to index