//  [python]
def _update_D_loading(self, states, inputs):
        """
        Update input simulation matrix D
        """
        # Get X and U
        X, X_old, U = self._compute_XU(states, inputs)

        # Compute conceptor of current pattern
        self.C = self._compute_conceptor(X)

        # Compute free zone
        self.F = self._compute_F_matrix()

        # Compute demilitarized zone and conflict zone
        self.M = self._compute_M(self.C)
        self.E = self._compute_E(self.M)

        # DEBUG E
        self.e_rank = rank(self.E.C)
        _, self.e_SVs, _ = torch.linalg.svd(self.E.C)

        # Truth for comparison and test (Win * U)
        win_u = torch.mm(self.w_in, U.t()).t()

        # Targets for the increment matrix Dinc(t+1)
        # What cannot be learned by D(t) alone.
        Yinc = (torch.mm(self.w_in, U.t()) - torch.mm(self.D, X_old.t())).t()

        # Compute the increment for matrix D
        # with adaptive ridge param (*1000 if free zone F is too small)
        if quota(self.F) < 1e-1:
            self.Dinc = self._compute_increment(X_old, Yinc, self._ridge_param_inc * 1000, F=self._compute_F_matrix())
        else:
            self.Dinc = self._compute_increment(X_old, Yinc, self._ridge_param_inc, F=self._compute_F_matrix())
        # end if

        # DEBUG Dinc
        self.dinc_nrmse = nrmse(torch.mm(self.D + self.Dinc, X_old.t()).t(), win_u)
        self.dinc_magnitude = torch.norm(self.Dinc)
        self.dinc_rank = rank(self.Dinc)
        _, self.dinc_SVs, _ = torch.linalg.svd(self.Dinc)

        # Targets for the update matrix Dup(t+1)
        # What cannot be predicted by the current matrix D(t)
        # Y = Win * U - D * X(t-1)
        Y = (torch.mm(self.w_in, U.t()) - torch.mm(self.D, X_old.t())).t()
        # Y = (torch.mm(self.w_in, U.t()) - torch.mm(self.D, torch.mm(self.M.C, X_old.t()))).t()
        # Y = (torch.mm(self.w_in, U.t())).t()

        # Debug
        self._call_debug_point("Td{}".format(self._n_samples), Y, "IncSPESNCell", "_update_D_loading")

        # Compute matrix Dup which predict what cannot be predicted by D using the conflict zone E and
        # free zone F (E+F)
        self.Dup = self._compute_update(X_old, Y, self.E, self._ridge_param_up)

        # DEBUG Dup
        self.dup_nrmse = nrmse(torch.mm(self.D + self.Dup, X_old.t()).t(), win_u)
        # self.dup_nrmse = nrmse(torch.mm(torch.mm(self.M.C, self.D) + (1.0 - self._lambda) * torch.mm(self.E.C, self.D) + self._lambda * self.Dup, X_old.t()).t(), win_u)
        self.dup_magnitude = torch.norm(self.Dup)
        self.dup_rank = rank(self.Dup)
        _, self.dup_SVs, _ = torch.linalg.svd(self.Dup)

        # Debug
        self._call_debug_point("Dinc{}".format(self._n_samples), self.Dinc, "IncSPESNCell", "_update_D_loading")
        self._call_debug_point("Dup{}".format(self._n_samples), self.Dup, "IncSPESNCell", "_update_D_loading")

        # We erase information in D with Dup if above a threshold
        if self.A.quota > self._forgetting_threshold:
            # Gradient
            self.d_gradient = torch.norm(self.D + self._lambda * self.Dup) - torch.norm(self.D)
            # self.d_gradient = torch.norm(torch.mm(self.M.C, self.D) + (1.0 - self._lambda) * torch.mm(self.E.C, self.D) + self._lambda * self.Dup) - torch.norm(self.D)
            print("update")
            # D = D + Dup
            self.D += self._lambda * self.Dup
            # self.D = torch.mm(self.M.C, self.D) + (1.0 - self._lambda) * torch.mm(self.E.C, self.D) + self._lambda * self.Dup

            # Update A
            self._update_A(self.M, self.C)
        else:
            # Gradient
            self.d_gradient = torch.norm(self.D + self.Dinc) - torch.norm(self.D)

            # D = D + Dinc
            self.D += self.Dinc
            # self.D += self._lambda * self.Dup

            # Update A
            self._update_A(self.M, self.C, increment=True)
            # self._update_A(self.M, C)
        # end if

        # Save D's magnitude and rank and SV
        self.d_magnitude = torch.norm(self.D)
        self.d_rank = rank(self.D)
        _, self.d_SVs, _ = torch.linalg.svd(self.D)

        # Debug
        self._call_debug_point("D{}".format(self._n_samples), self.D, "IncSPESNCell", "_update_D_loading")