Number of tower in CKKS FIXEDMANUAL

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!