Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Comparison sequence of enc_numbers #520

Closed
jahidhasanlinix opened this issue Jul 21, 2023 · 2 comments
Closed

Comparison sequence of enc_numbers #520

jahidhasanlinix opened this issue Jul 21, 2023 · 2 comments

Comments

@jahidhasanlinix
Copy link

jahidhasanlinix commented Jul 21, 2023

I have some questions, say I have a set or sequence of encrypted numbers outsourced to the cloud. Now client sent an encrypted range query to the server. Now I want the server to do the computation and return the value whose range is greater or equal to (>=) given numbers (ignore the lower numbers, filtered). How can this be implemented using concrete, any library, or pseudocode that explains this setup? Any help

@umut-sahin
Copy link
Contributor

Is this what you're looking for?

import numpy as np
from concrete import fhe

configuration = fhe.Configuration(
    enable_unsafe_features=True,
    use_insecure_key_cache=True,
    insecure_key_cache_location=".keys",
    single_precision=False,
)

@fhe.compiler({"numbers": "encrypted", "query": "encrypted"})
def filtering(numbers, query):
    is_greater = numbers > query

    shifted_numbers = numbers * 2  # open space for a single bit at the end
    combined_numbers_and_is_greater = shifted_numbers + is_greater  # put is_greater to that bit

    def extract(combination):
        is_greater = (combination % 2) == 1  # extract is_greater back from packing
        if_true = combination // 2  # if is greater is true, we unpack the number and use it
        if_false = 0  # otherwise we set the element to zero
        return np.where(is_greater, if_true, if_false)  # and apply the operation

    return fhe.univariate(extract)(combined_numbers_and_is_greater)

inputset = [
    (
        np.random.randint(0, 10, size=(5,)),
        np.random.randint(0, 10, size=()),
    )
    for _ in range(100)
]
circuit = filtering.compile(inputset, configuration, verbose=True)

print(filtering(np.array([1, 3, 2, 5, 4]), 3))
print(circuit.encrypt_run_decrypt([1, 3, 2, 5, 4], 3))

prints

[0 0 0 5 4]
[0 0 0 5 4]

Few notes:

  • It's impossible to return just to numbers because the server cannot know how many of the values are greater. Thus, we set the rest to 0.
  • It's not possible to have a dynamic number of inputs, in this case the size was set to 5 from the inputset and it cannot be called with 6 elements. This is due to how the compiler works. I can explain more if you want.

Let us know if this helps!

@aquint-zama
Copy link
Contributor

FYI this workaround is part of the new tutorial page in the documentation
Closing this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants