Created
November 7, 2017 06:48
-
-
Save bowbowbow/69db6eb257c727566c65a79c4908e520 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cstdio> | |
#include <iostream> | |
#include <vector> | |
#include <map> | |
#include <set> | |
#include <string> | |
#include <algorithm> | |
#include <ctime> | |
#include <fstream> | |
#include <cmath> | |
#include <functional> | |
#include <random> | |
#include <ctime> | |
using namespace std; | |
#define mp make_pair | |
#define ll long long | |
#define MAT vector<vector<double> > | |
#define MAT2 vector<vector<pair<int, int> > > | |
#define double long double | |
mt19937 engine(time(NULL)); | |
uniform_int_distribution<> dist(1, 4); | |
auto gen = bind(dist, engine); | |
struct PinTrust { | |
int TargetUser, U; | |
double alpha, beta, epsilon, RF; | |
MAT Belief, BeliefScore;//prior belief, final belief score | |
MAT2 adj; | |
// 0:postive, 1:negative, 2:reverse positive, 3: reverse negative | |
MAT propagationMatrix; | |
//for each user, <trust,distrust> score | |
MAT Globalmsg; | |
map<pair<int, int>, int> Trust; | |
map<pair<int, int>, int> DisTrust; | |
map<pair<int, int>, vector<int> > Rating; | |
PinTrust(double alpha, double beta, double epsilon, double RF, int U, int TargetUser) { | |
this->alpha = alpha; | |
this->beta = beta; | |
this->epsilon = epsilon; | |
this->RF = RF; | |
this->U = U; | |
this->TargetUser = TargetUser; | |
MakeBeliefScore(U, 2); | |
adj.resize(U); | |
} | |
void ChangeFactor(double alpha, double beta, double epsilon, double RF) { | |
this->alpha = alpha; | |
this->beta = beta; | |
this->epsilon = epsilon; | |
this->RF = RF; | |
MakeBeliefScore(U, 2); | |
adj.clear(); | |
adj.resize(U); | |
} | |
void InputTrust(int u, int v) { | |
Trust[mp(u, v)] = 1; | |
} | |
void InputDisTrust(int u, int v) { | |
DisTrust[mp(u, v)] = 1; | |
} | |
void InputRating(int u, int v, int R) { | |
Rating[mp(u, v)].push_back(R); | |
} | |
void MakeBeliefScore(int U, int S) { | |
Globalmsg.clear(); | |
Globalmsg.resize(U); | |
for (int i = 0; i < U; i++) { | |
Globalmsg[i].push_back(1); | |
Globalmsg[i].push_back(1); | |
} | |
Belief.clear(); | |
Belief.resize(U); | |
for (int i = 0; i < Belief.size(); i++)Belief[i].resize(S); | |
for (int i = 0; i < Belief.size(); i++) { | |
Belief[i][0] = 0.5 + beta; | |
Belief[i][1] = 0.5 - beta; | |
} | |
Belief[TargetUser][0] = 0.5 + alpha; | |
Belief[TargetUser][1] = 0.5 - alpha; | |
} | |
void MakeEdge0() { | |
//P[i][j] = Trust[i][j] or Rating[i][j] | |
map<pair<int, int>, int> tmpadj; | |
for (auto &it : Trust) { | |
int u = it.first.first; | |
int v = it.first.second; | |
tmpadj[mp(u, v)] = 1; | |
} | |
for (auto &it : Rating) { | |
int u = it.first.first; | |
int v = it.first.second; | |
tmpadj[mp(u, v)] = 1; | |
} | |
for (auto &it : tmpadj) { | |
int u = it.first.first; | |
int v = it.first.second; | |
adj[u].push_back({ v, 0 }); | |
adj[v].push_back({ u, 2 });////reverse positive | |
} | |
} | |
void MakeEdge1() { | |
for (auto &it : DisTrust) { | |
int u = it.first.first; | |
int v = it.first.second; | |
adj[u].push_back({ v, 1 }); | |
adj[v].push_back({ u, 3 });//reverse negative | |
} | |
} | |
map<pair<int, int >, double> myFR; | |
double GetFR(int u, int v) { | |
return myFR[mp(u, v)]; | |
int Ratingcnt = 0; | |
double Ratingavr = 0; | |
if (Rating.find(mp(u, v)) != Rating.end()) { | |
Ratingcnt = (int)Rating[mp(u, v)].size(); | |
if (Ratingcnt == 0)return 0; | |
auto tmp = Rating[mp(u, v)]; | |
for (int i = 0; i < tmp.size(); i++) { | |
Ratingavr += tmp[i]; | |
} | |
Ratingavr /= (double)Ratingcnt; | |
} | |
if (Ratingcnt == 0) { | |
return 0; | |
} | |
if (Ratingcnt >= 64) { | |
if (Ratingavr <= 3) { | |
return 0; | |
} | |
if (Ratingcnt <= 127)return 0.75; | |
if (Ratingcnt <= 255)return 0.8; | |
if (Ratingcnt <= 511)return 0.85; | |
return 0.85; | |
} | |
if (Ratingcnt == 1) { | |
if (Ratingavr <= 3)return 0.01; | |
return 0.05; | |
} | |
else if (Ratingcnt <= 3) { | |
if (Ratingavr <= 3)return 0.01; | |
return 0.1; | |
} | |
else if (Ratingcnt <= 7) { | |
if (Ratingavr <= 3)return 0.01; | |
return 0.3; | |
} | |
else if (Ratingcnt <= 15) { | |
if (Ratingavr <= 3)return 0.02; | |
return 0.4; | |
} | |
else if (Ratingcnt <= 31) { | |
if (Ratingavr <= 3)return 0.03; | |
return 0.55; | |
} | |
else if (Ratingcnt <= 63) { | |
if (Ratingavr <= 3)return 0.02; | |
return 0.7; | |
} | |
return 0; | |
} | |
//source -> destination | |
MAT MakePropagationMatrix0(int u, int v) { | |
propagationMatrix.clear(); | |
propagationMatrix.resize(2); | |
for (int i = 0; i < 2; i++)propagationMatrix[i].resize(2); | |
propagationMatrix[0][0] = propagationMatrix[1][1] = 0.5 + epsilon*((double)Trust[mp(u, v)] + GetFR(u, v)); | |
propagationMatrix[1][0] = propagationMatrix[0][1] = 0.5 - epsilon*((double)Trust[mp(u, v)] + GetFR(u, v)); | |
return propagationMatrix; | |
} | |
MAT MakePropagationMatrix1(int u, int v) { | |
propagationMatrix.clear(); | |
propagationMatrix.resize(2); | |
for (int i = 0; i < 2; i++)propagationMatrix[i].resize(2); | |
propagationMatrix[0][0] = propagationMatrix[1][1] = 0.5 - epsilon; | |
propagationMatrix[1][0] = propagationMatrix[0][1] = 0.5 + epsilon; | |
return propagationMatrix; | |
} | |
MAT MakePropagationMatrix2(int u, int v) { | |
propagationMatrix.clear(); | |
propagationMatrix.resize(2); | |
for (int i = 0; i < 2; i++)propagationMatrix[i].resize(2); | |
propagationMatrix[0][0] = propagationMatrix[1][1] = 0.5 + epsilon*((double)Trust[mp(u, v)] + GetFR(u, v))*RF; | |
propagationMatrix[1][0] = propagationMatrix[0][1] = 0.5 - epsilon*((double)Trust[mp(u, v)] + GetFR(u, v))*RF; | |
return propagationMatrix; | |
} | |
MAT MakePropagationMatrix3(int u, int v) { | |
propagationMatrix.clear(); | |
propagationMatrix.resize(2); | |
for (int i = 0; i < 2; i++)propagationMatrix[i].resize(2); | |
propagationMatrix[0][0] = propagationMatrix[1][1] = 0.5 - epsilon*RF; | |
propagationMatrix[1][0] = propagationMatrix[0][1] = 0.5 + epsilon*RF; | |
return propagationMatrix; | |
} | |
MAT newMatrix(int U, int S) { | |
MAT ret = vector<vector<double > >(U, vector<double>(S, 1)); | |
return ret; | |
} | |
vector<double> newMessage(int S) { | |
vector<double> ret(S, 1); | |
return ret; | |
} | |
// flag == what adj matrix(P, N, PR, NR) I have. | |
vector<double> PropagateMessage(int u, int v, vector<double>& msgvalue, int S, int flag) { | |
vector<double> msg = newMessage(S); | |
MAT psi; | |
if (flag == 0)psi = MakePropagationMatrix0(u, v); | |
else if (flag == 1)psi = MakePropagationMatrix1(u, v); | |
else if (flag == 2)psi = MakePropagationMatrix2(u, v);//!!!!!reverse edge자체를 반대로 넣어서 | |
else if (flag == 3)psi = MakePropagationMatrix3(u, v); | |
for (int p = 0; p < S; p++) { | |
double sum = 0; | |
for (int q = 0; q < S; q++) { | |
sum += Belief[u][q] * psi[q][p] * msgvalue[q]; | |
//sum += log(Belief[u][q]) + log(psi[q][p]) + log(msgvalue[q]); | |
} | |
msg[p] = sum; | |
} | |
return msg; | |
} | |
void NormalizeMessage(vector<double>& msg, int S) { | |
double sum = 0; | |
for (int i = 0; i < S; i++) { | |
sum += msg[i]; | |
} | |
for (int i = 0; i < S; i++) { | |
msg[i] = msg[i] / sum; | |
} | |
} | |
void run() { | |
//To erase reciprocal, erase type 2, 3 edge inside these func. | |
MakeEdge0(); | |
MakeEdge1(); | |
for (int i = 0; i < U; i++) { | |
sort(adj[i].begin(), adj[i].end()); | |
adj[i].erase(unique(adj[i].begin(), adj[i].end()), adj[i].end()); | |
} | |
//MAT MSG = newMatrix(U, 2); | |
map<pair<int, int>, vector<double> > MSG; | |
//while not converged | |
for (int ite = 0; ite < 8; ite++) { | |
// for (int ty = 0; ty < 4; ty++) { | |
for (int i = 0; i < U; i++) { | |
// vector<double> msg = newMessage(2); | |
vector<double> msg(2, 1); | |
for (int j = 0; j < adj[i].size(); j++) { | |
int k = adj[i][j].first; // neighbor | |
// if (ty != adj[i][j].second)continue; | |
for (int di = 0; di < 2; di++) { | |
if (MSG.find(mp(k, i)) == MSG.end()) { | |
MSG[mp(k, i)].push_back(1.0); | |
MSG[mp(k, i)].push_back(1.0); | |
} | |
msg[di] *= MSG[mp(k, i)][di]; | |
// msg[di] += log10(MSG[mp(k, i)][di]); | |
} | |
NormalizeMessage(msg, 2); | |
} | |
for (int j = 0; j < adj[i].size(); j++) { | |
int k = adj[i][j].first; // neighbor | |
int type = adj[i][j].second; | |
// if (type != ty)continue; | |
vector<double> msg_divided; | |
msg_divided = newMessage(2); | |
for (int p = 0; p < 2; p++) { | |
//msg_divided[p] = msg[p]; | |
msg_divided[p] = msg[p] / MSG[mp(k, i)][p]; | |
// msg_divided[p] -= log10(MSG[mp(k, i)][p]);//... | |
//너무 작으면 propagate할때 작은 값이 곱해져서 -nan나오는걸 방지 | |
} | |
// double mini = min(msg_divided[0], msg_divided[1]); | |
// msg_divided[0] -= mini, msg_divided[1] -= mini; | |
// msg_divided[0] = pow(10, msg_divided[0]), msg_divided[1] = pow(10, msg_divided[1]); | |
MSG[mp(i, k)] = PropagateMessage(i, k, msg_divided, 2, type); | |
NormalizeMessage(MSG[mp(i, k)], 2); | |
} | |
// } | |
} | |
printf("iteration %d fin\n", ite); | |
} | |
// nomalize 되기 전 최종 belif score를 여기서 계산 함 | |
for (int i = 0; i < U; i++) { | |
Globalmsg[i][0] = Globalmsg[i][1] = 1; | |
for (int j = 0; j < adj[i].size(); j++) { | |
int neighbor = adj[i][j].first; | |
//multiply message | |
Globalmsg[i][0] *= MSG[mp(neighbor, i)][0]; | |
Globalmsg[i][1] *= MSG[mp(neighbor, i)][1]; | |
NormalizeMessage(Globalmsg[i], 2); | |
//Globalmsg[i][0] += log10(MSG[mp(neighbor, i)][0]); | |
//Globalmsg[i][1] += log10(MSG[mp(neighbor, i)][1]); | |
} | |
//prior belief score | |
Globalmsg[i][0] *= Belief[i][0]; | |
Globalmsg[i][1] *= Belief[i][1]; | |
//while (Globalmsg[i][0] < 0.1 && Globalmsg[i][1] < 0.1)Globalmsg[i][0] *= 10.0, Globalmsg[i][1] *= 10.0; | |
/* | |
Globalmsg[i][0] += log10(Belief[i][0]); | |
Globalmsg[i][1] += log10(Belief[i][1]); | |
double minV = min(Globalmsg[i][0], Globalmsg[i][1]); | |
Globalmsg[i][0] -= minV; | |
Globalmsg[i][1] -= minV; | |
Globalmsg[i][0] = pow(10, Globalmsg[i][0]); | |
Globalmsg[i][1] = pow(10, Globalmsg[i][1]); | |
*/ | |
NormalizeMessage(Globalmsg[i], 2); | |
} | |
} | |
void RunAll() { | |
run(); | |
BeliefScore.resize(U); | |
for (int i = 0; i < U; i++) { | |
BeliefScore[i].resize(2); | |
} | |
for (int i = 0; i < U; i++) { | |
for (int di = 0; di < 2; di++) { | |
BeliefScore[i][di] = Globalmsg[i][di]; | |
} | |
} | |
} | |
}; | |
double alpha = 1e-2;//1e-1 | |
double beta = 1e-5;//1e-6 | |
double epsilon = 0.005; | |
double RF = 0.1; | |
int usernum = 10; | |
int targetUser = 0; | |
struct info { | |
int a, b; | |
double rate; | |
}; | |
struct inputting { | |
int u, v, tr; | |
double rating; | |
}; | |
int main(int argc, char ** argv) { | |
string cutRate(argv[1]); | |
cout << "cutRate : " << cutRate << endl; | |
int cutRateNum = stoi(cutRate); | |
cout << "cutRateNum : " << cutRateNum << endl; | |
clock_t start; | |
double duration; | |
start = clock(); | |
int M; // 간선 개수 | |
M = 841372; usernum = 131828;//120053, 121067, 122162 | |
int u, v, trust, distrust; | |
double rating; | |
ifstream in("input.txt"); | |
vector<inputting> fi, se; | |
int trcnt[1318888] = { 0, }; | |
while (!( | |
in >> u >> v >> trust >> rating).eof()) { | |
if (trust == 1)trcnt[u]++; | |
fi.push_back({ u, v, trust, rating }); | |
} | |
in.close(); | |
in.open("zero_injection_only.txt"); | |
while (!( | |
in >> u >> v >> rating).eof()) { | |
if (u < 0 || v < 0 || u >= 131828 || v >= 131828) { | |
puts("what"); continue; | |
} | |
se.push_back({ u, v, 0, rating }); | |
} | |
ofstream out("myout_"+cutRate+".txt"); | |
vector<int> targetarr = { 120053, 117979, 117517, 2586, 115058, | |
10695, 114376, 113465, 52620, 103690, 120302, 51143, 51655, 52188, | |
52334}; | |
for (int iii = 0; iii < targetarr.size(); iii++) { | |
//if (!(25<= trcnt[targetarr[iii]] && trcnt[targetarr[iii]]<50))continue;//그룹 제한 | |
int myfriend[131828] = { 0, }; myfriend[targetarr[iii]] = 1; | |
vector<info> hitsave, restoresave; | |
for (int jjj = 0; jjj < 1; jjj++) { | |
cout << targetarr[iii] << "번 유저 진행중" << endl; | |
int flag = 0; | |
int mmm = cutRateNum;//0이면 25%, 1이면 50%, 2이면 75%, 3이면 100% | |
set<int> cut, alive; | |
targetUser = targetarr[iii]; | |
PinTrust pinTrust(alpha, beta, epsilon, RF, usernum, targetUser); | |
ifstream in("input.txt"); | |
for (int i = 0; i < fi.size(); i++) { | |
u = fi[i].u, v = fi[i].v, trust = fi[i].tr, rating = fi[i].rating; | |
if (u == targetUser && (trust == 1)) { | |
int key = gen(); ++flag; | |
if (flag % 4 <= mmm) { | |
cut.insert(v); | |
continue; | |
} | |
alive.insert(v); myfriend[v] = 1; | |
} | |
if (trust == 1) | |
pinTrust.InputTrust(u, v); | |
else if (trust == -1) { | |
pinTrust.InputDisTrust(u, v); | |
} | |
else { | |
//if (u == targetUser)myfriend[v] = 1; | |
//if (pinTrust.Trust.find(mp(u, v)) != pinTrust.Trust.end()) | |
if (u == targetUser)myfriend[v] = 1;; | |
pinTrust.myFR[mp(u, v)] = rating; | |
pinTrust.adj[u].push_back({ v, 0 }); | |
pinTrust.adj[v].push_back({ u, 2 }); | |
} | |
} | |
//if (jjj == 0)goto there; | |
int cnt[131828] = { 0, }; | |
int tag = 0; | |
for (int i = 0; i < se.size(); i++) { | |
u = se[i].u, v = se[i].v, rating = se[i].rating; | |
if (!myfriend[u])continue; | |
if (cnt[u] == 400)continue; | |
if (u < 0 || v < 0 || u >= 131828 || v >= 131828) { | |
puts("what"); continue; | |
} | |
if (pinTrust.Trust.find({ u, v }) != pinTrust.Trust.end()) { | |
continue; | |
} | |
if (cnt[u] == 0)++tag; | |
cnt[u]++; | |
pinTrust.InputDisTrust(u, v); | |
} | |
printf("tag %d\n", tag); | |
//there: | |
int oo = (int)cut.size() + (int)alive.size(); | |
printf("trust 는 %d\n", (int)cut.size() + (int)alive.size()); | |
cout << "input ok" << endl; | |
printf("끊긴 개수 %d\n", (int)cut.size()); | |
pinTrust.RunAll(); | |
// belifScore 출력 | |
vector<pair<double, pair<double, int> > > output; | |
for (int i = 0; i < usernum; i++) { | |
output.push_back(mp(-pinTrust.BeliefScore[i][0], mp(pinTrust.BeliefScore[i][1], i))); | |
} | |
sort(output.begin(), output.end()); | |
out << fixed; | |
out.precision(1); | |
int hit = 0, restore = 0; | |
int sz1 = (int)alive.size(); | |
int sz2 = (int)cut.size(); | |
for (int i = 0; i < output.size(); i++) { | |
double TS = -output[i].first; | |
double DS = output[i].second.first; | |
int uu = output[i].second.second; | |
if (cut.find(uu) != cut.end())++restore; | |
else if (alive.find(uu) != alive.end()) { | |
++hit; | |
} | |
double rate = 100.0*(double)hit / (double)sz1; | |
double rate2 = 100.0*(double)restore / (double)sz2; | |
if (i%oo == 0 && oo <= i && i <= 5 * oo) { | |
hitsave.push_back({ hit, sz1, rate }); restoresave.push_back({ restore, sz2, rate2 }); | |
//out << "top " << i << ", " << hit << "/" << (int)alive.size() << "(" << 100.0*(double)hit / (double)sz1 << "%)" | |
// ", " << restore << "/" << (int)cut.size() << "(" << 100.0*(double)restore / (double)sz2 << "%)" << endl; | |
} | |
if (i > 5 * oo)break; | |
} | |
if (jjj == 0) { | |
out << targetUser << "user" << endl; | |
out << "[정확도]" << endl; | |
out << "전체 신뢰 관계 개수" << (int)alive.size() + (int)cut.size() << endl; | |
for (int i = 0; i < 5; i++) { | |
out << "top " << oo*(i + 1) << ", " << hitsave[i].a << "/" << sz1 << "(" << hitsave[i].rate << "%)" | |
<< ", " << restoresave[i].a << "/" << sz2 << "(" << restoresave[i].rate << "%)" << endl; | |
} | |
} | |
out << endl << endl; | |
duration = (std::clock() - start) / (double)CLOCKS_PER_SEC; | |
cout << "duration: " << duration << endl; | |
} | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment