Forráskód Böngészése

Merge pull request #16 from openfheorg/Oliveira_simple_ckks

Finalizing ckks example
Rener Oliveira 1 éve
szülő
commit
ba81089cec

+ 1 - 1
CMakeLists.txt

@@ -54,7 +54,7 @@ endif()
 ### add_executable( test demo-simple-example.cpp )
 
 ### Pybind Modules
-pybind11_add_module(openfhe src/bindings.cpp src/pke/decryption.cpp src/pke/serialization.cpp)
+pybind11_add_module(openfhe src/bindings.cpp src/pke/decryption.cpp src/pke/serialization.cpp src/pke/cryptocontext_wrapper.cpp)
 ### Python installation 
 find_package(Python REQUIRED COMPONENTS Interpreter Development)
 

+ 22 - 0
include/pke/cryptocontext_wrapper.h

@@ -0,0 +1,22 @@
+#ifndef OPENFHE_CRYPTOCONTEXT_BINDINGS_H
+#define OPENFHE_CRYPTOCONTEXT_BINDINGS_H
+
+#include <pybind11/pybind11.h>
+#include <pybind11/stl.h>
+#include <vector>
+#include <algorithm>
+#include <complex>
+#include "openfhe.h"
+#include "bindings.h"
+
+namespace py = pybind11;
+using namespace lbcrypto;
+using ParmType = typename DCRTPoly::Params;
+
+Plaintext MakeCKKSPackedPlaintextWrapper(std::shared_ptr<CryptoContextImpl<DCRTPoly>> &self, 
+            const std::vector<float> &value, 
+            size_t depth, uint32_t level, 
+            const std::shared_ptr<ParmType> params,
+            usint slots);
+
+#endif // OPENFHE_CRYPTOCONTEXT_BINDINGS_H

+ 107 - 75
src/bindings.cpp

@@ -2,32 +2,46 @@
 #include <pybind11/stl.h>
 #include <pybind11/iostream.h>
 #include <iostream>
-#include <openfhe/pke/openfhe.h>
-#include <openfhe/pke/key/key-ser.h>
+#include "openfhe.h"
+#include "key/key-ser.h"
 #include "bindings.h"
+#include "cryptocontext_wrapper.h"
 
 using namespace lbcrypto;
 namespace py = pybind11;
 
