Problem with multi-parameters functions

Hello.

I’m testing Concrete with a very simple function to multiply two integers. The code works but the result is totally false. For example, it says that 6*7=10.

Is it possible to have multi-parameters functions with all parameters encrypted or do I have to only select one argument to encrypt ?

Thank you in advance for your answer.

Hello @gergovie727,

Could you share your code please :slight_smile:

Thanks.

Hello @umutsahin. Here is my code:

from concrete import fhe

configuration = fhe.Configuration(dataflow_parallelize=True)
x=7
y=6

@fhe.compiler({"x": "encrypted", "y": "encrypted"})
def mult(x, y):
    return x * y

inputset_mult = [(3, 5), (2, 7), (9, 1), (1, 5), (4, 2)]

circuit_mult = mult.compile(inputset_mult)

resultat_mult = circuit_mult.encrypt_run_decrypt(x, y)

if resultat_mult != mult(x, y):
    print(f"Erreur dans le calcul de la multiplication. Le résultat est {mult(x, y)} et non {resultat_mult}")

And it returns 10 instead of 42.

Thanks for your answer !

The issue is with the inputset. If you add show_graph=True argument to your mult.compile call, you’ll see:

Computation Graph
--------------------------------------------------------------------------------
%0 = x                       # EncryptedScalar<uint4>        ∈ [1, 9]
%1 = y                       # EncryptedScalar<uint3>        ∈ [1, 7]
%2 = multiply(%0, %1)        # EncryptedScalar<uint4>        ∈ [5, 15]
return %2
--------------------------------------------------------------------------------

As you can see, your inputset resulted in at most 15 for the result, so Concrete assigned 4-bits to it. You’d need 6-bits to store 42.

When you run this circuit with 6 and 7, there is an overflow, and you get incorrect result. There are a few ways to fix it. The best option in my opinion is to increase the size of your inputset and maybe use a random one:

inputset = [
    (
        np.random.randint(0, 2**3, size=()),
        np.random.randint(0, 2**3, size=()),
    )
    for _ in range(100)
]

Alternatively, you can change your implementation to:

result = x * y
fhe.hint(result, bit_width=6)
return result

or

return fhe.hint(x * y, bit_width=6)

to explicitly tell concrete you need 6-bits.

Let me know if this solves your issue :slight_smile:

Thank you, that works !
And I found the answer for my previous problem lol.

Have a nice day.

1 Like

Glad to hear it :wink:

Let us know if you have more questions!