SeComLib
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Macros Pages
hub.cpp
Go to the documentation of this file.
1 /*
2 SeComLib
3 Copyright 2012-2013 TU Delft, Information Security & Privacy Lab (http://isplab.tudelft.nl/)
4 
5 Contributors:
6 Inald Lagendijk (R.L.Lagendijk@TUDelft.nl)
7 Mihai Todor (todormihai@gmail.com)
8 Thijs Veugen (P.J.M.Veugen@tudelft.nl)
9 Zekeriya Erkin (z.erkin@tudelft.nl)
10 
11 Licensed under the Apache License, Version 2.0 (the "License");
12 you may not use this file except in compliance with the License.
13 You may obtain a copy of the License at
14 
15 http://www.apache.org/licenses/LICENSE-2.0
16 
17 Unless required by applicable law or agreed to in writing, software
18 distributed under the License is distributed on an "AS IS" BASIS,
19 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 See the License for the specific language governing permissions and
21 limitations under the License.
22 */
30 #include "hub.h"
31 
32 namespace SeComLib {
33 namespace SecureRecommendations {
37  bool Hub::measureTraffic(false);
38 
42  BigInteger Hub::bitsSent(0);
43 
47  BigInteger Hub::bitsReceived(0);
48 
58  Hub::Hub () {
61 
63  this->kernel = SecureSvm::GetKernel(Utils::Config::GetInstance().GetParameter<std::string>("SecureRecommendations.kernel"));
64 
66  Hub::measureTraffic = Utils::Config::GetInstance().GetParameter<std::string>("SecureRecommendations.analysisType") == "traffic" ? true : false;
67 
68  // Get configuration parameters
69  this->attributeCount = Utils::Config::GetInstance().GetParameter<unsigned int>("SecureRecommendations.Hub.attributeCount");
70  //we assume that all test files have the same number of entries
71  this->testVectorCount = Utils::Config::GetInstance().GetParameter<unsigned int>("SecureRecommendations.Hub.testVectorCount");
72  this->featureScalingFactor = BigInteger(10).Pow(Utils::Config::GetInstance().GetParameter<unsigned long>("SecureRecommendations.Svm.minimumFeatureDecimalDigits"));
73  this->svWeightScaling = BigInteger(10).Pow(Utils::Config::GetInstance().GetParameter<unsigned long>("SecureRecommendations.Svm.minimumAiDecimalDigits"));
74 
75  //set the input test files paths
76  std::string testFilesDirectory = Utils::Config::GetInstance().GetParameter<std::string>("SecureRecommendations.Hub.testFilesDirectory");
77  std::string medicalRelevanceTestFile = Utils::Config::GetInstance().GetParameter<std::string>("SecureRecommendations.Hub.medicalRelevanceTestFile");
78  std::string safetyTestFilesPrefix = Utils::Config::GetInstance().GetParameter<std::string>("SecureRecommendations.Hub.safetyTestFilesPrefix");
79 
80  std::cout << "Pre-processing test data files." << std::endl;
81 
82  //create a file stream to the medical relevance test file
83  std::ifstream fileStream(testFilesDirectory + medicalRelevanceTestFile);
84 
85  //make sure the file exists and it is readable
86  if (!fileStream.good()) {
88  throw std::runtime_error("Can't open the medical relevance test file.");
89  }
90 
91  std::string line;
92  unsigned int lineCounter = 0;
93  //iterate over all the lines in the medical relevance test file and populate the medicalRelevanceTestData structure
94  while (std::getline(fileStream, line)) {
95  this->medicalRelevanceTestData.emplace_back(this->parseTestDataRow(line));
96  ++lineCounter;
97  }
98  //sanity check
99  if (lineCounter != this->testVectorCount) {
101  throw std::runtime_error("Unexpected number of test vectors detected in: " + testFilesDirectory + medicalRelevanceTestFile);
102  }
103 
104  //load the medical safety test data
105  this->loadSafetyTestData(testFilesDirectory, safetyTestFilesPrefix);
106 
107  std::cout << "Finished pre-processing test data files." << std::endl;
108  }
109 
114  return this->cryptoProvider.GetPublicKey();
115  }
116 
122  void Hub::SetServer (const std::shared_ptr<const Server> &server) {
123  this->server = server;
124  }
125 
134  for (size_t i = 0; i < input.size(); ++i) {
135  if (this->measureTraffic) {
136  Hub::bitsReceived += static_cast<unsigned long>(input[i].data.GetSize());
137  }
138 
140  BigInteger decryptedValue = this->cryptoProvider.DecryptInteger(input[i]);
141 
143  if (decryptedValue >= 0) {
144  input[i] = this->cryptoProvider.GetEncryptedOne();
145  }
146  else {
147  input[i] = this->cryptoProvider.GetEncryptedZero();
148  }
149 
150  if (this->measureTraffic) {
151  Hub::bitsSent += static_cast<unsigned long>(input[i].data.GetSize());
152  }
153  }
154  }
155 
166  if (this->measureTraffic) {
167  for (SecureSvm::EncryptedVector::const_iterator i = input.begin(); i != input.end(); ++i) {
168  Hub::bitsReceived += static_cast<unsigned long>((*i).data.GetSize());
169  }
170  }
171 
173  BigInteger maximum = this->cryptoProvider.DecryptInteger(input[0]);
174  //store the index of the maximum value
175  size_t index = 0;
176  //set the fist value to [0] (we'll update it later to [1], if this turns out to be the real maximum)
177  input[0] = this->cryptoProvider.GetEncryptedZero();//do not precompute this!
178 
179  //detect if the maximum value occurs more than once in the input data
180  bool uniqueMaximumValue = true;
181 
183  for (size_t i = 1; i < input.size(); ++i) {
184  //decrypt the current value
185  BigInteger value = this->cryptoProvider.DecryptInteger(input[i]);
186 
187  if (maximum == value) {
188  uniqueMaximumValue = false;
189  }
190  else if (maximum < value) {
191  maximum = value;
192  index = i;
193  uniqueMaximumValue = true;//reset this flag if we update the maximum
194  }
195 
196  //set all the values to [0]
197  input[i] = this->cryptoProvider.GetEncryptedZero();//do not precompute this!
198  }
199 
200  // Set [1] at the index where the first occurence of the maximum was found, but only if the maximum is unique
201  if (uniqueMaximumValue) input[index] = this->cryptoProvider.GetEncryptedOne();//do not precompute this!
202 
203  if (this->measureTraffic) {
204  for (SecureSvm::EncryptedVector::const_iterator i = input.begin(); i != input.end(); ++i) {
205  Hub::bitsSent += static_cast<unsigned long>((*i).data.GetSize());
206  }
207  }
208  }
209 
218  void Hub::EvaluateDivision (const BigInteger &numerator, SecureSvm::EncryptedVector &input) const {
220  for (size_t i = 0; i < input.size(); ++i) {
221  if (this->measureTraffic) {
222  Hub::bitsReceived += static_cast<unsigned long>(input[i].data.GetSize());
223  }
224 
225  input[i] = this->cryptoProvider.EncryptInteger(numerator / this->cryptoProvider.DecryptInteger(input[i]));
226 
227  if (this->measureTraffic) {
228  Hub::bitsSent += static_cast<unsigned long>(input[i].data.GetSize());
229  }
230  }
231  }
232 
241  std::cout << std::endl << Utils::DateTime::Now() << ": Starting accuracy analysis with " << this->getKernelName() << std::endl << std::endl;
242  std::cout << "Feature scaling factor: " << this->featureScalingFactor.ToString(10) << std::endl;
243  std::cout << "Support vector weights scaling factor: " << this->svWeightScaling.ToString(10) << std::endl << std::endl;
244 
245  for (unsigned long i = 0; i < this->testVectorCount; ++i) {
246  Server::EncryptedClusterVotes encryptedClusterVotes;
247  SecureSvm::EncryptedVector encryptedSafetyPredictions;
248  this->server->GetAccuracyPredictions(encryptedClusterVotes, encryptedSafetyPredictions, this->medicalRelevanceTestData[i], this->safetyTestData[i]);
249 
250  //extract the predicted cluster
251  this->predictedClusters.emplace_back(this->getVotedCluster(encryptedClusterVotes));
252 
253  //compute the predicted quality of life values
254  this->predictedQualityOfLifeMatrix.emplace_back(this->processSafetyPredictions(encryptedSafetyPredictions));
255 
256  std::cout << Utils::DateTime::Now() << ": Done " << i + 1 << " of " << this->testVectorCount
257  << ". Expected cluster: " << this->medicalRelevanceTestData[i].clusterLabel << ". Predicted cluster: " << this->predictedClusters.back() << std::endl;
258  }
259 
261  unsigned int medicalRelevanceBlockcorrectPredictions = this->getMedicalRelevanceBlockCorrectPredictionCount();
262  std::cout << "Medical relevance block correct predictions: " << medicalRelevanceBlockcorrectPredictions << " out of " << this->testVectorCount << "." << std::endl;
263  std::cout << "Medical relevance block accuracy: " << (static_cast<double>(medicalRelevanceBlockcorrectPredictions) / static_cast<double>(this->testVectorCount)) * 100.0 << "%" << std::endl;
264 
265  std::cout << "Safety block: " << std::endl;
267 
268  for (std::map<std::string, unsigned int>::const_iterator falsePositivesIterator = this->safetyBlockFalsePositives.begin(), falseNegativesIterator = this->safetyBlockFalseNegatives.begin();
269  falsePositivesIterator != this->safetyBlockFalsePositives.end(), falseNegativesIterator != this->safetyBlockFalseNegatives.end();
270  ++falsePositivesIterator, ++falseNegativesIterator) {
271  std::cout << "Done " << falsePositivesIterator->first << ". ";
272  std::cout << "Correct predictions: " << this->testVectorCount - (falsePositivesIterator->second + falseNegativesIterator->second) << " out of " << this->testVectorCount << "; ";
273  std::cout << "False positives: " << falsePositivesIterator->second << "; ";
274  std::cout << "False negatives: " << falseNegativesIterator->second << "; ";
275  std::cout << "Accuracy: " << (static_cast<double>(this->testVectorCount - (falsePositivesIterator->second + falseNegativesIterator->second)) / static_cast<double>(this->testVectorCount)) * 100.0 << "%." << std::endl;
276  }
277 
278  std::cout << std::endl << Utils::DateTime::Now() << ": Analysis complete." << std::endl;
279  }
280 
291  std::cout << std::endl << Utils::DateTime::Now() << ": Starting performance analysis with " << this->getKernelName() << std::endl << std::endl;
292  std::cout << "Feature scaling factor: " << this->featureScalingFactor.ToString(10) << std::endl;
293  std::cout << "Support vector weights scaling factor: " << this->svWeightScaling.ToString(10) << std::endl << std::endl;
294 
296  std::vector<Utils::CpuTimer::NanosecondType> durationVector;
297 
299  Utils::CpuTimer mainTimer;
300  for (unsigned long i = 0; i < this->testVectorCount; ++i) {
301  //create local variables
302  SecureSvm::EncryptedVector firstTwoBlocksPredictions;
303  SecureSvm::EncryptedVector safetyBlockPredictions;
304 
305  //start the timer
306  Utils::CpuTimer timer;
307 
308  this->server->GetPerformancePredictions(firstTwoBlocksPredictions, safetyBlockPredictions, this->medicalRelevanceTestData[i], this->safetyTestData[i]);
309 
311  for (size_t j = 0; j < firstTwoBlocksPredictions.size(); ++j) {
312  if (this->measureTraffic) {
313  Hub::bitsReceived += static_cast<unsigned long>(firstTwoBlocksPredictions[j].data.GetSize()) + static_cast<unsigned long>(safetyBlockPredictions[j].data.GetSize());
314  }
315 
316  this->cryptoProvider.DecryptInteger(firstTwoBlocksPredictions[j]) * this->cryptoProvider.DecryptInteger(safetyBlockPredictions[j]);
317  }
318 
320  durationVector.emplace_back(timer.GetDuration());
321 
322  std::cout << "Done " << i + 1 << " of " << this->testVectorCount << " in " << Utils::CpuTimer::ToString(durationVector.back()) << std::endl;
323  }
324 
326  std::cout << "Entire process duration: " << mainTimer.ToString()<< std::endl;
327 
328  //compute minimum and maximum durations
329  Utils::CpuTimer::NanosecondType minimum = durationVector[0];
330  Utils::CpuTimer::NanosecondType maximum = durationVector[0];
331 
332  //start from 1
333  for (size_t i = 1; i < this->testVectorCount; ++i) {
334  if (minimum > durationVector[i]) minimum = durationVector[i];
335  if (maximum < durationVector[i]) maximum = durationVector[i];
336  }
337 
338  std::cout << "Per test vector statistics: " << std::endl;
339  std::cout << "Minimum duration: " << Utils::CpuTimer::ToString(minimum) << std::endl;
340  std::cout << "Maximum duration: " << Utils::CpuTimer::ToString(maximum) << std::endl;
341 
342  long double mean = static_cast<double>(std::accumulate(durationVector.begin(), durationVector.end(), 0)) / static_cast<double>(durationVector.size());
343  std::cout << "Average duration: " << Utils::CpuTimer::ToString(static_cast<Utils::CpuTimer::NanosecondType>(mean)) << std::endl;
344  long double standardDeviation = std::sqrt(static_cast<double>(std::inner_product(durationVector.begin(), durationVector.end(), durationVector.begin(), 0)) / static_cast<double>(durationVector.size()) - mean * mean);
345  std::cout << "Standard deviation (in nanoseconds): " << Utils::CpuTimer::ToString(static_cast<Utils::CpuTimer::NanosecondType>(standardDeviation)) << std::endl;
346 
347  std::cout << std::endl << Utils::DateTime::Now() << ": Analysis complete." << std::endl;
348  }
349 
360  std::cout << std::endl << Utils::DateTime::Now() << ": Starting traffic analysis with " << this->getKernelName() << std::endl << std::endl;
361  std::cout << "Feature scaling factor: " << this->featureScalingFactor.ToString(10) << std::endl;
362  std::cout << "Support vector weights scaling factor: " << this->svWeightScaling.ToString(10) << std::endl << std::endl;
363 
364  this->resetTrafficCounters();
365  BigInteger totalBitsSent;
366  BigInteger totalBitsReceived;
367  for (unsigned long i = 0; i < this->testVectorCount; ++i) {
368  //create local variables
369  SecureSvm::EncryptedVector firstTwoBlocksPredictions;
370  SecureSvm::EncryptedVector safetyBlockPredictions;
371 
373  if (this->measureTraffic) {
374  for (SecureSvm::EncryptedVector::const_iterator i = this->medicalRelevanceTestData.back().x.begin(); i != this->medicalRelevanceTestData.back().x.end(); ++i)
375  Hub::bitsSent += static_cast<unsigned long>((*i).data.GetSize());
376  for (SecureSvm::EncryptedVector::const_iterator i = this->medicalRelevanceTestData.back().xx.begin(); i != this->medicalRelevanceTestData.back().xx.end(); ++i)
377  Hub::bitsSent += static_cast<unsigned long>((*i).data.GetSize());
378  for (SecureSvm::EncryptedVector::const_iterator i = this->medicalRelevanceTestData.back().xSquared.begin(); i != this->medicalRelevanceTestData.back().xSquared.end(); ++i)
379  Hub::bitsSent += static_cast<unsigned long>((*i).data.GetSize());
380  }
381 
382  this->server->GetPerformancePredictions(firstTwoBlocksPredictions, safetyBlockPredictions, this->medicalRelevanceTestData[i], this->safetyTestData[i]);
383 
384  for (size_t j = 0; j < firstTwoBlocksPredictions.size(); ++j) {
385  Hub::bitsReceived += static_cast<unsigned long>(firstTwoBlocksPredictions[j].data.GetSize()) + static_cast<unsigned long>(safetyBlockPredictions[j].data.GetSize());
386  }
387 
388  totalBitsSent += Hub::bitsSent;
389  totalBitsReceived += Hub::bitsReceived;
390  std::cout << "Done " << i + 1 << " of " << this->testVectorCount << "; Bits sent: " << Hub::bitsSent.ToString(10) << "; Bits received: " << Hub::bitsReceived.ToString(10) << std::endl;
391  this->resetTrafficCounters();
392  }
393 
394  std::cout << "Total Bits sent: " << totalBitsSent.ToString(10) << std::endl;
395  std::cout << "Total Bits received: " << totalBitsReceived.ToString(10) << std::endl;
396 
397  std::cout << std::endl << Utils::DateTime::Now() << ": Analysis complete." << std::endl;
398  }
399 
403  void Hub::DebugValue (const Paillier::Ciphertext &value) const {
404  std::cout << this->cryptoProvider.DecryptInteger(value).ToString(10) << std::endl;
405  }
406 
414  void Hub::loadSafetyTestData (const std::string &testFilesDirectory, const std::string &safetyTestFilesPrefix) {
415  //build a list of safety test files
416  std::deque<std::string> safetyTestFiles = Utils::Filesystem::GetFilesInDirectory(testFilesDirectory);
417 
418  if (safetyTestFiles.empty()) {
420  throw std::runtime_error("No files found in directory: " + testFilesDirectory);
421  }
422 
423  //resize the safety test data container accordingly
424  this->safetyTestData.resize(this->testVectorCount);
425 
426  for (std::deque<std::string>::const_iterator fileIterator = safetyTestFiles.begin(); fileIterator != safetyTestFiles.end(); ++fileIterator) {
427  //there may be other files in the folder
428  if (std::string::npos != (*fileIterator).find(safetyTestFilesPrefix)) {
429  //each file name ends with a series of digits, which represent the unsafe classes
430  //we want to extract and sort them in ascending order (just to be sure)
431  //iterate over each class (digit) in the file name
432  std::vector<unsigned short> unsafeClasses;
433  for (size_t i = (*fileIterator).find_last_not_of("0123456789") + 1; i < (*fileIterator).size(); ++i) {
434  //the difference between any digit and '0' will yield the desired numeric value
435  unsafeClasses.emplace_back((*fileIterator)[i] - '0');
436  }
437  std::sort(unsafeClasses.begin(), unsafeClasses.end());
438 
439  //convert the ordered unsafeClasses vector to a stringstream
440  std::stringstream unsafeClassesStream;
441  for (std::vector<unsigned short>::const_iterator unsafeClassesIterator = unsafeClasses.begin(); unsafeClassesIterator != unsafeClasses.end(); ++unsafeClassesIterator) {
442  unsafeClassesStream << *unsafeClassesIterator;
443  }
444 
445  //create a file stream to the medical relevance test file
446  std::ifstream fileStream(testFilesDirectory + *fileIterator);
447 
448  //make sure the file exists and it is readable
449  if (!fileStream.good()) {
451  throw std::runtime_error("Can't open the safety test file.");
452  }
453 
454  std::string line;
455  unsigned int lineCounter = 0;
456  //iterate over all the lines in the file and populate the safetyTestData structure column by column
457  while (std::getline(fileStream, line)) {
458  this->safetyTestData[lineCounter][unsafeClassesStream.str()] = this->parseTestDataRow(line);
459  ++lineCounter;
460  }
461 
462  //sanity check
463  if (lineCounter != this->testVectorCount) {
465  throw std::runtime_error("Unexpected number of test vectors detected in: " + testFilesDirectory + *fileIterator);
466  }
467  }
468  }
469  }
470 
478  TestDataRow Hub::parseTestDataRow (const std::string &line) const {
479  TestDataRow output;
480 
482 
483  std::string::size_type hashPosition = line.find('#');
484  std::string::size_type clPosition = line.find("cl");
485  std::string::size_type qolPosition = line.find("qol");
486  std::string::size_type genPosition = line.find("gen");
487  if (std::string::npos == hashPosition || std::string::npos == clPosition || std::string::npos == qolPosition || std::string::npos == genPosition) {
488  throw std::runtime_error("Label(s) not found in input file.");
489  }
490 
491  std::string::size_type clQolDelimiter = line.find(' ', clPosition);
492  std::string::size_type qolGenDelimiter = line.find(' ', qolPosition);
493 
494  if (std::string::npos == clQolDelimiter || std::string::npos == qolGenDelimiter) {
495  throw std::runtime_error("Labels should be delimited by a space character.");
496  }
497 
499  std::istringstream clusterLabel(line.substr(clPosition + 3, clQolDelimiter));
500  //the input line should end after the qol value
501  std::istringstream qualityOfLifeLabel(line.substr(qolPosition + 4, qolGenDelimiter));
502  //we're not interested in the gen label
503 
504  if (!clusterLabel || !qualityOfLifeLabel) {
505  throw std::runtime_error("Malformed labels detected in input file.");
506  }
507 
508  unsigned short labelValue;
509 
511 
512  //the input test data indexes the clusters starting from 1.
513  clusterLabel >> labelValue;
514  if (labelValue < 1 || labelValue > 5) {
515  throw std::runtime_error("Invalid cluster label.");
516  }
517  output.clusterLabel = labelValue;
518 
519  qualityOfLifeLabel >> labelValue;
521  if (labelValue > 6) {
522  throw std::runtime_error("Invalid quality of life label.");
523  }
524  //convert from unsigned short to char
525  output.qualityOfLifeLabel = static_cast<char>('0' + labelValue);
526 
528  std::vector<BigInteger> tempX;
529 
533  std::string::size_type attributeValueStartPosition = line.find(':');
534  if (std::string::npos == attributeValueStartPosition) {
535  throw std::runtime_error("Can't find the first attribute.");
536  }
537  for (unsigned int i = 0; i < this->attributeCount; ++i) {
538  std::string::size_type attributeDelimiterPosition = line.find(' ', attributeValueStartPosition);
539  if (std::string::npos == attributeDelimiterPosition) {
540  throw std::runtime_error("Input line does not contain the required number of attributes.");
541  }
542 
543  //extract the current attribute value to stringstream so that we can convert it easily to double
544  std::istringstream attributeStream(line.substr(attributeValueStartPosition + 1, attributeDelimiterPosition - attributeValueStartPosition - 1));
545 
546  if (!attributeStream) {
547  throw std::runtime_error("Invalid attribute value detected.");
548  }
549 
550  //std::cout << attributeStream.str() << std::endl;
551 
552  //convert stream to double (are 8 bytes / 15 digits enough???)
553  double attribute;
554  attributeStream >> attribute;
555 
556  //apply scaling
557  //in case of negative values, remap them at the end of the key space
558  tempX.push_back(BigInteger(attribute, this->featureScalingFactor));
559 
560  //jump to the next attribute
561  attributeValueStartPosition = line.find(':', attributeValueStartPosition + 1);
562  }
563 
564  //xx and xSqared matrices are required only for polynomial and rbf kernels
565  if (SecureSvm::inverseQuadraticRBF == this->kernel || SecureSvm::homogeneousPolynomial == this->kernel || SecureSvm::inhomogeneousPolynomial == this->kernel) {
566  for (unsigned int i = 0; i < tempX.size(); ++i) {
567  //xx matrix is required only for polynomial kernels
568  if (SecureSvm::homogeneousPolynomial == this->kernel || SecureSvm::inhomogeneousPolynomial == this->kernel) {
569  for (unsigned int j = i; j < tempX.size(); ++j) {
571  output.xx.push_back(this->cryptoProvider.EncryptInteger(tempX[i] * tempX[j]));
572  }
573  }
574 
575  //xSquared matrix is required only for the rbf kernel
576  if (SecureSvm::inverseQuadraticRBF == this->kernel) {
578  output.xSquared.push_back(this->cryptoProvider.EncryptInteger(tempX[i] * tempX[i]));
579  }
580  }
581  }
582 
583  //x matrix is not required for the homogeneous polynomial kernel
584  if (SecureSvm::homogeneousPolynomial != this->kernel) {
585  for (unsigned int i = 0; i < tempX.size(); ++i) {
586  output.x.emplace_back(this->cryptoProvider.EncryptInteger(tempX[i]));
587  }
588  }
589 
590  return output;
591  }
592 
601  unsigned short Hub::getVotedCluster (const std::vector<Paillier::Ciphertext> &encryptedClusterVotes) const {
602  //return 0 if the maximum does not exist in the input vector
603  unsigned short output = 0;
604 
605  BigInteger one(1);
606  for (size_t i = 0; i < encryptedClusterVotes.size(); ++i) {
607  if (one == this->cryptoProvider.DecryptInteger(encryptedClusterVotes[i])) {
608  //the input test data cluster labels are indexed starting from 1
609  output = static_cast<unsigned short>(i + 1);
610  break;
611  }
612  }
613 
614  return output;
615  }
616 
625  std::vector<unsigned short> Hub::processSafetyPredictions (const std::vector<Paillier::Ciphertext> &encryptedSafetyPredictions) const {
626  std::vector<unsigned short> output;
627  for (std::vector<Paillier::Ciphertext>::const_iterator prediction = encryptedSafetyPredictions.begin(); prediction != encryptedSafetyPredictions.end(); ++prediction) {
628  //debug
629  //DebugValue(*prediction);
630 
631  //we expect only 2 possible values: 0 (negative prediction) and 1 (pozitive prediction)
632  output.emplace_back(this->cryptoProvider.DecryptInteger(*prediction).ToUnsignedLong() == 0 ? 0 : 1);
633  }
634 
635  return output;
636  }
637 
642  unsigned int correctPredictions = 0;
643 
644  for (unsigned long i = 0; i < this->testVectorCount; ++i) {
645  correctPredictions += this->predictedClusters[i] == this->medicalRelevanceTestData[i].clusterLabel ? 1 : 0;
646  }
647 
648  return correctPredictions;
649  }
650 
654  std::vector<std::string> safetyBlockSvmsUnsafeClasses = this->server->GetSafetyBlockSvmsUnsafeClasses();
655  std::deque<std::string> safetyBlockSvmsModelFiles = this->server->GetSafetyBlockModelFiles();
656 
657  //initialize the false positives and false negatives counters
658  for (std::deque<std::string>::const_iterator modelFile = safetyBlockSvmsModelFiles.begin(); modelFile != safetyBlockSvmsModelFiles.end(); ++modelFile) {
659  this->safetyBlockFalsePositives[*modelFile] = 0;
660  this->safetyBlockFalseNegatives[*modelFile] = 0;
661  }
662 
663  //do iterate over all the prediction rows and count the false positives and false negatives
664  for (size_t testRowIndex = 0; testRowIndex < this->predictedQualityOfLifeMatrix.size(); ++testRowIndex) {
665  for (size_t svmIndex = 0; svmIndex < safetyBlockSvmsUnsafeClasses.size(); ++svmIndex) {
666  std::map<std::string, TestDataRow>::const_iterator safetyTestDataIterator = this->safetyTestData[testRowIndex].find(safetyBlockSvmsUnsafeClasses[svmIndex]);
667  if (this->safetyTestData[testRowIndex].end() != safetyTestDataIterator) {
668  //unsafe label => the safety prediction must be negative (= 0)
669  if (std::string::npos != safetyBlockSvmsUnsafeClasses[svmIndex].find(safetyTestDataIterator->second.qualityOfLifeLabel) && 1 == this->predictedQualityOfLifeMatrix[testRowIndex][svmIndex]) {
670  ++this->safetyBlockFalsePositives[safetyBlockSvmsModelFiles[svmIndex]];
671  }
672  //safe label => the safety prediction must be positive (= 1)
673  else if (std::string::npos == safetyBlockSvmsUnsafeClasses[svmIndex].find(safetyTestDataIterator->second.qualityOfLifeLabel) && 0 == this->predictedQualityOfLifeMatrix[testRowIndex][svmIndex]) {
674  ++this->safetyBlockFalseNegatives[safetyBlockSvmsModelFiles[svmIndex]];
675  }
676  }
677  else {
679  throw std::runtime_error("Missing safety test data for unsafe classes: " + safetyBlockSvmsUnsafeClasses[svmIndex]);
680  }
681  }
682  }
683  }
684 
686  Hub::bitsSent = 0;
687  Hub::bitsReceived = 0;
688  }
689 
694  std::string Hub::getKernelName () const {
695  std::string name;
696 
697  switch (this->kernel) {
698  case SecureSvm::linear:
699  name = "linear kernel";
700  break;
701  case SecureSvm::homogeneousPolynomial:
702  name = "homogeneous polynomial kernel";
703  break;
704  case SecureSvm::inhomogeneousPolynomial:
705  name = "inhomogeneous polynomial kernel";
706  break;
707  case SecureSvm::inverseQuadraticRBF:
708  name = "inverse quadratic RBF kernel";
709  break;
710  default:
712  throw std::runtime_error("Invalid kernel type.");
713  }
714 
715  return name;
716  }
717 
718 }//namespace SecureRecommendations
719 }//namespace SeComLib
std::vector< Paillier::Ciphertext > EncryptedVector
Define a vector template specialization for vectors of encrypted data.
Definition: secure_svm.h:62
std::vector< TestDataRow > medicalRelevanceTestData
The medical relevance block test data.
Definition: hub.h:123
Ciphertext GetEncryptedOne(const bool randomized=true) const
Returns [1].
unsigned int getMedicalRelevanceBlockCorrectPredictionCount() const
Computes the number of correct predictions of the medical relevance block.
Definition: hub.cpp:641
Processed test data container.
Definition: test_data_row.h:40
std::vector< unsigned short > predictedClusters
The predicted clusters.
Definition: hub.h:129
unsigned short getVotedCluster(const std::vector< Paillier::Ciphertext > &encryptedClusterVotes) const
Returns the cluster index, which corresponds to the maximum.
Definition: hub.cpp:601
std::vector< std::vector< unsigned short > > predictedQualityOfLifeMatrix
Vector of predicted quality of life values (contains 0 for negative values and 1 for positive values)...
Definition: hub.h:132
Ciphertext GetEncryptedZero(const bool randomized=true) const
Returns [0].
const T_PublicKey & GetPublicKey() const
Public key getter.
void DoTrafficAnalysis()
Execute the traffic analysis of the system.
Definition: hub.cpp:359
virtual BigInteger DecryptInteger(const Ciphertext &ciphertext) const
Decrypt number.
Definition: paillier.cpp:176
void DoPerformanceAnalysis()
Execute the performance analysis of the system.
Definition: hub.cpp:290
static Config & GetInstance()
Returns a reference to the singleton.
Definition: config.cpp:48
void EvaluateMaximum(SecureSvm::EncryptedVector &input) const
Secure maximum evaluation.
Definition: hub.cpp:165
boost::timer::nanosecond_type NanosecondType
Nanosecond data type (int_least64_t)
Definition: cpu_timer.h:50
SecureSvm::EncryptedVector x
Encrypted test data vector.
Definition: test_data_row.h:43
SecureSvm::KernelTypes kernel
The SVM kernel type. We want to pre-compute only the data that is necessary for a particular kernel...
Definition: hub.h:114
virtual bool GenerateKeys()
Definition: paillier.cpp:105
std::vector< Paillier::Ciphertext > EncryptedClusterVotes
Container for the encrypted cluster votes.
virtual T_Ciphertext EncryptInteger(const BigInteger &plaintext) const
Encrypt an integer and apply randomization.
std::vector< unsigned short > processSafetyPredictions(const std::vector< Paillier::Ciphertext > &encryptedSafetyPredictions) const
Returns the processed predictions of the safety block SVMs.
Definition: hub.cpp:625
void SetServer(const std::shared_ptr< const Server > &server)
Sets a reference to the recommendations server.
Definition: hub.cpp:122
Definition of class Hub.
static BigInteger bitsReceived
Counts the number of bits received from the server.
Definition: hub.h:147
Paillier cryptoProvider
The crypto provider.
Definition: hub.h:101
Utilitary class providing algorithm timing functionality.
Definition: cpu_timer.h:47
void DebugValue(const Paillier::Ciphertext &value) const
Decrypts and prints an encrypted value.
Definition: hub.cpp:403
std::string ToString() const
Returns the elapsed user process time as a formatted string (HH::MM::SS.mmm)
Definition: cpu_timer.cpp:63
SecureSvm::EncryptedVector xSquared
Encrypted squared test data vector.
Definition: test_data_row.h:49
unsigned short clusterLabel
The expected cluster (use this for accuracy measures)
Definition: test_data_row.h:52
Hub()
Default constructor.
Definition: hub.cpp:58
unsigned int attributeCount
The number of attributes in each test vector of the test data.
Definition: hub.h:111
static BigInteger bitsSent
Counts the numbe of bits sent to the server.
Definition: hub.h:144
static KernelTypes GetKernel(const std::string &input)
Converts the input string to the proper kernel.
Definition: secure_svm.cpp:170
void computeSafetyBlockFalsePredictions()
Computes the number of false negatives and false positives of the safety block.
Definition: hub.cpp:653
char qualityOfLifeLabel
The quality of life measure (use this for accuracy measures)
Definition: test_data_row.h:55
BigInteger svWeightScaling
The scaling applied to the SVM parameters, and .
Definition: hub.h:120
void DoAccuracyAnalysis()
Execute the accuracy analysis of the system.
Definition: hub.cpp:240
std::map< std::string, unsigned int > safetyBlockFalsePositives
Vector containing number of false positives per safety SVM.
Definition: hub.h:135
T GetParameter(const std::string &parameter) const
Template method which returns the value of the specified configuration parameter. ...
Definition: config.hpp:41
static bool measureTraffic
Enables traffic profiling.
Definition: hub.h:141
std::string getKernelName() const
Returns a string containing the name of the kernel specified in the configuration file...
Definition: hub.cpp:694
NanosecondType GetDuration() const
Returns the elapsed user process time (in nanoseconds)
Definition: cpu_timer.cpp:56
SecureSvm::EncryptedVector xx
Encrypted vector product combinations, , stored as an unraveled upper triangular matrix.
Definition: test_data_row.h:46
std::vector< std::map< std::string, TestDataRow > > safetyTestData
The safety block test data array (vector of collection of rows; each file should have the same number...
Definition: hub.h:126
std::shared_ptr< const Server > server
A reference to the recommendations server.
Definition: hub.h:104
std::map< std::string, unsigned int > safetyBlockFalseNegatives
Vector containing number of false negatives per safety SVM.
Definition: hub.h:138
static std::deque< std::string > GetFilesInDirectory(const std::string &directory)
Traverses the provided directory (non-recursively) and extracts the absolute paths to all the files i...
Definition: filesystem.cpp:40
BigInteger featureScalingFactor
The scaling applied to the test and model vectors and .
Definition: hub.h:117
const PaillierPublicKey & GetPublicKey() const
Returns a reference to the public key.
Definition: hub.cpp:113
TestDataRow parseTestDataRow(const std::string &line) const
Extracts test data from a single line.
Definition: hub.cpp:478
static std::string Now(const std::string &format="%H:%M:%S")
Returns the formatted current time.
Definition: date_time.cpp:38
void EvaluateDivision(const BigInteger &numerator, SecureSvm::EncryptedVector &input) const
Secure division evaluation.
Definition: hub.cpp:218
static void resetTrafficCounters()
Resets the traffic counters.
Definition: hub.cpp:685
The public key container structure for the Paillier cryptosystem.
Definition: paillier.h:49
void EvaluateSign(SecureSvm::EncryptedVector &input) const
Secure sign evaluation.
Definition: hub.cpp:133
void loadSafetyTestData(const std::string &testFilesDirectory, const std::string &safetyTestFilesPrefix)
Populates the safetyTestData structure.
Definition: hub.cpp:414