With composition
A simple way to say that a function f
should be compiled such that its outputs can be reused as inputs is to use the composable
configuration setting to True
when compiling. Doing so, we can then easily compute f(f(x))
or f**i(x) = f(f(...(f(x) ..))
for a variable non-encrypted integer i
, which is typically what happens for recursions.
from concrete import fhe
@fhe.compiler({"counter": "encrypted"})
def increment(counter):
return (counter + 1) % 100
print("Compiling `increment` function")
increment_fhe = increment.compile(list(range(0, 100)), composable=True)
print("Generating keyset ...")
increment_fhe.keygen()
print("Encrypting the initial counter value")
counter = 0
counter_enc = increment_fhe.encrypt(counter)
print(f"| iteration || decrypted | cleartext |")
for i in range(10):
counter_enc = increment_fhe.run(counter_enc)
counter = increment(counter)
# For demo purpose; no decryption is needed.
counter_dec = increment_fhe.decrypt(counter_enc)
print(f"| {i} || {counter_dec:<9} | {counter:<9} |")
Remark that this option is the equivalent of using the fhe.AllComposable
policy of modules. In particular, the same limitations may occur (see limitations documentation section).
Last updated
Was this helpful?