Incorrect result when using big numbers in CKKS

Hello, OpenFHE Team!

I have been conducting tests related to the approximation error of the CKKS scheme in the OpenFHE library. However, I encountered inaccurate results with the following code, and I would like to ask whether this is a bug or intended behavior:

int main() {
    CCParams<CryptoContextCKKSRNS> parameters;
    parameters.SetMultiplicativeDepth(2);
    parameters.SetScalingTechnique(FLEXIBLEAUTO);

    CryptoContext<DCRTPoly> cc = GenCryptoContext(parameters);

    cc->Enable(PKE);
    cc->Enable(LEVELEDSHE);

    auto keys = cc->KeyGen();

    cc->EvalMultKeyGen(keys.secretKey);

    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_real_distribution<> dis(-10000, 10000);

    std::vector<double> x1;
    std::vector<double> x2;
    for (int i = 0; i < 10; ++i) {
        x1.push_back(dis(gen));
    }

    for (int i = 0; i < 10; ++i) {
        x2.push_back(2);
    }

    Plaintext ptxt = cc->MakeCKKSPackedPlaintext(x1);
    Plaintext two = cc->MakeCKKSPackedPlaintext(x2);

    auto c = cc->Encrypt(keys.publicKey, ptxt);
    auto c2 = c;

    c2 = cc->EvalMult(c,two);
    c = cc->EvalSub(c2, c);

    c2 = cc->EvalMult(c,two);
    c = cc->EvalSub(c2, c);

    auto ctxtResult = c;
    Plaintext ptxtResult;
    cc->Decrypt(keys.secretKey, ctxtResult, &ptxtResult);
    ptxtResult->SetLength(10);

    std::vector<std::complex<double>> ptxtVector = ptxt->GetCKKSPackedValue();
    std::vector<std::complex<double>> ptxtResultVector = ptxtResult->GetCKKSPackedValue();
    std::cout << "ptxt: " << ptxt->GetCKKSPackedValue() << std::endl;
    std::cout << "ptxtResult: " << ptxtResult->GetCKKSPackedValue() << std::endl;
    return 0;
}

The result of the above code is:

ptxt: [ (-4518.65,0) (-6672.61,0) (8182.46,0) (4077.88,0) (4919.93,0) (7687.54,0) (-6666.36,0) (-9725.97,0) (-213.667,0) (8150.64,0) ]
ptxtResult: [ (-101.752,0) (-58.4617,0) (-15.5489,0) (49.0504,0) (-35.0718,0) (-103.309,0) (-100.685,0) (-172.045,0) (58.4681,0) (-21.6191,0) ]

,which seems to me weird because Dec(c) (= ptxtResult) must be very close to ptxt value.

Additional Info:
When I change MultiplicativeDepth(1), it throws error The decryption failed because the approximation error is too high. Check the parameters.
For MultiplicativeDepth(3), ptxt and ptxtResult are very close, with negligible errors.

The maximum message size is determined by the ratio of firstModSize to scalingModSize. By default, they are set to 60 and 59 (for bootstrapping). To fix the problem, you should set the scaling mod size to a smaller number, e.g., 40. In general, we try to work with numbers close to 1.0 in CKKS, especially in bootstrapping scenarios.

2 Likes