Repository: OpenMined/PySyft
Pull request: Addition operation on FV scheme
## Description
Closes #3656
Addition operation on FV scheme.

**Implemented:**
- Support Ciphertext Ciphertext addition
- Support Ciphertext Plaintext addition
- Support Plaintext Plaintext addition


## How has this been tested?
Added tests for every private method and simultaneously tested the public method `add` function.

## Checklist
- [x] I have followed the [Contribution Guidelines](https://github.com/OpenMined/.github/blob/master/CONTRIBUTING.md) and [Code of Conduct](https://github.com/OpenMined/.github/blob/master/CODE_OF_CONDUCT.md)
- [x] I have commented my code following the [OpenMined Styleguide](https://github.com/OpenMined/.github/blob/master/STYLEGUIDE.md)
- [x] I have labeled this PR with the relevant [Type labels](https://github.com/OpenMined/.github/labels?q=Type%3A)
- [x] My changes are covered by tests


Problem statement:
Implement Addition operation for FV HE Scheme
## Feature Description
Addition operations of FV Scheme need to be implemented.

1. It can **Add** 2 ciphertexts objects.
2. It can **Add** a ciphertext with plaintext objects.

In both cases, the result should be returned as a ciphertext object.

Hints from issue discussion:

Commit message: Docs update

Patch to review:
diff --git a/examples/experimental/FV HE Experimentation.ipynb b/examples/experimental/FV HE Experimentation.ipynb
index 0c852f98bad..15b2b2a3b5a 100644
--- a/examples/experimental/FV HE Experimentation.ipynb	
+++ b/examples/experimental/FV HE Experimentation.ipynb	
@@ -19,6 +19,8 @@
     }
    ],
    "source": [
+    "import random\n",
+    "\n",
     "from syft.frameworks.torch.he.fv.modulus import CoeffModulus\n",
     "from syft.frameworks.torch.he.fv.encryption_params import EncryptionParams\n",
     "from syft.frameworks.torch.he.fv.context import Context\n",
@@ -27,7 +29,8 @@
     "from syft.frameworks.torch.he.fv.encryptor import Encryptor\n",
     "from syft.frameworks.torch.he.fv.decryptor import Decryptor\n",
     "from syft.frameworks.torch.he.fv.integer_encoder import IntegerEncoder\n",
-    "from syft.frameworks.torch.he.fv.modulus import SeqLevelType"
+    "from syft.frameworks.torch.he.fv.modulus import SeqLevelType\n",
+    "from syft.frameworks.torch.he.fv.evaluator import Evaluator"
    ]
   },
   {
@@ -43,8 +46,7 @@
    "metadata": {},
    "outputs": [],
    "source": [
-    "params = EncryptionParams(128, CoeffModulus().create(128, [40, 40]), 1<<7 )\n",
-    "ctx = Context(params)\n",
+    "ctx = Context(EncryptionParams(128, CoeffModulus().create(128, [30]), 128 ))\n",
     "keygenerator = KeyGenerator(ctx)\n",
     "sk, pk = keygenerator.keygen()"
    ]
@@ -57,43 +59,30 @@
     {
      "output_type": "stream",
      "name": "stdout",
-     "text": "[1099511607041, 1099511619841]\n"
+     "text": "[1073738753]\n"
     }
    ],
    "source": [
-    "print(ctx.param.coeff_modulus)\n"
+    "print(ctx.param.coeff_modulus)"
    ]
   },
   {
    "cell_type": "code",
    "execution_count": 4,
    "metadata": {},
-   "outputs": [
-    {
-     "output_type": "stream",
-     "name": "stdout",
-     "text": "2\nsecret key values :  [[1099511607040, 1, 1099511607040, 0, 1099511607040, 1, 0, 0, 1, 1099511607040, 0, 1, 0, 0, 1099511607040, 1099511607040, 0, 1099511607040, 0, 0, 1099511607040, 1, 1, 1099511607040, 0, 1, 1, 1, 1099511607040, 1099511607040, 0, 1, 1, 0, 1099511607040, 1, 1, 1, 0, 0, 1, 1, 1, 1099511607040, 1, 1, 1099511607040, 0, 0, 0, 1099511607040, 1099511607040, 1099511607040, 0, 0, 1099511607040, 0, 0, 1, 0, 1099511607040, 1099511607040, 1099511607040, 0, 1099511607040, 0, 0, 1, 0, 1099511607040, 1099511607040, 1099511607040, 1099511607040, 1099511607040, 0, 1, 0, 0, 1099511607040, 0, 1099511607040, 1, 0, 1099511607040, 1099511607040, 1, 0, 1099511607040, 0, 1099511607040, 1099511607040, 1099511607040, 0, 0, 0, 0, 1, 1099511607040, 0, 1099511607040, 1, 1099511607040, 0, 1099511607040, 1099511607040, 1099511607040, 1099511607040, 1, 0, 1099511607040, 0, 1, 0, 1, 1099511607040, 0, 1099511607040, 1099511607040, 0, 0, 1, 0, 1, 1, 1099511607040, 1099511607040, 1, 1099511607040], [1099511619840, 1, 1099511619840, 0, 1099511619840, 1, 0, 0, 1, 1099511619840, 0, 1, 0, 0, 1099511619840, 1099511619840, 0, 1099511619840, 0, 0, 1099511619840, 1, 1, 1099511619840, 0, 1, 1, 1, 1099511619840, 1099511619840, 0, 1, 1, 0, 1099511619840, 1, 1, 1, 0, 0, 1, 1, 1, 1099511619840, 1, 1, 1099511619840, 0, 0, 0, 1099511619840, 1099511619840, 1099511619840, 0, 0, 1099511619840, 0, 0, 1, 0, 1099511619840, 1099511619840, 1099511619840, 0, 1099511619840, 0, 0, 1, 0, 1099511619840, 1099511619840, 1099511619840, 1099511619840, 1099511619840, 0, 1, 0, 0, 1099511619840, 0, 1099511619840, 1, 0, 1099511619840, 1099511619840, 1, 0, 1099511619840, 0, 1099511619840, 1099511619840, 1099511619840, 0, 0, 0, 0, 1, 1099511619840, 0, 1099511619840, 1, 1099511619840, 0, 1099511619840, 1099511619840, 1099511619840, 1099511619840, 1, 0, 1099511619840, 0, 1, 0, 1, 1099511619840, 0, 1099511619840, 1099511619840, 0, 0, 1, 0, 1, 1, 1099511619840, 1099511619840, 1, 1099511619840]]\n"
-    }
-   ],
+   "outputs": [],
    "source": [
-    "print(len(sk.data))\n",
-    "print('secret key values : ', sk.data)"
+    "# print(len(sk.data))\n",
+    "# print('secret key values : ', sk.data)"
    ]
   },
   {
    "cell_type": "code",
    "execution_count": 5,
    "metadata": {},
-   "outputs": [
-    {
-     "output_type": "stream",
-     "name": "stdout",
-     "text": "[[[964174082904, 850373235682, 978379498969, 415843427838, 197659747211, 788758661840, 254126077558, 962698441104, 384316079722, 956718713007, 380903014655, 462528075481, 588725214856, 383566100423, 214941947947, 470777328767, 688802314026, 666238506134, 868269072127, 951257939441, 159888481231, 984731270824, 782293359403, 755546621709, 937370835738, 711424938917, 994413865398, 428401841314, 567961218045, 21738632468, 418716678209, 1099207415623, 11890527895, 199781653947, 962675577524, 971971247693, 1032338459159, 661316426091, 1063787429485, 121079440287, 649300602225, 357295494954, 499784827730, 951207994688, 324165183515, 619877396929, 933098610333, 134911866283, 160367225211, 570634510418, 733905767831, 5652802079, 290234450541, 956336696716, 544996288219, 1055708704002, 1009936743924, 358838787038, 356763748139, 416754947028, 844735155055, 361554955960, 623857055717, 990969550155, 727338050931, 118499549383, 156939576667, 508980251, 226607083954, 622716032650, 472173901339, 1010902945000, 1039826942288, 130239377613, 731952357213, 1069132087124, 1016120622582, 276272438418, 878156308180, 1047372560258, 12098571198, 380626418477, 150443688672, 251683050079, 185071783430, 696862720406, 614092927699, 585757282680, 510475160731, 150816205562, 250099658653, 1096185382901, 437635898547, 441658254620, 615414922303, 835747171245, 264579158570, 828875050789, 177898340078, 819273229910, 391905069478, 1073329712248, 110969260065, 213055363838, 566534982118, 737532523957, 397597868976, 608015675201, 437143257037, 994561341332, 323100023238, 303947484595, 124927783612, 352192855388, 493474741712, 169153167591, 157291363437, 602449973672, 821143647400, 755425653354, 938348299015, 574607095562, 26631988482, 1000039408335, 288540962140, 56031423235, 585104420276, 698566640736], [511310093818, 523630849296, 606753421158, 117685121448, 848140878638, 152122301414, 783661801430, 705556957959, 695435642565, 973232401459, 1040667697989, 252429963935, 1049185953724, 847852776240, 976287229046, 540677170256, 29054129350, 828028883012, 54570806093, 414099942550, 1012521129984, 46805022728, 1063860983546, 489076778828, 473270949779, 453529088262, 726146508400, 820624105187, 266385531951, 807511399850, 226214326291, 831499819691, 976157932573, 880533361081, 854649617751, 233500914831, 528680362199, 129107388489, 955549406072, 638689184084, 643099003984, 640748587629, 179726229602, 1038947598036, 643029838215, 837079500863, 1067427357212, 240960575088, 289461100799, 692954018446, 1023870313716, 230769226719, 391149607008, 820943729665, 250276259278, 924087370465, 627450039667, 755287863552, 676972626888, 930742045706, 439443723007, 567404939453, 77862955726, 810866112120, 992348838764, 574919127287, 56038730161, 263906900213, 511864340748, 518008657364, 148290912007, 768306881309, 624461326479, 32695060485, 320748002775, 783154773930, 985967101782, 678532686180, 227753795928, 1022369885385, 930434377237, 723567295042, 382471745171, 1043115393487, 690509827772, 924341631151, 478769521113, 408163724499, 975218488795, 330405704620, 266165962078, 899694019303, 602014843889, 787836727837, 252190723828, 824342012211, 553795167946, 957221058951, 387454506946, 46036783017, 397585138654, 21333436012, 500926722509, 814902081526, 1034541121779, 404258039796, 444746780415, 900641038028, 165652709803, 318582892070, 302694387677, 1053617752735, 857018321379, 781077396900, 473355029329, 185954028906, 132752023132, 1077230976046, 892692585338, 16742053942, 16857007704, 579201179867, 124382513077, 470432475641, 11462090352, 566560443353, 499177974350, 1061762577448]], [[887086375737, 599767075666, 561895454746, 668862977203, 712036208964, 259469497217, 695761161101, 157598156275, 870164053756, 499773100077, 136343210543, 506474029492, 804994853304, 66295312344, 708310571452, 429012422661, 957067639474, 841444252086, 180766167648, 212100094167, 355930664763, 197568597100, 996093047729, 407465061619, 181917171612, 105121092261, 710470975238, 1004739046699, 889423725541, 201681665918, 199892778248, 464500189498, 215470523455, 105388137513, 521235026533, 660268746817, 1030385532240, 8354833348, 898138994621, 507421117644, 51741186505, 991936724999, 387105198597, 406162189288, 605257385039, 730991997978, 577330674206, 194567043561, 821758795939, 181475294655, 704652541403, 316757627957, 327661425601, 63544087631, 147236970349, 593322241270, 390440633270, 787182441512, 499072888635, 613874734375, 592549827013, 957435764943, 575615366590, 684521993868, 332733266917, 957393610647, 77807777903, 812159895539, 288646205671, 736185471509, 642817743489, 1049004363032, 692109056949, 866035119616, 823794857935, 414910001149, 724438453829, 1043185585975, 167122784284, 572509545807, 911315036952, 468866317246, 648036636780, 112982324904, 1000151728422, 890456488582, 817831831553, 1004598316818, 584403807003, 783744553943, 626695725621, 165464398008, 663874829214, 1080221287003, 388328293656, 391164621285, 1064765101743, 331862080682, 17416387002, 296522282501, 821773938593, 85952923022, 4596196251, 279103961498, 286551601749, 529015681931, 914897195982, 164962510805, 537849811407, 596116415628, 628264504119, 284864996462, 65647148047, 1076894171165, 508937214130, 706569998178, 1087789679762, 425697009508, 726996791848, 533905761451, 23504277804, 667685854854, 187082555441, 787097382396, 166047411468, 31239764477, 722501831639, 888511589720], [296824459076, 129786801273, 241639513121, 71462996314, 564571094773, 986202385414, 72044462546, 825232369538, 542294938938, 783556925133, 324251354745, 663152117792, 244377093814, 637806442398, 351950961817, 608544757438, 177689071545, 921822658524, 330313809294, 911708558279, 901475028040, 308684634180, 149769160906, 633504007068, 981679690806, 742385856637, 815023129124, 355484507869, 482146954900, 893774091331, 677163695620, 837606745635, 605087858946, 911292323715, 318154031924, 920589917196, 400240891416, 298294184570, 944916521740, 671755689804, 422460624236, 469326287013, 97178156090, 550798248641, 767645328818, 562093896863, 206627312943, 973847890022, 29331129456, 1023546517798, 107844461493, 1026671455238, 508551561952, 760793632073, 57390119164, 41674286694, 870322217565, 488393111307, 174527556761, 1084044319647, 601321096364, 859387937508, 493837375544, 595039789406, 457964163258, 729866700627, 911275215488, 123371329573, 84579136152, 534960811310, 733840293959, 737558077990, 809634489991, 428740170927, 912321434521, 885503163031, 412796402856, 473118203792, 484457258865, 486134806860, 240065012818, 778381215166, 590100350853, 460656852009, 875531625745, 60953014730, 1039051500953, 532614451026, 489386728046, 12604363849, 206886078809, 133263765787, 698852096352, 747213044156, 1007042677022, 717276292545, 1021258410551, 480158905302, 933641216787, 907268844293, 993884886460, 981747220122, 906861031963, 539466019465, 288640136666, 195662556282, 844240738595, 853793411911, 116306130479, 469101263144, 635668002205, 672483479275, 20759556892, 983094814389, 49067654203, 16695179064, 292922818235, 773354575196, 848135154740, 748472202229, 769957215929, 843420943232, 262441145395, 423249104179, 75568994070, 144918274862, 867666124099, 383414197059]]]\n<syft.frameworks.torch.he.fv.public_key.PublicKey object at 0x107519850>\n"
-    }
-   ],
+   "outputs": [],
    "source": [
-    "print(pk.data)\n",
-    "print(pk)\n",
+    "# print(pk.data)\n",
     "# print('public key values : ', pk.data)"
    ]
   },
