I tried to print the number of towers of c (fresh ciphertext) in the example code advanced-real-numbers.cpp. The code set the multiplicative depth = 5, so I expected I would get the number of towers = 6, but it turns out I got 7. So does it mean that in FIXEDMANUAL OpenFHE, an auxiliary tower is also implemented? Is there a way to use FIXEDMANUAL without an auxiliary tower?
Please share a minimum working example so we can help you better. Also, share the logic you use to count the number of towers.
In FIXEDMANUAL
, FIXEDAUTO
, or FLEXIBLEAUTO
modes, the number of the primary towers in the ciphertext modulus equals multiplicative_depth + 1
. Only in the FLEXIBLEAUTOEXT
mode (the default scaling mode in the OpenFHE implementation of CKKS), the number of towers will be multiplicative_depth + 2
.
I think you are using the default scaling technique or not counting the towers correctly.
I use the original advanced-real-numbers.cpp
in /src/pke/examples
. Then add this function:
void printCPinfo(Ciphertext<DCRTPoly>& c1){
std::cout << "CIPHERTEXT size: " << c1->GetElements().size() << " x " << c1->GetElements()[0].GetAllElements().size() << " x " << c1->GetElements()[0].GetAllElements()[0].GetValues().GetLength() << std::endl;
}
I called it inside ManualRescaleDemo
:
void ManualRescaleDemo(ScalingTechnique scalTech) {
...
printCPinfo(c);
auto c2_depth2 = cc->EvalMult(c, c);
auto c2_depth1 = cc->Rescale(c2_depth2);
it prints:
...
CIPHERTEXT size: 2 x 7 x 32768
...
That example uses multiple scaling techniques, see below. You may be confusing them.
AutomaticRescaleDemo(FLEXIBLEAUTO);
// default
AutomaticRescaleDemo(FLEXIBLEAUTOEXT);
AutomaticRescaleDemo(FIXEDAUTO);
ManualRescaleDemo(FIXEDMANUAL);
Can you use a simpler example like “simple-real-numbers.cpp” and specify the scaling technique explicitly via:
parameters.SetScalingTechnique(ScalingTechnique::FIXEDMANUAL);
Hmm… I tried to remove everything from the codes. Here is my full code (~45 lines) by deleting some unnecessary parts from advanced-real-numbers.cpp:
#define PROFILE
#include "openfhe.h"
using namespace lbcrypto;
void ManualRescaleDemo(ScalingTechnique scalTech);
void printCPinfo(Ciphertext<DCRTPoly>& c1){
std::cout << "CIPHERTEXT size: " << c1->GetElements().size() << " x " << c1->GetElements()[0].GetAllElements().size() << " x " << c1->GetElements()[0].GetAllElements()[0].GetValues().GetLength() << std::endl;
}
int main(int argc, char* argv[]) {
ManualRescaleDemo(FIXEDMANUAL);
return 0;
}
void ManualRescaleDemo(ScalingTechnique scalTech) {
std::cout << "\n\n\n ===== FixedManualDemo ============= " << std::endl;
uint32_t batchSize = 8;
CCParams<CryptoContextCKKSRNS> parameters;
parameters.SetMultiplicativeDepth(5);
parameters.SetScalingModSize(50);
parameters.SetBatchSize(batchSize);
CryptoContext<DCRTPoly> cc = GenCryptoContext(parameters);
std::cout << "CKKS scheme is using ring dimension " << cc->GetRingDimension() << std::endl << std::endl;
cc->Enable(PKE);
cc->Enable(KEYSWITCH);
cc->Enable(LEVELEDSHE);
auto keys = cc->KeyGen();
cc->EvalMultKeyGen(keys.secretKey);
// Input
std::vector<double> x = {1.0, 1.01, 1.02, 1.03, 1.04, 1.05, 1.06, 1.07};
Plaintext ptxt = cc->MakeCKKSPackedPlaintext(x);
std::cout << "Input x: " << ptxt << std::endl;
auto c = cc->Encrypt(keys.publicKey, ptxt);
printCPinfo(c);
}
Output:
===== FixedManualDemo =============
CKKS scheme is using ring dimension 32768
Input x: (1, 1.01, 1.02, 1.03, 1.04, 1.05, 1.06, 1.07, ... ); Estimated precision: 50 bits
CIPHERTEXT size: 2 x 7 x 32768
I save it as a different file, and call it in CMakeList:
add_executable( adv-debug adv-debug.cpp )
Oh, I found it! There is no parameters.SetScalingTechnique(scalTech);
in ManualRescaleDemo()
in the example code. So it runs with the default scaling technique, FLEXIBLEAUTOEXT
I think I will make an issue/pull request for this! Thank you!