Depth and complexity of circuit

Hello,

I would like to know if there is a method on the circuit that would give the depth level of the output ciphertext as in this thread?

I saw that the Circuit class has a property complexity but I do not understand what the output represents.

Here a small script for example:

import concrete.numpy as cnp
import numpy as np
import time

vec_size = 10
nbits = 5

tlu = np.random.randint(0, 2, size=(2**nbits))
tlu = cnp.LookupTable(tlu)
inputset = [(np.random.randint(0,2**nbits,size=(vec_size)),np.random.randint(0,20,size=(vec_size))) for _ in range(10)]# [(2, 3), (0, 0), (1, 6), (7, 7), (7, 1)]

x = np.random.randint(0,2**nbits,size=(vec_size)) #4
y = np.random.randint(0,20,size=(vec_size)) #4

def add(x, y):
    x = tlu[x]*y
    return x * y

compiler = cnp.Compiler(add, {"x": "encrypted", "y": "clear"})

circuit = compiler.compile(inputset)
print(circuit.complexity)
clear_evaluation = add(x, y)
t0 = time.time()
homomorphic_evaluation = circuit.encrypt_run_decrypt(x, y)
t1 = time.time()

print(t1-t0)

The outputs gives 61382636700.0, which I do not understand what is represents.

The depth level of my ciphertexts should be 2 at the output of this circuit, is there a way to get this number automatically?

Thank you

Hello,

Depth level
There is no way to have the “depth level” of the output. Concrete-numpy enforces that the crypto-parameters are adequate given your circuit. So under the wood it computes for any expression a kind of “multiplicative load” but this information is not exposed yet. There is no easy way to have it.

Please, if you need it for some purpose, you can explain us your needs, we may consider exposing this information.

BTW in your case the multiplicative operand y constant is unknown. Assuming y is 5bits, each of the 2 multiplications will increase the “multiplicative load” by a factor 2^5. So the “multiplicative load” computed by concrete-numpy will be 2^5 * 2^5 and is not the value you want.

Complexity
circuit.complexity is an estimation of the number of primitive operation (currently 64bits add and mul) required to run the circuit.
For instance, if you try several configuration of variants of the same circuit, you can estimate which one will be the faster by comparing circuit.complexity .

Thank you for your insight

Thus if I get it correctly the multiplicative load is not tied by the outputs of the tlu? It is 2^5 * 2^5 as the bootstrapping from the tlu reduces the noise level of my ciphertext?

Thanks

Yes. The TLU (containing bootsrap) always resets “multiplicative load” to 1. tlu[x] has a “multiplicative load” of 1, whatever x and tlu content. Freshly encrypted cyphertext also have a multiplicative load of 1. The multiplication with a clear value had a factor proportional to the clear value.

Expression: multiplicative loads
x : 1
tlu[x] : 1
tlu[x] * y : 1 x 2^5
tlu[x] * y * y : 1 x 2^5 x 2^5