/* 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 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; }