-void bind_parameters(py::module &m){
+void bind_parameters(py::module &m)
+{
     py::class_<Params>(m, "Params");
     py::class_<CCParams<CryptoContextBFVRNS>, Params>(m, "CCParamsBFVRNS")
-            .def(py::init<>())
-            // setters
-            .def("SetPlaintextModulus", &CCParams<CryptoContextBFVRNS>::SetPlaintextModulus)
-            .def("SetMultiplicativeDepth",&CCParams<CryptoContextBFVRNS>::SetMultiplicativeDepth)
-            // getters
-            .def("GetPlaintextModulus", &CCParams<CryptoContextBFVRNS>::GetPlaintextModulus)
-            .def("GetMultiplicativeDepth", &CCParams<CryptoContextBFVRNS>::GetMultiplicativeDepth);
+        .def(py::init<>())
+        // setters
+        .def("SetPlaintextModulus", &CCParams<CryptoContextBFVRNS>::SetPlaintextModulus)
+        .def("SetMultiplicativeDepth", &CCParams<CryptoContextBFVRNS>::SetMultiplicativeDepth)
+        // getters
+        .def("GetPlaintextModulus", &CCParams<CryptoContextBFVRNS>::GetPlaintextModulus)
+        .def("GetMultiplicativeDepth", &CCParams<CryptoContextBFVRNS>::GetMultiplicativeDepth);
     py::class_<CCParams<CryptoContextBGVRNS>, Params>(m, "CCParamsBGVRNS")
-            .def(py::init<>())
-            // setters
-            .def("SetPlaintextModulus", &CCParams<CryptoContextBGVRNS>::SetPlaintextModulus)
-            .def("SetMultiplicativeDepth",&CCParams<CryptoContextBGVRNS>::SetMultiplicativeDepth)
-            // getters
-            .def("GetPlaintextModulus", &CCParams<CryptoContextBGVRNS>::GetPlaintextModulus)
-            .def("GetMultiplicativeDepth", &CCParams<CryptoContextBGVRNS>::GetMultiplicativeDepth);
-           
+        .def(py::init<>())
+        // setters
+        .def("SetPlaintextModulus", &CCParams<CryptoContextBGVRNS>::SetPlaintextModulus)
+        .def("SetMultiplicativeDepth", &CCParams<CryptoContextBGVRNS>::SetMultiplicativeDepth)
+        // getters
+        .def("GetPlaintextModulus", &CCParams<CryptoContextBGVRNS>::GetPlaintextModulus)
+        .def("GetMultiplicativeDepth", &CCParams<CryptoContextBGVRNS>::GetMultiplicativeDepth);
+    // bind ckks rns params
+    py::class_<CCParams<CryptoContextCKKSRNS>, Params>(m, "CCParamsCKKSRNS")
+        .def(py::init<>())
+        // setters
+        .def("SetPlaintextModulus", &CCParams<CryptoContextCKKSRNS>::SetPlaintextModulus)
+        .def("SetMultiplicativeDepth", &CCParams<CryptoContextCKKSRNS>::SetMultiplicativeDepth)
+        .def("SetScalingModSize", &CCParams<CryptoContextCKKSRNS>::SetScalingModSize)
+        .def("SetBatchSize", &CCParams<CryptoContextCKKSRNS>::SetBatchSize)
+        // getters
+        .def("GetPlaintextModulus", &CCParams<CryptoContextCKKSRNS>::GetPlaintextModulus)
+        .def("GetMultiplicativeDepth", &CCParams<CryptoContextCKKSRNS>::GetMultiplicativeDepth)
+        .def("GetScalingModSize", &CCParams<CryptoContextCKKSRNS>::GetScalingModSize)
+        .def("GetBatchSize", &CCParams<CryptoContextCKKSRNS>::GetBatchSize);
 }
 
 void bind_crypto_context(py::module &m)
@@ -36,6 +50,7 @@ void bind_crypto_context(py::module &m)
         .def(py::init<>())
         .def("GetKeyGenLevel", &CryptoContextImpl<DCRTPoly>::GetKeyGenLevel)
         .def("SetKeyGenLevel", &CryptoContextImpl<DCRTPoly>::SetKeyGenLevel)
+        .def("GetRingDimension", &CryptoContextImpl<DCRTPoly>::GetRingDimension)
         .def("Enable", static_cast<void (CryptoContextImpl<DCRTPoly>::*)(PKESchemeFeature)>(&CryptoContextImpl<DCRTPoly>::Enable), "Enable a feature for the CryptoContext")
         .def("KeyGen", &CryptoContextImpl<DCRTPoly>::KeyGen, "Generate a key pair with public and private keys")
         .def("EvalMultKeyGen", &CryptoContextImpl<DCRTPoly>::EvalMultKeyGen, "Generate the evaluation key for multiplication")
@@ -43,11 +58,19 @@ void bind_crypto_context(py::module &m)
              py::arg("privateKey"), py::arg("indexList"), py::arg("publicKey") = nullptr)
         .def("MakePackedPlaintext", &CryptoContextImpl<DCRTPoly>::MakePackedPlaintext, "Make a plaintext from a vector of integers",
              py::arg("value"), py::arg("depth") = 1, py::arg("level") = 0)
