-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathBP.cpp
More file actions
177 lines (159 loc) · 5.63 KB
/
Copy pathBP.cpp
File metadata and controls
177 lines (159 loc) · 5.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#include"rnbp_a1_a2.h"
#include"const.h"
#include"regidster.h"
#include"bfi.h"
extern int SIZE;
bool is_target(uint64_t x, uint64_t NumTargets, uint64_t *Target);
void PickNewBaseElement_bp(vector<list> &seq, uint64_t NumInputs, uint64_t NumTargets, uint64_t *XorCount, uint64_t * BaseSize, uint64_t *TargetsFound, uint64_t *Target, uint64_t *Base, uint64_t *Dist, uint64_t *NDist, string *Program);
int BP_algorithm(vector<list> &seq, uint64_t NumInputs, uint64_t NumTargets, uint64_t *Target, uint64_t *Dist)
{
uint64_t BaseSize = 0;
uint64_t XorCount = 0;
uint64_t TargetsFound = 0;
uint64_t Base[MaxBaseSize] = { 0 };
uint64_t NDist[MaxBaseSize] = { 0 };
vector<uint64_t> P;
vector<uint64_t> Q;
int randomly_flag = rand() % 2;
if(randomly_flag == 1)
{
P = generate_p(NumTargets);
Q = generate_p(NumInputs);
p_m_q(Target, NumTargets, NumInputs, Dist, P, Q);
}
string Program[MaxBaseSize];
InitBase(NumInputs, NumTargets, &BaseSize, &TargetsFound, Base, Dist, Program);
int counter = 0;
while (TargetsFound < NumTargets)
{
counter++;
if (!EasyMove(seq, NumInputs, NumTargets, &XorCount, &BaseSize, &TargetsFound, Target, Base, Dist, Program)) PickNewBaseElement_bp(seq, NumInputs, NumTargets, &XorCount, &BaseSize, &TargetsFound, Target, Base, Dist, NDist, Program);
}
if(randomly_flag == 1)
{
recover_implementation(seq, P, Q);
}
return XorCount;
}
int TotalDistance_bp(uint64_t NumInputs, uint64_t NumTargets, uint64_t BaseSize, uint64_t NewBase, uint64_t *Target, uint64_t *Base, uint64_t *Dist, uint64_t *NDist)
{ //returns the sum of distances to targets
int D = 0;
int t;
for (unsigned int i = 0; i < NumTargets; i++)
{
t = NewDistance(i, NumInputs, BaseSize, NewBase, Target, Base, Dist);
NDist[i] = t;
D = D + t;
}
return D;
}
// PickNewBaseElement is only called when there are no 1's in Dist[]
void PickNewBaseElement_bp(vector<list> &seq, uint64_t NumInputs, uint64_t NumTargets, uint64_t *XorCount, uint64_t * BaseSize, uint64_t *TargetsFound, uint64_t *Target, uint64_t *Base, uint64_t *Dist, uint64_t *NDist, string *Program)
{
int MinDistance = 0;
uint64_t TheBest = 0;
int ThisDist = 0;
int ThisNorm = 0, OldNorm = 0;
int besti = 0, bestj = 0, d = 0;
bool easytarget = false;
int BestDist[MaxBaseSize] = { 0 };
uint64_t NewBase = 0;
MinDistance = (*BaseSize) * NumTargets; //i.e. something big
OldNorm = 0; //i.e. something small
//try all pairs of bases
for (unsigned int i = 0; i < *BaseSize - 1; i++)
{
for (unsigned int j = i+1; j < *BaseSize; j++)
{
NewBase = Base[i] ^ Base[j];
//sanity check
if (NewBase == 0) { cout << "a base is 0, should't happen " << endl; exit(0); }
//if NewBase is not new continue
if (is_base(NewBase, *BaseSize, Base)) continue;
//if NewBase is target then choose it
easytarget = false;
if (is_target(NewBase, NumTargets, Target))
{ cout<< "newbase" << NewBase << endl;
cout << "shouldn't find an easy target here " << endl;
exit(0);
easytarget = true;
besti = i;
bestj = j;
TheBest = NewBase;
break;
}
ThisDist = TotalDistance_bp(NumInputs, NumTargets, *BaseSize, NewBase, Target, Base, Dist, NDist); //this also calculates NDist[]
if (ThisDist <= MinDistance)
{
//calculate Norm
ThisNorm = 0;
for (unsigned int k = 0; k < NumTargets; k++)
{
d = NDist[k];
ThisNorm = ThisNorm + d * d;
}
//resolve tie in favor of largest norm
if ((ThisDist < MinDistance) || (ThisNorm > OldNorm))
{
besti = i;
bestj = j;
TheBest = NewBase;
for (unsigned int uu = 0; uu < NumTargets; uu++)
{
BestDist[uu] = NDist[uu];
}
MinDistance = ThisDist;
OldNorm = ThisNorm;
}
}
}
if (easytarget)
{
break;
}
}
//update Dist array
NewBase = TheBest;
for (unsigned int i = 0; i < NumTargets; i++)
{
Dist[i] = BestDist[i];
}
//update Base with TheBest
Base[*BaseSize] = TheBest;
//update linear program
int n = *XorCount + NumTargets;
if(NumTargets < NumInputs){ n = *XorCount + NumInputs; }
string a = Program[besti].substr(0, Program[besti].find(" "));
string b = Program[bestj].substr(0, Program[bestj].find(" "));
// Program[BaseSize] = "t" + to_string(XorCount+NumInputs) + " = " + a + " + " + b;
Program[*BaseSize] = to_string(n) + " = " + a + " + " + b;
stringstream ss_a, ss_b;
list row;
row.value.push_back(n);
row.flag = -1;
row.usd = 0;
ss_a << a;
ss_a >> n;
row.value.push_back(n);
ss_b << b;
ss_b >> n;
row.value.push_back(n);
seq.push_back(row);
*BaseSize = *BaseSize + 1;
*XorCount = *XorCount + 1;
if (is_target(TheBest, NumTargets, Target))
{
*TargetsFound = *TargetsFound + 1; //this shouldn't happen
}
}
bool is_target(uint64_t x, uint64_t NumTargets, uint64_t *Target)
{
for (unsigned int i = 0; i < NumTargets; i++)
{
if (x == Target[i])
{
return true;
}
}
return false;
}