Browse Source

finishing simple ckks example

Rener Oliveira (Ubuntu WSL) 2 years ago
parent
commit
80f5cab0f8
2 changed files with 39 additions and 44 deletions
  1. 8 38
      src/bindings.cpp
  2. 31 6
      src/pke/examples/simple-real-numbers.py

+ 8 - 38
src/bindings.cpp

@@ -1,11 +1,11 @@
 #include <pybind11/pybind11.h>
 #include <pybind11/stl.h>
-//#include <pybind11/stl_bind.h>
 #include <pybind11/iostream.h>
 #include <iostream>
 #include <openfhe/pke/openfhe.h>
 #include <openfhe/pke/key/key-ser.h>
 #include "bindings.h"
+#include "cryptocontext.h"
 
 using namespace lbcrypto;
 namespace py = pybind11;
@@ -46,7 +46,7 @@ void bind_parameters(py::module &m){
 
 void bind_crypto_context(py::module &m)
 {
-    using ParmType = typename DCRTPoly::Params;
+    //using ParmType = typename DCRTPoly::Params;
     py::class_<CryptoContextImpl<DCRTPoly>, std::shared_ptr<CryptoContextImpl<DCRTPoly>>>(m, "CryptoContext")
         .def(py::init<>())
         .def("GetKeyGenLevel", &CryptoContextImpl<DCRTPoly>::GetKeyGenLevel)
@@ -57,55 +57,25 @@ void bind_crypto_context(py::module &m)
         .def("EvalMultKeyGen", &CryptoContextImpl<DCRTPoly>::EvalMultKeyGen, "Generate the evaluation key for multiplication")
         .def("EvalRotateKeyGen", &CryptoContextImpl<DCRTPoly>::EvalRotateKeyGen, "Generate the evaluation key for rotation",
              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("MakeCKKSPackedPlaintext2", static_cast<Plaintext (CryptoContextImpl<DCRTPoly>::*)(const std::vector<double>&, size_t, uint32_t, const std::shared_ptr<ParmType>, usint) const>(&CryptoContextImpl<DCRTPoly>::MakeCKKSPackedPlaintext), "Make a CKKS plaintext from a vector of floats",
-             py::arg("value"), py::arg("depth") = 1, py::arg("level") = 0, py::arg("params") = nullptr, py::arg("slots") = 0)
-        .def("MakeCKKSPackedPlaintext3",[](std::shared_ptr<CryptoContextImpl<DCRTPoly>> &self, py::list value, size_t depth, uint32_t level, const std::shared_ptr<ParmType> params, usint slots) -> auto {
-                std::vector<std::complex<double>> complexValue;
-                for (auto item : value)
-                    complexValue.push_back(item.cast<std::complex<double>>());
-
-                return self->MakeCKKSPackedPlaintext(complexValue, depth, level, params, slots);
-            }, "Make a CKKS plaintext from a list of floats",
-            py::arg("value"), py::arg("depth") = 1, py::arg("level") = 0, py::arg("params") = nullptr, py::arg("slots") = 0)
-        .def("MakeCKKSPackedPlaintext", [] (std::shared_ptr<CryptoContextImpl<DCRTPoly>> &self, const std::vector<float>& value, int depth, int level, std::shared_ptr<ParmType> params, int slots) -> auto {
-                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);},
-                "Make a CKKS plaintext from a vector of doubles",
-                py::arg("value"), py::arg("depth") = 1, py::arg("level") = 0, py::arg("params") = nullptr, py::arg("slots") = 0)
-        .def("MakeCKKSPackedPlaintext4",[](std::shared_ptr<CryptoContextImpl<DCRTPoly>> &self,const int &value, size_t depth, uint32_t level, const std::shared_ptr<ParmType> params, usint slots) -> auto {
-                std::vector<std::complex<double>> complexValue;
-                complexValue.push_back(std::complex<double>(value, 0));
-                return self->MakeCKKSPackedPlaintext(complexValue, depth, level, params, slots);
-            }, "Make a CKKS plaintext from a list of floats",
-            py::arg("value"), py::arg("depth") = 1, py::arg("level") = 0, py::arg("params") = nullptr, py::arg("slots") = 0)
-        .def("MakeCKKSPackedPlaintext5", [] (std::shared_ptr<CryptoContextImpl<DCRTPoly>> &self, const std::vector<float>& value) -> auto {
+       
+            //py::arg("value"), py::arg("depth") = 1, py::arg("level") = 0, py::arg("params") = nullptr, py::arg("slots") = 0)
+        .def("MakeCKKSPackedPlaintext", [](std::shared_ptr<CryptoContextImpl<DCRTPoly>> &self, const std::vector<float>& value){
                 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, 1, 0, nullptr, 0);},
-                "Make a CKKS plaintext from a vector of doubles",
+                return self->MakeCKKSPackedPlaintext(complexValue, 1, 0, nullptr, 0);
+                },"Make a CKKS plaintext from a vector of doubles",
                 py::arg("value"))
-
-        .def("Test_Member_Function",[](std::shared_ptr<CryptoContextImpl<DCRTPoly>> &self, const std::string &str) { 
-                std::cout << "Ring Dimension: " << self->GetRingDimension() << std::endl;
-                std::cout << "String: " << str << std::endl;
-            }, "A test member function that receives a string and print it along with ring dimension")
         .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(); },

+ 31 - 6
src/pke/examples/simple-real-numbers.py

@@ -23,9 +23,8 @@ 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]
 
-cc.Test_Member_Function('test')
-ptx1 = cc.MakeCKKSPackedPlaintext5(x1)
-ptx2 = cc.MakeCKKSPackedPlaintext5(x2)
+ptx1 = cc.MakeCKKSPackedPlaintext(x1)
+ptx2 = cc.MakeCKKSPackedPlaintext(x2)
 
 print("Input x1: " + str(ptx1))
 print("Input x2: " + str(ptx2))
@@ -37,11 +36,13 @@ c2 = cc.Encrypt(keys.publicKey, ptx2)
 # Step 4: Evaluation
 # Homomorphic additions
 cAdd = cc.EvalAdd(c1, c2)
-# Homomorphic Subtraction
+# Homomorphic subtraction
 cSub = cc.EvalSub(c1, c2)
-# Homomorphic Multiplication
+# Homomorphic scalar multiplication
+cScalar = cc.EvalMult(c1,4)
+# Homomorphic multiplication
 cMult = cc.EvalMult(c1, c2)
-# Homomorphic Rotations
+# Homomorphic rotations
 cRot1 = cc.EvalRotate(c1, 1)
 cRot2 = cc.EvalRotate(c1, -2)
 
@@ -60,5 +61,29 @@ 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))
+
+
+
+
+