Hi, is it possible to perform an operation with a negative exponent (e.g. 2^(-10))? It throws the following error message when I try:
ValueError: Integers to negative integer powers are not allowed.
The above exception was the direct cause of the following exception:
…
RuntimeError: Evaluation of the graph failed
I’m also having issues even with a positive exponent, e.g.:
import numpy as np
from concrete import fhe
@fhe.compiler({"x": "encrypted"})
def f(x):
arr1 = np.array([2] * len(x))
return arr1 ** x # i.e. np.power(arr1, x)
inputset = [[2**8,2**8,1]]
circuit = f.compile(inputset)
circuit.keygen()
test_data = ([1, 2, 3])
print(circuit.encrypt_run_decrypt(test_data))
Returns [2, 4, 0], and the following:
import numpy as np
from concrete import fhe
@fhe.compiler({"x": "encrypted"})
def f(x):
arr2 = []
for i in x:
arr2.append(2**i)
return fhe.array(arr2)
You’re doing (2**8) ** (2**8) which is 256**256, which cannot fit into numpy.int64 type we use. This expression overflows into 0, and that’s reflected in the measured bounds:
It’s essentially a sum of powers which have a negative exponent - I have some int() casts to avoid float values, but I’m trying to do something like:
2**(-255)a + 2**(-254)b + ...
At the moment, I’m just trying to find a way to calculate something as simple as 2**(-1), which throws the errors about not being able to have an integer to a negative integer power - I was then going to extend to my particular usecase.
Given that you mentioned that the numpy.int64 type is used, and the absolute value of my exponents are larger than that, I don’t think I could use a positive exponent and a division, as I’d still be calculating values like 2**(255). I’m assuming that using negative exponents is the easiest way around this.
2 ** (-1) is 0.5 which is not an integer. In fact every negative exponent would result in a value in range [0, 1), so none of them are integers. What you want is quantization! I’d recommend checking Quantization | 1.5 | Concrete ML for ideas. I’ll ask my fellow concrete-ml developers to give you some pointers as well
Hello @ac2421 . Before going into the details of the quantization, could I ask what kind of function you want to compute and for which use, please?
I see your 2**(-255)a + 2**(-254)b + ... but it’s not obvious to me why you want to compute this. Could you show us the python function you would like to move to Concrete Python? In particular, what is a variable here and what is a constant? In your expression, 2**(-255) and friends are constant? If yes, it would not be related to the 2**x that you asked about, in the beginning of the question, is it?
Also in Concrete, there is the concept of table lookup (TLU), which is very useful to handle a lot of computation. I don’t know if it’s what you’re trying, but we shouldn’t use polynomial approximations in Concrete, it’s better to directly go for a TLU.
Once we know more (give ideally a lot of details), we should be able to help you.
Cheers
Thank you both! Apologies for the delay.
I’m basically trying to do a variant of the log-sum-exp function, which involves computing the very small powers:
For my usecase the powers decrease sequentially, but they are also multiplied by another number (hence I can’t simplify the expression further). I was just trying to see if Concrete could handle the negative exponents somehow?
and then, you can compute exp(x_i-x*) as first d_i = x_i-x* which is linear so easy, and then one PBS with table T where T[i] = int(D * exp(i)); and you will add the results; that’s another n PBS
and finally, you can compute log() with another PBS, this time with T’[i] = int(log(i / D))
and add with x*. You will have to select D such that it’s precise enough.