How does function AdjustCiphertext work?

Hi,

I am trying to learn the bootstrapping procedure, and would like to learn what does AdjustCiphertext in bootstrapping procedure do, especially the adjustmentFactor = (targetSF / sourceSF) * (modToDrop / sourceSF) * std::pow(2, -correction);
I understand there is an scaling ( std::pow(2, -correction) before the bs starts and after it ends, but what does the (targetSF / sourceSF) * (modToDrop / sourceSF) do?

Great thanks for your help!

I suggest checking the paper “Approximate Homomorphic Encryption with Reduced Approximation Error” by Kim et al. It proposes that to avoid the approximate rescaling error in CKKS, we can keep a scale factor (SF) table that holds the SF of each different level corresponding to its RNS modulus. AdjustCiphertext is a method to match the SFs when the input to the Add or Mult operation are two ciphertexts having different levels. When that happens, the one with more #levels is reduced to the SF of the smaller one. Section 4.1 of the paper provides more details.
modToDrop stems from the method proposed in the same paper to increase the precision by increasing the first-level ct modulus q0. You can check Section 3.2 of the same paper.

Thanks for your reply. And i am still a little confused.

I still dont understand why the sourceFactor is divided by twice, and in normal case do i need to multiply modTodrop every times?

Say the current level is 1, and the noisedeg is 1 as well. If i want to drop three limbs of the ciphertext, and keep the noisedeg=1, how should i set the factors(i.e. what adjustment factor should i multiply to)? Is it correct if i do the operation in sequence {mult(adjustment_factor), level reduce(#To_drop -1), and mod reduce?

We do each step of scaling with 2 scales, so at the first adjustment we scale by (target/source) and in the second we scale by (modToDrop/source). These steps are explained in the first paragraph of page 18. If you print out the values, you will get results like this:

Added the following print statements to Adjust Ciphertext:

        std::cout << std::fixed << std::setprecision(0);
        std::cout << "targetSF: " << targetSF << std::endl;
        std::cout << "sourceSF: " << sourceSF << std::endl;
        std::cout << "modToDrop: " << modToDrop << std::endl;
        std::cout << std::fixed << std::setprecision(20);
        std::cout << "targetSF/sourceSF: " << (double)(targetSF/sourceSF) << std::endl;
        std::cout << "modToDrop/sourceSF: " <<(double) (modToDrop/sourceSF) << std::endl;

Output of running bootstrapping example:

targetSF: 576460752303439872
sourceSF: 576460752297730048
modToDrop: 576460752297492480
targetSF/sourceSF: 1.00000000000990496574
modToDrop/sourceSF: 0.99999999999958788521

For your second question, do you mean, with a level of 1, you will run EvalBootstrap() first and then reduce 3 limbs? Otherwise, you cannot consume 3 levels with a level budget of 1. In EvalBootstrap, the adjustment factor depends on several parameters you set in your script. Have you tried looking at those and their impact on the adjustment factor?

I understand! Great thanks for your help!

1 Like