/* Web Polygraph http://www.web-polygraph.org/
* (C) 2003-2006 The Measurement Factory
* Licensed under the Apache License, Version 2.0 */
#include "base/polygraph.h"
#include "runtime/Farm.h"
#include "csm/BodyIter.h"
#include "csm/ContentCfg.h"
#include "csm/ContentMgr.h"
#include "pgl/ContentSym.h"
#include "csm/EmbedContMdl.h"
#include "base/rndDistrStat.h"
EmbedContMdl::EmbedContMdl(): theCfgSel(0), theEmbedCount(0), theEmbedCountMean(-1) {
}
void EmbedContMdl::configure(const ContentSym *cfg) {
Assert(!theEmbedCount);
if ((theEmbedCount = cfg->embedCount()))
theEmbedCountMean = RndDistrStat(theEmbedCount).mean();
configureEmbedCfgs(cfg);
if (theEmbedCount && !theCfgs.count()) {
cerr << cfg->loc()
<< "the number of embedded objects per container is specified, "
<< "but object content types are undefined"
<< endl;
exit(-2);
}
if (!theEmbedCount && theCfgs.count()) {
cerr << cfg->loc()
<< "object content types are specified, "
<< "but the number of embedded objects per container is not"
<< endl;
exit(-2);
}
}
double EmbedContMdl::compContPerCall(const ContentCfg *cc) const {
int idx = 0;
if (find(cc->id(), idx))
return theEmbedCountMean * theProbs[idx];
return 0.0;
}
void EmbedContMdl::noteNewContProb(ContentCfg *cc, double newProb) {
int idx = 0;
if (!find(cc->id(), idx))
return;
theNewContProb[idx] = newProb;
Assert(cc->newPerOid() > 0);
}
int EmbedContMdl::embedGoal(RndGen &rng) {
if (!theEmbedCount)
return 0;
theEmbedCount->rndGen(&rng); // note: we do not reset rng back
return (int)theEmbedCount->trial();
}
ObjId EmbedContMdl::embedRndOid(const ObjId &oid, int oidCount, RndGen &rng) {
// select the embeded content type
// XXX: consistency: pick name first; type should be deterimed by name
theCfgSel->rndGen(&rng); // note: we do not reset rng back
const int idx = (int)theCfgSel->trial();
Assert(0 <= idx && idx < theCfgs.count());
const ContentCfg *cc = theCfgs[idx];
return embedTypedOid(oid, oidCount, cc->id());
}
ObjId EmbedContMdl::embedCatOid(const ObjId &oid, int oidCount, const String &category) {
int etype = -1;
if (!Should(theTypes.findEmbedContType(category.area(0), etype)))
clog << here << "invalid embedded type category: " << category << endl;
return embedTypedOid(oid, oidCount, etype);
}
ObjId EmbedContMdl::embedTypedOid(const ObjId &oid, int oidCount, int etype) {
ObjId eoid = oid;
eoid.world(oid.world().genMutant());
Should(etype >= 0); // how to check upper boundary?
eoid.type(etype);
// with large numbers, embedded objects will start sharing containers
static int maxOidCountSeen = 500;
if (oidCount > maxOidCountSeen) {
if (oidCount - maxOidCountSeen > maxOidCountSeen/10) {
cerr << here << "warning: saw " << oidCount <<
" embedded objects in a single container, possibly causing " <<
"container sharing among embedded objects" << endl;
}
maxOidCountSeen = oidCount;
}
const int off = oidCount + 1;
eoid.name(abs((oid.name() << 8) | off));
return eoid;
}
bool EmbedContMdl::findEmbedContType(const Area &category, int &etype) const {
return theTypes.findEmbedContType(category, etype);
}
void EmbedContMdl::configureEmbedCfgs(const ContentSym *cfg) {
Array<ContentSym*> syms;
cfg->contains(syms, theCfgSel, theProbs);
theCfgs.stretch(syms.count());
for (int i = 0; i < syms.count(); ++i) {
ContentCfg *cfg = TheContentMgr.get(syms[i]);
theCfgs.append(cfg);
}
theNewContProb.stretch(syms.count());
theNewContProb.count(syms.count());
theTypes.configure(theCfgs);
}
bool EmbedContMdl::find(int cfgId, int &idx) const {
for (idx = 0; idx < theCfgs.count(); ++idx) {
if (theCfgs[idx]->id() == cfgId)
return true;
}
return false;
}
syntax highlighted by Code2HTML, v. 0.9.1