evalAddCount not working

OpenFHE paper says: the user specifies the multiplicative depth (and for some schemes also the maximum number of additions/key-switching operations)
(https://hal-lirmm.ccsd.cnrs.fr/lirmm-04703074v1/document)

And the read-me file at openfhe-development/src/pke/examples/README.md at 6bcca756e9d52b4db3dd2168414df8a7316b1a61 · openfheorg/openfhe-development · GitHub says

**uint32_t evalAddCount (BGV/BFV only)** - maximum number of additions (used for setting noise). In BGV, it is the maximum number of additions at any level.

Based on this, I assume my program (which has 85 cipher additions and 3 cipher multiplications) below should run correctly, but it does not. I am not sure what I am doing wrong here. Please help me.


    CCParams<CryptoContextBGVRNS> parameters;
    parameters.SetMultiplicativeDepth(3);
    parameters.SetEvalAddCount(85);
    parameters.SetPlaintextModulus(536903681);
    parameters.SetMaxRelinSkDeg(4);

    std::vector<int64_t> vectorOfInts1 = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    Plaintext plaintext1               = cryptoContext->MakePackedPlaintext(vectorOfInts1);
    std::vector<int64_t> vectorOfInts2 = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
    Plaintext plaintext2               = cryptoContext->MakePackedPlaintext(vectorOfInts2);
    std::vector<Ciphertext<DCRTPoly>> ciphertexts;

    ciphertexts.push_back(cryptoContext->Encrypt(keyPair.publicKey, plaintext1));
    ciphertexts.push_back(cryptoContext->Encrypt(keyPair.publicKey, plaintext2));

    auto ciphertextMult12 = cryptoContext->EvalMult(ciphertexts[0], ciphertexts[1]);
    cryptoContext->ModReduceInPlace(ciphertextMult12);

    for(int i=0; i<25; i++){                                                                                                                                                                       
    ciphertextMult12 = cryptoContext->EvalAdd(ciphertextMult12,ciphertextMult12);                                                                                                                     
    }

    Plaintext plaintextDecMult123;
    auto ciphertexts2 = ciphertexts[1];

    for(int i=0; i<=35; i++){                                                                                                                                                                       
    ciphertextMult12 = cryptoContext->EvalAdd(ciphertextMult12,ciphertextMult12);                                                                                                                     
    }

    ciphertextMult12 = cryptoContext->EvalMult(ciphertextMult12, ciphertexts2);
    ciphertextMult12 = cryptoContext->EvalMult(ciphertextMult12, ciphertexts2);

    cryptoContext->RelinearizeInPlace(ciphertextMult12);
    cryptoContext->Decrypt(keyPair.secretKey, ciphertextMult12, &plaintextDecMult123);

    plaintextDecMult123->SetLength(plaintext1->GetLength());
    std::cout << "\nResult of 3 homomorphic multiplications: \n";
    std::cout << plaintextDecMult123 << std::endl;
    for(int i=0; i<=25; i++){
    ciphertextMult12 = cryptoContext->EvalAdd(ciphertextMult12,ciphertexts2);
    }
    cryptoContext->Decrypt(keyPair.secretKey, ciphertextMult12, &plaintextDecMult123);
    plaintextDecMult123->SetLength(plaintext1->GetLength());
    std::cout << plaintextDecMult123 << std::endl

Instead of : ( 86 0 0 0 0 0 0 0 0 0 0 85 ... )

I get
( 118792352 23987527 -207205692 -172374152 3066270 -251675412 183218421 -202333350 46098309 4166024 -89071655 -102998818 ... )

I am not sure what is going on. Is evalAddCount deprecated?
Thank you.

The problem you are facing has nothing to do with evalAddCount.
Your computation does not stay within the dynamic range specified in the plaintext modulus.
Your dynamic range is: [-536903681/2,536903681/2] \cap \mathbb{Z}, which is NOT wide enough for your computation in BGV.

What are you trying to do?
Maybe CKKS would be a better choice if you require such high precision.

I am not sure why my computation goes outside the dynamic range. I re-run the same program with

    std::vector<int64_t> vectorOfInts1 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    std::vector<int64_t> vectorOfInts2 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

and got a similar result. If I increased the multiplicative depth, then I have the correct output ( 0 ... ) .

My program involves a combination of additions and multiplication and SetMultiplicativeDepth is not enough for me, I also need to factor in additions while choosing the parameters. I am trying to use EvalAddCount for that purpose.

ciphertextMult12 grows exponentially below, no?

Also, you have another for-loop over the same variable.

My understanding is that you are computing the following:

v=1;
for(i=0;i<=24;i++;
   v=v+v;
For(j=0;j<=34;j++;
   v=v+v;

If that is the case, v will be 61-bit long, much larger than your plaintext modulus.

Thanks, one thing I failed to see is how you computed 61 bits.

Could you explain? Thank you

As follows:

1+1 = 2 = (2^1)
2+2 = 4 = (2^2)
4+4 = 8 = (2^3)
.
.
.
2^59+2^59 = (2^60)

and 2^{60} is a 61-bit integer.