Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CKKS accuracy difference 16k vs 32k poly modulus #685

Open
meirgold opened this issue May 24, 2024 · 0 comments
Open

CKKS accuracy difference 16k vs 32k poly modulus #685

meirgold opened this issue May 24, 2024 · 0 comments

Comments

@meirgold
Copy link

meirgold commented May 24, 2024

Hi,

I'm working with the CKKS scheme to perform a calculation involving plaintexts and ciphertexts. It appears that there is a larger accuracy difference to the same cleartext calculations when using 32k vs 16k cyclotomic polynomial.
What could be the reason for it?

The encryption parameters are: scale=2^60, coefficient modulus: {60, 60, 60, 60, 60}.
I tested the calculation using 16k and 32k cyclotomic polynomial separately.
My SEAL version is 4.1.1.

The cleartext vs encrypted comparison results are:

testing poly modulus: 16384
enc result: 274895208699.0369873046875
cleartext result: 274895208699
diff: 0.0369873046875

testing poly modulus: 32768
enc result: 274895208700.9400634765625
cleartext result: 274895208699
diff: 1.9400634765625

The code:

void run_test_16_32_poly_1(int poly_modulus_degree)
{
    cout.precision(32);
    cout << "testing poly modulus: " << poly_modulus_degree << endl;
    EncryptionParameters parms(scheme_type::ckks);
    parms.set_poly_modulus_degree(poly_modulus_degree);
    parms.set_coeff_modulus(CoeffModulus::Create(poly_modulus_degree, { 60, 60, 60, 60, 60 }));


    double scale = pow(2.0, 60);

    // Create context
    SEALContext context(parms);

    // Create keys
    KeyGenerator keygen(context);
    seal::PublicKey public_key;
    keygen.create_public_key(public_key);
    SecretKey secret_key = keygen.secret_key();
    RelinKeys relin_keys;
    keygen.create_relin_keys(relin_keys);

    // Create encryptor, evaluator, decryptor
    Encryptor encryptor(context, public_key);
    Evaluator evaluator(context);
    Decryptor decryptor(context, secret_key);


    CKKSEncoder encoder(context);

    vector<double> result;

    double p = 524309;
    double p_square = p*p;

    double a = p-1;
    double u = 1;

// calculation
    Plaintext plain_u, plain_p_square, plain_a, plain_p_times_10, plain_result;
    Ciphertext encrypted_u, encrypted_a;

    encoder.encode(u, scale, plain_u);
    encryptor.encrypt(plain_u, encrypted_u);

    encoder.encode(p_square, scale, plain_p_square);

    evaluator.multiply_plain_inplace(encrypted_u, plain_p_square);
    evaluator.rescale_to_next_inplace(encrypted_u);
    encrypted_u.scale() = scale;


    encoder.encode(a, encrypted_u.parms_id(), encrypted_u.scale(), plain_a);
    encryptor.encrypt(plain_a, encrypted_a);

    evaluator.add_inplace(encrypted_u, encrypted_a);

    encoder.encode(p*10, encrypted_u.parms_id(), encrypted_u.scale(), plain_p_times_10);
    evaluator.sub_plain_inplace(encrypted_u, plain_p_times_10);

    decryptor.decrypt(encrypted_u, plain_result);
    encoder.decode(plain_result, result);

    double cleartext_calc = (u*p_square)+a-(p*10);


    cout << "result vec[0]: " << result[0] << endl;
    cout << "cleartext: " << cleartext_calc << endl;
    cout << "diff: " << result[0] - cleartext_calc << endl;
}

void test_16_32_poly(void)
{
    run_test_16_32_poly_1(16384);
    cout << endl;
    run_test_16_32_poly_1(32768);

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant