Skip to content

A potential issue in fhe.inputset or fhe.constant #1304

@yuriname

Description

@yuriname

Description

  • versions affected: concrete-python 2.11.0
  • python version: 3.11.0

I met some problems in my project. After reducing it, I obtained this program below:

from concrete import fhe
import numpy as np

@fhe.compiler({'x1': 'encrypted', 'x2': 'encrypted'})
def debug_foo(x1, x2):
    x2_pow = x2 * x2
    con_secret = np.invert(-fhe.constant(4)).astype(np.int64)
    cond_val = (x2_pow > 0)
    res = con_secret >> cond_val
    return res

if __name__ == '__main__':
    x1, x2 = -12, 13
    
    expect_result = debug_foo(x1, x2)
    print(f"expect result: {expect_result}")

    inputset = fhe.inputset(fhe.int8, fhe.int8)
    circuit = debug_foo.compile(inputset)
    circuit.keygen()
    encrypted_x1, encrypted_x2 = circuit.encrypt(x1, x2)
    encrypted_result = circuit.run(encrypted_x1, encrypted_x2)
    result = circuit.decrypt(encrypted_result)
    print(f"concrete result: {result}")
    print(f"{circuit}")

Its final output does not match the expected plaintext output:

expect result: 1
concrete result: 3

I printed the circuit of this program, and the bit range looks correct:

 %0 = x2                            # EncryptedScalar<int8>          ∈ [-125, 124]
 %1 = multiply(%0, %0)              # EncryptedScalar<uint14>        ∈ [1, 15625]
 %2 = zeros()                       # EncryptedScalar<uint1>         ∈ [0, 0]
 %3 = 4                             # ClearScalar<uint3>             ∈ [4, 4]
 %4 = add(%2, %3)                   # EncryptedScalar<uint3>         ∈ [4, 4]
 %5 = negative(%4)                  # EncryptedScalar<int3>          ∈ [-4, -4]
 %6 = invert(%5)                    # EncryptedScalar<uint2>         ∈ [3, 3]
 %7 = astype(%6, dtype=int_)        # EncryptedScalar<uint2>         ∈ [3, 3]
 %8 = 0                             # ClearScalar<uint1>             ∈ [0, 0]
 %9 = greater(%1, %8)               # EncryptedScalar<uint1>         ∈ [1, 1]
%10 = right_shift(%7, %9)           # EncryptedScalar<uint1>         ∈ [1, 1]
return %10

Since my input x2=13 falls within the valid range of -125 to 124, I would expect the program to output a correct value.

I also find that if I use -4 rather than -fhe.constant(4), the output becomes consistent.
OR, if I use fhe.inputset(fhe.int8, fhe.int8, size=1000) to increase the number of samples, the output can also become consistent.

But this is still strange, because the circuit shows that the valid input range for x2 is [-125, 124], so I would expect inputs within this range to always yield a correct result. I wonder whether this is an issue with fhe.inputset or fhe.constant, or just an issue with how the circuit is printed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions