Distance / Similarity

In the context of machine learning attacks on PUFs, it is often required to estimate the accuracy of predictions made by a PUF model. pypuf provides a metric to estimate the similarity of two PUFs, given either as response data or simulation, which can be used to compute the accuracy of predictions.

pypuf.metrics.accuracy(simulation: Simulation, test_set: ChallengeResponseSet) ndarray

Given a simulation and a test set, returns the relative frequency of responses by the simulation that match responses recorded in the test set by response bit, i.e. an approximation of

\[\Pr_x \left[ f(x) = g(x) \right],\]

where \(f\) is given by the provided simulation and \(g\) is defined by the \(\mathtt{test\_set}\); \(x\) is from the set of challenges given in the \(\mathtt{test\_set}\).

If response length is greater than 1, the similarity is given for each bit seperately. To obtain the general similarity, average the response.

Returns an array of shape \((m,)\).

>>> from pypuf.simulation import XORArbiterPUF
>>> from pypuf.io import ChallengeResponseSet
>>> from pypuf.metrics import accuracy
>>> puf = XORArbiterPUF(n=128, k=4, noisiness=.1, seed=1)
>>> test_set = ChallengeResponseSet.from_simulation(puf, N=1000, seed=2)
>>> accuracy(puf, test_set)
array([0.843])
>>> puf = XORArbiterPUF(n=64, k=4, noisiness=.3, seed=2)
>>> test_set = ChallengeResponseSet.from_simulation(puf, N=1000, seed=2, r=5)
>>> accuracy(puf, test_set)
array([0.69])
pypuf.metrics.similarity(instance1: Simulation, instance2: Simulation, seed: int, N: int = 1000) ndarray

Approximate the similarity in response behavior of two simulations with identical challenge and response length, i.e. an approximation of

\[\Pr_x \left[ f(x) = g(x) \right],\]

where \(f\) and \(g\) are given by the provided simulations, and the \(N\) challenges \(x\) are generated randomly using the provided \(\mathtt{seed}\).

If response length is greater than 1, the similarity is given for each bit seperately. To obtain the general similarity, average the response.

Returns an array of shape \((m,)\).

>>> from pypuf.simulation import XORArbiterPUF
>>> from pypuf.metrics import similarity
>>> similarity(XORArbiterPUF(n=128, k=4, seed=1), XORArbiterPUF(n=128, k=4, seed=1), seed=31415)  # same seed
array([1.])
>>> similarity(XORArbiterPUF(n=128, k=4, seed=1), XORArbiterPUF(n=128, k=4, seed=2), seed=31415)  # different seed
array([0.516])
pypuf.metrics.similarity_data(responses1: ndarray, responses2: ndarray) ndarray

Given two arrays of responses of shape \((N, m)\), returns the relative frequency of equal responses in the arrays for each response bit, i.e. an approximation of

\[\Pr_x \left[ f(x) = g(x) \right],\]

where \(f\) and \(g\) are the functions given by \(\mathtt{responses1}\) and \(\mathtt{responses2}\), respectively; \(x\) are the challenges (given implicitly by ordering of the response arrays).

If response length \(m\) is greater than 1, the similarity is given for each bit seperately. To obtain the general similarity, average the response.

Returns an array of shape \((m,)\).

>>> from pypuf.metrics import similarity_data
>>> from numpy import array
>>> similarity_data(array([[1, 1], [1, 1], [1, 1], [1, 1]]), array([[1, 1], [1, 1], [1, 1], [-1, 1]]))
array([0.75, 1.  ])