def test_proper_dimension(self): """The function recognizes that the array has dimension zero.""" arr = zeros((), dtype=dtype('int64')) item = 30 with self.assertRaisesRegex(AssertionError, 'arr must have at least one dimension.'): append_last(arr, item)
def test_same_dtype(self): """This function checks for type safety""" typ = dtype('int64') arr = zeros((3, 2, 1), dtype=typ) item = 30 arr_res = append_last(arr, item) self.assertEqual(arr_res.dtype, typ, 'The types must be equal.') arr = zeros((3, 2, 1), dtype=typ) item = 30.1 with self.assertRaisesRegex(AssertionError, 'The elements of arr and item must be of the same type.'): append_last(arr, item)
def __init__(self, weight_array, transform, combiner, bias=None): """ Initializes an LTFArray based on given weight_array and combiner function with appropriate transformation of challenges. The bias is committed through the (n+1)th value in weight_array. So the parameter bias only states if the given weight_array has n+1 values (or not) while the challenges still has length n. :param bias: None, float or a two dimensional array of float with shape (k, 1) This bias value or array of bias values will be appended to the weight_array. Use a single value if you want the same bias for all weight_vectors. """ (self.k, self.n) = shape(weight_array) self.weight_array = weight_array self.transform = transform self.combiner = combiner self.bias = bias # If it is a float append the same value to all PUFs if isinstance(self.bias, float): self.weight_array = tools.append_last(self.weight_array, self.bias) # If it is an array append a value to each PUF elif isinstance(self.bias, type(array([]))): dimensions = len(shape(self.bias)) assert dimensions == 2, 'bias is an {0} dimensional array. Only two dimensions are allowed'.format( dimensions) self.weight_array = append(self.weight_array, self.bias, axis=1)
def efba_bit(cls, sub_challenges): """ Converts sub-challenges to "efba" (extended for bias awareness) sub-challenges, i.e. appends a 1-bit to each sub-challenge. :param sub_challenges: A list of sub-challenge arrays, that is, an array of shape (N, k, n). :return: A list of "efba" sub-challenge arrays, that is, an array of shape (N, k, n+1). """ return tools.append_last(sub_challenges, sub_challenges.dtype.type(1))
def test_append_result(self): """This function checks for the correct calculation of the function with predefined results.""" typ = dtype('int64') arr_check = zeros((3, 2, 2), dtype=typ) arr = zeros((3, 2, 1), dtype=typ) item = 0 arr_res = append_last(arr, item) self.assertTrue(array_equal(arr_check, arr_res), 'The arrays should be equal.')
def ltf_eval(self, inputs): """ This method evaluates a given array of challenges. For this purpose it uses the dot product on every challenge and weight of the weight_array. :param inputs: array of int shape(N,k,n) Array of challenges which should be evaluated by the simulation. :return: array of int shape(N,k) Array of responses for the N different challenges. """ if self.bias is not None: responses = ph.eval(tools.append_last(inputs, 1), self.weight_array) else: responses = ph.eval(inputs, self.weight_array) return responses
def test_append_dimensions(self): """This test checks the correct behavior for different shapes.""" typ = dtype('int64') item = 0 # iterate over several dimensions for dimensions in range(1, 11): # generate the shape of arr shape = [i for i in range(dimensions)] # generate the shape of the array which is used to check the adding shape_res = [i for i in range(dimensions)] # the last dimension must have one more element than the last dimension of arr shape_res[-1] = shape_res[-1]+1 # generate the arrays arr_check = zeros(shape_res, dtype=typ) arr = zeros(shape, dtype=typ) # append the last item arr_res = append_last(arr, item) # check for equality self.assertTrue(array_equal(arr_res, arr_check), 'The arrays should be equal.')