I’m experimenting with the FHEW scheme after switching from CKKS in OpenFHE-Python (running inside a Docker environment). I followed the context creation steps as shown in the scheme-switching.py example.
However, when running the function for finding the maximum value and its index (argmax), the outputs vary significantly between runs. Sometimes, the function works with 100% accuracy, and other times, it gives completely incorrect results.
Example of Two Consecutive Runs
Run 1 (Correct Result)
vecA:
[-74.0, 8.0, 7.0, -80.0, 15.0, -41.0, 100.0, -29.0]
Expected maximum value 100.0 at location 6
ctx_maximum: 100.0
Argmax: 6
Run 2 (Incorrect Result):
vecA:
[-92.0, 1.0, 47.0, 37.0, 99.0, 25.0, -77.0, 2.0]
Expected maximum value 99.0 at location 4
ctx_maximum: -92.0
Argmax: 0
Here’s the code I’m using:
from openfhe import *
import random
from math import log2
# region - Set CryptoContext
parameters = CCParamsCKKSRNS()
if get_native_int() == 128:
rescaleTech = ScalingTechnique.FLEXIBLEAUTOEXT
dcrtBits = 78
firstMod = 89
else:
rescaleTech = ScalingTechnique.FLEXIBLEAUTOEXT
dcrtBits = 59
firstMod = 60
dim = 2**3
batch_size = 2**3
sec_lvl = SecurityLevel.HEStd_NotSet
ringDim = pow(2, 10)
sec_lvl_Bin = TOY
secretKeyDist = SecretKeyDist.UNIFORM_TERNARY
slots = batch_size
numValues = dim
parameters.SetScalingModSize(dcrtBits)
parameters.SetFirstModSize(firstMod)
parameters.SetScalingTechnique(rescaleTech)
parameters.SetNumLargeDigits(3)
parameters.SetSecretKeyDist(secretKeyDist)
parameters.SetSecurityLevel(sec_lvl)
parameters.SetRingDim(ringDim)
parameters.SetBatchSize(batch_size)
# NOTE: Multiplicative Depth = 12 (scheme switch comparison) + 1 (extra) + log2(numValues) for argmax
multDepth = 13 + int(log2(numValues))
parameters.SetMultiplicativeDepth(multDepth)
cryptocontext = GenCryptoContext(parameters)
cryptocontext.Enable(PKESchemeFeature.PKE)
cryptocontext.Enable(PKESchemeFeature.KEYSWITCH)
cryptocontext.Enable(PKESchemeFeature.LEVELEDSHE)
cryptocontext.Enable(PKESchemeFeature.ADVANCEDSHE)
cryptocontext.Enable(PKESchemeFeature.SCHEMESWITCH)
# endregion
# region - Key Generation
keys = cryptocontext.KeyGen()
cryptocontext.EvalMultKeyGen(keys.secretKey)
# endregion
# region - FHEW Env Creation
params = SchSwchParams()
logQ_ccLWE = 25
params.SetSecurityLevelCKKS(sec_lvl)
params.SetSecurityLevelFHEW(sec_lvl_Bin)
params.SetCtxtModSizeFHEWLargePrec(logQ_ccLWE)
params.SetNumSlotsCKKS(slots)
params.SetNumValues(numValues)
privateKeyFHEW = cryptocontext.EvalSchemeSwitchingSetup(params)
ccLWE = cryptocontext.GetBinCCForSchemeSwitch()
cryptocontext.EvalSchemeSwitchingKeyGen(keys, privateKeyFHEW)
scaleSign = 512
modulus_LWE = 1 << logQ_ccLWE
beta = ccLWE.GetBeta()
pLWE = int(modulus_LWE / (2 * beta)) # Large precision
cryptocontext.EvalCompareSwitchPrecompute(pLWE, scaleSign)
# endregion
# region - PTX Generation
vecA = [random.randint(-100, 100) / 1.0 for i in range(dim)]
print(f"vecA:\n{vecA}")
actual_max = max(vecA)
actual_argmax = vecA.index(max(vecA))
# endregion
# region - Packing & Encryption
ptx_A = cryptocontext.MakeCKKSPackedPlaintext(vecA)
ctx_A = cryptocontext.Encrypt(keys.publicKey, ptx_A)
# endregion
# region - Detailed Functions Evaluations
ctx_result = cryptocontext.EvalMaxSchemeSwitching(
ctx_A,
keys.publicKey,
numValues,
slots,
)
ctx_maximum = ctx_result[0]
ctx_argmax = ctx_result[1]
# endregion
# region - Results Decryption & Clear Evaluation
ptxtMax = cryptocontext.Decrypt(keys.secretKey, ctx_maximum)
ptxtMax.SetLength(1)
res_vec = ptxtMax.GetRealPackedValue()
max_res = round(res_vec[0], 2)
oneHot_ptxtMax = cryptocontext.Decrypt(keys.secretKey, ctx_argmax)
oneHot_ptxtMax.SetLength(numValues)
oneHot_res_vec = oneHot_ptxtMax.GetRealPackedValue()
oneHot_res_vec = [round(val, 2) for val in oneHot_res_vec]
argmax_res = oneHot_res_vec.index(max(oneHot_res_vec))
print("Expected maximum value ", actual_max, " at location ", actual_argmax)
print("ctx_maximum: ", max_res)
print("Argmax: ", argmax_res)
# endregion
- Sometimes the function correctly returns the maximum value and its index, while other times it returns completely incorrect results.
- Since I’m using FHEW after switching from CKKS, could there be a problem with the context setup?
Would appreciate any insights or suggestions