Hello,
I’m trying to run the following simple program in CKKS, it’s similar to the code in advanced-ckks-bootstrapping.cpp. I’m using WSL on Windows and the program compiles. But when I run it, it prints “CKKS scheme is using ring dimension 131072”, then the program crashes, printing “killed”. I tried to change the values of levelsBudget and levelsAvailableAfterBootstrap, but the program causes the terminal to crash and terminates!
Thanks in advance
#include "openfhe.h"
#include <assert.h>
using namespace lbcrypto;
using namespace std;
void test_additions(int num_additions) {
CCParams<CryptoContextCKKSRNS> parameters;
SecretKeyDist secretKeyDist = UNIFORM_TERNARY;
parameters.SetSecretKeyDist(secretKeyDist);
parameters.SetSecurityLevel(HEStd_128_classic);
#if NATIVEINT == 128
ScalingTechnique rescaleTech = FIXEDAUTO;
usint dcrtBits = 78;
usint firstMod = 89;
#else
ScalingTechnique rescaleTech = FLEXIBLEAUTO;
usint dcrtBits = 59;
usint firstMod = 60;
#endif
parameters.SetScalingModSize(dcrtBits);
parameters.SetScalingTechnique(rescaleTech);
parameters.SetFirstModSize(firstMod);
std::vector<uint32_t> levelBudget = {4, 4};
uint32_t levelsAvailableAfterBootstrap = 10;
usint depth = levelsAvailableAfterBootstrap + FHECKKSRNS::GetBootstrapDepth(levelBudget, secretKeyDist);
parameters.SetMultiplicativeDepth(depth);
cout << depth << endl;
CryptoContext<DCRTPoly> cryptoContext = GenCryptoContext(parameters);
cryptoContext->Enable(PKE);
cryptoContext->Enable(KEYSWITCH);
cryptoContext->Enable(LEVELEDSHE);
cryptoContext->Enable(ADVANCEDSHE);
cryptoContext->Enable(FHE);
usint ringDim = cryptoContext->GetRingDimension();
// This is the maximum number of slots that can be used for full packing.
usint numSlots = ringDim / 2;
cout << "CKKS scheme is using ring dimension " << ringDim << endl << endl;
cryptoContext->EvalBootstrapSetup(levelBudget);
auto keyPair = cryptoContext->KeyGen();
cryptoContext->EvalMultKeyGen(keyPair.secretKey);
cryptoContext->EvalBootstrapKeyGen(keyPair.secretKey, numSlots);
vector<double> x1 = {0.25, 0.5, 0.75, 1.0, 2.0, 3.0, 4.0, 5.0};
vector<double> y1 = {0.25, 0.5, 0.75, 1.0, 2.0, 3.0, 4.0, 5.0};
vector<double> x2 = {0.25, 0.5, 0.75, 1.0, 2.0, 3.0, 4.0, 5.0};
vector<double> y2 = {0.25, 0.5, 0.75, 1.0, 2.0, 3.0, 4.0, 5.0};
size_t encodedLength = x1.size();
cout << "1" << endl;
// We start with a depleted ciphertext that has used up all of its levels.
Plaintext ptxt1 = cryptoContext->MakeCKKSPackedPlaintext(x1,1, 0, nullptr, numSlots);
Plaintext ptxt2 = cryptoContext->MakeCKKSPackedPlaintext(y1,1, 0, nullptr, numSlots);
Plaintext ptxt3 = cryptoContext->MakeCKKSPackedPlaintext(x2,1, 0, nullptr, numSlots);
Plaintext ptxt4 = cryptoContext->MakeCKKSPackedPlaintext(y2,1, 0, nullptr, numSlots);
ptxt1->SetLength(encodedLength);
ptxt2->SetLength(encodedLength);
cout << "Input 1: " << ptxt1 << endl;
cout << "Input 2: " << ptxt2 << endl;
ptxt3->SetLength(encodedLength);
ptxt4->SetLength(encodedLength);
cout << "Input 3: " << ptxt3 << endl;
cout << "Input 4: " << ptxt4 << endl;
Ciphertext<DCRTPoly> ciph1 = cryptoContext->Encrypt(keyPair.publicKey, ptxt1);
Ciphertext<DCRTPoly> ciph2 = cryptoContext->Encrypt(keyPair.publicKey, ptxt2);
Ciphertext<DCRTPoly> ciph3 = cryptoContext->Encrypt(keyPair.publicKey, ptxt3);
Ciphertext<DCRTPoly> ciph4 = cryptoContext->Encrypt(keyPair.publicKey, ptxt4);
cout << "Initial number of levels remaining 1: " << depth - ciph1->GetLevel() << endl;
cout << "Initial number of levels remaining 2: " << depth - ciph2->GetLevel() << endl;
cout << "Initial number of levels remaining 3: " << depth - ciph3->GetLevel() << endl;
cout << "Initial number of levels remaining 4: " << depth - ciph4->GetLevel() << endl;
auto start = chrono::high_resolution_clock::now();
auto res1 = cryptoContext->EvalAdd(ciph1, ciph2);
auto res2 = cryptoContext->EvalAdd(ciph3, ciph4);
// auto res3 = cryptoContext->EvalAdd(res1, res2);
//
// for (int i = 1; i < num_additions; i++) {
// res3 = cryptoContext->EvalAdd(res3, res3);
// }
auto end = chrono::high_resolution_clock::now();
// Perform the bootstrapping operation. The goal is to increase the number of levels remaining
// for HE computation.
// auto ciphertextAfter = cryptoContext->EvalBootstrap(res3);
//
// res3 = cryptoContext->EvalAdd(ciphertextAfter, ciphertextAfter);
// res3 = cryptoContext->EvalAdd(res3, res3);
cout << "Number of levels remaining after bootstrapping: "
<< depth - res1->GetLevel() - (res1->GetNoiseScaleDeg() - 1) << endl
<< endl;
cout << "Level: " << res1->GetLevel() << endl << endl;
cout << "Noise Scale log: " << res1->GetNoiseScaleDeg() << endl << endl;
cout << "Hop Level: " << res1->GetHopLevel() << endl << endl;
cout << "Scaling factor: " << res1->GetScalingFactor() << endl << endl;
cout << "Scaling factor int: " << res1->GetScalingFactorInt() << endl << endl;
cout << "last number of levels remaining: " << depth - res1->GetLevel() << std::endl;
Plaintext result;
cryptoContext->Decrypt(keyPair.secretKey, res1, &result);
result->SetLength(encodedLength);
cout << "Duration: " << chrono::duration_cast<chrono::milliseconds>(end - start).count() << "ms" << endl;
vector<double> true_res;
for (long unsigned int j = 0; j < x1.size(); j++) {
auto tmp1 = x1[j] + y1[j];
auto tmp2 = x2[j] + y2[j];
auto tmp3 = tmp1 + tmp2;
for (int i = 1; i < num_additions; i++) {
tmp3 = tmp3 + tmp3;
}
true_res.push_back(tmp3);
}
cout << "Output after bootstrapping \n\t" << result << endl;
cout << "true result: " << true_res << endl;
}
int main(int argc, char* argv[]) {
test_additions(1);
}