Euclidean Distance
Hello,
I am writing a code to calculate the Euclidean distance between two vectors, where both of them are encrypted. and I have yet to master SEAL, so I have some questions.
-
what I did so far is the subtraction and the squaring, however, for the summation I am using
evaluator.add_manywhich is supposed to accept a vector as a first argument and a destination on the second. the squaring result is declared as aCiphertext, I get "cannot convert argument 1 from Ciphertext to vector", then when I try to declare it as a vector theevaluator.squaredoesn't work because of the expected input datatypes. How can I useadd_many? .... I tried to convert all of the ciphertexts tovector<Ciphertext>but it caused an error to the header file. -
The square root was mentioned in a talk that it could be approximated. would using the power function suffices?
I am attaching the code in hopes that it would shed the light on what's wrong
void testDistance() {
EncryptionParameters parms(scheme_type::bfv);;
size_t poly_modulus_degree = 8192;
parms.set_poly_modulus_degree(poly_modulus_degree);
parms.set_coeff_modulus(CoeffModulus::BFVDefault(poly_modulus_degree));
parms.set_plain_modulus(PlainModulus::Batching(poly_modulus_degree, 50));
SEALContext context(parms);
print_parameters(context);
cout << endl;
auto qualifiers = context.first_context_data()->qualifiers();
cout << "Batching enabled: " << boolalpha << qualifiers.using_batching << endl;
KeyGenerator keygen(context);
SecretKey secret_key = keygen.secret_key();
PublicKey public_key;
keygen.create_public_key(public_key);
Encryptor encryptor(context, public_key);
Evaluator evaluator(context);
Decryptor decryptor(context, secret_key);
BatchEncoder batch_encoder(context);
size_t slot_count = batch_encoder.slot_count();
size_t row_size = slot_count / 2;
cout << "Plaintext vector row size: " << row_size << endl;
vector<int64_t> x_vector(slot_count, 0ULL);
x_vector[0] = 1;
x_vector[1] = 2;
x_vector[2] = 3;
x_vector[3] = 4;
x_vector[4] = 5;
x_vector[5] = 6;
x_vector[6] = 7;
cout << "x plaintext vector: " << endl;
print_matrix(x_vector, row_size);
Plaintext x_plain_vector;
print_line(__LINE__);
cout << "Encode plaintext x vector: " << endl;
batch_encoder.encode(x_vector, x_plain_vector);
Ciphertext x_encrypted_vector;
cout << "Encrypt plain_vector x to encrypted_vector." << endl;
Stopwatch sw("Encryption Time");
encryptor.encrypt(x_plain_vector, x_encrypted_vector);
cout << " + Noise budget in encrypted_matrix: " << decryptor.invariant_noise_budget(x_encrypted_vector) << " bits"
<< endl;
vector<int64_t> y_vector(slot_count, 0ULL);
y_vector[0] = 7;
y_vector[1] = 6;
y_vector[2] = 5;
y_vector[3] = 4;
y_vector[4] = 3;
y_vector[5] = 2;
y_vector[6] = 1;
cout << "y plaintext vector:" << endl;
print_matrix(y_vector, row_size);
Plaintext y_plain_vector;
cout << "Encode plaintext y vector:" << endl;
batch_encoder.encode(y_vector, y_plain_vector);
Ciphertext y_encrypted_vector;
Ciphertext squared;
Ciphertext subtracted;
encryptor.encrypt(y_plain_vector, y_encrypted_vector);
cout << " + Noise budget in encrypted_matrix: " << decryptor.invariant_noise_budget(y_encrypted_vector) << " bits"
<< endl;
cout << "Encrypt plain_vector y to encrypted_vector." << endl;
evaluator.sub(x_encrypted_vector, y_encrypted_vector, subtracted);
evaluator.square(subtracted, squared);
Ciphertext addition;
/* Here I am supposed to use add_many for addition*/
//evaluator.add_many(squared, addition);
// Decrypt the result
Plaintext x_plain_result;
decryptor.decrypt(addition, x_plain_result);
vector <uint64_t> pod_result;
cout << " + Decode plaintext matrix ...... Correct." << endl;
batch_encoder.decode(x_plain_result, pod_result);
for (int i = 0; i < 7; i++) {
cout << pod_result[i] << endl;
}
}
Thank you in advance.
Don't use add_many if you have a single Ciphertext then.
would using the power function suffices?
What do you mean by the power function?
Thank you Mr. @WeiDaiWD for taking the time to answer my question, I understand I am asking questions coming from inexperience.
Don't use add_many if you have a single Ciphertext then.
I used rotate rows and and then I added it to the first cell of a copied squared ciphertext. I kept rotating and adding.
What do you mean by the power function?
As for the power function, I keep thinking of alternative ways to approximately calculate a root but I am not sure what would work in an encrypted domain, what I meant by power function is to use the power to scale down a ciphertext's plaintext value. Or maybe multiplying it with a constant that could result in a number close to the expected. However, I am not sure how to do the approximation as these two vectors should represent image features and I am not confident that the result won't be too tailored for some and doesn't work on others.