+        .def("MakeCKKSPackedPlaintext",&MakeCKKSPackedPlaintextWrapper, "Make a CKKS plaintext from a vector of floats",
+            py::arg("value"),
+            py::arg("depth") = static_cast<size_t>(1),
+            py::arg("level") = static_cast<uint32_t>(0),
+            py::arg("params") = py::none(),
+            py::arg("slots") = 0)
         .def("EvalRotate", &CryptoContextImpl<DCRTPoly>::EvalRotate, "Rotate a ciphertext")
         .def("Encrypt", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(const PublicKey<DCRTPoly>, Plaintext) const>(&CryptoContextImpl<DCRTPoly>::Encrypt),
              "Encrypt a plaintext using public key")
         .def("EvalAdd", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(ConstCiphertext<DCRTPoly>, ConstCiphertext<DCRTPoly>) const>(&CryptoContextImpl<DCRTPoly>::EvalAdd), "Add two ciphertexts")
+        .def("EvalSub", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(ConstCiphertext<DCRTPoly>, ConstCiphertext<DCRTPoly>) const>(&CryptoContextImpl<DCRTPoly>::EvalSub), "Subtract two ciphertexts")
         .def("EvalMult", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(ConstCiphertext<DCRTPoly>, ConstCiphertext<DCRTPoly>) const>(&CryptoContextImpl<DCRTPoly>::EvalMult), "Multiply two ciphertexts")
+        .def("EvalMult", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(ConstCiphertext<DCRTPoly>, double) const>(&CryptoContextImpl<DCRTPoly>::EvalMult), "Multiply a ciphertext with a scalar")
         .def_static(
             "ClearEvalMultKeys", []()
             { CryptoContextImpl<DCRTPoly>::ClearEvalMultKeys(); },
@@ -75,106 +98,115 @@ void bind_crypto_context(py::module &m)
                 outfile.close();
                 return res; },
             py::arg("filename"), py::arg("sertype"), py::arg("id") = "", "Serialize evaluation keys for rotation")
