Выполните добавление к продукту, используя библиотеку SEAL
Я пытаюсь выполнить операцию в форме: (A * B) + C. Умножение работает нормально, так как все числа имеют одинаковую шкалу в этой точке, но произведение A * B имеет другую шкалу, чем C. Имеет смысл, что умножение изменит масштаб, но мне было интересно, есть ли способ выполнить такую операцию, используя библиотеку SEAL.
Информация об окружающей среде:
- Язык: C++
- Схема шифрования: CKKS
- Маленькие закодированные двойные числа (например, 0,4531)
- Шкала, используемая для кодирования: pow(2.0, 60) как в примере
Заранее спасибо и дайте мне знать, если потребуется дополнительная информация.
1 ответ
Решение
Есть несколько способов заставить это работать. Например, предположим, что все шифротексты A, B, C имеют одинаковый масштаб Z. Тогда A * B будет иметь масштаб Z^2. На этом этапе вам следует также перераспределить A * B, если у вас нет веских причин не делать этого.
Например, для вычисления A * B + C вы можете:
- перекодировать C (если у вас есть открытый текст) со шкалой Z ^ 2 и использовать его вместо этого;
- использование
multiply_plain
умножить C на скалярный открытый текст 1,0 со шкалой Z, чтобы увеличить масштаб до Z ^ 2, но сохранить значение таким же (существует перегрузка дляCKKSEncoder::encode
за это); - сначала измените масштаб A * B, чтобы он имел масштаб Z^2/q_k, где q_k - последнее простое число в
coeff_modulus
, Теперь вы можете перекодировать C, чтобы иметь масштаб точно Z^2/q_k (если у вас есть открытый текст), или умножить C на скалярный текст 1.0, как объяснено выше, чтобы изменить масштаб точно на Z^2/q_k; - если Z близко к q_k, так что Z^2/q_k ~ Z, то после изменения масштаба вы можете просто использовать
double &Ciphertext::scale()
чтобы установить шкалу A * B точноC.scale()
за счет небольшой мультипликативной ошибки ~ Z/q_k. Например, вместо шкалы 2^60 для A, B, C вы можете использоватьstatic_cast<double>(parms.coeff_modulus().back())
, Тогда Z^2/q_k = Z (точно), и сложение работает сразу без переключения шкалы. Конечно, это уже не так хорошо работает после второго умножения + масштабирования, так как число от второго до последнего больше не может быть равно Z (все простые числа вcoeff_modulus
должно быть отчетливым).