示例#1
0
    def structured_product(self, x, OMEGA, OMEGA_CONJ):

        y = np.copy(x)
        #print(self._d_pr, self._d)
        if self._d_pr <= self._d:

            for block in self._BBB[::-1]:

                # matrix-vector product
                if block._hash_func == 'random':
                    y = np.dot(block._A, y)

                if block._hash_func == 'circulant':
                    y = StructuredMatrices.circulant_product(block._col, y)

                if block._hash_func == 'skew_circulant':
                    y = StructuredMatrices.skew_circulant_product(
                        block._col, y, OMEGA, OMEGA_CONJ)

                if block._hash_func == 'toeplitz':
                    y = StructuredMatrices.toeplitz_product(
                        block._col, block._row, y)

                if block._hash_func == 'hadamard':
                    y = StructuredMatrices.hadamard_cross_polytope_product(
                        y, block._D, block._nblocks)

                if block._hash_func == 'hankel':
                    y = StructuredMatrices.hankel_product(
                        block._col, block._row, y)

                if block._hash_func == 'low_displacement_rank':
                    y = StructuredMatrices.low_displacement_product(
                        block._G, block._H, block._r, y, OMEGA, OMEGA_CONJ)

                if block._hash_func == 'kronecker':
                    y = StructuredMatrices.kronecker_product_rec(
                        block._A_list, y)

                if block._hash_func == 'pure_hadamard':
                    #y = fht.fht1(y)
                    a = ffht.create_aligned(y.shape[0], np.float32)
                    np.copyto(a, y)
                    ffht.fht(a, min(y.shape[0], 1024, 2048))
                    y = a
                if block._hash_func == 'diagonal' or block._hash_func == 'diagonal_kronecker' or block._hash_func == 'diagonal_gaussian':
                    y = block._D * y

                #print(block, y.shape)

            # all blocks have been handled.

            # dimensionality reduction
            y = y[:self._d_pr]
            if self._normalization:
                y *= self._norm_factor_list
            return y

        else:

            if len(self._BBB) == 1 and self._BBB[0]._hash_func == 'random':
                y = np.dot(self._BBB[0]._A, y)
                return y

            y_global = np.zeros(self._d_pr)

            div = self._d_pr // self._d  # number of parameters
            div_real = self._d_pr / self._d
            #print(div, div_real, self._d_pr, self._d)
            assert div == div_real  # we handle only this case
            # /!\ + d_pr should be an integral power of 2!!!
            for i_div in xrange(div):

                #print('i_div', i_div)
                y = np.copy(x)

                # if div_real != div, the last mini block should be truncated => never happened because of the case of hadamard
                # split  y into small vectors  and reunit all results after
                for block in self._BBB[::-1]:
                    #if i_div == div or i_div < div -1:
                    # easy

                    # matrix-vector product

                    if block._hash_func == 'circulant':
                        y = StructuredMatrices.circulant_product(
                            block._col[i_div], y)

                    if block._hash_func == 'skew_circulant':
                        y = StructuredMatrices.skew_circulant_product(
                            block._col[i_div], y, OMEGA, OMEGA_CONJ)

                    if block._hash_func == 'toeplitz':
                        y = StructuredMatrices.toeplitz_product(
                            block._col[i_div], block._row[i_div], y)

                    if block._hash_func == 'hadamard':
                        y = StructuredMatrices.hadamard_cross_polytope_product(
                            y, block._D[i_div], block._nblocks)

                    if block._hash_func == 'hankel':
                        y = StructuredMatrices.hankel_product(
                            block._col[i_div], block._row[i_div], y)

                    if block._hash_func == 'low_displacement_rank':
                        y = StructuredMatrices.low_displacement_product(
                            block._G[i_div], block._H[i_div], block._r, y,
                            OMEGA, OMEGA_CONJ)

                    if block._hash_func == 'kronecker':
                        y = StructuredMatrices.kronecker_product_rec(
                            block._A_list[i_div], y)

                    if block._hash_func == 'pure_hadamard':
                        a = ffht.create_aligned(y.shape[0], np.float32)
                        np.copyto(a, y)
                        ffht.fht(a, min(x.shape[0], 1024, 2048))
                        y = a

                    if block._hash_func == 'diagonal' or block._hash_func == 'diagonal_kronecker' or block._hash_func == 'diagonal_gaussian':
                        y = block._D[i_div] * y

                y_global[i_div * self._d:i_div * self._d + self._d] = y
                #print(y_global)
                if self._normalization:
                    y_global *= self._norm_factor_list

            return y_global
