Пример #1
0
void SGNDArray<T>::expand(SGNDArray &big_array, SGVector<index_t>& axes)
{
	// TODO: A nice implementation would be a function like repmat in matlab
	REQUIRE(axes.size() <= 2,
			"Provided axes size (%d) must be smaller than 2.\n", axes.size());
	REQUIRE(num_dims <= 2,
			"Number of dimensions (%d) must be smaller than 2. Only 1-d and 2-d array can be expanded currently.\n", num_dims);

	// Initialize indices in big array to zeros
	SGVector<index_t> inds_big(big_array.num_dims);
	inds_big.zero();

	// Replicate the small array to the big one.
	// Go over the big one by one and take the corresponding value
	T* data_big = &big_array.array[0];
	for (int32_t vi = 0; vi < big_array.len_array; vi++)
	{
		int32_t y = 0;

		if (axes.size() == 1)
		{
			y = inds_big[axes[0]];
		}
		else if (axes.size() == 2)
		{
			int32_t ind1 = axes[0];
			int32_t ind2 = axes[1];
			y = inds_big[ind1] * dims[1] + inds_big[ind2];
		}

		*data_big = array[y];
		data_big++;

		// Move to the next index
		big_array.next_index(inds_big);
	}
}
Пример #2
0
SGMatrix<float64_t> CUWedge::diagonalize(SGNDArray<float64_t> C, SGMatrix<float64_t> V0,
					double eps, int itermax)
{
	int d = C.dims[0];
	int L = C.dims[2];

	SGMatrix<float64_t> V;
	if (V0.num_rows == d && V0.num_cols == d)
	{
		V = V0.clone();
	}
	else
	{
		Map<MatrixXd> C0(C.get_matrix(0),d,d);
		EigenSolver<MatrixXd> eig;
		eig.compute(C0);

		// sort eigenvectors
		MatrixXd eigenvectors = eig.pseudoEigenvectors();
		MatrixXd eigenvalues = eig.pseudoEigenvalueMatrix();

		bool swap = false;
		do
		{
			swap = false;
			for (int j = 1; j < d; j++)
			{
				if ( eigenvalues(j,j) > eigenvalues(j-1,j-1) )
				{
					std::swap(eigenvalues(j,j),eigenvalues(j-1,j-1));
					eigenvectors.col(j).swap(eigenvectors.col(j-1));
					swap = true;
				}
			}

		} while(swap);

		V = SGMatrix<float64_t>::create_identity_matrix(d,1);
		Map<MatrixXd> EV(V.matrix, d,d);
		EV = eigenvalues.cwiseAbs().cwiseSqrt().inverse() * eigenvectors.transpose();
	}
	Map<MatrixXd> EV(V.matrix, d,d);

	index_t * Cs_dims = SG_MALLOC(index_t, 3);
	Cs_dims[0] = d;
	Cs_dims[1] = d;
	Cs_dims[2] = L;
	SGNDArray<float64_t> Cs(Cs_dims,3);
	sg_memcpy(Cs.array, C.array, Cs.dims[0]*Cs.dims[1]*Cs.dims[2]*sizeof(float64_t));

	MatrixXd Rs(d,L);
	std::vector<float64_t> crit;
	crit.push_back(0.0);
	for (int l = 0; l < L; l++)
	{
		Map<MatrixXd> Ci(C.get_matrix(l),d,d);
		Map<MatrixXd> Csi(Cs.get_matrix(l),d,d);
		Ci = 0.5 * (Ci + Ci.transpose());
		Csi = EV * Ci * EV.transpose();
		Rs.col(l) = Csi.diagonal();
		crit.back() += Csi.cwiseAbs2().sum() - Rs.col(l).cwiseAbs2().sum();
	}

	float64_t iter = 0;
	float64_t improve = 10;
	while (improve > eps && iter < itermax)
	{
		MatrixXd B = Rs * Rs.transpose();

		MatrixXd C1 = MatrixXd::Zero(d,d);
		for (int id = 0; id < d; id++)
		{
			// rowSums
			for (int l = 0; l < L; l++)
			{
				Map<MatrixXd> Csi(Cs.get_matrix(l),d,d);
				C1.row(id) += Csi.row(id) * Rs(id,l);
			}
		}

		MatrixXd D0 = B.cwiseProduct(B.transpose()) - B.diagonal() * B.diagonal().transpose();
		MatrixXd A0 = MatrixXd::Identity(d,d) + (C1.cwiseProduct(B) - B.diagonal().asDiagonal() * C1.transpose()).cwiseQuotient(D0+MatrixXd::Identity(d,d));
		EV = A0.inverse() * EV;

		Map<MatrixXd> C0(C.get_matrix(0),d,d);
		MatrixXd Raux = EV * C0 * EV.transpose();
		MatrixXd aux = Raux.diagonal().cwiseAbs().cwiseSqrt().asDiagonal().inverse();
		EV = aux * EV;

		crit.push_back(0.0);
		for (int l = 0; l < L; l++)
		{
			Map<MatrixXd> Ci(C.get_matrix(l),d,d);
			Map<MatrixXd> Csi(Cs.get_matrix(l),d,d);
			Csi = EV * Ci * EV.transpose();
			Rs.col(l) = Csi.diagonal();
			crit.back() += Csi.cwiseAbs2().sum() - Rs.col(l).cwiseAbs2().sum();
		}

		improve = CMath::abs(crit.back() - crit[iter]);
		iter++;
	}

	if (iter == itermax)
		SG_SERROR("Convergence not reached\n")

	return V;

}
Пример #3
0
SGMatrix<float64_t> CFFDiag::diagonalize(SGNDArray<float64_t> C0, SGMatrix<float64_t> V0,
						double eps, int itermax)
{
	int n = C0.dims[0];
	int K = C0.dims[2];

	index_t * C_dims = SG_MALLOC(index_t, 3);
	C_dims[0] = C0.dims[0];
	C_dims[1] = C0.dims[1];
	C_dims[2] = C0.dims[2];
	SGNDArray<float64_t> C(C_dims,3);
	memcpy(C.array, C0.array, C0.dims[0]*C0.dims[1]*C0.dims[2]*sizeof(float64_t));

	SGMatrix<float64_t> V;
	if (V0.num_rows == n && V0.num_cols == n)
		V = V0.clone();
	else
		V = SGMatrix<float64_t>::create_identity_matrix(n,1);

	MatrixXd Id(n,n); Id.setIdentity();
	Map<MatrixXd> EV(V.matrix,n,n);

	float64_t inum = 0;
	float64_t df = 1;
	std::vector<float64_t> crit;
	while (df > eps && inum < itermax)
	{
		MatrixXd W = MatrixXd::Zero(n,n);

		getW(C.get_matrix(0),
			 &n, &K,
			 W.data());

		W.transposeInPlace();
		int e = CMath::ceil(log2(W.array().abs().rowwise().sum().maxCoeff()));
		int s = std::max(0,e-1);
		W /= pow(2,s);

		EV = (Id+W) * EV;
		MatrixXd d = MatrixXd::Zero(EV.rows(),EV.cols());
		d.diagonal() = VectorXd::Ones(EV.diagonalSize()).cwiseQuotient((EV * EV.transpose()).diagonal().cwiseSqrt());
		EV = d * EV;

		for (int i = 0; i < K; i++)
		{
			Map<MatrixXd> Ci(C.get_matrix(i), n, n);
			Map<MatrixXd> C0i(C0.get_matrix(i), n, n);
			Ci = EV * C0i * EV.transpose();
		}

		float64_t f = 0;
		for (int i = 0; i < K; i++)
		{
			Map<MatrixXd> C0i(C0.get_matrix(i), n, n);
			MatrixXd F = EV * C0i * EV.transpose();
			f += (F.transpose() * F).diagonal().sum() - F.array().pow(2).matrix().diagonal().sum();
		}

		crit.push_back(f);

		if (inum > 1)
			df = CMath::abs(crit[inum-1]-crit[inum]);

		inum++;
	}

	if (inum == itermax)
		SG_SERROR("Convergence not reached\n")

	return V;

}