Browse Source

Fix for v1.1.3/4 (#116)

* Updated API for EvalAuomorphismKeyGen

* compilation based on v1.1.3 is now working

* initial fixing for the python example for scheme switching

* fixed all scheme switching examples

---------

Co-authored-by: Yuriy Polyakov <ypolyakod@dualitytech.com>
yspolyakov 9 months ago
parent
commit
f09bb66dfd

+ 1 - 1
CMakeLists.txt

@@ -10,7 +10,7 @@ set(OPENFHE_PYTHON_VERSION ${OPENFHE_PYTHON_VERSION_MAJOR}.${OPENFHE_PYTHON_VERS
 set(CMAKE_CXX_STANDARD 17)
 option( BUILD_STATIC "Set to ON to include static versions of the library" OFF)
 
-find_package(OpenFHE 1.1.2 EXACT REQUIRED)
+find_package(OpenFHE 1.1.2 REQUIRED)
 find_package(pybind11 REQUIRED)
 
 set( CMAKE_CXX_FLAGS ${OpenFHE_CXX_FLAGS} )

+ 134 - 120
examples/pke/scheme-switching.py

@@ -5,13 +5,13 @@ def main():
     SwitchCKKSToFHEW()
     SwitchFHEWtoCKKS()
     FloorViaSchemeSwitching()
-    # FuncViaSchemeSwitching()
-    # PolyViaSchemeSwitching()
+    FuncViaSchemeSwitching()
+    PolyViaSchemeSwitching()
     ComparisonViaSchemeSwitching()
     ArgminViaSchemeSwitching()
     ArgminViaSchemeSwitchingAlt()
-    #ArgminViaSchemeSwitchingUnit()
-    #ArgminViaSchemeSwitchingAltUnit()
+    ArgminViaSchemeSwitchingUnit()
+    ArgminViaSchemeSwitchingAltUnit()
 
 def SwitchCKKSToFHEW():
 
@@ -57,9 +57,18 @@ def SwitchCKKSToFHEW():
     keys = cc.KeyGen()
 
     # Step 2: Prepare the FHEW cryptocontext and keys for FHEW and scheme switching
-    FHEWparams     = cc.EvalCKKStoFHEWSetup(sl, slBin, False, logQ_ccLWE, False, slots)
-    ccLWE          = FHEWparams[0]
-    privateKeyFHEW = FHEWparams[1]
+    # FHEWparams     = cc.EvalCKKStoFHEWSetup(sl, slBin, False, logQ_ccLWE, False, slots)    
+    params = SchSwchParams()
+    params.SetSecurityLevelCKKS(sl)
+    params.SetSecurityLevelFHEW(slBin)
+    params.SetCtxtModSizeFHEWLargePrec(logQ_ccLWE)
+    params.SetNumSlotsCKKS(slots)
+    
+    privateKeyFHEW = cc.EvalCKKStoFHEWSetup(params)
+    ccLWE = cc.GetBinCCForSchemeSwitch()
+    
+    # ccLWE          = FHEWparams[0]
+    # privateKeyFHEW = FHEWparams[1]
     cc.EvalCKKStoFHEWKeyGen(keys, privateKeyFHEW)
 
     print(f"FHEW scheme is using a lattice parameter {ccLWE.Getn()},")
@@ -67,18 +76,13 @@ def SwitchCKKSToFHEW():
     print(f"and modulus q {ccLWE.Getq()}\n")
 
     #  Compute the scaling factor to decrypt correctly in FHEW; the LWE mod switch is performed on the ciphertext at the last level
-    modulus_CKKS_from = cc.GetModulusCKKS()
-
     pLWE1 = ccLWE.GetMaxPlaintextSpace() # Small precision
     modulus_LWE  = 1 << logQ_ccLWE
     beta = ccLWE.GetBeta()
     pLWE2 = modulus_LWE / (2*beta) # Large precision
 
-    scFactor = cc.GetScalingFactorReal(0)
-    # if (cc.GetScalingTechnique() == FLEXIBLEAUTOEXT):
-    #     scFactor = cc.GetScalingFactorReal(1)
-    scale1 = modulus_CKKS_from / (scFactor * pLWE1)
-    scale2 = modulus_CKKS_from / (scFactor * pLWE2)
+    scale1 = 1 / pLWE1
+    scale2 = 1 / pLWE2
 
     # Perform the precomputation for switching
     cc.EvalCKKStoFHEWPrecompute(scale1)
@@ -226,7 +230,7 @@ def SwitchFHEWtoCKKS():
         x2.extend(zeros)
 
     # Encrypt
-    # Encrypted nder small plaintext modulus p = 4 and ciphertext modulus:
+    # Encrypted under small plaintext modulus p = 4 and ciphertext modulus:
     ctxtsLWE1 = [ccLWE.Encrypt(lwesk, x1[i]) for i in range(slots)]
     # Encrypted under larger plaintext modulus p = 16 but small ciphertext modulus:
     ctxtsLWE2 = [ccLWE.Encrypt(lwesk, x1[i], FRESH, pLWE1) for i in range(slots)]
@@ -314,13 +318,17 @@ def FloorViaSchemeSwitching():
 
     # Generate encryption keys.
     keys = cc.KeyGen()
-
+    
     # Step 2: Prepare the FHEW cryptocontext and keys for FHEW and scheme switching
-    arbFunc = False
-    FHEWparams = cc.EvalSchemeSwitchingSetup(sl, slBin, arbFunc, logQ_ccLWE, False, slots)
-
-    ccLWE = FHEWparams[0]
-    privateKeyFHEW = FHEWparams[1]
+    params = SchSwchParams()
+    params.SetSecurityLevelCKKS(sl)
+    params.SetSecurityLevelFHEW(slBin)
+    params.SetCtxtModSizeFHEWLargePrec(logQ_ccLWE)
+    params.SetNumSlotsCKKS(slots)
+    params.SetNumValues(slots)
+    
+    privateKeyFHEW = cc.EvalSchemeSwitchingSetup(params)
+    ccLWE = cc.GetBinCCForSchemeSwitch()
 
     cc.EvalSchemeSwitchingKeyGen(keys, privateKeyFHEW)
 
@@ -336,10 +344,7 @@ def FloorViaSchemeSwitching():
     beta = ccLWE.GetBeta()
     pLWE = int(modulus_LWE / (2 * beta))  # Large precision
 
-    scFactor = cc.GetScalingFactorReal(0)
-    if cc.GetScalingTechnique() == FLEXIBLEAUTOEXT:
-        scFactor = cc.GetScalingFactorReal(1)
-    scaleCF = int(modulus_CKKS_from) / (scFactor * pLWE)
+    scaleCF = 1.0 / pLWE
 
     cc.EvalCKKStoFHEWPrecompute(scaleCF)
 
@@ -348,14 +353,14 @@ def FloorViaSchemeSwitching():
     x1 = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0]
 
     # Encoding as plaintexts
-    ptxt1 = cc.MakeCKKSPackedPlaintext(x1, 1, 0)#, None)
+    ptxt1 = cc.MakeCKKSPackedPlaintext(x1, 1, 0, None)#, None)
 
     # Encrypt the encoded vectors
     c1 = cc.Encrypt(keys.publicKey, ptxt1)
 
     # Step 4: Scheme switching from CKKS to FHEW
-    cTemp = cc.EvalCKKStoFHEW(c1)
-
+    cTemp = cc.EvalCKKStoFHEW(c1, slots)
+    
     # Step 5: Evaluate the floor function
     bits = 2
 
@@ -417,10 +422,16 @@ def FuncViaSchemeSwitching():
     keys = cc.KeyGen()
 
     # Step 2: Prepare the FHEW cryptocontext and keys for FHEW and scheme switching
-    FHEWparams = cc.EvalSchemeSwitchingSetup(sl, slBin, arbFunc, logQ_ccLWE, False, slots)
-
-    ccLWE = FHEWparams[0]
-    privateKeyFHEW = FHEWparams[1]
+    params = SchSwchParams()
+    params.SetSecurityLevelCKKS(sl)
+    params.SetSecurityLevelFHEW(slBin)
+    params.SetArbitraryFunctionEvaluation(True)
+    params.SetCtxtModSizeFHEWLargePrec(logQ_ccLWE)
+    params.SetNumSlotsCKKS(slots)
+    params.SetNumValues(slots)
+    
+    privateKeyFHEW = cc.EvalSchemeSwitchingSetup(params)
+    ccLWE = cc.GetBinCCForSchemeSwitch()
 
     cc.EvalSchemeSwitchingKeyGen(keys, privateKeyFHEW)
 
@@ -430,12 +441,8 @@ def FuncViaSchemeSwitching():
     print(f"FHEW scheme is using lattice parameter {ccLWE.Getn()},\n logQ {logQ_ccLWE},\n and modulus q {ccLWE.Getq()}\n")
 
     # Set the scaling factor to be able to decrypt; the LWE mod switch is performed on the ciphertext at the last level
-    modulus_CKKS_from = cc.GetModulusCKKS()
     pLWE = ccLWE.GetMaxPlaintextSpace()  # Small precision because GenerateLUTviaFunction needs p < q
-    scFactor = cc.GetScalingFactorReal(0)
-    if cc.GetScalingTechnique() == FLEXIBLEAUTOEXT:
-        scFactor = cc.GetScalingFactorReal(1)
-    scaleCF = modulus_CKKS_from / (scFactor * pLWE)
+    scaleCF = 1.0 / pLWE
 
     cc.EvalCKKStoFHEWPrecompute(scaleCF)
 
@@ -461,7 +468,7 @@ def FuncViaSchemeSwitching():
     c1 = cc.Encrypt(keys.publicKey, ptxt1)
 
     # Step 5: Scheme switching from CKKS to FHEW
-    cTemp = cc.EvalCKKStoFHEW(c1)
+    cTemp = cc.EvalCKKStoFHEW(c1, slots)
 
     print(f"Input x1: {ptxt1.GetRealPackedValue()}")
     print("FHEW decryption: ", end="")
@@ -487,7 +494,7 @@ def FuncViaSchemeSwitching():
 
     plaintextDec2 = cc.Decrypt(keys.secretKey, cTemp2)
     plaintextDec2.SetLength(slots)
-    print(f"\nSwitched decryption modulus_LWE mod {pLWE}\nwoeks only for messages << p: {plaintextDec2}")
+    print(f"\nSwitched decryption modulus_LWE mod {pLWE}\nworks only for messages << p: {plaintextDec2}")
 
     # Transform through arcsine
     cTemp2 = cc.EvalFHEWtoCKKS(cFunc, slots, slots, 4, 0, 2)
@@ -545,27 +552,27 @@ def PolyViaSchemeSwitching():
     keys = cc.KeyGen()
 
     # Step 2: Prepare the FHEW cryptocontext and keys for FHEW and scheme switching
-    FHEWparams = cc.EvalSchemeSwitchingSetup(sl, slBin, False, logQ_ccLWE, False, slots)
-
-    ccLWE = FHEWparams[0]
-    privateKeyFHEW = FHEWparams[1]
+    params = SchSwchParams()
+    params.SetSecurityLevelCKKS(sl)
+    params.SetSecurityLevelFHEW(slBin)
+    params.SetCtxtModSizeFHEWLargePrec(logQ_ccLWE)
+    params.SetNumSlotsCKKS(slots)
+    params.SetNumValues(slots)
+    
+    privateKeyFHEW = cc.EvalSchemeSwitchingSetup(params)
+    ccLWE = cc.GetBinCCForSchemeSwitch()
 
-    # Step 3: Precompute the necessary keys and information for switching from FHEW to CKKS
-    cc.EvalSchemeSwitchingKeyGen(keys, privateKeyFHEW, slots)
+    cc.EvalSchemeSwitchingKeyGen(keys, privateKeyFHEW)
 
     print(f"FHEW scheme is using lattice parameter {ccLWE.Getn()},\n logQ {logQ_ccLWE},\n and modulus q {ccLWE.Getq()}\n")
 
     pLWE1 = ccLWE.GetMaxPlaintextSpace()  # Small precision
     modulus_LWE = 1 << logQ_ccLWE
     beta = ccLWE.GetBeta()
-    pLWE2 = modulus_LWE // (2 * beta)  # Large precision
+    pLWE2 = int(modulus_LWE / (2 * beta))  # Large precision
 
-    modulus_from_CKKS = cc.GetModulusCKKS()
-    scFactor = cc.GetScalingFactorReal(0)
-    if cc.GetScalingTechnique() == FLEXIBLEAUTOEXT:
-        scFactor = cc.GetScalingFactorReal(1)
-    scale1 = modulus_from_CKKS // (scFactor * pLWE1)
-    scale2 = modulus_from_CKKS // (scFactor * pLWE2)
+    scale1 = 1.0 / pLWE1
+    scale2 = 1.0 / pLWE2
 
     # Generate keys for the CKKS intermediate computation
     cc.EvalMultKeyGen(keys.secretKey)
@@ -636,10 +643,6 @@ def PolyViaSchemeSwitching():
     print("\n")
 
 
-
-
-
-
 def ComparisonViaSchemeSwitching():
     print("\n-----ComparisonViaSchemeSwitching-----\n")
     print("Output precision is only wrt the operations in CKKS after switching back.\n")
@@ -686,11 +689,15 @@ def ComparisonViaSchemeSwitching():
     keys = cc.KeyGen()
 
     # Step 2: Prepare the FHEW cryptocontext and keys for FHEW and scheme switching
-    FHEWparams = cc.EvalSchemeSwitchingSetup(sl, slBin, False, logQ_ccLWE, False, slots)
-
-    ccLWE = FHEWparams[0]
-    privateKeyFHEW = FHEWparams[1]
-    ccLWE.BTKeyGen(privateKeyFHEW)
+    params = SchSwchParams()
+    params.SetSecurityLevelCKKS(sl)
+    params.SetSecurityLevelFHEW(slBin)
+    params.SetCtxtModSizeFHEWLargePrec(logQ_ccLWE)
+    params.SetNumSlotsCKKS(slots)
+    params.SetNumValues(slots)
+    
+    privateKeyFHEW = cc.EvalSchemeSwitchingSetup(params)
+    ccLWE = cc.GetBinCCForSchemeSwitch()
 
     cc.EvalSchemeSwitchingKeyGen(keys, privateKeyFHEW)
 
@@ -700,14 +707,10 @@ def ComparisonViaSchemeSwitching():
     pLWE1 = ccLWE.GetMaxPlaintextSpace()  # Small precision
     modulus_LWE = 1 << logQ_ccLWE
     beta = ccLWE.GetBeta()
-    pLWE2 = modulus_LWE // (2 * beta)  # Large precision
+    pLWE2 = int(modulus_LWE / (2 * beta))  # Large precision
 
-    scaleSignFHEW = 1
-    init_level = 0
-    if cc.GetScalingTechnique() == FLEXIBLEAUTOEXT:
-        init_level = 1 
-
-    cc.EvalCompareSwitchPrecompute(pLWE2, init_level, scaleSignFHEW)
+    scaleSignFHEW = 1.0
+    cc.EvalCompareSwitchPrecompute(pLWE2, scaleSignFHEW)
 
     # Step 3: Encoding and encryption of inputs
     x1 = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0]
@@ -756,10 +759,10 @@ def ComparisonViaSchemeSwitching():
     print()
 
     # Step 5'': Direct comparison via CKKS->FHEW->CKKS
-    cResult = cc.EvalCompareSchemeSwitching(c1, c2, slots, 0, scaleSignFHEW)
+    cResult = cc.EvalCompareSchemeSwitching(c1, c2, slots, slots)
     plaintextDec3 = cc.Decrypt(keys.secretKey, cResult)
     plaintextDec3.SetLength(slots)
-    print(f"Decrypted swutched result: {plaintextDec3}\n")
+    print(f"Decrypted switched result: {plaintextDec3}\n")
    
 
 def ArgminViaSchemeSwitching():
@@ -809,11 +812,18 @@ def ArgminViaSchemeSwitching():
     keys = cc.KeyGen()
 
     # Step 2: Prepare the FHEW cryptocontext and keys for FHEW and scheme switching
-    FHEWparams = cc.EvalSchemeSwitchingSetup(sl, slBin, arbFunc, logQ_ccLWE, False, slots)
-    ccLWE = FHEWparams[0]
-    privateKeyFHEW = FHEWparams[1]
+    params = SchSwchParams()
+    params.SetSecurityLevelCKKS(sl)
+    params.SetSecurityLevelFHEW(slBin)
+    params.SetCtxtModSizeFHEWLargePrec(logQ_ccLWE)
+    params.SetNumSlotsCKKS(slots)
+    params.SetNumValues(numValues)
+    params.SetComputeArgmin(True)
+    
+    privateKeyFHEW = cc.EvalSchemeSwitchingSetup(params)
+    ccLWE = cc.GetBinCCForSchemeSwitch()
 
-    cc.EvalSchemeSwitchingKeyGen(keys, privateKeyFHEW, numValues, oneHot)
+    cc.EvalSchemeSwitchingKeyGen(keys, privateKeyFHEW)
 
     print(f"FHEW scheme is using lattice parameter {ccLWE.Getn()},\n logQ {logQ_ccLWE},\n and modulus q {ccLWE.Getq()}\n")
 
@@ -821,12 +831,9 @@ def ArgminViaSchemeSwitching():
     scaleSign = 512
     modulus_LWE = 1 << logQ_ccLWE
     beta = ccLWE.GetBeta()
-    pLWE = modulus_LWE // (2 * beta)  # Large precision
+    pLWE = int(modulus_LWE / (2 * beta))  # Large precision
 
-    init_level = 0
-    if cc.GetScalingTechnique() == FLEXIBLEAUTOEXT:
-        init_level = 1
-    cc.EvalCompareSwitchPrecompute(pLWE, init_level, scaleSign)
+    cc.EvalCompareSwitchPrecompute(pLWE, scaleSign)
 
     # Step 3: Encoding and encryption of inputs
     x1 = [-1.125, -1.12, 5.0, 6.0, -1.0, 2.0, 8.0, -1.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.25, 15.30]
@@ -839,7 +846,7 @@ def ArgminViaSchemeSwitching():
     c1 = cc.Encrypt(keys.publicKey, ptxt1)
 
     # Step 4: Argmin evaluation
-    result = cc.EvalMinSchemeSwitching(c1, keys.publicKey, numValues, slots, oneHot)
+    result = cc.EvalMinSchemeSwitching(c1, keys.publicKey, numValues, slots)
 
     ptxtMin = cc.Decrypt(keys.secretKey, result[0])
     ptxtMin.SetLength(1)
@@ -853,7 +860,7 @@ def ArgminViaSchemeSwitching():
         ptxtMin.SetLength(1)
         print("Argmin: ", ptxtMin)
 
-    result = cc.EvalMaxSchemeSwitching(c1, keys.publicKey, numValues, slots, oneHot)
+    result = cc.EvalMaxSchemeSwitching(c1, keys.publicKey, numValues, slots)
 
     ptxtMax = cc.Decrypt(keys.secretKey, result[0])
     ptxtMax.SetLength(1)
@@ -909,27 +916,30 @@ def ArgminViaSchemeSwitchingAlt():
     print(f"number of slots {slots}, and supports a multiplicative depth of {multDepth}\n")
 
     keys = cc.KeyGen()
-
+    
     # Step 2: Prepare the FHEW cryptocontext and keys for FHEW and scheme switching
-    FHEWparams = cc.EvalSchemeSwitchingSetup(sl, slBin, arbFunc, logQ_ccLWE, False, slots)
-    ccLWE = FHEWparams[0]
-    privateKeyFHEW = FHEWparams[1]
+    params = SchSwchParams()
+    params.SetSecurityLevelCKKS(sl)
+    params.SetSecurityLevelFHEW(slBin)
+    params.SetCtxtModSizeFHEWLargePrec(logQ_ccLWE)
+    params.SetNumSlotsCKKS(slots)
+    params.SetNumValues(numValues)
+    params.SetComputeArgmin(True)
+    params.SetUseAltArgmin(True)
+    
+    privateKeyFHEW = cc.EvalSchemeSwitchingSetup(params)
+    ccLWE = cc.GetBinCCForSchemeSwitch()
 
-    cc.EvalSchemeSwitchingKeyGen(keys, privateKeyFHEW, numValues, oneHot, alt)
+    cc.EvalSchemeSwitchingKeyGen(keys, privateKeyFHEW)
 
     print(f"FHEW scheme is using lattice parameter {ccLWE.Getn()},\n logQ {logQ_ccLWE},\n and modulus q {ccLWE.Getq()}\n")
 
     scaleSign = 512
     modulus_LWE = 1 << logQ_ccLWE
     beta = ccLWE.GetBeta()
-    pLWE = modulus_LWE // (2 * beta)
+    pLWE = int(modulus_LWE / (2 * beta))
 
-    init_level = 0
-    if cc.GetScalingTechnique() == FLEXIBLEAUTOEXT:
-        init_level = 1
-    cc.EvalCompareSwitchPrecompute(pLWE, init_level, scaleSign)
-    # But we can also include the scaleSign in pLWE (here we use the fact both pLWE and scaleSign are powers of two)
-    # cc.EvalCompareSwitchPrecompute(pLWE / scaleSign, init_level, 1)
+    cc.EvalCompareSwitchPrecompute(pLWE, scaleSign)
 
     # Step 3: Encoding and encryption of inputs
 
@@ -947,7 +957,7 @@ def ArgminViaSchemeSwitchingAlt():
     c1 = cc.Encrypt(keys.publicKey, ptxt1)
 
     # Step 4: Argmin evaluation
-    result = cc.EvalMinSchemeSwitchingAlt(c1, keys.publicKey, numValues, slots, oneHot)
+    result = cc.EvalMinSchemeSwitchingAlt(c1, keys.publicKey, numValues, slots)
 
     ptxtMin = cc.Decrypt(keys.secretKey, result[0])
     ptxtMin.SetLength(1)
@@ -961,7 +971,7 @@ def ArgminViaSchemeSwitchingAlt():
         ptxtMin.SetLength(1)
         print("Argmin: ", ptxtMin)
 
-    result = cc.EvalMaxSchemeSwitchingAlt(c1, keys.publicKey, numValues, slots, oneHot)
+    result = cc.EvalMaxSchemeSwitchingAlt(c1, keys.publicKey, numValues, slots)
 
     ptxtMax = cc.Decrypt(keys.secretKey, result[0])
     ptxtMax.SetLength(1)
@@ -1023,22 +1033,23 @@ def ArgminViaSchemeSwitchingUnit():
     keys = cc.KeyGen()
 
     # Step 2: Prepare the FHEW cryptocontext and keys for FHEW and scheme switching
-    FHEWparams = cc.EvalSchemeSwitchingSetup(sl, slBin, arbFunc, logQ_ccLWE, False, slots)
-
-    ccLWE = FHEWparams[0]
-    privateKeyFHEW = FHEWparams[1]
+    params = SchSwchParams()
+    params.SetSecurityLevelCKKS(sl)
+    params.SetSecurityLevelFHEW(slBin)
+    params.SetCtxtModSizeFHEWLargePrec(logQ_ccLWE)
+    params.SetNumSlotsCKKS(slots)
+    params.SetNumValues(numValues)
+    params.SetComputeArgmin(True)
+    
+    privateKeyFHEW = cc.EvalSchemeSwitchingSetup(params)
+    ccLWE = cc.GetBinCCForSchemeSwitch()
 
-    cc.EvalSchemeSwitchingKeyGen(keys, privateKeyFHEW, numValues, oneHot)
+    cc.EvalSchemeSwitchingKeyGen(keys, privateKeyFHEW)
 
     print(f"FHEW scheme is using lattice parameter {ccLWE.Getn()},\n logQ {logQ_ccLWE},\n and modulus q {ccLWE.Getq()}\n")
 
-    init_level = 0
-
-    if cc.GetScalingTechnique() == FLEXIBLEAUTOEXT:
-        init_level = 1
-
     # Here we assume the message does not need scaling, as they are in the unit circle.
-    cc.EvalCompareSwitchPrecompute(1, init_level, 1)
+    cc.EvalCompareSwitchPrecompute(1, 1)
 
     # Step 3: Encoding and encryption of inputs
 
@@ -1062,7 +1073,7 @@ def ArgminViaSchemeSwitchingUnit():
     c1 = cc.Encrypt(keys.publicKey, ptxt1)
 
     # Step 4: Argmin evaluation
-    result = cc.EvalMinSchemeSwitching(c1, keys.publicKey, numValues, slots, oneHot)
+    result = cc.EvalMinSchemeSwitching(c1, keys.publicKey, numValues, slots)
 
     ptxtMin = cc.Decrypt(keys.secretKey, result[0])
     ptxtMin.SetLength(1)
@@ -1076,7 +1087,7 @@ def ArgminViaSchemeSwitchingUnit():
         ptxtMin.SetLength(1)
         print("Argmin: ", ptxtMin)
 
-    result = cc.EvalMaxSchemeSwitching(c1, keys.publicKey, numValues, slots, oneHot)
+    result = cc.EvalMaxSchemeSwitching(c1, keys.publicKey, numValues, slots)
 
     ptxtMax = cc.Decrypt(keys.secretKey, result[0])
     ptxtMax.SetLength(1)
@@ -1139,21 +1150,24 @@ def ArgminViaSchemeSwitchingAltUnit():
     keys = cc.KeyGen()
 
     # Step 2: Prepare the FHEW cryptocontext and keys for FHEW and scheme switching
-    FHEWparams = cc.EvalSchemeSwitchingSetup(sl, slBin, arbFunc, logQ_ccLWE, False, slots)
-
-    ccLWE = FHEWparams[0]
-    privateKeyFHEW = FHEWparams[1]
+    params = SchSwchParams()
+    params.SetSecurityLevelCKKS(sl)
+    params.SetSecurityLevelFHEW(slBin)
+    params.SetCtxtModSizeFHEWLargePrec(logQ_ccLWE)
+    params.SetNumSlotsCKKS(slots)
+    params.SetNumValues(numValues)
+    params.SetComputeArgmin(True)
+    params.SetUseAltArgmin(True)
+    
+    privateKeyFHEW = cc.EvalSchemeSwitchingSetup(params)
+    ccLWE = cc.GetBinCCForSchemeSwitch()
 
-    cc.EvalSchemeSwitchingKeyGen(keys, privateKeyFHEW, numValues, oneHot, alt)
+    cc.EvalSchemeSwitchingKeyGen(keys, privateKeyFHEW)
 
     print(f"FHEW scheme is using lattice parameter {ccLWE.Getn()},\n logQ {logQ_ccLWE},\n and modulus q {ccLWE.Getq()}\n")
 
-    init_level = 0
-
-    if cc.GetScalingTechnique() == FLEXIBLEAUTOEXT:
-        init_level = 1
     # Here we assume the message does not need scaling, as they are in the unit circle.
-    cc.EvalCompareSwitchPrecompute(1, init_level, 1)
+    cc.EvalCompareSwitchPrecompute(1, 1)
 
     # Step 3: Encoding and encryption of inputs
     # Inputs
@@ -1177,7 +1191,7 @@ def ArgminViaSchemeSwitchingAltUnit():
     c1 = cc.Encrypt(keys.publicKey, ptxt1)
 
     # Step 4: Argmin evaluation
-    result = cc.EvalMinSchemeSwitchingAlt(c1, keys.publicKey, numValues, slots, oneHot)
+    result = cc.EvalMinSchemeSwitchingAlt(c1, keys.publicKey, numValues, slots)
 
     ptxtMin = cc.Decrypt(keys.secretKey, result[0])
     ptxtMin.SetLength(1)
@@ -1191,7 +1205,7 @@ def ArgminViaSchemeSwitchingAltUnit():
         ptxtMin.SetLength(1)
         print("Argmin: ", ptxtMin)
 
-    result = cc.EvalMaxSchemeSwitchingAlt(c1, keys.publicKey, numValues, slots, oneHot)
+    result = cc.EvalMaxSchemeSwitchingAlt(c1, keys.publicKey, numValues, slots)
 
     ptxtMax = cc.Decrypt(keys.secretKey, result[0])
     ptxtMax.SetLength(1)

+ 2 - 1
src/include/bindings.h

@@ -38,4 +38,5 @@ void bind_encodings(pybind11::module &m);
 void bind_ciphertext(pybind11::module &m);
 void bind_serialization(pybind11::module &m);
 void bind_schemes(pybind11::module &m);
-#endif // OPENFHE_BINDINGS_H
+void bind_sch_swch_params(pybind11::module &m);
+#endif // OPENFHE_BINDINGS_H

+ 0 - 4
src/include/docstrings/cryptocontext_docs.h

@@ -1253,10 +1253,6 @@ const char* cc_EvalAutomorphismKeyGen_docs = R"pbdoc(
     :rtype: EvalKeyMap
 )pbdoc";
 
-const char* cc_EvalAutomorphismKeyGenPublic_docs = R"pbdoc(
-    NOT USED BY ANY CRYPTO SCHEME: Generate automophism keys for a public and private key
-)pbdoc";
-
 const char* cc_FindAutomorphismIndex_docs = R"pbdoc(
     Finds an automorphism index for a given vector index using a scheme-specific algorithm
 

+ 1 - 2
src/include/pke/cryptocontext_wrapper.h

@@ -57,7 +57,6 @@ const PrivateKey<DCRTPoly> privateKey,ConstCiphertext<DCRTPoly> ciphertext);
 Plaintext MultipartyDecryptFusionWrapper(CryptoContext<DCRTPoly>& self,const std::vector<Ciphertext<DCRTPoly>>& partialCiphertextVec);
 
 const std::map<usint, EvalKey<DCRTPoly>> EvalAutomorphismKeyGenWrapper(CryptoContext<DCRTPoly>& self,const PrivateKey<DCRTPoly> privateKey,const std::vector<usint> &indexList);
-const std::map<usint, EvalKey<DCRTPoly>> EvalAutomorphismKeyGenWrapper_PublicKey(CryptoContext<DCRTPoly>& self,const PublicKey<DCRTPoly> publicKey, const PrivateKey<DCRTPoly> privateKey, const std::vector<usint> &indexList);
 const std::shared_ptr<std::map<usint, EvalKey<DCRTPoly>>> GetEvalSumKeyMapWrapper(CryptoContext<DCRTPoly>& self, const std::string &id);
 const PlaintextModulus GetPlaintextModulusWrapper(CryptoContext<DCRTPoly>& self);
 const double GetModulusWrapper(CryptoContext<DCRTPoly>& self);
@@ -66,4 +65,4 @@ const double GetScalingFactorRealWrapper(CryptoContext<DCRTPoly>& self, uint32_t
 const uint64_t GetModulusCKKSWrapper(CryptoContext<DCRTPoly>& self);
 const ScalingTechnique GetScalingTechniqueWrapper(CryptoContext<DCRTPoly>& self);
 const usint GetDigitSizeWrapper(CryptoContext<DCRTPoly>& self);
-#endif // OPENFHE_CRYPTOCONTEXT_BINDINGS_H
+#endif // OPENFHE_CRYPTOCONTEXT_BINDINGS_H

+ 62 - 39
src/lib/bindings.cpp

@@ -597,19 +597,11 @@ void bind_crypto_context(py::module &m)
              py::arg("precision") = 0)
         .def("EvalCKKStoFHEWSetup", &CryptoContextImpl<DCRTPoly>::EvalCKKStoFHEWSetup,
             cc_EvalCKKStoFHEWSetup_docs,
-            py::arg("sl") = HEStd_128_classic,
-            py::arg("slBin") = BINFHE_PARAMSET::STD128,
-            py::arg("arbFunc") = false,
-            py::arg("logQ") = 25,
-            py::arg("dynamic") = false,
-            py::arg("numSlotsCKKS") = 0,
-            py::arg("logQswitch") = 27)
+            py::arg("schswchparams"))
         .def("EvalCKKStoFHEWKeyGen", &CryptoContextImpl<DCRTPoly>::EvalCKKStoFHEWKeyGen,
              cc_EvalCKKStoFHEWKeyGen_docs,
              py::arg("keyPair"),
-             py::arg("lwesk"),
-             py::arg("dim1") = 0,
-             py::arg("L") = 1)
+             py::arg("lwesk"))
         .def("EvalCKKStoFHEWPrecompute", &CryptoContextImpl<DCRTPoly>::EvalCKKStoFHEWPrecompute,
              cc_EvalCKKStoFHEWPrecompute_docs,
              py::arg("scale") = 1.0)
@@ -627,6 +619,7 @@ void bind_crypto_context(py::module &m)
              py::arg("keyPair"),
              py::arg("lwesk"),
              py::arg("numSlots") = 0,
+             py::arg("numCtxts") = 0,
              py::arg("dim1") = 0,
              py::arg("L") = 0)
         .def("EvalFHEWtoCKKS", &CryptoContextImpl<DCRTPoly>::EvalFHEWtoCKKS,
@@ -636,32 +629,19 @@ void bind_crypto_context(py::module &m)
              py::arg("numSlots") = 0,
              py::arg("p") = 4,
              py::arg("pmin") = 0.0,
-             py::arg("pmax") = 2.0)
+             py::arg("pmax") = 2.0,
+             py::arg("dim1") = 0)
         .def("EvalSchemeSwitchingSetup", &CryptoContextImpl<DCRTPoly>::EvalSchemeSwitchingSetup,
              cc_EvalSchemeSwitchingSetup_docs,
-             py::arg("sl") = HEStd_128_classic,
-             py::arg("slBin") = BINFHE_PARAMSET::STD128,
-             py::arg("arbFunc") = false,
-             py::arg("logQ") = 25,
-             py::arg("dynamic") = false,
-             py::arg("numSlotsCKKS") = 0,
-             py::arg("logQswitch") = 27)
+             py::arg("schswchparams"))
         //void EvalSchemeSwitchingKeyGen(const KeyPair<Element> &keyPair, ConstLWEPrivateKey &lwesk, uint32_t numValues = 0, bool oneHot = true, bool alt = false, uint32_t dim1CF = 0, uint32_t dim1FC = 0, uint32_t LCF = 1, uint32_t LFC = 0)
         .def("EvalSchemeSwitchingKeyGen", &CryptoContextImpl<DCRTPoly>::EvalSchemeSwitchingKeyGen,
              cc_EvalSchemeSwitchingKeyGen_docs,
              py::arg("keyPair"),
-             py::arg("lwesk"),
-             py::arg("numValues") = 0,
-             py::arg("oneHot") = true,
-             py::arg("alt") = false,
-             py::arg("dim1CF") = 0,
-             py::arg("dim1FC") = 0,
-             py::arg("LCF") = 1,
-             py::arg("LFC") = 0)
+             py::arg("lwesk"))
         .def("EvalCompareSwitchPrecompute", &CryptoContextImpl<DCRTPoly>::EvalCompareSwitchPrecompute,
              cc_EvalCompareSwitchPrecompute_docs,
              py::arg("pLWE") = 0,
-             py::arg("initLevel") = 0,
              py::arg("scaleSign") = 1.0,
              py::arg("unit") = false)
         .def("EvalCompareSchemeSwitching", &CryptoContextImpl<DCRTPoly>::EvalCompareSchemeSwitching,
@@ -679,7 +659,6 @@ void bind_crypto_context(py::module &m)
              py::arg("publicKey"),
              py::arg("numValues") = 0,
              py::arg("numSlots") = 0,
-             py::arg("oneHot") = true,
              py::arg("pLWE") = 0,
              py::arg("scaleSign") = 1.0)
         .def("EvalMinSchemeSwitchingAlt", &CryptoContextImpl<DCRTPoly>::EvalMinSchemeSwitchingAlt,
@@ -688,7 +667,6 @@ void bind_crypto_context(py::module &m)
              py::arg("publicKey"),
              py::arg("numValues") = 0,
              py::arg("numSlots") = 0,
-             py::arg("oneHot") = true,
              py::arg("pLWE") = 0,
              py::arg("scaleSign") = 1.0)
         .def("EvalMaxSchemeSwitching", &CryptoContextImpl<DCRTPoly>::EvalMaxSchemeSwitching,
@@ -697,7 +675,6 @@ void bind_crypto_context(py::module &m)
              py::arg("publicKey"),
              py::arg("numValues") = 0,
              py::arg("numSlots") = 0,
-             py::arg("oneHot") = true,
              py::arg("pLWE") = 0,
              py::arg("scaleSign") = 1.0)
         .def("EvalMaxSchemeSwitchingAlt", &CryptoContextImpl<DCRTPoly>::EvalMaxSchemeSwitchingAlt,
@@ -706,7 +683,6 @@ void bind_crypto_context(py::module &m)
              py::arg("publicKey"),
              py::arg("numValues") = 0,
              py::arg("numSlots") = 0,
-             py::arg("oneHot") = true,
              py::arg("pLWE") = 0,
              py::arg("scaleSign") = 1.0)
         //TODO (Oliveira, R.): Solve pointer handling bug when returning EvalKeyMap objects for the next functions
