def compute_p2(P_stencil,n,grid_size):
    batch_size = P_stencil.shape[0]
    K = map_2_to_1(grid_size=grid_size)
    pi = np.pi
    theta_x = np.array(([i * 2 * pi / n for i in range(-n // (grid_size*2) + 1, n // (grid_size*2) + 1)]))
    theta_y = np.array([i * 2 * pi / n for i in range(-n // (grid_size*2) + 1, n // (grid_size*2) + 1)])
    num_modes = theta_x.shape[0]

    X, Y = np.meshgrid(np.arange(-1, 2), np.arange(-1, 2))
    with tf.device("gpu:0"):
        P = tf.zeros((len(theta_y), len(theta_x),batch_size,grid_size**2,(grid_size//2)**2),dtype=tf.complex128)
        modes = np.array([[np.exp(-1j * (tx * X + ty * Y)) for tx in theta_x] for ty in theta_y])
        fourier_component = tf.to_complex128(np.tile(modes, (batch_size,1,1,1,1)))
        for ic in range(grid_size//2):
            i = 2*ic #ic is the index on the coarse grid, and i is the index on the fine grid
            for jc in range(grid_size//2):
                j = 2*jc #jc is the index on the coarse grid, and j is the index on the fine grid
                J = int(grid_size//2*jc+ic)
                for k in range(3):
                    for m in range(3):
                        I = int(K[i,j,k,m])
                        a = fourier_component[:,:,:,k, m] * tf.reshape(P_stencil[:, ic, jc, k, m],(-1,1,1))
                        a = tf.transpose(a,(1,2,0))

                        P = P + tf.to_complex128(
                            tf.scatter_nd(tf.constant(idx_array((I,J,int(batch_size),num_modes))),
                                          tf.ones(batch_size*(num_modes**2)),
                                          tf.constant([num_modes,num_modes,batch_size, grid_size**2, (grid_size//2)**2])))*tf.reshape(a, (theta_x.shape[0],theta_y.shape[0], batch_size, 1, 1))
        return P
Example #2
0
    def partial_trace(tensor, dims_subsystems):
        '''
        Take the partial trace, leaving H_A, where H = H_A \otimes H_B \otimes H_N
        # Einsum does not allow you to do traces so we need this hacky method.
        # reorder the axes and take the trace of the final two.
        # These loops does the following (for 2 subsystems):
        # first loop
        # permute axes 0,a,b,c,a,b,c -> 0,a,a,c,b,b,c
        # permute axes 0,a,a,c,b,b,c -> 0,a,a,b,b,c,c
        # perform permutation
        # second loop
        # trace 0,a,a,b,b,c,c -> 0,a,a,b,b
        # trace 0,a,a,b,b -> 0,a,a

        :param tensor: NxN density matrix
        :param dims_subsystems: Dimensions of subsystems
        :return: Reduced density matrix
        '''
        dims = np.tile(dims_subsystems, 2)
        # insert batch dimension
        dims = np.insert(dims, [0], [-1])
        tensor = tf.reshape(tensor, dims)
        idx = list(range(len(dims)))
        n = len(dims_subsystems)
        for i in range(n - 1):
            idx[n + i + 1], idx[2 + i] = idx[2 + i], idx[n + i + 1]
        tensor = tf.transpose(tensor, perm=idx)
        for _ in range(n - 1):
            tensor = tf.trace(tensor)
        return tf.to_complex128(tensor)
Example #3
0
 def to_complex(self, x):
     if self.dtype(x) in (np.complex64, np.complex128):
         return x
     if self.dtype(x) == np.float64:
         return tf.to_complex128(x)
     else:
         return tf.to_complex64(x)
Example #4
0
    def build_graph(self,
                    hilbert_space_composition,
                    epsilon=0.1,
                    complex_weights=True,
                    device='CPU'):
        # Assert first that the model is compiled properly
        assert self.dim != None, 'Data dimension unknown, specify as model argument or run QubitLearning.get_statistics'
        assert self.n_samples != None, 'Number of samples unknown, specify as model argument or run QubitLearning.get_statistics'
        assert isinstance(
            hilbert_space_composition,
            (list, tuple, np.ndarray
             )), 'Pass list, tuple or ndarray of Hilbert space dimensions'
        assert len(
            hilbert_space_composition
        ) > 0, 'Hilbert space must consist of at least one dimension'
        assert all(
            isinstance(d, int) for d in hilbert_space_composition
        ), 'Expected list of integers for the dimensions of the composite Hilbert spaces'
        assert all(d >= 2 for d in hilbert_space_composition
                   ), 'Composite Hilbert spaces must have dim(H_i) >= 2'
        assert (
            hilbert_space_composition[0] == self.c
        ), 'dim(H_A) must be equal to the number of classes = {}, but dim(H_A) = {}'.format(
            self.c, hilbert_space_composition[0])

        # Build the model
        with tf.name_scope('model'):
            # TODO: X now has shape 1 but needs shape -1, rest of functions needs to be adapted
            dims = np.array([d for d in hilbert_space_composition])
            # self.x = tf.placeholder(dtype=tf.float32, shape=(None, self.dim))
            # The data density matrix is C x C where C is the number of classes
            self.eta = tf.placeholder(dtype=tf.complex128,
                                      shape=(None, self.c, self.c))

            if len(hilbert_space_composition) == 1:
                print('Building non-entangled model')
                self.MODEL_TYPE = 'single'
                generators = self.SU_generators(dims[0])
                self.x = tf.placeholder(dtype=tf.float32,
                                        shape=(None, self.dim))
                # For single system we just take the SU(C) matrices with C^2 - 1 free parameters
                weights = tf.get_variable("weights",
                                          (self.dim, dims[0]**2 - 1),
                                          dtype=tf.float32)
                # Multiply the weights with the inputs to get a field phi for each vector parameter.
                phi = tf.matmul(self.x, weights)
                phi_norm = tf.sqrt(
                    tf.reshape(tf.einsum('nj,nj->n', phi, tf.conj(phi)),
                               (-1, 1)))
                phi = tf.tanh(phi_norm) * phi / phi_norm
                # Construct the model density matrix from the SU(C) generators.
                rho_red = 0.5 * (
                    tf.eye(dims[0], dims[0], dtype=tf.complex128) + tf.einsum(
                        'ni,jki->njk', tf.to_complex128(phi), generators))
            else:
                print('Building entangled model')

                if len(hilbert_space_composition) == 2:
                    self.MODEL_TYPE = 'bipartite'
                elif len(hilbert_space_composition) > 2:
                    self.MODEL_TYPE = 'multipartite'
                # In the bi- or multipartite case the number of parameters is equal to the size the combined Hilbert space
                if self.learn_hamiltonian is None:

                    # weights = tf.get_variable("weights", (self.dim, (np.product(dims, keepdims=True))), dtype=tf.float32)

                    if complex_weights:
                        self.x = tf.placeholder(dtype=tf.complex128,
                                                shape=(None, self.dim))
                        weights_r = tf.get_variable(
                            "weights_r",
                            (self.dim, (np.product(dims, keepdims=True))),
                            dtype=tf.float32)
                        weights_c = tf.get_variable(
                            "weights_c",
                            (self.dim, (np.product(dims, keepdims=True))),
                            dtype=tf.float32)
                        weights = tf.to_complex128(
                            tf.complex(weights_r, weights_c))
                    else:
                        self.x = tf.placeholder(dtype=tf.float32,
                                                shape=(None, self.dim))
                        weights = tf.get_variable(
                            "weights",
                            (self.dim, (np.product(dims, keepdims=True))),
                            dtype=tf.float32)
                    phi = tf.matmul(self.x, weights)
                    phi_norm = tf.sqrt(
                        tf.reshape(tf.einsum('nj,nj->n', phi, tf.conj(phi)),
                                   (-1, 1)))
                    phi /= phi_norm
                    rho = tf.einsum('ni,nj->nij', phi, tf.conj(phi))
                    # Trace out the entangled systems to get a C x C density matrix
                    rho_red = self.partial_trace(rho, dims)
                else:
                    self.x = tf.placeholder(dtype=tf.complex128,
                                            shape=(None, self.dim))
                    I = tf.ones((tf.shape(self.x)[0], 1), dtype=tf.complex128)
                    H = tf.zeros(shape=(np.product(dims), np.product(dims)),
                                 dtype=tf.complex128)
                    num_weights = 0
                    for flag, name, f in self.hamiltonian.field_hamiltonian_iterator(
                    ):
                        if flag:
                            weight = tf.get_variable("weight_{}".format(name),
                                                     (self.dim, 1),
                                                     dtype=tf.float32)
                            h = tf.matmul(self.x,
                                          tf.to_complex128(weight),
                                          name="field_{}".format(name))
                            H += tf.einsum('ni,jk->njk', h, tf.constant(f))
                            num_weights += 1
                        else:
                            H += tf.einsum('ni,jk->njk', I, tf.constant(f))

                    for flag, name, f in self.hamiltonian.coupling_hamiltonian_iterator(
                    ):
                        if flag:
                            weight = tf.get_variable("weight_{}".format(name),
                                                     (self.dim, 1),
                                                     dtype=tf.float32)
                            h = tf.matmul(self.x,
                                          tf.to_complex128(weight),
                                          name="coupling_{}".format(name))
                            H += tf.einsum('ni,jk->njk', h, tf.constant(f))
                            num_weights += 1
                        else:
                            H += tf.einsum('ni,jk->njk', I, tf.constant(f))

                    energies, phi = tf.linalg.eigh(H)
                    energies = tf.identity(energies, name='energies')

                    if self.rank_one_approx:
                        rho = tf.einsum('ni,nj->nij', phi[:, 0],
                                        tf.conj(phi[:, 0]))
                    else:
                        rho = self.matrix_exp(H)
                        rho /= tf.reshape(tf.trace(rho), (-1, 1, 1))
                    rho_red = self.partial_trace(rho, dims)

                    with tf.name_scope('quantities'):
                        tf.identity(energies[:, 0], name='gs_energy')
                        tf.identity(energies[:, 0] - energies[:, 1],
                                    name='width')
                        lams, _ = tf.linalg.eigh(rho_red)
                        lams = tf.identity(lams, name='lams')
                        tf.reduce_sum(-lams * tf.log(lams),
                                      axis=1,
                                      name='vn_entropy')

        with tf.name_scope('negative_quantum_log_likelihood'):
            # if lambda_op:
            #     gamma_0 = tf.constant(np.array([[1, 0], [0, 0]]), dtype=tf.complex128)
            #     gamma_1 = tf.constant(np.array([[0, 0], [0, 1]]), dtype=tf.complex128)
            #
            #     self.negqll =- tf.reduce_sum(self.q_y[0] * tf.real(tf.log(tf.trace(tf.einsum('nij,jk->nik', rho_red, gamma_0)))))
            #     self.negqll -= tf.reduce_sum(self.q_y[1] * tf.real(tf.log(tf.trace(tf.einsum('nij,jk->nik', rho_red, gamma_1)))))
            if self.c == 2:
                self.negqll = -tf.reduce_sum(
                    tf.real(
                        tf.trace(
                            tf.matmul(self.eta,
                                      self.matrix_log_2x2(rho_red)))))
            else:
                self.negqll = -tf.reduce_sum(
                    tf.real(
                        tf.trace(tf.matmul(self.eta,
                                           self.matrix_log(rho_red)))))

            tf.summary.scalar('negative_quantum_log_likelihood', self.negqll)

        with tf.name_scope('optimizer'):
            # Get the optimizer
            opt = tf.train.GradientDescentOptimizer(learning_rate=epsilon)
            # opt = tf.train.AdagradOptimizer(learning_rate=epsilon)
            # self.train_step = opt.minimize(self.negqll, var_list=[weights])
            if self.MODEL_TYPE == 'bipartite' or self.MODEL_TYPE == 'multipartite':
                if self.learn_hamiltonian:
                    self.train_step = opt.minimize(
                        self.negqll,
                        var_list=[var for var in tf.trainable_variables()])
                else:
                    if complex_weights:
                        self.train_step = opt.minimize(
                            self.negqll, var_list=[weights_r, weights_c])
                    else:
                        self.train_step = opt.minimize(self.negqll,
                                                       var_list=[weights])
            else:
                self.train_step = opt.minimize(self.negqll, var_list=[weights])
            self._initialize_session(device)

        with tf.name_scope('predictor'):

            # if lambda_op:
            #     self.probabilities = tf.trace(tf.einsum('nij,jk->nik', rho_red, gamma_0))
            #     self.probabilities = tf.stack([self.probabilities, 1 - self.probabilities], axis=1)
            if self.c == 2:
                self.probabilities = tf.stack(
                    [rho_red[:, 0, 0], rho_red[:, 1, 1]], axis=1)
            else:
                _, v = tf.linalg.eigh(rho_red)
                self.probabilities = tf.abs(v[:, :, 0])**2

        self.FLAG_GRAPH = True
Example #5
0
    writer = SummaryWriter(log_dir='runs/' + run_name)

    periodic: bool = args.bc == 'periodic'
    input_transforms = model.periodic_input_transform if periodic else model.dirichlet_input_transform
    output_transforms = model.periodic_output_transform if periodic else model.dirichlet_output_tranform

    with tf.device(DEVICE):
        m = PNetwork() if not args.simple else PNetworkSimple()

    root = tf.train.Checkpoint(optimizer=optimizer, model=m, optimizer_step=tf.train.get_or_create_global_step())

    blackbox_model = blackbox.black_box_periodic_output_transform if periodic else blackbox.black_box_dirichlet_output_transform

    with tf.device(DEVICE):
        pi = tf.constant(np.pi)
        ci = tf.to_complex128(1j)

    A_stencils_test, A_matrices_test, S_matrices_test, num_of_modes = utils.get_A_S_matrices(num_test_samples, np.pi,
                                                                                             grid_size, n_test)

    with tf.device(DEVICE):
        A_stencils_test = tf.convert_to_tensor(A_stencils_test, dtype=tf.double)
        A_matrices_test = tf.convert_to_tensor(A_matrices_test, dtype=tf.complex128)
        S_matrices_test = tf.reshape(tf.convert_to_tensor(S_matrices_test, dtype=tf.complex128),
                                     (-1, num_of_modes, num_of_modes, grid_size ** 2, grid_size ** 2))

    A_stencils_train = np.array(utils.two_d_stencil(num_training_samples))

    n_train_list = [16, 16, 32]
    initial_epsi = 1e-0
    def call(self,
             inputs,
             black_box=False,
             index=None,
             pos=-1.,
             phase='Training'):

        with tf.device(self.device):
            batch_size = inputs.shape[0]
            right_contributions_input = tf.gather(
                params=inputs,
                indices=[i for i in range(1, self.grid_size, 2)],
                axis=1)
            right_contributions_input = tf.gather(
                params=right_contributions_input,
                indices=[i for i in range(0, self.grid_size, 2)],
                axis=2)
            idx = [(i - 1) % self.grid_size
                   for i in range(0, self.grid_size, 2)]
            left_contributions_input = tf.gather(params=inputs,
                                                 indices=idx,
                                                 axis=1)
            left_contributions_input = tf.gather(
                params=left_contributions_input,
                indices=[i for i in range(0, self.grid_size, 2)],
                axis=2)
            left_contributions_input = tf.reshape(
                tensor=left_contributions_input,
                shape=(-1, self.grid_size // 2, self.grid_size // 2, 3, 3))

            up_contributions_input = tf.gather(
                params=inputs,
                indices=[i for i in range(0, self.grid_size, 2)],
                axis=1)
            up_contributions_input = tf.gather(
                params=up_contributions_input,
                indices=[i for i in range(1, self.grid_size, 2)],
                axis=2)
            up_contributions_input = tf.reshape(tensor=up_contributions_input,
                                                shape=(-1, self.grid_size // 2,
                                                       self.grid_size // 2, 3,
                                                       3))

            down_contributions_input = tf.gather(
                params=inputs,
                indices=[i for i in range(0, self.grid_size, 2)],
                axis=1)
            down_contributions_input = tf.gather(
                params=down_contributions_input, indices=idx, axis=2)
            down_contributions_input = tf.reshape(
                tensor=down_contributions_input,
                shape=(-1, self.grid_size // 2, self.grid_size // 2, 3, 3))
            #
            center_contributions_input = tf.gather(
                params=inputs,
                indices=[i for i in range(0, self.grid_size, 2)],
                axis=1)
            center_contributions_input = tf.gather(
                params=center_contributions_input,
                indices=[i for i in range(0, self.grid_size, 2)],
                axis=2)
            center_contributions_input = tf.reshape(
                tensor=center_contributions_input,
                shape=(-1, self.grid_size // 2, self.grid_size // 2, 3, 3))

            inputs_combined = tf.concat([
                right_contributions_input, left_contributions_input,
                up_contributions_input, down_contributions_input,
                center_contributions_input
            ], 0)

            flattended = tf.reshape(inputs_combined, (-1, 9))

            temp = (self.grid_size // 2)**2

            # bug then augmented with doubled grid size
            flattended = tf.concat([
                flattended[:batch_size * temp],
                flattended[temp * batch_size:temp * 2 * batch_size],
                flattended[temp * 2 * batch_size:temp * 3 * batch_size],
                flattended[temp * 3 * batch_size:temp * 4 * batch_size],
                flattended[temp * 4 * batch_size:]
            ], -1)

            # x = self.linear0(flattended)
            # x = tf.nn.relu(x)
            # for i in range(1, self.num_layers, 2):
            #     x1 = getattr(self, "bias_1%i" % i) + x
            #     x1 = getattr(self, "linear%i" % i)(x1)
            #     x1 = x1 + getattr(self, "bias_2%i" % i) + x1
            #     x1 = tf.nn.relu(x1)
            #     x1 = x1 + getattr(self, "bias_3%i" % i) + x1
            #     x1 = getattr(self, "linear%i" % (i + 1))(x1)
            #     x1 = tf.multiply(x1, getattr(self, "multiplier_%i" % i))
            #     x = x + x1
            #     x = x + getattr(self, "bias_4%i" % i)
            #     x = tf.nn.relu(x)

            x = self.dense0(flattended)
            for i in range(1, self.num_layers):
                x = getattr(self, "dense%i" % 1)(x)
            x = self.output_layer(x)

            if index is not None:
                indices = tf.constant([[index]])
                updates = [tf.to_double(pos)]
                shape = tf.constant([2 * 2 * 2 * 8])
                scatter = tf.scatter_nd(indices, updates, shape)
                x = self.new_output + tf.reshape(scatter, (-1, 2, 2, 8))
                ld_contribution = x[:, :, :, 0]
                left_contributions_output = x[:, :, :, 1]
                lu_contribution = x[:, :, :, 2]
                down_contributions_output = x[:, :, :, 3]
                up_contributions_output = x[:, :, :, 4]
                ones = tf.ones_like(up_contributions_output)
                right_contributions_output = x[:, :, :, 6]
                rd_contribution = x[:, :, :, 5]
                ru_contribution = x[:, :, :, 7]
                first_row = tf.concat([
                    tf.expand_dims(ld_contribution, -1),
                    tf.expand_dims(left_contributions_output, -1),
                    tf.expand_dims(lu_contribution, -1)
                ], -1)
                second_row = tf.concat([
                    tf.expand_dims(down_contributions_output, -1),
                    tf.expand_dims(ones, -1),
                    tf.expand_dims(up_contributions_output, -1)
                ], -1)
                third_row = tf.concat([
                    tf.expand_dims(rd_contribution, -1),
                    tf.expand_dims(right_contributions_output, -1),
                    tf.expand_dims(ru_contribution, -1)
                ], -1)

                output = tf.stack([first_row, second_row, third_row], 0)
                output = tf.transpose(output, (1, 2, 3, 0, 4))
                if not black_box:
                    return tf.to_complex128(output)
            else:
                x = tf.reshape(
                    x, (-1, self.grid_size // 2, self.grid_size // 2, 4))
            if black_box:
                up_contributions_output = tf.gather(
                    inputs, [i for i in range(0, self.grid_size, 2)], axis=1)
                up_contributions_output = tf.gather(
                    up_contributions_output,
                    [i for i in range(1, self.grid_size, 2)],
                    axis=2)
                up_contributions_output = -tf.reduce_sum(
                    up_contributions_output[:, :, :, :, 0],
                    axis=-1) / tf.reduce_sum(
                        up_contributions_output[:, :, :, :, 1], axis=-1)

                left_contributions_output = tf.gather(inputs, idx, axis=1)
                left_contributions_output = tf.gather(
                    left_contributions_output,
                    [i for i in range(0, self.grid_size, 2)],
                    axis=2)
                left_contributions_output = -tf.reduce_sum(
                    left_contributions_output[:, :, :, 2, :],
                    axis=-1) / tf.reduce_sum(
                        left_contributions_output[:, :, :, 1, :], axis=-1)

                right_contributions_output = tf.gather(
                    inputs, [i for i in range(1, self.grid_size, 2)], axis=1)
                right_contributions_output = tf.gather(
                    right_contributions_output,
                    [i for i in range(0, self.grid_size, 2)],
                    axis=2)
                right_contributions_output = -tf.reduce_sum(
                    right_contributions_output[:, :, :, 0, :],
                    axis=-1) / tf.reduce_sum(
                        right_contributions_output[:, :, :, 1, :], axis=-1)
                down_contributions_output = tf.gather(
                    inputs, [i for i in range(0, self.grid_size, 2)], axis=1)
                down_contributions_output = tf.gather(
                    down_contributions_output, idx, axis=2)
                down_contributions_output = -tf.reduce_sum(
                    down_contributions_output[:, :, :, :, 2],
                    axis=-1) / tf.reduce_sum(
                        down_contributions_output[:, :, :, :, 1], axis=-1)
            else:
                jm1 = [(i - 1) % (self.grid_size // 2)
                       for i in range(self.grid_size // 2)]
                jp1 = [(i + 1) % (self.grid_size // 2)
                       for i in range(self.grid_size // 2)]
                right_contributions_output = x[:, :, :, 0] / (
                    tf.gather(x[:, :, :, 1], jp1, axis=1) + x[:, :, :, 0])
                left_contributions_output = x[:, :, :, 1] / (
                    x[:, :, :, 1] + tf.gather(x[:, :, :, 0], jm1, axis=1))
                up_contributions_output = x[:, :, :, 2] / (
                    x[:, :, :, 2] + tf.gather(x[:, :, :, 3], jp1, axis=2))
                down_contributions_output = x[:, :, :, 3] / (
                    tf.gather(x[:, :, :, 2], jm1, axis=2) + x[:, :, :, 3])
            ones = tf.ones_like(down_contributions_output)

            # based on rule 2 given rule 1:
            up_right_contribution = tf.gather(
                inputs, [i for i in range(1, self.grid_size, 2)], axis=1)
            up_right_contribution = tf.gather(
                up_right_contribution,
                [i for i in range(1, self.grid_size, 2)],
                axis=2)
            up_right_contribution = up_right_contribution[:, :, :, 0, 1]
            right_up_contirbution = tf.gather(
                inputs, [i for i in range(1, self.grid_size, 2)], axis=1)
            right_up_contirbution = tf.gather(
                right_up_contirbution,
                [i for i in range(1, self.grid_size, 2)],
                axis=2)
            right_up_contirbution_additional_term = right_up_contirbution[:, :, :,
                                                                          0, 0]
            right_up_contirbution = right_up_contirbution[:, :, :, 1, 0]
            ru_center_ = tf.gather(inputs,
                                   [i for i in range(1, self.grid_size, 2)],
                                   axis=1)
            ru_center_ = tf.gather(ru_center_,
                                   [i for i in range(1, self.grid_size, 2)],
                                   axis=2)
            ru_center_ = ru_center_[:, :, :, 1, 1]
            ru_contribution = -tf.expand_dims((right_up_contirbution_additional_term +
                                               tf.multiply(right_up_contirbution, right_contributions_output) + \
                                               tf.multiply(up_right_contribution,
                                                           up_contributions_output)) / ru_center_, -1)

            up_left_contribution = tf.gather(inputs, idx, axis=1)
            up_left_contribution = tf.gather(
                up_left_contribution, [i for i in range(1, self.grid_size, 2)],
                axis=2)
            up_left_contribution = up_left_contribution[:, :, :, 2, 1]
            left_up_contirbution = tf.gather(inputs, idx, axis=1)
            left_up_contirbution = tf.gather(
                left_up_contirbution, [i for i in range(1, self.grid_size, 2)],
                axis=2)
            left_up_contirbution_addtional_term = left_up_contirbution[:, :, :,
                                                                       2, 0]
            left_up_contirbution = left_up_contirbution[:, :, :, 1, 0]
            lu_center_ = tf.gather(inputs, idx, axis=1)
            lu_center_ = tf.gather(lu_center_,
                                   [i for i in range(1, self.grid_size, 2)],
                                   axis=2)
            lu_center_ = lu_center_[:, :, :, 1, 1]
            lu_contribution = -tf.expand_dims((left_up_contirbution_addtional_term +
                                               tf.multiply(up_left_contribution, up_contributions_output) + \
                                               tf.multiply(left_up_contirbution,
                                                           left_contributions_output)) / lu_center_, -1)

            down_left_contribution = tf.gather(inputs, idx, axis=1)
            down_left_contribution = tf.gather(down_left_contribution,
                                               idx,
                                               axis=2)
            down_left_contribution = down_left_contribution[:, :, :, 2, 1]
            left_down_contirbution = tf.gather(inputs, idx, axis=1)
            left_down_contirbution = tf.gather(left_down_contirbution,
                                               idx,
                                               axis=2)
            left_down_contirbution_additional_term = left_down_contirbution[:, :, :,
                                                                            2,
                                                                            2]
            left_down_contirbution = left_down_contirbution[:, :, :, 1, 2]
            ld_center_ = tf.gather(inputs, idx, axis=1)
            ld_center_ = tf.gather(ld_center_, idx, axis=2)
            ld_center_ = ld_center_[:, :, :, 1, 1]
            ld_contribution = -tf.expand_dims((left_down_contirbution_additional_term +
                                               tf.multiply(down_left_contribution, down_contributions_output) + \
                                               tf.multiply(left_down_contirbution,
                                                           left_contributions_output)) / ld_center_, -1)

            down_right_contribution = tf.gather(
                inputs, [i for i in range(1, self.grid_size, 2)], axis=1)
            down_right_contribution = tf.gather(down_right_contribution,
                                                idx,
                                                axis=2)
            down_right_contribution = down_right_contribution[:, :, :, 0, 1]
            right_down_contirbution = tf.gather(
                inputs, [i for i in range(1, self.grid_size, 2)], axis=1)
            right_down_contirbution = tf.gather(right_down_contirbution,
                                                idx,
                                                axis=2)
            right_down_contirbution_addtional_term = right_down_contirbution[:, :, :,
                                                                             0,
                                                                             2]
            right_down_contirbution = right_down_contirbution[:, :, :, 1, 2]
            rd_center_ = tf.gather(inputs,
                                   [i for i in range(1, self.grid_size, 2)],
                                   axis=1)
            rd_center_ = tf.gather(rd_center_, idx, axis=2)
            rd_center_ = rd_center_[:, :, :, 1, 1]
            rd_contribution = -tf.expand_dims((right_down_contirbution_addtional_term + tf.multiply(
                down_right_contribution, down_contributions_output) + \
                                               tf.multiply(right_down_contirbution,
                                                           right_contributions_output)) / rd_center_, -1)

            first_row = tf.concat([
                ld_contribution,
                tf.expand_dims(left_contributions_output, -1), lu_contribution
            ], -1)
            second_row = tf.concat([
                tf.expand_dims(down_contributions_output, -1),
                tf.expand_dims(ones, -1),
                tf.expand_dims(up_contributions_output, -1)
            ], -1)
            third_row = tf.concat([
                rd_contribution,
                tf.expand_dims(right_contributions_output, -1), ru_contribution
            ], -1)

            output = tf.stack([first_row, second_row, third_row], 0)
            output = tf.transpose(output, (1, 2, 3, 0, 4))

            return tf.to_complex128(output)
Example #7
0
 def body_inside(rho, next_term, k, iter, my_L):
     help = tf.add(k, one)
     help2 = (delta_t / tf.to_complex128(tf.complex(help * iter, zero)))
     temp = tf.matmul(help2 * my_L, next_term)
     return [rho + temp, temp, help, iter, my_L]
Example #8
0
    def call(self,
             inputs,
             black_box=False,
             index=None,
             pos=-1.,
             phase='Training'):
        with tf.device("gpu:0"):
            batch_size = inputs.shape[0]
            right_contributions_input = tf.gather(
                inputs, [i for i in range(2, self.grid_size, 2)], axis=1)
            right_contributions_input = tf.gather(
                right_contributions_input,
                [i for i in range(1, self.grid_size, 2)],
                axis=2)
            idx = [i for i in range(0, self.grid_size - 1, 2)]
            left_contributions_input = tf.gather(inputs, idx, axis=1)
            left_contributions_input = tf.gather(
                left_contributions_input,
                [i for i in range(1, self.grid_size, 2)],
                axis=2)
            left_contributions_input = tf.reshape(
                left_contributions_input,
                (-1, self.grid_size // 2, self.grid_size // 2, 3, 3))

            up_contributions_input = tf.gather(
                inputs, [i for i in range(1, self.grid_size, 2)], axis=1)
            up_contributions_input = tf.gather(
                up_contributions_input,
                [i for i in range(2, self.grid_size, 2)],
                axis=2)
            up_contributions_input = tf.reshape(
                up_contributions_input,
                (-1, self.grid_size // 2, self.grid_size // 2, 3, 3))

            down_contributions_input = tf.gather(
                inputs, [i for i in range(1, self.grid_size, 2)], axis=1)
            down_contributions_input = tf.gather(down_contributions_input,
                                                 idx,
                                                 axis=2)
            down_contributions_input = tf.reshape(
                down_contributions_input,
                (-1, self.grid_size // 2, self.grid_size // 2, 3, 3))
            #
            center_contributions_input = tf.gather(
                inputs, [i for i in range(1, self.grid_size, 2)], axis=1)
            center_contributions_input = tf.gather(
                center_contributions_input,
                [i for i in range(1, self.grid_size, 2)],
                axis=2)
            center_contributions_input = tf.reshape(
                center_contributions_input,
                (-1, self.grid_size // 2, self.grid_size // 2, 3, 3))

            inputs_combined = tf.concat([
                right_contributions_input, left_contributions_input,
                up_contributions_input, down_contributions_input,
                center_contributions_input
            ], 0)
            inputs_combined_temp = tf.concat([
                tf.reduce_sum(inputs_combined, axis=3),
                tf.reduce_sum(inputs_combined, axis=4)
            ],
                                             axis=-1)

            inputs_combined_temp = tf.reshape(inputs_combined_temp, (-1, 6))
            inputs_combined_temp_fixed = tf.where(
                tf.equal(inputs_combined_temp,
                         0), 1e20 * tf.ones_like(inputs_combined_temp),
                inputs_combined_temp)

            #
            flattended = tf.reshape(inputs_combined, (-1, 9))
            # flattended = tf.concat([flattended, inputs_combined_temp,tf.reduce_sum(flattended,1,keepdims=True)],-1)
            # flattended = tf.check_numerics(tf.concat([flattended,tf.reciprocal(flattended)], axis=-1),"sdf")
            # flattended = tf.concat([flattended, tf.reciprocal(flattended)], -1)
            temp = (self.grid_size // 2)**2

            flattended = tf.concat([
                flattended[:batch_size * temp],
                flattended[temp * batch_size:temp * 2 * batch_size],
                flattended[temp * 2 * batch_size:temp * 3 * batch_size],
                flattended[temp * 3 * batch_size:temp * 4 * batch_size],
                flattended[temp * 4 * batch_size:]
            ], -1)

            x = self.linear0(flattended)
            x = tf.nn.relu(x)
            for i in range(1, self.num_layers, 2):
                x1 = getattr(self, "bias_1%i" % i) + x
                x1 = getattr(self, "linear%i" % i)(x1)
                x1 = x1 + getattr(self, "bias_2%i" % i) + x1
                x1 = tf.nn.relu(x1)
                x1 = x1 + getattr(self, "bias_3%i" % i) + x1
                x1 = getattr(self, "linear%i" % (i + 1))(x1)
                x1 = tf.multiply(x1, getattr(self, "multiplier_%i" % i))
                x = x + x1
                x = x + getattr(self, "bias_4%i" % i)
                x = tf.nn.relu(x)

            x = self.output_layer(x)

            if index is not None:
                indices = tf.constant([[index]])
                updates = [tf.to_double(pos)]
                shape = tf.constant([2 * 2 * 2 * 8])
                scatter = tf.scatter_nd(indices, updates, shape)
                x = self.new_output + tf.reshape(scatter, (-1, 2, 2, 8))
                ld_contribution = x[:, :, :, 0]
                left_contributions_output = x[:, :, :, 1]
                lu_contribution = x[:, :, :, 2]
                down_contributions_output = x[:, :, :, 3]
                up_contributions_output = x[:, :, :, 4]
                ones = tf.ones_like(up_contributions_output)
                right_contributions_output = x[:, :, :, 6]
                rd_contribution = x[:, :, :, 5]
                ru_contribution = x[:, :, :, 7]
                first_row = tf.concat([
                    tf.expand_dims(ld_contribution, -1),
                    tf.expand_dims(left_contributions_output, -1),
                    tf.expand_dims(lu_contribution, -1)
                ], -1)
                second_row = tf.concat([
                    tf.expand_dims(down_contributions_output, -1),
                    tf.expand_dims(ones, -1),
                    tf.expand_dims(up_contributions_output, -1)
                ], -1)
                third_row = tf.concat([
                    tf.expand_dims(rd_contribution, -1),
                    tf.expand_dims(right_contributions_output, -1),
                    tf.expand_dims(ru_contribution, -1)
                ], -1)

                output = tf.stack([first_row, second_row, third_row], 0)
                output = tf.transpose(output, (1, 2, 3, 0, 4))
                if not black_box:
                    return tf.to_complex128(output)
            else:
                x = tf.reshape(
                    x, (-1, self.grid_size // 2, self.grid_size // 2, 4))
            if black_box:
                up_contributions_output = tf.gather(
                    inputs, [i for i in range(1, self.grid_size, 2)], axis=1)
                up_contributions_output = tf.gather(
                    up_contributions_output,
                    [i for i in range(2, self.grid_size, 2)],
                    axis=2)
                up_contributions_output = -tf.reduce_sum(
                    up_contributions_output[:, :, :, :, 0],
                    axis=-1) / tf.reduce_sum(
                        up_contributions_output[:, :, :, :, 1], axis=-1)
                left_contributions_output = tf.gather(inputs, idx, axis=1)
                left_contributions_output = tf.gather(
                    left_contributions_output,
                    [i for i in range(1, self.grid_size, 2)],
                    axis=2)
                left_contributions_output = -tf.reduce_sum(
                    left_contributions_output[:, :, :, 2, :],
                    axis=-1) / tf.reduce_sum(
                        left_contributions_output[:, :, :, 1, :], axis=-1)
                right_contributions_output = tf.gather(
                    inputs, [i for i in range(2, self.grid_size, 2)], axis=1)
                right_contributions_output = tf.gather(
                    right_contributions_output,
                    [i for i in range(1, self.grid_size, 2)],
                    axis=2)
                right_contributions_output = -tf.reduce_sum(
                    right_contributions_output[:, :, :, 0, :],
                    axis=-1) / tf.reduce_sum(
                        right_contributions_output[:, :, :, 1, :], axis=-1)

                down_contributions_output = tf.gather(
                    inputs, [i for i in range(1, self.grid_size, 2)], axis=1)
                down_contributions_output = tf.gather(
                    down_contributions_output, idx, axis=2)
                down_contributions_output = -tf.reduce_sum(
                    down_contributions_output[:, :, :, :, 2],
                    axis=-1) / tf.reduce_sum(
                        down_contributions_output[:, :, :, :, 1], axis=-1)
            else:
                jm1 = [(i - 0) % (self.grid_size // 2)
                       for i in range(self.grid_size // 2 - 1)]
                jp1 = [(i + 1) % (self.grid_size // 2)
                       for i in range(self.grid_size // 2 - 1)]
                right_contributions_output = x[:, :-1, :, 0] / (
                    tf.gather(x[:, :, :, 1], jp1, axis=1) + x[:, :-1, :, 0])
                left_contributions_output = x[:, 1:, :, 1] / (
                    x[:, 1:, :, 1] + tf.gather(x[:, :, :, 0], jm1, axis=1))
                up_contributions_output = x[:, :, :-1, 2] / (
                    x[:, :, :-1, 2] + tf.gather(x[:, :, :, 3], jp1, axis=2))
                down_contributions_output = x[:, :, 1:, 3] / (
                    tf.gather(x[:, :, :, 2], jm1, axis=2) + x[:, :, 1:, 3])

                #complete right with black box:
                right_contributions_output_bb = tf.gather(
                    inputs, [i for i in range(2, self.grid_size, 2)], axis=1)
                right_contributions_output_bb = tf.gather(
                    right_contributions_output_bb,
                    [i for i in range(1, self.grid_size, 2)],
                    axis=2)
                right_contributions_output_bb = -tf.reduce_sum(
                    right_contributions_output_bb[:, :, :, 0, :],
                    axis=-1) / tf.reduce_sum(
                        right_contributions_output_bb[:, :, :, 1, :], axis=-1)
                right_contributions_output_bb = tf.reshape(
                    right_contributions_output_bb[:, -1, :], (1, 1, -1))
                right_contributions_output = tf.concat([
                    right_contributions_output, right_contributions_output_bb
                ],
                                                       axis=1)
                left_contributions_output_bb = tf.gather(inputs, idx, axis=1)
                left_contributions_output_bb = tf.gather(
                    left_contributions_output_bb,
                    [i for i in range(1, self.grid_size, 2)],
                    axis=2)
                left_contributions_output_bb = -tf.reduce_sum(
                    left_contributions_output_bb[:, :, :, 2, :],
                    axis=-1) / tf.reduce_sum(
                        left_contributions_output_bb[:, :, :, 1, :], axis=-1)
                left_contributions_output_bb = tf.reshape(
                    left_contributions_output_bb[:, 0, :], (1, 1, -1))
                left_contributions_output = tf.concat(
                    [left_contributions_output_bb, left_contributions_output],
                    axis=1)
                up_contributions_output_bb = tf.gather(
                    inputs, [i for i in range(1, self.grid_size, 2)], axis=1)
                up_contributions_output_bb = tf.gather(
                    up_contributions_output_bb,
                    [i for i in range(2, self.grid_size, 2)],
                    axis=2)
                up_contributions_output_bb = -tf.reduce_sum(
                    up_contributions_output_bb[:, :, :, :, 0],
                    axis=-1) / tf.reduce_sum(
                        up_contributions_output_bb[:, :, :, :, 1], axis=-1)
                up_contributions_output_bb = tf.reshape(
                    up_contributions_output_bb[:, :, -1], (1, -1, 1))
                up_contributions_output = tf.concat(
                    [up_contributions_output, up_contributions_output_bb],
                    axis=-1)
                down_contributions_output_bb = tf.gather(
                    inputs, [i for i in range(1, self.grid_size, 2)], axis=1)
                down_contributions_output_bb = tf.gather(
                    down_contributions_output_bb, idx, axis=2)
                down_contributions_output_bb = -tf.reduce_sum(
                    down_contributions_output_bb[:, :, :, :, 2],
                    axis=-1) / tf.reduce_sum(
                        down_contributions_output_bb[:, :, :, :, 1], axis=-1)
                down_contributions_output_bb = tf.reshape(
                    down_contributions_output_bb[:, :, 0], (1, -1, 1))
                down_contributions_output = tf.concat(
                    [down_contributions_output_bb, down_contributions_output],
                    axis=-1)
            ones = tf.ones_like(down_contributions_output)
            idx = [i for i in range(0, self.grid_size - 1, 2)]

            #based on rule 2 given rule 1:
            # x,y = np.ix_([3, 1], [1, 3])
            up_right_contribution = tf.gather(
                inputs, [i for i in range(2, self.grid_size, 2)], axis=1)
            up_right_contribution = tf.gather(
                up_right_contribution,
                [i for i in range(2, self.grid_size, 2)],
                axis=2)
            up_right_contribution = up_right_contribution[:, :, :, 0, 1]
            right_up_contirbution = tf.gather(
                inputs, [i for i in range(2, self.grid_size, 2)], axis=1)
            right_up_contirbution = tf.gather(
                right_up_contirbution,
                [i for i in range(2, self.grid_size, 2)],
                axis=2)
            right_up_contirbution_additional_term = right_up_contirbution[:, :, :,
                                                                          0, 0]
            right_up_contirbution = right_up_contirbution[:, :, :, 1, 0]
            ru_center_ = tf.gather(inputs,
                                   [i for i in range(2, self.grid_size, 2)],
                                   axis=1)
            ru_center_ = tf.gather(ru_center_,
                                   [i for i in range(2, self.grid_size, 2)],
                                   axis=2)
            ru_center_ = ru_center_[:, :, :, 1, 1]
            ru_contribution = -tf.expand_dims((right_up_contirbution_additional_term+
                                               tf.multiply(right_up_contirbution,right_contributions_output) +\
                              tf.multiply(up_right_contribution,up_contributions_output))/ru_center_, -1)

            # x,y = np.ix_([3, 1], [3, 1])
            up_left_contribution = tf.gather(inputs, idx, axis=1)
            up_left_contribution = tf.gather(
                up_left_contribution, [i for i in range(2, self.grid_size, 2)],
                axis=2)
            up_left_contribution = up_left_contribution[:, :, :, 2, 1]
            left_up_contirbution = tf.gather(inputs, idx, axis=1)
            left_up_contirbution = tf.gather(
                left_up_contirbution, [i for i in range(2, self.grid_size, 2)],
                axis=2)
            left_up_contirbution_addtional_term = left_up_contirbution[:, :, :,
                                                                       2, 0]
            left_up_contirbution = left_up_contirbution[:, :, :, 1, 0]
            lu_center_ = tf.gather(inputs, idx, axis=1)
            lu_center_ = tf.gather(lu_center_,
                                   [i for i in range(2, self.grid_size, 2)],
                                   axis=2)
            lu_center_ = lu_center_[:, :, :, 1, 1]
            lu_contribution = -tf.expand_dims((left_up_contirbution_addtional_term+
                                               tf.multiply(up_left_contribution , up_contributions_output) + \
                               tf.multiply(left_up_contirbution , left_contributions_output)) / lu_center_, -1)

            # x,y = np.ix_([1, 3], [3, 1])
            down_left_contribution = tf.gather(inputs, idx, axis=1)
            down_left_contribution = tf.gather(down_left_contribution,
                                               idx,
                                               axis=2)
            down_left_contribution = down_left_contribution[:, :, :, 2, 1]
            left_down_contirbution = tf.gather(inputs, idx, axis=1)
            left_down_contirbution = tf.gather(left_down_contirbution,
                                               idx,
                                               axis=2)
            left_down_contirbution_additional_term = left_down_contirbution[:, :, :,
                                                                            2,
                                                                            2]
            left_down_contirbution = left_down_contirbution[:, :, :, 1, 2]
            ld_center_ = tf.gather(inputs, idx, axis=1)
            ld_center_ = tf.gather(ld_center_, idx, axis=2)
            ld_center_ = ld_center_[:, :, :, 1, 1]
            ld_contribution = -tf.expand_dims((left_down_contirbution_additional_term+
                                               tf.multiply(down_left_contribution , down_contributions_output) + \
                               tf.multiply(left_down_contirbution , left_contributions_output)) / ld_center_,-1)

            # x,y = np.ix_([1, 3], [1, 3])
            down_right_contribution = tf.gather(
                inputs, [i for i in range(2, self.grid_size, 2)], axis=1)
            down_right_contribution = tf.gather(down_right_contribution,
                                                idx,
                                                axis=2)
            down_right_contribution = down_right_contribution[:, :, :, 0, 1]
            right_down_contirbution = tf.gather(
                inputs, [i for i in range(2, self.grid_size, 2)], axis=1)
            right_down_contirbution = tf.gather(right_down_contirbution,
                                                idx,
                                                axis=2)
            right_down_contirbution_addtional_term = right_down_contirbution[:, :, :,
                                                                             0,
                                                                             2]
            right_down_contirbution = right_down_contirbution[:, :, :, 1, 2]
            rd_center_ = tf.gather(inputs,
                                   [i for i in range(2, self.grid_size, 2)],
                                   axis=1)
            rd_center_ = tf.gather(rd_center_, idx, axis=2)
            rd_center_ = rd_center_[:, :, :, 1, 1]
            rd_contribution = -tf.expand_dims((right_down_contirbution_addtional_term+tf.multiply(down_right_contribution , down_contributions_output) + \
                               tf.multiply(right_down_contirbution, right_contributions_output)) / rd_center_,-1)

            first_row = tf.concat([
                ld_contribution,
                tf.expand_dims(left_contributions_output, -1), lu_contribution
            ], -1)
            second_row = tf.concat([
                tf.expand_dims(down_contributions_output, -1),
                tf.expand_dims(ones, -1),
                tf.expand_dims(up_contributions_output, -1)
            ], -1)
            third_row = tf.concat([
                rd_contribution,
                tf.expand_dims(right_contributions_output, -1), ru_contribution
            ], -1)

            output = tf.stack([first_row, second_row, third_row], 0)
            output = tf.transpose(output, (1, 2, 3, 0, 4))
            return tf.to_complex128(output)