33 namespace SecureRecommendations {
80 std::cout <<
"Pre-processing test data files." << std::endl;
83 std::ifstream fileStream(testFilesDirectory + medicalRelevanceTestFile);
86 if (!fileStream.good()) {
88 throw std::runtime_error(
"Can't open the medical relevance test file.");
92 unsigned int lineCounter = 0;
94 while (std::getline(fileStream, line)) {
99 if (lineCounter != this->testVectorCount) {
101 throw std::runtime_error(
"Unexpected number of test vectors detected in: " + testFilesDirectory + medicalRelevanceTestFile);
107 std::cout <<
"Finished pre-processing test data files." << std::endl;
134 for (
size_t i = 0; i < input.size(); ++i) {
143 if (decryptedValue >= 0) {
151 Hub::bitsSent +=
static_cast<unsigned long>(input[i].data.GetSize());
167 for (SecureSvm::EncryptedVector::const_iterator i = input.begin(); i != input.end(); ++i) {
180 bool uniqueMaximumValue =
true;
183 for (
size_t i = 1; i < input.size(); ++i) {
187 if (maximum == value) {
188 uniqueMaximumValue =
false;
190 else if (maximum < value) {
193 uniqueMaximumValue =
true;
204 for (SecureSvm::EncryptedVector::const_iterator i = input.begin(); i != input.end(); ++i) {
205 Hub::bitsSent +=
static_cast<unsigned long>((*i).data.GetSize());
220 for (
size_t i = 0; i < input.size(); ++i) {
228 Hub::bitsSent +=
static_cast<unsigned long>(input[i].data.GetSize());
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;
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;
265 std::cout <<
"Safety block: " << std::endl;
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;
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;
296 std::vector<Utils::CpuTimer::NanosecondType> durationVector;
311 for (
size_t j = 0; j < firstTwoBlocksPredictions.size(); ++j) {
313 Hub::bitsReceived +=
static_cast<unsigned long>(firstTwoBlocksPredictions[j].data.GetSize()) + static_cast<unsigned long>(safetyBlockPredictions[j].data.GetSize());
322 std::cout <<
"Done " << i + 1 <<
" of " << this->testVectorCount <<
" in " <<
Utils::CpuTimer::ToString(durationVector.back()) << std::endl;
326 std::cout <<
"Entire process duration: " << mainTimer.
ToString()<< std::endl;
334 if (minimum > durationVector[i]) minimum = durationVector[i];
335 if (maximum < durationVector[i]) maximum = durationVector[i];
338 std::cout <<
"Per test vector statistics: " << std::endl;
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;
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;
365 BigInteger totalBitsSent;
366 BigInteger totalBitsReceived;
375 Hub::bitsSent += static_cast<unsigned long>((*i).data.GetSize());
377 Hub::bitsSent += static_cast<unsigned long>((*i).data.GetSize());
379 Hub::bitsSent += static_cast<unsigned long>((*i).data.GetSize());
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());
390 std::cout <<
"Done " << i + 1 <<
" of " << this->testVectorCount <<
"; Bits sent: " <<
Hub::bitsSent.ToString(10) <<
"; Bits received: " <<
Hub::bitsReceived.ToString(10) << std::endl;
394 std::cout <<
"Total Bits sent: " << totalBitsSent.ToString(10) << std::endl;
395 std::cout <<
"Total Bits received: " << totalBitsReceived.ToString(10) << std::endl;
418 if (safetyTestFiles.empty()) {
420 throw std::runtime_error(
"No files found in directory: " + testFilesDirectory);
426 for (std::deque<std::string>::const_iterator fileIterator = safetyTestFiles.begin(); fileIterator != safetyTestFiles.end(); ++fileIterator) {
428 if (std::string::npos != (*fileIterator).find(safetyTestFilesPrefix)) {
432 std::vector<unsigned short> unsafeClasses;
433 for (
size_t i = (*fileIterator).find_last_not_of(
"0123456789") + 1; i < (*fileIterator).size(); ++i) {
435 unsafeClasses.emplace_back((*fileIterator)[i] -
'0');
437 std::sort(unsafeClasses.begin(), unsafeClasses.end());
440 std::stringstream unsafeClassesStream;
441 for (std::vector<unsigned short>::const_iterator unsafeClassesIterator = unsafeClasses.begin(); unsafeClassesIterator != unsafeClasses.end(); ++unsafeClassesIterator) {
442 unsafeClassesStream << *unsafeClassesIterator;
446 std::ifstream fileStream(testFilesDirectory + *fileIterator);
449 if (!fileStream.good()) {
451 throw std::runtime_error(
"Can't open the safety test file.");
455 unsigned int lineCounter = 0;
457 while (std::getline(fileStream, line)) {
465 throw std::runtime_error(
"Unexpected number of test vectors detected in: " + testFilesDirectory + *fileIterator);
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.");
491 std::string::size_type clQolDelimiter = line.find(
' ', clPosition);
492 std::string::size_type qolGenDelimiter = line.find(
' ', qolPosition);
494 if (std::string::npos == clQolDelimiter || std::string::npos == qolGenDelimiter) {
495 throw std::runtime_error(
"Labels should be delimited by a space character.");
499 std::istringstream clusterLabel(line.substr(clPosition + 3, clQolDelimiter));
501 std::istringstream qualityOfLifeLabel(line.substr(qolPosition + 4, qolGenDelimiter));
504 if (!clusterLabel || !qualityOfLifeLabel) {
505 throw std::runtime_error(
"Malformed labels detected in input file.");
508 unsigned short labelValue;
513 clusterLabel >> labelValue;
514 if (labelValue < 1 || labelValue > 5) {
515 throw std::runtime_error(
"Invalid cluster label.");
519 qualityOfLifeLabel >> labelValue;
521 if (labelValue > 6) {
522 throw std::runtime_error(
"Invalid quality of life label.");
528 std::vector<BigInteger> tempX;
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.");
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.");
544 std::istringstream attributeStream(line.substr(attributeValueStartPosition + 1, attributeDelimiterPosition - attributeValueStartPosition - 1));
546 if (!attributeStream) {
547 throw std::runtime_error(
"Invalid attribute value detected.");
554 attributeStream >> attribute;
561 attributeValueStartPosition = line.find(
':', attributeValueStartPosition + 1);
565 if (SecureSvm::inverseQuadraticRBF == this->
kernel || SecureSvm::homogeneousPolynomial == this->
kernel || SecureSvm::inhomogeneousPolynomial == this->
kernel) {
566 for (
unsigned int i = 0; i < tempX.size(); ++i) {
568 if (SecureSvm::homogeneousPolynomial == this->
kernel || SecureSvm::inhomogeneousPolynomial == this->
kernel) {
569 for (
unsigned int j = i; j < tempX.size(); ++j) {
576 if (SecureSvm::inverseQuadraticRBF == this->
kernel) {
584 if (SecureSvm::homogeneousPolynomial != this->
kernel) {
585 for (
unsigned int i = 0; i < tempX.size(); ++i) {
603 unsigned short output = 0;
606 for (
size_t i = 0; i < encryptedClusterVotes.size(); ++i) {
609 output =
static_cast<unsigned short>(i + 1);
626 std::vector<unsigned short> output;
627 for (std::vector<Paillier::Ciphertext>::const_iterator prediction = encryptedSafetyPredictions.begin(); prediction != encryptedSafetyPredictions.end(); ++prediction) {
642 unsigned int correctPredictions = 0;
648 return correctPredictions;
654 std::vector<std::string> safetyBlockSvmsUnsafeClasses = this->
server->GetSafetyBlockSvmsUnsafeClasses();
655 std::deque<std::string> safetyBlockSvmsModelFiles = this->
server->GetSafetyBlockModelFiles();
658 for (std::deque<std::string>::const_iterator modelFile = safetyBlockSvmsModelFiles.begin(); modelFile != safetyBlockSvmsModelFiles.end(); ++modelFile) {
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) {
669 if (std::string::npos != safetyBlockSvmsUnsafeClasses[svmIndex].find(safetyTestDataIterator->second.qualityOfLifeLabel) && 1 == this->predictedQualityOfLifeMatrix[testRowIndex][svmIndex]) {
673 else if (std::string::npos == safetyBlockSvmsUnsafeClasses[svmIndex].find(safetyTestDataIterator->second.qualityOfLifeLabel) && 0 == this->predictedQualityOfLifeMatrix[testRowIndex][svmIndex]) {
679 throw std::runtime_error(
"Missing safety test data for unsafe classes: " + safetyBlockSvmsUnsafeClasses[svmIndex]);
698 case SecureSvm::linear:
699 name =
"linear kernel";
701 case SecureSvm::homogeneousPolynomial:
702 name =
"homogeneous polynomial kernel";
704 case SecureSvm::inhomogeneousPolynomial:
705 name =
"inhomogeneous polynomial kernel";
707 case SecureSvm::inverseQuadraticRBF:
708 name =
"inverse quadratic RBF kernel";
712 throw std::runtime_error(
"Invalid kernel type.");
PaillierCiphertext Ciphertext
Provide public access to the T_Ciphertext type.
std::vector< Paillier::Ciphertext > EncryptedVector
Define a vector template specialization for vectors of encrypted data.
std::vector< TestDataRow > medicalRelevanceTestData
The medical relevance block test data.
Ciphertext GetEncryptedOne(const bool randomized=true) const
Returns [1].
unsigned int getMedicalRelevanceBlockCorrectPredictionCount() const
Computes the number of correct predictions of the medical relevance block.
Processed test data container.
std::vector< unsigned short > predictedClusters
The predicted clusters.
unsigned short getVotedCluster(const std::vector< Paillier::Ciphertext > &encryptedClusterVotes) const
Returns the cluster index, which corresponds to the maximum.
std::vector< std::vector< unsigned short > > predictedQualityOfLifeMatrix
Vector of predicted quality of life values (contains 0 for negative values and 1 for positive values)...
unsigned long testVectorCount
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.
virtual BigInteger DecryptInteger(const Ciphertext &ciphertext) const
Decrypt number.
void DoPerformanceAnalysis()
Execute the performance analysis of the system.
static Config & GetInstance()
Returns a reference to the singleton.
void EvaluateMaximum(SecureSvm::EncryptedVector &input) const
Secure maximum evaluation.
boost::timer::nanosecond_type NanosecondType
Nanosecond data type (int_least64_t)
SecureSvm::EncryptedVector x
Encrypted test data vector.
SecureSvm::KernelTypes kernel
The SVM kernel type. We want to pre-compute only the data that is necessary for a particular kernel...
virtual bool GenerateKeys()
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.
void SetServer(const std::shared_ptr< const Server > &server)
Sets a reference to the recommendations server.
static BigInteger bitsReceived
Counts the number of bits received from the server.
Paillier cryptoProvider
The crypto provider.
Utilitary class providing algorithm timing functionality.
void DebugValue(const Paillier::Ciphertext &value) const
Decrypts and prints an encrypted value.
std::string ToString() const
Returns the elapsed user process time as a formatted string (HH::MM::SS.mmm)
SecureSvm::EncryptedVector xSquared
Encrypted squared test data vector.
unsigned short clusterLabel
The expected cluster (use this for accuracy measures)
Hub()
Default constructor.
unsigned int attributeCount
The number of attributes in each test vector of the test data.
static BigInteger bitsSent
Counts the numbe of bits sent to the server.
static KernelTypes GetKernel(const std::string &input)
Converts the input string to the proper kernel.
void computeSafetyBlockFalsePredictions()
Computes the number of false negatives and false positives of the safety block.
char qualityOfLifeLabel
The quality of life measure (use this for accuracy measures)
BigInteger svWeightScaling
The scaling applied to the SVM parameters, and .
void DoAccuracyAnalysis()
Execute the accuracy analysis of the system.
std::map< std::string, unsigned int > safetyBlockFalsePositives
Vector containing number of false positives per safety SVM.
T GetParameter(const std::string ¶meter) const
Template method which returns the value of the specified configuration parameter. ...
static bool measureTraffic
Enables traffic profiling.
std::string getKernelName() const
Returns a string containing the name of the kernel specified in the configuration file...
NanosecondType GetDuration() const
Returns the elapsed user process time (in nanoseconds)
SecureSvm::EncryptedVector xx
Encrypted vector product combinations, , stored as an unraveled upper triangular matrix.
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...
std::shared_ptr< const Server > server
A reference to the recommendations server.
std::map< std::string, unsigned int > safetyBlockFalseNegatives
Vector containing number of false negatives per safety SVM.
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...
BigInteger featureScalingFactor
The scaling applied to the test and model vectors and .
const PaillierPublicKey & GetPublicKey() const
Returns a reference to the public key.
TestDataRow parseTestDataRow(const std::string &line) const
Extracts test data from a single line.
static std::string Now(const std::string &format="%H:%M:%S")
Returns the formatted current time.
void EvaluateDivision(const BigInteger &numerator, SecureSvm::EncryptedVector &input) const
Secure division evaluation.
static void resetTrafficCounters()
Resets the traffic counters.
The public key container structure for the Paillier cryptosystem.
void EvaluateSign(SecureSvm::EncryptedVector &input) const
Secure sign evaluation.
void loadSafetyTestData(const std::string &testFilesDirectory, const std::string &safetyTestFilesPrefix)
Populates the safetyTestData structure.