Huelse / SEAL-Python

Microsoft SEAL 4.X For Python
MIT License
310 stars 66 forks source link

Precision for operations in CKKS #48

Closed pandasamanvaya closed 3 years ago

pandasamanvaya commented 3 years ago

I am trying to multiply a small constant(of order e-04) with a variable x.

        a = Plaintext()
    b = Plaintext()
    temp = Plaintext()
    encoder.encode(-1.11308404e-04, scale, a)
    encoder.encode(1.17652073e-01, scale, b)
    encoder.encode(x, scale, temp)
    X = Ciphertext()
    encryptor.encrypt(temp, X)
    evaluator.multiply_plain_inplace(X, a)
    evaluator.mod_switch_to_inplace(b, X.parms_id())
    X.scale(scale)
    evaluator.add_plain_inplace(X, b)

But when I perform this, I get the following error:-

evaluator.multiply_plain_inplace(X, a)
RuntimeError: result ciphertext is transparent

Changing e-04 to e-03 works fine. So, what is the amount of precision allowed in CKKS? Or can it be changed?

Huelse commented 3 years ago

It depends on: parms.set_coeff_modulus(CoeffModulus.Create(poly_modulus_degree, [60, 40, 40, 60])). If poly_modulus_degree higher, the CoeffModulus.MaxBitCount(poly_modulus_degree) will be bigger, but the sum of [60, 40, 40, 60] should be the same or smaller than the MaxBitCount, and the size of keys and ciphers will be bigger and the delay will be higher.

In summary: the precision of number <- CoeffModulus(like 60, 40, 30...) <- poly_modulus_degree precision <-> speed and keys' size

pandasamanvaya commented 3 years ago

So, if I want to use constants of order 1e-5(without getting error), what kind of parameters should I use? Could you suggest some?

pandasamanvaya commented 3 years ago

I guess scale determines the amount of precision(1/scale of precision). If you use scale = 2^10, you could use numbers of order 1e-3 where as if you use scale = 2^40, you could use numbers of the order 1e-13.

kumarm17 commented 1 year ago

Hi @Huelse, I tried to run https://github.com/Huelse/SEAL-Python/blob/main/examples/matrix_operations.py file after some minor changes and I am getting same error : evaluator.multiply_plain(temp_rot, plain_diags[0], temp) RuntimeError: result ciphertext is transparent. matrix_operation.txt

Huelse commented 1 year ago

@Mishra1992 For security, the SEAL does not support pure zero vector, refer to is_transparent().

kumarm17 commented 1 year ago

Thank you so much for quick response @Huelse.

  1. Is there any way to disable it ?
  2. Since you have already added 0.00000001 so it is not pure zero vector but still getting transparent ciphertext error.
  3. Any suggestion to resolve this issue.
Huelse commented 1 year ago

@Mishra1992 disable it by passing -DSEAL_THROW_ON_TRANSPARENT_CIPHERTEXT=OFF when configuring SEAL through CMake, or evaluate in pure ciphertext.