@@ -715,12 +691,6 @@ void bind_crypto_context(py::module &m)
             py::arg("privateKey"),
             py::arg("indexList"),
             py::return_value_policy::reference_internal)
-        .def("EvalAutomorphismKeyGen", &EvalAutomorphismKeyGenWrapper_PublicKey, 
-            cc_EvalAutomorphismKeyGenPublic_docs,
-            py::arg("publicKey"),
-            py::arg("privateKey"),
-            py::arg("indexList"),
-            py::return_value_policy::reference_internal)
         .def("FindAutomorphismIndex", &CryptoContextImpl<DCRTPoly>::FindAutomorphismIndex,
             cc_FindAutomorphismIndex_docs,
             py::arg("idx"))
@@ -734,7 +704,8 @@ void bind_crypto_context(py::module &m)
         .def_static(
             "InsertEvalSumKey", &CryptoContextImpl<DCRTPoly>::InsertEvalSumKey,
             cc_InsertEvalSumKey_docs,
-            py::arg("evalKeyMap"))
+            py::arg("evalKeyMap"),
+            py::arg("keyTag") = "")
         .def_static(
             "InsertEvalMultKey", &CryptoContextImpl<DCRTPoly>::InsertEvalMultKey,
             cc_InsertEvalMultKey_docs,
@@ -746,6 +717,8 @@ void bind_crypto_context(py::module &m)
         .def("GetEvalSumKeyMap", &GetEvalSumKeyMapWrapper,
             cc_GetEvalSumKeyMap_docs,
             py::return_value_policy::reference)
+        .def("GetBinCCForSchemeSwitch", &CryptoContextImpl<DCRTPoly>::GetBinCCForSchemeSwitch,
+        		py::return_value_policy::reference_internal)
         .def_static(
             "SerializeEvalMultKey", [](const std::string &filename, const SerType::SERBINARY &sertype, std::string id = "")
             {
@@ -1136,6 +1109,56 @@ void bind_schemes(py::module &m){
     
 }
 
+void bind_sch_swch_params(py::module &m)
+{
+    py::class_<SchSwchParams>(m, "SchSwchParams")
+        .def(py::init<>())
+        .def("GetSecurityLevelCKKS", &SchSwchParams::GetSecurityLevelCKKS)
+        .def("GetSecurityLevelFHEW", &SchSwchParams::GetSecurityLevelFHEW)
+        .def("GetArbitraryFunctionEvaluation", &SchSwchParams::GetArbitraryFunctionEvaluation)
+        .def("GetUseDynamicModeFHEW", &SchSwchParams::GetUseDynamicModeFHEW)
+        .def("GetComputeArgmin", &SchSwchParams::GetComputeArgmin)
+        .def("GetOneHotEncoding", &SchSwchParams::GetOneHotEncoding)
+        .def("GetUseAltArgmin", &SchSwchParams::GetUseAltArgmin)
+        .def("GetNumSlotsCKKS", &SchSwchParams::GetNumSlotsCKKS)
+        .def("GetNumValues", &SchSwchParams::GetNumValues)
+        .def("GetCtxtModSizeFHEWLargePrec", &SchSwchParams::GetCtxtModSizeFHEWLargePrec)
+        .def("GetCtxtModSizeFHEWIntermedSwch", &SchSwchParams::GetCtxtModSizeFHEWIntermedSwch)
+        .def("GetBStepLTrCKKStoFHEW", &SchSwchParams::GetBStepLTrCKKStoFHEW)
+        .def("GetBStepLTrFHEWtoCKKS", &SchSwchParams::GetBStepLTrFHEWtoCKKS)
+        .def("GetLevelLTrCKKStoFHEW", &SchSwchParams::GetLevelLTrCKKStoFHEW)
+        .def("GetLevelLTrFHEWtoCKKS", &SchSwchParams::GetLevelLTrFHEWtoCKKS)
+        .def("GetInitialCKKSModulus", &SchSwchParams::GetInitialCKKSModulus)
+        .def("GetRingDimension", &SchSwchParams::GetRingDimension)
+        .def("GetScalingModSize", &SchSwchParams::GetScalingModSize)
+        .def("GetBatchSize", &SchSwchParams::GetBatchSize)
+        .def("SetSecurityLevelCKKS", &SchSwchParams::SetSecurityLevelCKKS)
+        .def("SetSecurityLevelFHEW", &SchSwchParams::SetSecurityLevelFHEW)
+        .def("SetArbitraryFunctionEvaluation", &SchSwchParams::SetArbitraryFunctionEvaluation)
+        .def("SetUseDynamicModeFHEW", &SchSwchParams::SetUseDynamicModeFHEW)
+        .def("SetComputeArgmin", &SchSwchParams::SetComputeArgmin)
+        .def("SetOneHotEncoding", &SchSwchParams::SetOneHotEncoding)
+        .def("SetUseAltArgmin", &SchSwchParams::SetUseAltArgmin)
+        .def("SetNumSlotsCKKS", &SchSwchParams::SetNumSlotsCKKS)
+        .def("SetNumValues", &SchSwchParams::SetNumValues)
+        .def("SetCtxtModSizeFHEWLargePrec", &SchSwchParams::SetCtxtModSizeFHEWLargePrec)
+        .def("SetCtxtModSizeFHEWIntermedSwch", &SchSwchParams::SetCtxtModSizeFHEWIntermedSwch)
+        .def("SetBStepLTrCKKStoFHEW", &SchSwchParams::SetBStepLTrCKKStoFHEW)
+        .def("SetBStepLTrFHEWtoCKKS", &SchSwchParams::SetBStepLTrFHEWtoCKKS)
+        .def("SetLevelLTrCKKStoFHEW", &SchSwchParams::SetLevelLTrCKKStoFHEW)
+        .def("SetLevelLTrFHEWtoCKKS", &SchSwchParams::SetLevelLTrFHEWtoCKKS)
+        .def("SetInitialCKKSModulus", &SchSwchParams::SetInitialCKKSModulus)
+        .def("SetRingDimension", &SchSwchParams::SetRingDimension)
+        .def("SetScalingModSize", &SchSwchParams::SetScalingModSize)
+        .def("SetBatchSize", &SchSwchParams::SetBatchSize)
+        .def("__str__",[](const SchSwchParams &params) {
+            std::stringstream stream;
+            stream << params;
+            return stream.str();
+        });
+}
+
+
 PYBIND11_MODULE(openfhe, m)
 {
     m.doc() = "Open-Source Fully Homomorphic Encryption Library";
@@ -1155,5 +1178,5 @@ PYBIND11_MODULE(openfhe, m)
     bind_crypto_context(m);
     bind_serialization(m);
     bind_schemes(m);
-    
+    bind_sch_swch_params(m);
 }

+ 1 - 1
src/lib/binfhe_bindings.cpp

@@ -153,7 +153,7 @@ void bind_binfhe_ciphertext(py::module &m)
 
 void bind_binfhe_context(py::module &m)
 {
-    py::class_<BinFHEContext>(m, "BinFHEContext")
+    py::class_<BinFHEContext, std::shared_ptr<BinFHEContext>>(m, "BinFHEContext")
         .def(py::init<>())
         .def("GenerateBinFHEContext", static_cast<void (BinFHEContext::*)(BINFHE_PARAMSET, BINFHE_METHOD)>(&BinFHEContext::GenerateBinFHEContext),
              binfhe_GenerateBinFHEContext_parset_docs,

+ 0 - 4
src/lib/pke/cryptocontext_wrapper.cpp

@@ -79,10 +79,6 @@ const std::map<usint, EvalKey<DCRTPoly>> EvalAutomorphismKeyGenWrapper(CryptoCon
     return *(self->EvalAutomorphismKeyGen(privateKey, indexList));
 }
 
-const std::map<usint, EvalKey<DCRTPoly>> EvalAutomorphismKeyGenWrapper_PublicKey(CryptoContext<DCRTPoly>& self,const PublicKey<DCRTPoly> publicKey, const PrivateKey<DCRTPoly> privateKey, const std::vector<usint> &indexList){
-    return *(self->EvalAutomorphismKeyGen(publicKey, privateKey, indexList));
-};
-
 const std::shared_ptr<std::map<usint, EvalKey<DCRTPoly>>> GetEvalSumKeyMapWrapper(CryptoContext<DCRTPoly>& self,const std::string &id){
     auto evalSumKeyMap = 
         std::make_shared<std::map<usint, EvalKey<DCRTPoly>>>(self->GetEvalSumKeyMap(id));