ML (Core)
manhattan_distance()¶
Calculate the Manhattan (L1) distance between two encrypted arrays.
This cell verifies the manhattan_distance function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
from concrete import fhe
from concrete_fhe_toolkit.ml.core import manhattan_distance
def test_manhattan_distance(array1, array2):
import numpy as np
res = manhattan_distance(array1, array2)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_manhattan_distance, {'array1': 'encrypted', 'array2': 'encrypted'})
inputset = [([0, 1, 1], [0, 0, 1]), ([1, 0, 1], [1, 0, 1]), ([0, 0, 0], [1, 1, 1])]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = manhattan_distance(inp[0], inp[1])
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "manhattan_distance: all inputs were skipped — test is broken"
print(f"manhattan_distance tests passed! ({_successes}/{len(inputset)})")
hamming_distance()¶
Calculate the Hamming distance (number of mismatches) between two encrypted arrays.
This cell verifies the hamming_distance function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
from concrete import fhe
from concrete_fhe_toolkit.ml.core import hamming_distance
def test_hamming_distance(array1, array2):
import numpy as np
res = hamming_distance(array1, array2)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_hamming_distance, {'array1': 'encrypted', 'array2': 'encrypted'})
inputset = [([0, 1, 1], [0, 0, 1]), ([1, 0, 1], [1, 0, 1]), ([0, 0, 0], [1, 1, 1])]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = hamming_distance(inp[0], inp[1])
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "hamming_distance: all inputs were skipped — test is broken"
print(f"hamming_distance tests passed! ({_successes}/{len(inputset)})")
euclidean_distance_squared()¶
Calculate the squared Euclidean (L2) distance between two encrypted arrays.
This cell verifies the euclidean_distance_squared function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
from concrete import fhe
from concrete_fhe_toolkit.ml.core import euclidean_distance_squared
def test_euclidean_distance_squared(array1, array2):
import numpy as np
res = euclidean_distance_squared(array1, array2)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_euclidean_distance_squared, {'array1': 'encrypted', 'array2': 'encrypted'})
inputset = [([0, 1, 1], [0, 0, 1]), ([1, 0, 1], [1, 0, 1]), ([0, 0, 0], [1, 1, 1])]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = euclidean_distance_squared(inp[0], inp[1])
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "euclidean_distance_squared: all inputs were skipped — test is broken"
print(f"euclidean_distance_squared tests passed! ({_successes}/{len(inputset)})")
mean_squared_error()¶
Calculate the Mean Squared Error (MSE) between two encrypted arrays.
This cell verifies the mean_squared_error function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
from concrete import fhe
from concrete_fhe_toolkit.ml.core import mean_squared_error
def test_mean_squared_error(array1, array2):
import numpy as np
res = mean_squared_error(array1, array2)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_mean_squared_error, {'array1': 'encrypted', 'array2': 'encrypted'})
inputset = [([0, 1, 1], [0, 0, 1]), ([1, 0, 1], [1, 0, 1]), ([0, 0, 0], [1, 1, 1])]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = mean_squared_error(inp[0], inp[1])
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "mean_squared_error: all inputs were skipped — test is broken"
print(f"mean_squared_error tests passed! ({_successes}/{len(inputset)})")
mean_absolute_error()¶
Calculate the Mean Absolute Error (MAE) between predictions and true values.
This cell verifies the mean_absolute_error function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
from concrete import fhe
from concrete_fhe_toolkit.ml.core import mean_absolute_error
def test_mean_absolute_error(y_preds, y_trues):
import numpy as np
res = mean_absolute_error(y_preds, y_trues)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_mean_absolute_error, {'y_preds': 'encrypted', 'y_trues': 'encrypted'})
inputset = [([0, 1, 1], [0, 0, 1]), ([1, 0, 1], [1, 0, 1]), ([0, 0, 0], [1, 1, 1])]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = mean_absolute_error(inp[0], inp[1])
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "mean_absolute_error: all inputs were skipped — test is broken"
print(f"mean_absolute_error tests passed! ({_successes}/{len(inputset)})")
accuracy_score() (Helper)¶
Demonstrates the accuracy_score function. This is a client-side (cleartext) helper function. It is not an FHE circuit and cannot be compiled with fhe.Compiler.
from concrete_fhe_toolkit.ml.core import accuracy_score
inputset = [([0, 1, 1], [0, 0, 1]), ([1, 0, 1], [1, 0, 1]), ([0, 0, 0], [1, 1, 1])]
for inp in inputset:
try:
expected = accuracy_score(*inp)
print(f'Helper output: {expected}')
except Exception as e:
print(f'Skipping {inp}: {e}')
print('accuracy_score helper executed successfully!')
true_positives()¶
Calculate the number of True Positives in binary classification.
This cell verifies the true_positives function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
from concrete import fhe
from concrete_fhe_toolkit.ml.core import true_positives
def test_true_positives(y_preds, y_trues):
import numpy as np
res = true_positives(y_preds, y_trues)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_true_positives, {'y_preds': 'encrypted', 'y_trues': 'encrypted'})
inputset = [([0, 1, 1], [0, 0, 1]), ([1, 0, 1], [1, 0, 1]), ([0, 0, 0], [1, 1, 1])]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = true_positives(inp[0], inp[1])
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "true_positives: all inputs were skipped — test is broken"
print(f"true_positives tests passed! ({_successes}/{len(inputset)})")
true_negatives()¶
Calculate the number of True Negatives in binary classification.
This cell verifies the true_negatives function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
from concrete import fhe
from concrete_fhe_toolkit.ml.core import true_negatives
def test_true_negatives(y_preds, y_trues):
import numpy as np
res = true_negatives(y_preds, y_trues)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_true_negatives, {'y_preds': 'encrypted', 'y_trues': 'encrypted'})
inputset = [([0, 1, 1], [0, 0, 1]), ([1, 0, 1], [1, 0, 1]), ([0, 0, 0], [1, 1, 1])]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = true_negatives(inp[0], inp[1])
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "true_negatives: all inputs were skipped — test is broken"
print(f"true_negatives tests passed! ({_successes}/{len(inputset)})")
false_negatives()¶
Calculate the number of False Negatives in binary classification.
This cell verifies the false_negatives function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
from concrete import fhe
from concrete_fhe_toolkit.ml.core import false_negatives
def test_false_negatives(y_preds, y_trues):
import numpy as np
res = false_negatives(y_preds, y_trues)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_false_negatives, {'y_preds': 'encrypted', 'y_trues': 'encrypted'})
inputset = [([0, 1, 1], [0, 0, 1]), ([1, 0, 1], [1, 0, 1]), ([0, 0, 0], [1, 1, 1])]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = false_negatives(inp[0], inp[1])
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "false_negatives: all inputs were skipped — test is broken"
print(f"false_negatives tests passed! ({_successes}/{len(inputset)})")
false_positives()¶
Calculate the number of False Positives in binary classification.
This cell verifies the false_positives function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
from concrete import fhe
from concrete_fhe_toolkit.ml.core import false_positives
def test_false_positives(y_preds, y_trues):
import numpy as np
res = false_positives(y_preds, y_trues)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_false_positives, {'y_preds': 'encrypted', 'y_trues': 'encrypted'})
inputset = [([0, 1, 1], [0, 0, 1]), ([1, 0, 1], [1, 0, 1]), ([0, 0, 0], [1, 1, 1])]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = false_positives(inp[0], inp[1])
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "false_positives: all inputs were skipped — test is broken"
print(f"false_positives tests passed! ({_successes}/{len(inputset)})")
confusion_matrix() (Helper)¶
Demonstrates the confusion_matrix function. This is a client-side (cleartext) helper function. It is not an FHE circuit and cannot be compiled with fhe.Compiler.
from concrete_fhe_toolkit.ml.core import confusion_matrix
inputset = [([0, 1, 1], [0, 0, 1]), ([1, 0, 1], [1, 0, 1]), ([0, 0, 0], [1, 1, 1])]
for inp in inputset:
try:
expected = confusion_matrix(*inp)
print(f'Helper output: {expected}')
except Exception as e:
print(f'Skipping {inp}: {e}')
print('confusion_matrix helper executed successfully!')
hinge_loss()¶
Calculate the encrypted Hinge Loss for a single prediction and true value.
This cell verifies the hinge_loss function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
from concrete import fhe
from concrete_fhe_toolkit.ml.core import hinge_loss
def test_hinge_loss(y_pred, y_true):
return hinge_loss(y_pred, y_true)
compiler = fhe.Compiler(test_hinge_loss, {'y_pred': 'encrypted', 'y_true': 'encrypted'})
inputset = [([-1, 1], [-1, 1])]
circuit = compiler.compile(inputset)
circuit.encrypt_run_decrypt(*inputset[0])
print("hinge_loss tests passed! (1/1)")
l1_norm()¶
Tests the function.
This cell verifies the l1_norm function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
from concrete import fhe
from concrete_fhe_toolkit.ml.core import l1_norm
def test_l1_norm(array):
import numpy as np
res = l1_norm(array)
return fhe.array(res) if isinstance(res, list) else res
compiler = fhe.Compiler(test_l1_norm, {'array': 'encrypted'})
inputset = [([0, 1, 2],), ([-1, 0, 1],), ([0, 0, 0],)]
circuit = compiler.compile(inputset)
_successes = 0
for inp in inputset:
try:
expected = l1_norm(inp[0])
import numpy as np
if isinstance(expected, (list, tuple)) or type(expected).__name__ == 'ndarray':
np.testing.assert_array_equal(circuit.encrypt_run_decrypt(*inp), expected)
else:
assert int(circuit.encrypt_run_decrypt(*inp)) == int(expected), f"Failed at {inp}"
except AssertionError:
raise
except Exception as e:
print(f"Skipping {inp} due to bounds or other error: {e}")
else:
_successes += 1
assert _successes > 0, "l1_norm: all inputs were skipped — test is broken"
print(f"l1_norm tests passed! ({_successes}/{len(inputset)})")
compile_hinge_loss()¶
Compile encrypted hinge loss.
This cell verifies the compile_hinge_loss function mathematically against its cleartext counterpart, using a dynamically generated input set that covers positive, negative, zero, and array edge cases while respecting the [-7, 7] FHE RAM constraints.
from concrete_fhe_toolkit.ml.core import compile_hinge_loss
circuit = compile_hinge_loss(min_value=-2, max_value=3)
inputset = [(0, 1)]
circuit.encrypt_run_decrypt(*inputset[0])
print("compile_hinge_loss tests passed! (1/1)")
make_cross_entropy_loss()¶
Create a scaled Binary Cross-Entropy loss function.
This cell tests the function logic strictly in cleartext (standard Python). Since this function acts as a client-side helper or faces FHE compilation limits, it is evaluated outside the compiler.
from concrete_fhe_toolkit.ml.core import make_cross_entropy_loss
fn = make_cross_entropy_loss(min_input=0, max_input=100, input_scale=100, output_scale=100)
y_preds = [90, 10] # representing 0.9 and 0.1 scaled by 100
y_trues = [1, 0]
loss = fn(y_preds, y_trues)
assert loss is not None
print(f"Calculated cleartext loss: {loss}")
print("make_cross_entropy_loss_enc tests passed! (1/1)")
compile_cross_entropy_loss()¶
Tests the function.
This cell attempts to compile the circuit and explicitly expects it to fail due to Concrete's 16-bit Table Lookup (TLU) limitation. This serves as a safety check for the 22-bit noise growth.
from concrete import fhe
from concrete_fhe_toolkit.ml.core import compile_cross_entropy_loss
import warnings
warnings.filterwarnings('ignore')
print("Attempting to compile compile_cross_entropy_loss...")
try:
circuit = compile_cross_entropy_loss(array_size=4)
print("compile_cross_entropy_loss tests passed natively! (1/1)")
except Exception as e:
print("compile_cross_entropy_loss expected failure tests passed! (1/1)")
print(f"-> Caught expected Concrete 16-bit limitation error.")
precision_score() (Helper)¶
Demonstrates the precision_score function. This is a client-side (cleartext) helper function. It is not an FHE circuit and cannot be compiled with fhe.Compiler.
from concrete_fhe_toolkit.ml.core import precision_score
inputset = [([0, 1, 1], [0, 0, 1]), ([1, 0, 1], [1, 0, 1]), ([0, 0, 0], [1, 1, 1])]
for inp in inputset:
try:
expected = precision_score(*inp)
print(f'Helper output: {expected}')
except Exception as e:
print(f'Skipping {inp}: {e}')
print('precision_score helper executed successfully!')
recall_score() (Helper)¶
Demonstrates the recall_score function. This is a client-side (cleartext) helper function. It is not an FHE circuit and cannot be compiled with fhe.Compiler.
from concrete_fhe_toolkit.ml.core import recall_score
inputset = [([0, 1, 1], [0, 0, 1]), ([1, 0, 1], [1, 0, 1]), ([0, 0, 0], [1, 1, 1])]
for inp in inputset:
try:
expected = recall_score(*inp)
print(f'Helper output: {expected}')
except Exception as e:
print(f'Skipping {inp}: {e}')
print('recall_score helper executed successfully!')
f1_score() (Helper)¶
Demonstrates the f1_score function. This is a client-side (cleartext) helper function. It is not an FHE circuit and cannot be compiled with fhe.Compiler.
from concrete_fhe_toolkit.ml.core import f1_score
inputset = [([0, 1, 1], [0, 0, 1]), ([1, 0, 1], [1, 0, 1]), ([0, 0, 0], [1, 1, 1])]
for inp in inputset:
try:
expected = f1_score(*inp)
print(f'Helper output: {expected}')
except Exception as e:
print(f'Skipping {inp}: {e}')
print('f1_score helper executed successfully!')
r2_score() (Helper)¶
Demonstrates the r2_score function. This is a client-side (cleartext) helper function. It is not an FHE circuit and cannot be compiled with fhe.Compiler.
from concrete_fhe_toolkit.ml.core import r2_score
inputset = [([0, 1, 1], [0, 0, 1]), ([1, 0, 1], [1, 0, 1]), ([0, 0, 0], [1, 1, 1])]
for inp in inputset:
try:
expected = r2_score(*inp)
print(f'Helper output: {expected}')
except Exception as e:
print(f'Skipping {inp}: {e}')
print('r2_score helper executed successfully!')