#include #include #include #include "tref.hpp" namespace tref { // class rating // public: rating::rating(objectID _o, userID _u, double _value) { o = _o; u = _u; value = _value; } // class __tref // protected: void __tref::addLink(objectID o, userID u) {} void __tref::iterationInit() {} double __tref::qualityUpdate() { return 0; } void __tref::weightUpdate() {} // class __tref // public: __tref::__tref(long unsigned int _objects, long unsigned int _users, long unsigned int _links, double _beta, double _epsilon, double _convergence, bool _verbose) { verbose = _verbose; ratings.reserve(_links); if(verbose) { std::cout << "Reserved space for " << ratings.capacity() << " links." << std::endl; std::cout << "Maximum possible: " << ratings.max_size() << std::endl; } quality.resize(_objects,0); weight.resize(_users,1); beta = _beta; epsilon = _epsilon; convergence = _convergence; } void __tref::addRating(objectID o, userID u, double value) { ratings.push_back(tref::rating(o,u,value)); if(o>=quality.size()) quality.resize(o+1,0); if(u>=weight.size()) weight.resize(u+1,1); addLink(o,u); } unsigned int __tref::iterationCycle() { iterationInit(); if(verbose) { std::cout << "Performing iteration cycle with " << quality.size() << " objects, "; std::cout << weight.size() << " users" << std::endl; std::cout << "and " << ratings.size() << " links, "; std::cout << "beta = " << beta << ", epsilon = " << epsilon << std::endl; std::cout << "and convergence condition = " << convergence << std::endl; } unsigned int iter = 0; double qdiff = qualityUpdate(); do { ++iter; weightUpdate(); qdiff = qualityUpdate(); } while(qdiff > convergence); if(verbose) std::cout << "Exited in " << iter << " iterations with qdiff = " << qdiff << std::endl; return iter; } long unsigned int __tref::objects() { return quality.size(); } long unsigned int __tref::users() { return weight.size(); } long unsigned int __tref::links() { return ratings.size(); } double __tref::objectQuality(objectID o) { return quality[o]; } double __tref::userWeight(userID u) { return weight[u]; } void __tref::printRatings() { for(std::vector::iterator r=ratings.begin();r!=ratings.end();++r) std::cout << r->o << "\t" << r->u << "\t" << r->value << std::endl; } // class smalltref : public __tref // protected: void smalltref::addLink(objectID o, userID u) { if(o>=qualityLast.size()) { qualityLast.resize(o+1); weightSum.resize(o+1); } if(u>=userLinks.size()) userLinks.resize(u+1,0); ++(userLinks[u]); } double smalltref::qualityUpdate() { double qdiff = 0; qualityLast.assign(quality.begin(),quality.end()); quality.assign(quality.size(),0); weightSum.assign(weightSum.size(),0); for(std::vector::iterator r=ratings.begin();r!=ratings.end();++r) { quality[r->o] += weight[r->u] * r->value; weightSum[r->o] += weight[r->u]; } for(objectID o=0;o!=quality.size();++o) { if(weightSum[o]>0) quality[o] /= weightSum[o]; double aux = quality[o]-qualityLast[o]; qdiff += aux*aux; } return sqrt(qdiff); } void smalltref::weightUpdate() { weight.assign(weight.size(),0); for(std::vector::iterator r=ratings.begin();r!=ratings.end();++r) { double aux = r->value - quality[r->o]; weight[r->u] += aux*aux; } for(userID u=0;u!=weight.size();++u) { if(userLinks[u]!=0) weight[u] = pow( ((weight[u]/userLinks[u]) + epsilon), -beta); } } // class smalltref : public __tref // public: smalltref::smalltref(long unsigned int _objects, long unsigned int _users, long unsigned int _links, double _beta, double _epsilon, double _convergence, bool _verbose) : __tref(_objects,_users,_links, _beta,_epsilon,_convergence, _verbose) { qualityLast.resize(_objects); weightSum.resize(_objects); userLinks.resize(_users,0); } // class bigtref : public __tref // protected: void bigtref::iterationInit() { for(objectID o=0;o!=objectRatings.size();++o) objectRatings[o].reserve(objectLinks[o]); for(userID u=0;u!=userRatings.size();++u) userRatings[u].reserve(userLinks[u]); for(std::vector::iterator r=ratings.begin();r!=ratings.end();++r) { objectRatings[r->o].push_back(&(*r)); userRatings[r->u].push_back(&(*r)); } } double bigtref::qualityUpdate() { double qdiff = 0; for(objectID o=0;o!=objectRatings.size();++o) { double qold = quality[o]; double weightSum = quality[o] = 0; for(std::vector::iterator r=objectRatings[o].begin();r!=objectRatings[o].end();++r) { quality[o] += weight[(*r)->u] * (*r)->value; weightSum += weight[(*r)->u]; } if(weightSum>0) quality[o] /= weightSum; qdiff += pow((quality[o]-qold),2); } return sqrt(qdiff); } void bigtref::weightUpdate() { for(userID u=0;u!=userRatings.size();++u) { if(userRatings[u].size()>0) { weight[u] = 0; for(std::vector::iterator r=userRatings[u].begin();r!=userRatings[u].end();++r) weight[u] += pow( ((*r)->value - quality[(*r)->o]), 2); if(weight[u]==0) weight[u] = epsilon; weight[u] = pow( (weight[u]/userRatings[u].size()), -beta); } } } // class bigtref : public __tref // public: bigtref::bigtref(long unsigned int _objects, long unsigned int _users, long unsigned int _links, double _beta, double _epsilon, double _convergence, bool _verbose) : __tref(_objects,_users,_links, _beta,_epsilon,_convergence, _verbose) { objectRatings.resize(_objects); userRatings.resize(_users); objectLinks.resize(_objects,0); userLinks.resize(_users,0); } }