示例#2
0
    def __init__(self, d, d_pr, hash_func, bonus):

        # intialization

        # /!\ the following parameters are one parameter if d_pr <= d
        # or list of parameters if d_pr > d
        # example: for a circulant matrix :
        # div = d_pr// d (euclidean division)
        # so we need div columns parameter to compute the rectangular circulant matrix

        self._d = d  # number of columns
        self._d_pr = d_pr  # number of rows
        self._hash_func = hash_func

        self._A = None

        self._col = None
        self._row = None

        # specific to an HDi block
        self._nblocks = None
        self._D = None

        # specific to a low-displacement rank block
        self._r = None
        if self._r:
            assert self._r < self._d
        self._G = None
        self._H = None

        # specific to a kronecker block
        self._discrete = None  # boolean
        self._de = None
        self._A_list = None

        # to be sure I forgot no cases
        self._check = False

        assert self._hash_func in [
            'random', 'circulant', 'skew_circulant', 'toeplitz', 'hankel',
            'pure_hadamard', 'hadamard', 'low_displacement_rank', 'kronecker',
            'diagonal', 'diagonal_kronecker', 'diagonal_gaussian'
        ]

        # filling necessary variables
        # TODO: simplify the code by reunification of the two cases

        # less rows than columns
        if self._d_pr <= self._d:

            if self._hash_func == 'random':
                self._A = np.random.normal(0.0, 1.0, (self._d_pr, self._d))
                self._check = True

            if self._hash_func == 'circulant' or hash_func == 'skew_circulant' or hash_func == 'toeplitz' or hash_func == 'hankel':
                self._col = np.random.normal(0.0, 1.0, self._d)
                self._check = True

            if self._hash_func == 'hadamard':
                assert 'nblocks' in bonus
                self._nblocks = bonus['nblocks']
                self._D = StructuredMatrices.compute_diagonal_matrices(
                    self._d, self._nblocks)
                self._check = True
                # do not compute Hadamard matrix in advance

            if self._hash_func == 'toeplitz':
                self._row = np.random.normal(0.0, 1.0, self._d)
                self._row[0] = self._col[0]
                self._check = True

            if self._hash_func == 'hankel':
                self._row = np.random.normal(0.0, 1.0, self._d)
                self._row[0] = self._col[self._d - 1]
                self._check = True

            if self._hash_func == 'low_displacement_rank':
                assert 'r' in bonus
                self._r = bonus['r']
                self._G = np.random.normal(0.0, 1.0, (self._d, self._r))
                self._H = np.random.normal(0.0, 1.0, (self._d, self._r))

                #TODO:
                # each column should be 5-sparse for G50C => 10%
                # UGLY
                for i in xrange(self._r):
                    zeros = np.random.randint(0,
                                              self._r,
                                              size=int(0.1 * self._d))
                    for zero in zeros:
                        self._H[zero, i] = 0

                self._check = True

            if self._hash_func == 'kronecker':
                assert 'discrete' in bonus
                assert 'de' in bonus
                self._discrete = bonus['discrete']
                self._de = bonus['de']
                self._A_list = StructuredMatrices.kronecker(
                    int(math.log(self._d, 2)), self._de, self._discrete)
                self._check = True

            if self._hash_func == 'diagonal':
                self._D = StructuredMatrices.compute_diagonal_matrices(
                    self._d, 1).reshape(self._d, )
                self._check = True

            if self._hash_func == 'diagonal_kronecker':
                self._D = StructuredMatrices.compute_kronecker_vector(
                    self._d, n_lev=3, n_bits=2, discrete=True)
                self._check = True

            if self._hash_func == 'diagonal_kronecker':
                self._D = StructuredMatrices.compute_kronecker_vector(
                    self._d, n_lev=3, n_bits=2, discrete=True)
                self._check = True

            if self._hash_func == 'diagonal_gaussian':
                self._D = np.random.normal(0.0, 1.0, self._d)
                self._check = True

            if self._hash_func == 'pure_hadamard':
                self._check = True
                # nothing to do
                pass

        else:
            # d_pr > d
            div = self._d_pr // self._d  # number of parameters

            if self._hash_func == 'random':
                self._A = np.random.normal(0.0, 1.0, (self._d_pr, self._d))
                self._check = True

            if self._hash_func == 'circulant' or hash_func == 'skew_circulant' or hash_func == 'toeplitz' or hash_func == 'hankel':
                self._col = [
                    np.random.normal(0.0, 1.0, self._d) for i in xrange(div)
                ]
                self._check = True

            if self._hash_func == 'hadamard':
                assert 'nblocks' in bonus
                self._nblocks = bonus['nblocks']
                self._D = [
                    StructuredMatrices.compute_diagonal_matrices(
                        self._d, self._nblocks) for i in xrange(div)
                ]
                self._check = True
                # do not compute Hadamard matrix in advance

            if self._hash_func == 'toeplitz':
                self._row = [
                    np.random.normal(0.0, 1.0, self._d) for i in xrange(div)
                ]
                for i in xrange(div):
                    self._row[i][0] = self._col[i][0]
                self._check = True

            if self._hash_func == 'hankel':
                self._row = [
                    np.random.normal(0.0, 1.0, self._d) for i in xrange(div)
                ]
                for i in xrange(div):
                    self._row[i][0] = self._col[i][self._d - 1]
                self._check = True

            if self._hash_func == 'low_displacement_rank':
                assert 'r' in bonus
                self._r = bonus['r']
                self._G = [
                    np.random.normal(0.0, 1.0, (self._d, self._r))
                    for i in xrange(div)
                ]
                self._H = [
                    np.random.normal(0.0, 1.0, (self._d, self._r))
                    for i in xrange(div)
                ]

                #TODO:
                # each column should be 5-sparse for G50C => 10%
                # UGLY
                for j in xrange(div):
                    for i in xrange(self._r):
                        zeros = np.random.randint(0,
                                                  self._r,
                                                  size=int(0.1 * self._d))
                        for zero in zeros:
                            self._H[j][zero, i] = 0

                self._check = True

            if self._hash_func == 'kronecker':
                assert 'discrete' in bonus
                assert 'de' in bonus
                self._discrete = bonus['discrete']
                self._de = bonus['de']
                self._A_list = [
                    StructuredMatrices.kronecker(int(math.log(self._d, 2)),
                                                 self._de, self._discrete)
                    for i in xrange(div)
                ]
                self._check = True

            if self._hash_func == 'diagonal':
                self._D = [
                    StructuredMatrices.compute_diagonal_matrices(
                        self._d, 1).reshape(self._d, ) for i in xrange(div)
                ]
                self._check = True

            if self._hash_func == 'diagonal_kronecker':
                self._D = [
                    StructuredMatrices.compute_kronecker_vector(self._d,
                                                                n_lev=3,
                                                                n_bits=2,
                                                                discrete=True)
                    for i in xrange(div)
                ]
                self._check = True

            if self._hash_func == 'diagonal_gaussian':
                self._D = [
                    np.random.normal(0.0, 1.0, self._d) for i in xrange(div)
                ]
                self._check = True

            if self._hash_func == 'pure_hadamard':
                self._check = True
                # nothing to do
                pass

        # to be sure we entered at least in one if
        assert self._check