@@ -107,19 +96,24 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 13,
+   "execution_count": 6,
    "metadata": {},
    "outputs": [
     {
      "output_type": "stream",
      "name": "stdout",
-     "text": "[0, 1, 1, 1, 0, 1, 1]\n"
+     "text": "[1, 0, 0, 1, 1, 1, 0, 0, 1, 1]     [1, 1, 0, 1, 0, 0, 1, 0, 1]     [1, 1, 1, 0, 1, 1, 0, 1, 1]\n"
     }
    ],
    "source": [
     "int_encoder = IntegerEncoder(ctx)\n",
-    "plaintext = int_encoder.encode(110)\n",
-    "print(plaintext.data)\n",
+    "ri1 = random.randint(0,1000)\n",
+    "ri2 = random.randint(0,1000)\n",
+    "ri3 = random.randint(0,1000)\n",
+    "pt1 = int_encoder.encode(ri1)\n",
+    "pt2 = int_encoder.encode(ri2)\n",
+    "pt3 = int_encoder.encode(ri3)\n",
+    "print(pt1.data,\"   \", pt2.data, \"   \", pt3.data)\n",
     "# print('plaintext data',plaintext.data)"
    ]
   },
@@ -138,11 +132,13 @@
     {
      "output_type": "stream",
      "name": "stdout",
-     "text": "110\n"
+     "text": "825\n331\n439\n"
     }
    ],
    "source": [
-    "print(int_encoder.decode(plaintext))"
+    "print(int_encoder.decode(pt1))\n",
+    "print(int_encoder.decode(pt2))\n",
+    "print(int_encoder.decode(pt3))"
    ]
   },
   {
@@ -157,19 +153,20 @@
    "cell_type": "code",
    "execution_count": 8,
    "metadata": {},
-   "outputs": [
-    {
-     "output_type": "stream",
-     "name": "stdout",
-     "text": "<syft.frameworks.torch.he.fv.ciphertext.CipherText object at 0x107519250>\nciphertext data : [[[535562519665, 886768163865, 297892494300, 968346898392, 622107070335, 1077884880377, 951678553528, 1059816751518, 335805453222, 233515490532, 480108829678, 765913691467, 787734059567, 552399491757, 313105618767, 719546646087, 375880647827, 628561498084, 621872052923, 156298033504, 328742233978, 900517124627, 756418205127, 1067773700553, 726276195043, 658283421806, 208006187788, 530479422068, 508116688987, 376721035286, 168619123858, 919256582331, 2032498433, 14303017904, 872910166499, 7453438095, 165306555439, 688722768551, 447584282080, 523643842516, 933619798800, 936398277066, 750657280362, 145198170317, 480406164416, 728388214567, 975167998833, 482966255145, 972644821221, 761571587141, 239667697511, 838497808431, 60185415536, 237830496767, 249428061969, 171479677532, 344599941862, 343171956107, 894698793771, 579283532754, 520700104601, 945324622519, 684215805984, 40889135803, 871233450135, 453718018741, 639795790462, 322331041673, 214627432810, 421059973288, 1041838428876, 347112586803, 178257442836, 466988407603, 507538035240, 649915928825, 1045820678731, 94138716865, 463862241031, 563681603207, 207868325175, 954137960813, 599984965094, 900106980920, 968882407086, 270671086037, 948264973878, 554523256812, 437583848576, 270681202497, 270036014589, 793726071780, 380375543135, 615953283450, 659494168987, 883296920614, 631661751963, 807523626309, 453088891527, 901341477245, 555410714920, 638649702569, 999207326555, 1077832099465, 454756737391, 411130635097, 585807713083, 151050903859, 142735906200, 815627225991, 552339625749, 183613794598, 551468479016, 1087582263305, 948816558956, 442001561115, 374325661069, 607178343078, 216876649226, 469733430018, 273184101315, 776246399031, 445623597934, 83908134264, 11344692395, 785136846656, 518173865345, 902823865362], [398070366015, 887146557203, 264077685342, 852567298236, 424014826600, 921985141778, 359425392449, 1034026379329, 382111755426, 471009996754, 1081138802092, 327936437586, 306958031556, 790492717511, 449629461815, 231606418641, 489009986921, 637843412340, 910252669387, 464709483733, 481599397746, 649856837350, 590452272751, 435593969763, 563774640156, 94557185023, 629450408835, 387535759432, 216628633179, 878032040637, 369947518209, 1015609821129, 147090878613, 800035035665, 432583285867, 511120063799, 481512156522, 103941624187, 846002496974, 735929279412, 251501642777, 739868393381, 10488418785, 785623019272, 144188401752, 151124961740, 695271847472, 306235625128, 425252812956, 177516345709, 1083252380570, 458802834026, 575605260246, 1013592158052, 223401149563, 1059632421597, 931051467217, 53068004571, 57542209526, 330767153524, 801104276262, 584563441098, 712980145544, 986490814929, 205439948757, 868960495749, 637347401057, 374808890082, 160925934097, 722216261192, 197174332904, 148223833162, 487806088380, 912521636735, 476237210441, 673797796517, 383031813171, 286225288140, 819143395949, 470238294870, 49139265856, 421871516245, 655785936720, 420305902330, 548758627650, 2919543090, 530263521801, 151945589376, 897931693535, 23807674583, 596652542908, 537935747515, 1076576628815, 292205323427, 101319819808, 313784850180, 287610102535, 41607337015, 764190919704, 780136341087, 413237336844, 146731243804, 36564883936, 356873886396, 386280818582, 1058708716206, 604349045890, 570341612168, 696894476556, 453177996004, 964923046542, 547945996064, 304728678636, 548689610119, 5726211371, 931691287119, 512899880496, 658953971219, 950846097458, 683293059789, 620676907280, 1060224607868, 266016915339, 417170628397, 959998514383, 770182580003, 497314299144, 490621335265]], [[457006039656, 642797275902, 752635382625, 46770977529, 971990175387, 523481523640, 656153731450, 94276731252, 882553713231, 229934403852, 339032020959, 1047945725310, 199472360611, 1055137793396, 821175913674, 658554962139, 1084767066752, 404279359012, 653364221376, 1068323448381, 256791403662, 571393574694, 596938205679, 9704798080, 499784733425, 981084954624, 906849992482, 1033221677305, 424533150722, 336107894102, 763312902658, 162001291199, 556368263034, 167979308521, 41486434783, 654907588662, 878147234299, 442670376127, 930970570863, 582136426849, 918380600284, 285170070974, 1086201848150, 131869490527, 1054243925972, 149283506766, 282095842942, 606204135346, 829967283088, 678815864931, 7549131175, 1068900490140, 74543548312, 989654114603, 583468291218, 724011943101, 385952023446, 602226612200, 841383191014, 6605847549, 1077652846170, 1071518267317, 407713035909, 451335037945, 38552196791, 727632409542, 996070677926, 1020120307983, 448057703926, 532578716371, 358214827105, 242248686937, 718294925594, 891051746483, 505886490762, 1049965562988, 107766854734, 473098174040, 937846003457, 603987754358, 856919774979, 340956375157, 916209904825, 566029702985, 109225203206, 307908937217, 916020700902, 942750556496, 585548007871, 888248658871, 906786842934, 684754564421, 663966100955, 699199309071, 131489543559, 270227245999, 1076697394602, 1047031169595, 164669655475, 217182502147, 320144396415, 632995150762, 14561881489, 881554975483, 103440632663, 314622912110, 749981344011, 412092687267, 862656029320, 980680667021, 562175837380, 308181767830, 815080865992, 833778319950, 947715309223, 369984575690, 420161651485, 476875378980, 469657063897, 964816394478, 584359293804, 204707218106, 435592268690, 266597952027, 317959612306, 707564189820, 12526837540, 211077440962], [675668454071, 592212612362, 281622301356, 572710094559, 69069350828, 1008932507875, 956276414268, 327187499117, 226358062566, 174183069267, 631279208239, 233471939407, 425385419684, 211131398519, 661365976023, 681741485603, 318492875599, 135635176867, 474675823802, 476483031506, 191422949471, 488749425685, 706567225981, 562838095443, 601463559975, 425204246244, 264248154708, 642587627845, 1069088388940, 153655307621, 362185909951, 933848990723, 406355713889, 447214392895, 319731396394, 29722654957, 738420816750, 270376310971, 182666316935, 669272026809, 553909804018, 334351592977, 973555945640, 268273559738, 551202085349, 764935199342, 294759316297, 959691817377, 988855887236, 1053637882889, 311894368320, 717489530242, 1030176827060, 310128136253, 700122368201, 178811249544, 956323932799, 381256235745, 654337651968, 967675380526, 1035369841393, 591827263202, 499896866393, 355898244117, 10470064361, 627471157064, 393822984108, 116567237450, 231536568329, 889895932851, 130142418185, 127740414373, 190923140351, 879436197072, 259756992792, 418543869428, 332926864298, 84694713586, 299370240308, 263597802938, 1088260283896, 151574973497, 469277255399, 665996873825, 674394156505, 80805231733, 885490129475, 275547345016, 928935029436, 91083000442, 207044819403, 866735243646, 507044545758, 892331609916, 260189303189, 593252263094, 366123200773, 181016429846, 678038991999, 604014116106, 237470108159, 605836365925, 878891549393, 370623977279, 877657318116, 636745241693, 579895296844, 673177217493, 28695565155, 162775515554, 242295098521, 934661765631, 751176481593, 499011803265, 658656115401, 239772186975, 98095457244, 647296963749, 308591593114, 223691272834, 889247184624, 143589159067, 318394255410, 69371309522, 512558598143, 211668335698, 660535716147, 375048630660]]]\nlen ciphertext data : 2\n"
-    }
-   ],
+   "outputs": [],
+   "source": [
+    "encrypter = Encryptor(ctx, pk)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "metadata": {},
+   "outputs": [],
    "source": [
-    "encrypter = Encryptor(ctx, pk)\n",
-    "ciphertext = encrypter.encrypt(plaintext)\n",
-    "print(ciphertext)\n",
-    "print('ciphertext data :', ciphertext.data)\n",
-    "print('len ciphertext data :', len(ciphertext.data))"
+    "ct1 = encrypter.encrypt(pt1)\n",
+    "ct2 = encrypter.encrypt(pt2)\n",
+    "ct3 = encrypter.encrypt(pt3)"
    ]
   },
   {
@@ -189,90 +186,120 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 9,
+   "execution_count": 10,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "decrypter = Decryptor(ctx, sk)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 11,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "dec1 = decrypter.decrypt(ct1)\n",
+    "dec2 = decrypter.decrypt(ct2)\n",
+    "dec3 = decrypter.decrypt(ct3)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 12,
    "metadata": {},
    "outputs": [
     {
      "output_type": "stream",
      "name": "stdout",
-     "text": "len :  7\n[0, 1, 1, 1, 0, 1, 1]\n<syft.frameworks.torch.he.fv.plaintext.PlainText object at 0x14ba7c8d0>\n"
+     "text": "825     331     439\n"
     }
    ],
    "source": [
-    "decrypter = Decryptor(ctx, sk)\n",
-    "result = decrypter.decrypt(ciphertext)\n",
-    "print(\"len : \",len(result.data))\n",
-    "print(result.data)\n",
-    "print(result)"
+    "print(int_encoder.decode(dec1), \"   \", int_encoder.decode(dec2), \"   \", int_encoder.decode(dec3))"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Evaluator"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 10,
+   "execution_count": 13,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "eval = Evaluator(ctx)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 14,
    "metadata": {},
    "outputs": [
     {
      "output_type": "stream",
      "name": "stdout",
-     "text": "110\n"
+     "text": "1156\n"
     }
    ],
    "source": [
-    "print(int_encoder.decode(result))"
+    "cc12 = eval.add(ct1, ct2)\n",
+    "cc12 = decrypter.decrypt(cc12)\n",
+    "print(int_encoder.decode(cc12))"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 11,
+   "execution_count": 15,
    "metadata": {},
-   "outputs": [],
+   "outputs": [
+    {
+     "output_type": "stream",
+     "name": "stdout",
+     "text": "1156\n"
+    }
+   ],
    "source": [
-    "import numpy as np\n",
-    "from numpy.polynomial import polynomial as poly\n",
-    "sk = [[1,1,1],[1,2,3]]\n",
-    "cm = [3,5]\n",
-    "def get_sufficient_sk_power(max_power):\n",
-    "    \"\"\"Generate an list of secret key polynomial raised to 1...max_power\"\"\"\n",
-    "    sk_power = [0] * (max_power)\n",
-    "    for i in range(1, max_power):\n",
-    "        sk_power[i] = [0] * len(cm)  # for every polynomial.\n",
-    "\n",
-    "    sk_power[0] = sk\n",
-    "\n",
-    "    for i in range(2, max_power+1):\n",
-    "        for j in range(len(cm)):\n",
-    "            sk_power[i-1][j] = poly.polypow(sk[j], i).astype(int).tolist()\n",
-    "    return sk_power"
+    "pc12 = eval.add(pt1, ct2)\n",
+    "pc12 = decrypter.decrypt(pc12)\n",
+    "print(int_encoder.decode(pc12))"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 12,
+   "execution_count": 16,
    "metadata": {},
    "outputs": [
     {
      "output_type": "stream",
      "name": "stdout",
-     "text": "[[[1, 1, 1], [1, 2, 3]]]\n"
+     "text": "1156\n"
     }
    ],
    "source": [
-    "print(get_sufficient_sk_power(1))"
+    "pp12 = eval.add(pt1, pt2)\n",
+    "print(int_encoder.decode(pp12))"
    ]
   },
   {
-   "cell_type": "code",
-   "execution_count": null,
+   "cell_type": "markdown",
    "metadata": {},
-   "outputs": [],
-   "source": []
+   "source": [
+    "### Verify result"
+   ]
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 17,
    "metadata": {},
    "outputs": [],
-   "source": []
+   "source": [
+    "assert int_encoder.decode(cc12) == int_encoder.decode(pc12) == int_encoder.decode(pp12) == ri1+ri2"
+   ]
   }
  ],
  "metadata": {
diff --git a/syft/frameworks/torch/he/fv/evaluator.py b/syft/frameworks/torch/he/fv/evaluator.py
new file mode 100644
index 00000000000..334b2b8c366
--- /dev/null
+++ b/syft/frameworks/torch/he/fv/evaluator.py
@@ -0,0 +1,91 @@
+import copy
+
+from syft.frameworks.torch.he.fv.util.operations import poly_add_mod
+from syft.frameworks.torch.he.fv.util.operations import multiply_add_plain_with_delta
+from syft.frameworks.torch.he.fv.ciphertext import CipherText
+from syft.frameworks.torch.he.fv.plaintext import PlainText
+from syft.frameworks.torch.he.fv.integer_encoder import IntegerEncoder
+
+
+class Evaluator:
+    def __init__(self, context):
+        self.context = context
+        self.coeff_modulus = context.param.coeff_modulus
+
+    def add(self, op1, op2):
+        """Adds two operands using FV scheme.
+
+        Args:
+            op1 (Ciphertext/Plaintext): First argument.
+            op2 (Ciphertext/Plaintext): Second argument.
+
+        Retruns:
+            If both arguments are Plaintext elements then the result will be a Plaintext object
+                otherwise a Ciphertext object with value equivalent to the result of addition
+                operation of two provided arguments.
+        """
+        op1, op2 = copy.deepcopy(op1), copy.deepcopy(op2)
+
+        if isinstance(op1, CipherText) and isinstance(op2, CipherText):
+            return self._add_cipher_cipher(op1, op2)
+
+        elif isinstance(op1, PlainText) and isinstance(op2, PlainText):
+            return self._add_plain_plain(op1, op2)
+
+        elif isinstance(op1, PlainText) and isinstance(op2, CipherText):
+            return self._add_plain_cipher(op1, op2)
+
+        elif isinstance(op1, CipherText) and isinstance(op2, PlainText):
+            return self._add_plain_cipher(op2, op1)
+
+        else:
+            raise TypeError(f"Addition Operation not supported between {type(op1)} and {type(op2)}")
+
+    def _add_cipher_cipher(self, ct1, ct2):
+        """Adds two ciphertexts.
+
+        Args:
+            ct1 (Ciphertext): First argument.
+            ct2 (Ciphertext): Second argument.
+
+        Retruns:
+            A Ciphertext object with value equivalent to result of addition of two provided
+                arguments.
+        """
+        ct1, ct2 = copy.deepcopy(ct1.data), copy.deepcopy(ct2.data)
+        result = ct2 if len(ct2) > len(ct1) else ct1
+
+        for i in range(min(len(ct1), len(ct2))):
+            for j in range(len(self.coeff_modulus)):
+                result[i][j] = poly_add_mod(ct1[i][j], ct2[i][j], self.coeff_modulus[j])
+
+        return CipherText(result)
+
+    def _add_plain_cipher(self, pt, ct):
+        """Adds a ciphertext and a plaintext.
+
+        Args:
+            pt (Plaintext): First argument.
+            ct (Ciphertext): Second argument.
+        Retruns:
+            A Ciphertext object with value equivalent to result of addition of two provided
+                arguments.
+        """
+        pt, ct = copy.deepcopy(pt), copy.deepcopy(ct)
+        return multiply_add_plain_with_delta(ct, pt, self.context)
+
+    def _add_plain_plain(self, pt1, pt2):
+        """Adds two plaintexts object.
+
+        Args:
+            pt1 (Plaintext): First argument.
+            pt2 (Plaintext): Second argument.
+
+        Retruns:
+            A Plaintext object with value equivalent to result of addition of two provided
+                arguments.
+        """
+        pt1, pt2 = copy.deepcopy(pt1), copy.deepcopy(pt2)
+        encoder = IntegerEncoder(self.context)
+
+        return encoder.encode(encoder.decode(pt1) + encoder.decode(pt2))
diff --git a/syft/frameworks/torch/he/fv/util/operations.py b/syft/frameworks/torch/he/fv/util/operations.py
index 2c5052bd020..9a632bc76de 100644
--- a/syft/frameworks/torch/he/fv/util/operations.py
+++ b/syft/frameworks/torch/he/fv/util/operations.py
@@ -152,10 +152,10 @@ def xgcd(x, y):
 
 
 def multiply_add_plain_with_delta(phase, message, context):
-    """Add message (PlainText) into phase.
+    """Add message into phase.
 
     Args:
-        phase: phase is pre-computed carrier polynomial where we can add message data.
+        phase (Ciphertext): phase is pre-computed carrier polynomial where we can add message data.
         message (Plaintext): A plaintext representation of integer data to be encrypted.
         context (Context): Context for extracting encryption parameters.
 
diff --git a/test/torch/tensors/test_fv.py b/test/torch/tensors/test_fv.py
index 7872569ee2c..8540ffa5c9e 100644
--- a/test/torch/tensors/test_fv.py
+++ b/test/torch/tensors/test_fv.py
@@ -19,6 +19,7 @@
 from syft.frameworks.torch.he.fv.util.operations import reverse_bit
 from syft.frameworks.torch.he.fv.encryptor import Encryptor
 from syft.frameworks.torch.he.fv.decryptor import Decryptor
+from syft.frameworks.torch.he.fv.evaluator import Evaluator
 
 
 @pytest.mark.parametrize(
@@ -373,3 +374,54 @@ def test_fv_encryption_decrption_without_changing_parameters():
         ct = encryptor.encrypt(encoder.encode(value))
         for _ in range(3):
             assert value == encoder.decode(decryptor.decrypt(ct))
+
+
+@pytest.mark.parametrize("int1, int2", [(0, 0), (-1, 1), (100, -10), (1000, 100), (-1000, 100)])
+def test_fv_add_cipher_cipher(int1, int2):
+    ctx = Context(EncryptionParams(1024, CoeffModulus().create(1024, [30, 30]), 1024))
+    keys = KeyGenerator(ctx).keygen()
+    encoder = IntegerEncoder(ctx)
+    encryptor = Encryptor(ctx, keys[1])  # keys[1] = public_key
+    decryptor = Decryptor(ctx, keys[0])  # keys[0] = secret_key
+    evaluator = Evaluator(ctx)
+
+    op1 = encryptor.encrypt(encoder.encode(int1))
+    op2 = encryptor.encrypt(encoder.encode(int2))
+    assert (
+        int1 + int2
+        == encoder.decode(decryptor.decrypt(evaluator._add_cipher_cipher(op1, op2)))
+        == encoder.decode(decryptor.decrypt(evaluator.add(op1, op2)))
+    )
+
+
+@pytest.mark.parametrize("int1, int2", [(0, 0), (-1, 1), (100, -10), (1000, 100), (-1000, 100)])
+def test_fv_add_plain_cipher(int1, int2):
+    ctx = Context(EncryptionParams(1024, CoeffModulus().create(1024, [30, 30]), 1024))
+    keys = KeyGenerator(ctx).keygen()
+    encoder = IntegerEncoder(ctx)
+    encryptor = Encryptor(ctx, keys[1])  # keys[1] = public_key
+    decryptor = Decryptor(ctx, keys[0])  # keys[0] = secret_key
+    evaluator = Evaluator(ctx)
+
+    op1 = encoder.encode(int1)
+    op2 = encryptor.encrypt(encoder.encode(int2))
+
+    assert (
+        int1 + int2
+        == encoder.decode(decryptor.decrypt(evaluator._add_plain_cipher(op1, op2)))
+        == encoder.decode(decryptor.decrypt(evaluator.add(op1, op2)))
+    )
+
+
+@pytest.mark.parametrize("int1, int2", [(0, 0), (-1, 1), (100, -10), (1000, 100), (-1000, 100)])
+def test_fv_add_plain_plain(int1, int2):
+    ctx = Context(EncryptionParams(1024, CoeffModulus().create(1024, [30, 30]), 1024))
+    encoder = IntegerEncoder(ctx)
+    evaluator = Evaluator(ctx)
+    op1 = encoder.encode(int1)
+    op2 = encoder.encode(int2)
+    assert (
+        int1 + int2
+        == encoder.decode(evaluator._add_plain_plain(op1, op2))
+        == encoder.decode(evaluator.add(op1, op2))
+    )


Code review comments:
diff_hunk: @@ -0,0 +1,91 @@
+import copy
+
+from syft.frameworks.torch.he.fv.util.operations import poly_add_mod
+from syft.frameworks.torch.he.fv.util.operations import multiply_add_plain_with_delta
+from syft.frameworks.torch.he.fv.ciphertext import CipherText
+from syft.frameworks.torch.he.fv.plaintext import PlainText
+from syft.frameworks.torch.he.fv.integer_encoder import IntegerEncoder
+
+
+class Evaluator:
+    def __init__(self, context):
+        self.context = context
+        self.coeff_modulus = context.param.coeff_modulus
+
+    def add(self, op1, op2):
+        """Adds two operands using FV scheme.
+
+        Args:
+            op1 (Ciphertext/Plaintext): First argument.
+            op2 (Ciphertext/Plaintext): Second argument.
+
+        Retruns:
+            If both arguments are Plaintext elements then the result will be a Plaintext object
+                otherwise a Ciphertext object with value equivalent to the result of addition
+                operation of two provided arguments.
+        """
+        op1, op2 = copy.deepcopy(op1), copy.deepcopy(op2)
+
+        if isinstance(op1, CipherText) and isinstance(op2, CipherText):
+            return self._add_cipher_cipher(op1, op2)
+
+        elif isinstance(op1, PlainText) and isinstance(op2, PlainText):
+            return self._add_plain_plain(op1, op2)
+
+        elif isinstance(op1, PlainText) and isinstance(op2, CipherText):
+            return self._add_plain_cipher(op1, op2)
+
+        elif isinstance(op1, CipherText) and isinstance(op2, PlainText):
+            return self._add_plain_cipher(op2, op1)
+
+        else:
+            raise TypeError(f"Addition Operation not supported between {type(op1)} and {type(op2)}")
+
+    def _add_cipher_cipher(self, ct1, ct2):
+        """Adds two ciphertexts.
+
+        Args:
+            ct1 (Ciphertext): First argument.
+            ct2 (Ciphertext): Second argument.
+
+        Retruns:
+            A Ciphertext object with value equivalent to result of addition of two provided
+                arguments.
+        """
+        ct1, ct2 = copy.deepcopy(ct1.data), copy.deepcopy(ct2.data)
+        result = ct2 if len(ct2) > len(ct1) else ct1
+
+        for i in range(min(len(ct1), len(ct2))):
+            for j in range(len(self.coeff_modulus)):
+                result[i][j] = poly_add_mod(ct1[i][j], ct2[i][j], self.coeff_modulus[j])
+
+        return CipherText(result)
+
+    def _add_plain_cipher(self, pt, ct):
+        """Adds a ciphertext and a plaintext.
+
+        Args:
+            pt (Plaintext): First argument.
+            ct (Ciphertext): Second argument.
+        Retruns:
path: syft/frameworks/torch/he/fv/evaluator.py
text: @user1:
Typo

diff_hunk: @@ -0,0 +1,91 @@
+import copy
+
+from syft.frameworks.torch.he.fv.util.operations import poly_add_mod
+from syft.frameworks.torch.he.fv.util.operations import multiply_add_plain_with_delta
+from syft.frameworks.torch.he.fv.ciphertext import CipherText
+from syft.frameworks.torch.he.fv.plaintext import PlainText
+from syft.frameworks.torch.he.fv.integer_encoder import IntegerEncoder
+
+
+class Evaluator:
+    def __init__(self, context):
+        self.context = context
+        self.coeff_modulus = context.param.coeff_modulus
+
+    def add(self, op1, op2):
+        """Adds two operands using FV scheme.
+
+        Args:
+            op1 (Ciphertext/Plaintext): First argument.
+            op2 (Ciphertext/Plaintext): Second argument.
+
+        Retruns:
+            If both arguments are Plaintext elements then the result will be a Plaintext object
+                otherwise a Ciphertext object with value equivalent to the result of addition
+                operation of two provided arguments.
+        """
+        op1, op2 = copy.deepcopy(op1), copy.deepcopy(op2)
+
+        if isinstance(op1, CipherText) and isinstance(op2, CipherText):
+            return self._add_cipher_cipher(op1, op2)
+
+        elif isinstance(op1, PlainText) and isinstance(op2, PlainText):
+            return self._add_plain_plain(op1, op2)
+
+        elif isinstance(op1, PlainText) and isinstance(op2, CipherText):
+            return self._add_plain_cipher(op1, op2)
+
+        elif isinstance(op1, CipherText) and isinstance(op2, PlainText):
+            return self._add_plain_cipher(op2, op1)
+
+        else:
+            raise TypeError(f"Addition Operation not supported between {type(op1)} and {type(op2)}")
+
+    def _add_cipher_cipher(self, ct1, ct2):
+        """Adds two ciphertexts.
+
+        Args:
+            ct1 (Ciphertext): First argument.
+            ct2 (Ciphertext): Second argument.
+
+        Retruns:
+            A Ciphertext object with value equivalent to result of addition of two provided
+                arguments.
+        """
+        ct1, ct2 = copy.deepcopy(ct1.data), copy.deepcopy(ct2.data)
+        result = ct2 if len(ct2) > len(ct1) else ct1
+
+        for i in range(min(len(ct1), len(ct2))):
+            for j in range(len(self.coeff_modulus)):
+                result[i][j] = poly_add_mod(ct1[i][j], ct2[i][j], self.coeff_modulus[j])
+
+        return CipherText(result)
+
+    def _add_plain_cipher(self, pt, ct):
+        """Adds a ciphertext and a plaintext.
+
+        Args:
+            pt (Plaintext): First argument.
+            ct (Ciphertext): Second argument.
+        Retruns:
+            A Ciphertext object with value equivalent to result of addition of two provided
+                arguments.
+        """
+        pt, ct = copy.deepcopy(pt), copy.deepcopy(ct)
+        return multiply_add_plain_with_delta(ct, pt, self.context)
+
+    def _add_plain_plain(self, pt1, pt2):
+        """Adds two plaintexts object.
+
+        Args:
+            pt1 (Plaintext): First argument.
+            pt2 (Plaintext): Second argument.
+
+        Retruns:
path: syft/frameworks/torch/he/fv/evaluator.py
text: @user1:
typo

diff_hunk: @@ -0,0 +1,91 @@
+import copy
+
+from syft.frameworks.torch.he.fv.util.operations import poly_add_mod
+from syft.frameworks.torch.he.fv.util.operations import multiply_add_plain_with_delta
+from syft.frameworks.torch.he.fv.ciphertext import CipherText
+from syft.frameworks.torch.he.fv.plaintext import PlainText
+from syft.frameworks.torch.he.fv.integer_encoder import IntegerEncoder
+
+
+class Evaluator:
+    def __init__(self, context):
+        self.context = context
+        self.coeff_modulus = context.param.coeff_modulus
+
+    def add(self, op1, op2):
+        """Adds two operands using FV scheme.
+
+        Args:
+            op1 (Ciphertext/Plaintext): First argument.
+            op2 (Ciphertext/Plaintext): Second argument.
+
+        Retruns:
+            If both arguments are Plaintext elements then the result will be a Plaintext object
+                otherwise a Ciphertext object with value equivalent to the result of addition
+                operation of two provided arguments.
+        """
+        op1, op2 = copy.deepcopy(op1), copy.deepcopy(op2)
+
+        if isinstance(op1, CipherText) and isinstance(op2, CipherText):
+            return self._add_cipher_cipher(op1, op2)
+
+        elif isinstance(op1, PlainText) and isinstance(op2, PlainText):
+            return self._add_plain_plain(op1, op2)
+
+        elif isinstance(op1, PlainText) and isinstance(op2, CipherText):
+            return self._add_plain_cipher(op1, op2)
+
+        elif isinstance(op1, CipherText) and isinstance(op2, PlainText):
+            return self._add_plain_cipher(op2, op1)
+
+        else:
+            raise TypeError(f"Addition Operation not supported between {type(op1)} and {type(op2)}")
+
+    def _add_cipher_cipher(self, ct1, ct2):
+        """Adds two ciphertexts.
+
+        Args:
+            ct1 (Ciphertext): First argument.
+            ct2 (Ciphertext): Second argument.
+
+        Retruns:
+            A Ciphertext object with value equivalent to result of addition of two provided
+                arguments.
+        """
+        ct1, ct2 = copy.deepcopy(ct1.data), copy.deepcopy(ct2.data)
+        result = ct2 if len(ct2) > len(ct1) else ct1
+
+        for i in range(min(len(ct1), len(ct2))):
+            for j in range(len(self.coeff_modulus)):
+                result[i][j] = poly_add_mod(ct1[i][j], ct2[i][j], self.coeff_modulus[j])
+
+        return CipherText(result)
+
+    def _add_plain_cipher(self, pt, ct):
+        """Adds a ciphertext and a plaintext.
+
+        Args:
+            pt (Plaintext): First argument.
+            ct (Ciphertext): Second argument.
+        Retruns:
+            A Ciphertext object with value equivalent to result of addition of two provided
+                arguments.
+        """
+        pt, ct = copy.deepcopy(pt), copy.deepcopy(ct)
path: syft/frameworks/torch/he/fv/evaluator.py
text: @user1:
same question: is the deepcopy necessary here too?

@author:
It is required for Ciphertext case but, not for Plaintext, So I updated it. Thanks!

diff_hunk: @@ -0,0 +1,91 @@
+import copy
+
+from syft.frameworks.torch.he.fv.util.operations import poly_add_mod
+from syft.frameworks.torch.he.fv.util.operations import multiply_add_plain_with_delta
+from syft.frameworks.torch.he.fv.ciphertext import CipherText
+from syft.frameworks.torch.he.fv.plaintext import PlainText
+from syft.frameworks.torch.he.fv.integer_encoder import IntegerEncoder
+
+
+class Evaluator:
+    def __init__(self, context):
+        self.context = context
+        self.coeff_modulus = context.param.coeff_modulus
+
+    def add(self, op1, op2):
+        """Adds two operands using FV scheme.
+
+        Args:
+            op1 (Ciphertext/Plaintext): First argument.
+            op2 (Ciphertext/Plaintext): Second argument.
+
+        Retruns:
+            If both arguments are Plaintext elements then the result will be a Plaintext object
+                otherwise a Ciphertext object with value equivalent to the result of addition
+                operation of two provided arguments.
+        """
+        op1, op2 = copy.deepcopy(op1), copy.deepcopy(op2)
+
+        if isinstance(op1, CipherText) and isinstance(op2, CipherText):
+            return self._add_cipher_cipher(op1, op2)
+
+        elif isinstance(op1, PlainText) and isinstance(op2, PlainText):
+            return self._add_plain_plain(op1, op2)
+
+        elif isinstance(op1, PlainText) and isinstance(op2, CipherText):
+            return self._add_plain_cipher(op1, op2)
+
+        elif isinstance(op1, CipherText) and isinstance(op2, PlainText):
+            return self._add_plain_cipher(op2, op1)
+
+        else:
+            raise TypeError(f"Addition Operation not supported between {type(op1)} and {type(op2)}")
+
+    def _add_cipher_cipher(self, ct1, ct2):
+        """Adds two ciphertexts.
+
+        Args:
+            ct1 (Ciphertext): First argument.
+            ct2 (Ciphertext): Second argument.
+
+        Retruns:
path: syft/frameworks/torch/he/fv/evaluator.py
text: @user1:
typo

diff_hunk: @@ -0,0 +1,91 @@
+import copy
+
+from syft.frameworks.torch.he.fv.util.operations import poly_add_mod
+from syft.frameworks.torch.he.fv.util.operations import multiply_add_plain_with_delta
+from syft.frameworks.torch.he.fv.ciphertext import CipherText
+from syft.frameworks.torch.he.fv.plaintext import PlainText
+from syft.frameworks.torch.he.fv.integer_encoder import IntegerEncoder
+
+
+class Evaluator:
+    def __init__(self, context):
+        self.context = context
+        self.coeff_modulus = context.param.coeff_modulus
+
+    def add(self, op1, op2):
+        """Adds two operands using FV scheme.
+
+        Args:
+            op1 (Ciphertext/Plaintext): First argument.
+            op2 (Ciphertext/Plaintext): Second argument.
+
+        Retruns:
path: syft/frameworks/torch/he/fv/evaluator.py
text: @user1:
typo