-        .def_static("DeserializeEvalMultKey", [](const std::string &filename, const SerType::SERBINARY &sertype)
+        .def_static("DeserializeEvalMultKey", [](std::shared_ptr<CryptoContextImpl<DCRTPoly>> &self,const std::string &filename, const SerType::SERBINARY &sertype)
                     {
                         std::ifstream emkeys(filename, std::ios::in | std::ios::binary);
                          if (!emkeys.is_open()) {
                             std::cerr << "I cannot read serialization from " << filename << std::endl;
                          }
                         bool res;
-                        res = CryptoContextImpl<DCRTPoly>::DeserializeEvalMultKey<SerType::SERBINARY>(emkeys, sertype);
+                        res = self->DeserializeEvalMultKey<SerType::SERBINARY>(emkeys, sertype);
                         return res; })
-        .def_static("DeserializeEvalAutomorphismKey", [](const std::string &filename, const SerType::SERBINARY &sertype)
+        .def_static("DeserializeEvalAutomorphismKey", [](std::shared_ptr<CryptoContextImpl<DCRTPoly>> &self,const std::string &filename, const SerType::SERBINARY &sertype)
                     {
                         std::ifstream erkeys(filename, std::ios::in | std::ios::binary);
                          if (!erkeys.is_open()) {
                             std::cerr << "I cannot read serialization from " << filename << std::endl;
                          }
                         bool res;
-                        res = CryptoContextImpl<DCRTPoly>::DeserializeEvalAutomorphismKey<SerType::SERBINARY>(erkeys, sertype);
+                        res = self->DeserializeEvalAutomorphismKey<SerType::SERBINARY>(erkeys, sertype);
                         return res; });
 
     // Generator Functions
     m.def("GenCryptoContext", &GenCryptoContext<CryptoContextBFVRNS>);
     m.def("GenCryptoContext", &GenCryptoContext<CryptoContextBGVRNS>);
-    m.def("ReleaseAllContexts",&CryptoContextFactory<DCRTPoly>::ReleaseAllContexts);
+    m.def("GenCryptoContext", &GenCryptoContext<CryptoContextCKKSRNS>);
+    m.def("ReleaseAllContexts", &CryptoContextFactory<DCRTPoly>::ReleaseAllContexts);
 }
 
-void bind_enums_and_constants(py::module &m){
+void bind_enums_and_constants(py::module &m)
+{
     // Scheme Types
     py::enum_<SCHEME>(m, "SCHEME")
-            .value("INVALID_SCHEME", SCHEME::INVALID_SCHEME)
-            .value("CKKSRNS_SCHEME", SCHEME::CKKSRNS_SCHEME)
-            .value("BFVRNS_SCHEME", SCHEME::BFVRNS_SCHEME)
-            .value("BGVRNS_SCHEME", SCHEME::BGVRNS_SCHEME);
+        .value("INVALID_SCHEME", SCHEME::INVALID_SCHEME)
+        .value("CKKSRNS_SCHEME", SCHEME::CKKSRNS_SCHEME)
+        .value("BFVRNS_SCHEME", SCHEME::BFVRNS_SCHEME)
+        .value("BGVRNS_SCHEME", SCHEME::BGVRNS_SCHEME);
     // PKE Features
     py::enum_<PKESchemeFeature>(m, "PKESchemeFeature")
-            .value("PKE", PKESchemeFeature::PKE)
-            .value("KEYSWITCH", PKESchemeFeature::KEYSWITCH)
-            .value("PRE", PKESchemeFeature::PRE)
-            .value("LEVELEDSHE", PKESchemeFeature::LEVELEDSHE)
-            .value("ADVANCEDSHE", PKESchemeFeature::ADVANCEDSHE)
-            .value("MULTIPARTY", PKESchemeFeature::MULTIPARTY)
-            .value("FHE", PKESchemeFeature::FHE);
+        .value("PKE", PKESchemeFeature::PKE)
+        .value("KEYSWITCH", PKESchemeFeature::KEYSWITCH)
+        .value("PRE", PKESchemeFeature::PRE)
+        .value("LEVELEDSHE", PKESchemeFeature::LEVELEDSHE)
+        .value("ADVANCEDSHE", PKESchemeFeature::ADVANCEDSHE)
+        .value("MULTIPARTY", PKESchemeFeature::MULTIPARTY)
+        .value("FHE", PKESchemeFeature::FHE);
     // Serialization Types
-    py::class_<SerType::SERJSON >(m, "SERJSON");
+    py::class_<SerType::SERJSON>(m, "SERJSON");
     py::class_<SerType::SERBINARY>(m, "SERBINARY");
     m.attr("JSON") = py::cast(SerType::JSON);
     m.attr("BINARY") = py::cast(SerType::BINARY);
+
+    //Parameters Type
+    using ParmType = typename DCRTPoly::Params;
+    py::class_<ParmType, std::shared_ptr<ParmType>>(m, "ParmType");
 }
 
-void bind_keys(py::module &m){
-    py::class_<PublicKeyImpl<DCRTPoly>,std::shared_ptr<PublicKeyImpl<DCRTPoly>>>(m,"PublicKey")
-    .def(py::init<>());
-    py::class_<PrivateKeyImpl<DCRTPoly>,std::shared_ptr<PrivateKeyImpl<DCRTPoly>>>(m,"PrivateKey");
-    py::class_<KeyPair<DCRTPoly>>(m,"KeyPair")
-            .def_readwrite("publicKey", &KeyPair<DCRTPoly>::publicKey)
-            .def_readwrite("secretKey", &KeyPair<DCRTPoly>::secretKey);
+void bind_keys(py::module &m)
+{
+    py::class_<PublicKeyImpl<DCRTPoly>, std::shared_ptr<PublicKeyImpl<DCRTPoly>>>(m, "PublicKey")
+        .def(py::init<>());
+    py::class_<PrivateKeyImpl<DCRTPoly>, std::shared_ptr<PrivateKeyImpl<DCRTPoly>>>(m, "PrivateKey");
+    py::class_<KeyPair<DCRTPoly>>(m, "KeyPair")
+        .def_readwrite("publicKey", &KeyPair<DCRTPoly>::publicKey)
+        .def_readwrite("secretKey", &KeyPair<DCRTPoly>::secretKey);
 }
 
-void bind_encodings(py::module &m){
-    py::class_<PlaintextImpl,std::shared_ptr<PlaintextImpl>>(m,"Plaintext")
-    .def("GetScalingFactor", &PlaintextImpl::GetScalingFactor)
-    .def("SetScalingFactor", &PlaintextImpl::SetScalingFactor)
-    .def("GetLength", &PlaintextImpl::GetLength)
-    .def("GetSchemeID", &PlaintextImpl::GetSchemeID)
-    .def("SetLength", &PlaintextImpl::SetLength)
-    .def("IsEncoded", &PlaintextImpl::IsEncoded)
-    //.def("GetEncondingParams", &PlaintextImpl::GetEncondingParams)
-    .def("Encode", &PlaintextImpl::Encode)
-    .def("Decode", &PlaintextImpl::Decode)
-    .def("__repr__", [] (const PlaintextImpl& p) {
+void bind_encodings(py::module &m)
+{
+    py::class_<PlaintextImpl, std::shared_ptr<PlaintextImpl>>(m, "Plaintext")
+        .def("GetScalingFactor", &PlaintextImpl::GetScalingFactor)
+        .def("SetScalingFactor", &PlaintextImpl::SetScalingFactor)
+        .def("GetLength", &PlaintextImpl::GetLength)
+        .def("GetSchemeID", &PlaintextImpl::GetSchemeID)
+        .def("SetLength", &PlaintextImpl::SetLength)
+        .def("IsEncoded", &PlaintextImpl::IsEncoded)
+        .def("GetLogPrecision", &PlaintextImpl::GetLogPrecision)
+        //.def("GetEncondingParams", &PlaintextImpl::GetEncondingParams)
+        .def("Encode", &PlaintextImpl::Encode)
+        .def("Decode", &PlaintextImpl::Decode)
+        .def("__repr__", [](const PlaintextImpl &p)
+             {
         std::stringstream ss;
         ss << "<Plaintext Object: ";
         p.PrintValue(ss);
         ss << ">";
-        return ss.str();
-    })
-    .def("__str__", [] (const PlaintextImpl& p) {
+        return ss.str(); })
+        .def("__str__", [](const PlaintextImpl &p)
+             {
         std::stringstream ss;
         p.PrintValue(ss);
-        return ss.str();
-    });
-
+        return ss.str(); });
 }
 
-void bind_ciphertext(py::module &m){
-    py::class_<CiphertextImpl<DCRTPoly>,std::shared_ptr<CiphertextImpl<DCRTPoly>>>(m,"Ciphertext")
+void bind_ciphertext(py::module &m)
+{
+    py::class_<CiphertextImpl<DCRTPoly>, std::shared_ptr<CiphertextImpl<DCRTPoly>>>(m, "Ciphertext")
         .def(py::init<>());
-        // .def("GetDepth", &CiphertextImpl<DCRTPoly>::GetDepth)
-        // .def("SetDepth", &CiphertextImpl<DCRTPoly>::SetDepth)
-        // .def("GetLevel", &CiphertextImpl<DCRTPoly>::GetLevel)
-        // .def("SetLevel", &CiphertextImpl<DCRTPoly>::SetLevel)
-        // .def("GetHopLevel", &CiphertextImpl<DCRTPoly>::GetHopLevel)
-        // .def("SetHopLevel", &CiphertextImpl<DCRTPoly>::SetHopLevel)
-        // .def("GetScalingFactor", &CiphertextImpl<DCRTPoly>::GetScalingFactor)
-        // .def("SetScalingFactor", &CiphertextImpl<DCRTPoly>::SetScalingFactor)
-        // .def("GetSlots", &CiphertextImpl<DCRTPoly>::GetSlots)
-        // .def("SetSlots", &CiphertextImpl<DCRTPoly>::SetSlots);
+    // .def("GetDepth", &CiphertextImpl<DCRTPoly>::GetDepth)
+    // .def("SetDepth", &CiphertextImpl<DCRTPoly>::SetDepth)
+    // .def("GetLevel", &CiphertextImpl<DCRTPoly>::GetLevel)
+    // .def("SetLevel", &CiphertextImpl<DCRTPoly>::SetLevel)
+    // .def("GetHopLevel", &CiphertextImpl<DCRTPoly>::GetHopLevel)
+    // .def("SetHopLevel", &CiphertextImpl<DCRTPoly>::SetHopLevel)
+    // .def("GetScalingFactor", &CiphertextImpl<DCRTPoly>::GetScalingFactor)
+    // .def("SetScalingFactor", &CiphertextImpl<DCRTPoly>::SetScalingFactor)
+    // .def("GetSlots", &CiphertextImpl<DCRTPoly>::GetSlots)
+    // .def("SetSlots", &CiphertextImpl<DCRTPoly>::SetSlots);
 }
 
-
-PYBIND11_MODULE(openfhe, m) {
+PYBIND11_MODULE(openfhe, m)
+{
     m.doc() = "Open-Source Fully Homomorphic Encryption Library";
     bind_parameters(m);
     bind_crypto_context(m);

+ 24 - 0
src/pke/cryptocontext_wrapper.cpp

@@ -0,0 +1,24 @@
+#include <pybind11/pybind11.h>
+#include <pybind11/stl.h>
+#include <openfhe/pke/openfhe.h>
+#include <vector>
+#include <algorithm>
+#include <complex> 
+#include "cryptocontext_wrapper.h"
+
+using namespace lbcrypto;
+namespace py = pybind11;
+
+Plaintext MakeCKKSPackedPlaintextWrapper(std::shared_ptr<CryptoContextImpl<DCRTPoly>> &self, 
+            const std::vector<float> &value, 
+            size_t depth, uint32_t level, 
+            const std::shared_ptr<ParmType> params,
+            usint slots)
+            {
+                if (!value.size())
+                    OPENFHE_THROW(config_error, "Cannot encode an empty value vector");
+
+                std::vector<std::complex<double>> complexValue(value.size());
+                std::transform(value.begin(), value.end(), complexValue.begin(),
+                       [](float da) { return std::complex<double>(da); });
+                return self->MakeCKKSPackedPlaintext(complexValue, depth, level, params, slots); }

+ 1 - 1
src/pke/decryption.cpp

@@ -1,6 +1,6 @@
 #include <pybind11/pybind11.h>
 #include <pybind11/stl.h>
-#include <openfhe/pke/openfhe.h>
+#include "openfhe.h"
 #include "bindings.h"
 
 using namespace lbcrypto;

+ 6 - 6
src/pke/examples/simple-integers-serial.py

@@ -115,15 +115,15 @@ if not DeserializeFromFile(datafolder + "/key-public.txt", pk, BINARY):
 
 print("The public key has been deserialized.")
 
-# if cryptoContext.DeserializeEvalMultKey(datafolder + "/key-eval-mult.txt",BINARY):
-#    raise Exception("Could not deserialize the eval mult key file")
+if cryptoContext.DeserializeEvalMultKey(datafolder + "/key-eval-mult.txt",BINARY):
+   raise Exception("Could not deserialize the eval mult key file")
 
-# print("The relinearization key has been deserialized.")
+print("The relinearization key has been deserialized.")
 
-# if cryptoContext.DeserializeEvalAutomorphismKey(datafolder + "/key-eval-rot.txt",BINARY):
-#    raise Exception("Could not deserialize the eval rotation key file")
+if cryptoContext.DeserializeEvalAutomorphismKey(datafolder + "/key-eval-rot.txt",BINARY):
+   raise Exception("Could not deserialize the eval rotation key file")
 
-# print("Deserialized the eval rotation keys.")
+print("Deserialized the eval rotation keys.")
 
 # Deserialize the ciphertexts
 

+ 89 - 0
src/pke/examples/simple-real-numbers.py

@@ -0,0 +1,89 @@
+from openfhe import *
+
+multDepth = 1
+scaleModSize = 50
+batchSize = 8
+
+parameters = CCParamsCKKSRNS()
+parameters.SetMultiplicativeDepth(multDepth)
+parameters.SetScalingModSize(scaleModSize)
+parameters.SetBatchSize(batchSize)
+
+cc = GenCryptoContext(parameters)
+cc.Enable(PKESchemeFeature.PKE)
+cc.Enable(PKESchemeFeature.KEYSWITCH)
+cc.Enable(PKESchemeFeature.LEVELEDSHE)
+
+print("The CKKS scheme is using ring dimension: " + str(cc.GetRingDimension()))
+
+keys = cc.KeyGen()
+cc.EvalMultKeyGen(keys.secretKey)
+cc.EvalRotateKeyGen(keys.secretKey, [1, -2])
+
+x1 = [0.25, 0.5, 0.75, 1.0, 2.0, 3.0, 4.0, 5.0]
+x2 = [5.0, 4.0, 3.0, 2.0, 1.0, 0.75, 0.5, 0.25]
+
+ptx1 = cc.MakeCKKSPackedPlaintext(x1)
+ptx2 = cc.MakeCKKSPackedPlaintext(x2)
+
+print("Input x1: " + str(ptx1))
+print("Input x2: " + str(ptx2))
+
+# Encrypt the encoded vectors
+c1 = cc.Encrypt(keys.publicKey, ptx1)
+c2 = cc.Encrypt(keys.publicKey, ptx2)
+
+# Step 4: Evaluation
+# Homomorphic additions
+cAdd = cc.EvalAdd(c1, c2)
+# Homomorphic subtraction
+cSub = cc.EvalSub(c1, c2)
+# Homomorphic scalar multiplication
+cScalar = cc.EvalMult(c1,4)
+# Homomorphic multiplication
+cMult = cc.EvalMult(c1, c2)
+# Homomorphic rotations
+cRot1 = cc.EvalRotate(c1, 1)
+cRot2 = cc.EvalRotate(c1, -2)
+
+# Step 5: Decryption and output
+# Decrypt the result of additions
+ptAdd = Decrypt(cAdd,keys.secretKey)
+
+# We set the precision to 8 decimal digits for a nicer output.
+# If you want to see the error/noise introduced by CKKS, bump it up
+# to 15 and it should become visible.
+
+precision = 8
+print("Results of homomorphic computations:")
+result = Decrypt(c1, keys.secretKey)
+result.SetLength(batchSize)
+print("x1 = " + str(result))
+print("Estimated precision in bits: " + str(result.GetLogPrecision()))
+
+# Decrypt the result of scalar multiplication
+result = Decrypt(cScalar,keys.secretKey)
+result.SetLength(batchSize)
+print("4 * x1 = " + str(result))
+
+# Decrypt the result of multiplication
+result = Decrypt(cMult,keys.secretKey)
+result.SetLength(batchSize)
+print("x1 * x2 = " + str(result))
+
+# Decrypt the result of rotations
+result = Decrypt(cRot1,keys.secretKey)
+result.SetLength(batchSize)
+print("In rotations, very small outputs (~10^-10 here) correspond to 0's:")
+print("x1 rotated by 1 = " + str(result))
+
+result = Decrypt(cRot2,keys.secretKey)
+result.SetLength(batchSize)
+print("x1 rotated by -2 = " + str(result))
+
+
+
+
+
+
+

+ 4 - 4
src/pke/serialization.cpp

@@ -1,9 +1,9 @@
 #include <pybind11/pybind11.h>
 #include <pybind11/stl.h>
-#include <openfhe/pke/openfhe.h>
-#include <openfhe/pke/scheme/bfvrns/bfvrns-ser.h>
-#include <openfhe/pke/scheme/bgvrns/bgvrns-ser.h>
-#include <openfhe/pke/cryptocontext-ser.h>
+#include "openfhe.h"
+#include "scheme/bfvrns/bfvrns-ser.h"
+#include "scheme/bgvrns/bgvrns-ser.h"
+#include "cryptocontext-ser.h"
 #include "bindings.h"
 #include "serialization.h"