Numpy array manipulation

Hello, i’m trying to test an algorithm to check different chunks of a numpy array to find similarities. I’ve tried by using a whole u16bit number, but the subtraction could cause an underflow into a signed 17 bits. My current approach uses numpy arrays to make it more flexible:

    def _create_circuit(self):
        """Create the FHE circuit for comparing arrays of 4-bit values."""
        @fhe.compiler({"x": "encrypted", "y": "clear"})
        def compare_positions(x, y):
            # Assuming x and y are np.uint4 values (0-15)
            b_enc = fhe.zeros(y.shape) + y
            c = fhe.multivariate(lambda a, b: a % b)(x, b_enc)
            return c
            
        # Create representative input arrays for compilation
        # Define array size (number of 4-bit elements in each array)
        array_size = 4  # Adjust as needed
        
        # Generate sample arrays for inputset
        # We'll create arrays with values from 0-15 (4-bit range)
        sample_arrays = []
        
        # Add edge cases
        sample_arrays.append(np.zeros(array_size, dtype=np.uint8))
        sample_arrays.append(np.ones(array_size, dtype=np.uint8) * 15)  # Max 4-bit value
        
        # Add arrays with different patterns
        sample_arrays.append(np.array([0, 5, 10, 15], dtype=np.uint8))
        sample_arrays.append(np.array([15, 10, 5, 0], dtype=np.uint8))
        sample_arrays.append(np.array([7, 7, 7, 7], dtype=np.uint8))
        
        # Add some random samples
        for _ in range(min(20, self.input_set_size)):
            sample = np.random.randint(0, 16, size=array_size, dtype=np.uint8)
            sample_arrays.append(sample)
        
        # Create inputset with pairs of arrays
        # Limit combinations to keep compilation time reasonable
        inputset = [(x, y) for x in sample_arrays for y in sample_arrays[:10]]
        
        print(inputset)
        
        return compare_positions.compile(inputset, self.configuration, show_mlir=False)

this is the way i’m calling the function:

    def test_circuit_creation(self):
        """Test that the circuit is created and works correctly."""
        # Test the circuit with a simple comparison
        pos1_array = self.uint16_to_array(42)
        pos2_array = self.uint16_to_array(42)
        
        # Encrypt first position
        encrypted_pos1, _ = self.client.encrypt(pos1_array, None)
        
        # Run the circuit
        encrypted_result = self.encryption.run_comparison(
            encrypted_pos1, 
            pos2_array,
            self.client.evaluation_keys
        )
        
        # Decrypt the result
        result = self.client.decrypt(encrypted_result)
        
        # Check result - should be all the values from the array should be equal to 0
        for i in range(4):
            self.assertEqual(result[i], 0, 
                             f"Expected position {i} to be 0, got {result[i]} for positions {pos1_array} and {pos2_array}")

By doing so i get this runtime error which i can’t figure ou the cause:

Traceback (most recent call last):
  File "/home/diebbo/Clones/tesi/python/test/test_encryption_functions.py", line 48, in test_circuit_creation
    encrypted_result = self.encryption.run_comparison(
  File "/home/diebbo/Clones/tesi/python/utils/concrete_encryption.py", line 79, in run_comparison
    result = self.circuit.run(
  File "/home/diebbo/Clones/tesi/python/lib/python3.8/site-packages/concrete/fhe/compilation/server.py", line 460, in run
    simulated_client_circuit.val.simulate_prepare_input(Value_(arg), i)
RuntimeError: bad optional access