27 using namespace shogun;
29 #ifndef DOXYGEN_SHOULD_SKIP_THIS
30 struct TRIANGULATION_THREAD_PARAM
55 const int32_t* lmk_idxs;
57 const bool* to_process;
77 "the number of landmarks for approximation",
MS_AVAILABLE);
92 SG_ERROR(
"Number of landmarks should be greater than 3 to make triangulation possible while %d given.",
114 return "MultidimensionalScaling";
134 return distance_matrix;
154 int32_t N = distance_matrix.
num_cols;
163 distance_matrix(i,j) =
CMath::sq(distance_matrix(i,j));
169 distance_matrix(i,j) = distance_matrix(i,j)*(-0.5);
176 int eigenproblem_status = 0;
181 arpack_dsxupd(distance_matrix.
matrix,NULL,
false,N,m_target_dim,
"LM",
false,1,
false,
false,0.0,0.0,
182 eigenvalues_vector,replace_feature_matrix,eigenproblem_status);
184 ASSERT(eigenproblem_status == 0);
189 for (i=0; i<m_target_dim/2; i++)
191 tmp = replace_feature_matrix[j*m_target_dim+i];
192 replace_feature_matrix[j*m_target_dim+i] =
193 replace_feature_matrix[j*m_target_dim+(m_target_dim-i-1)];
194 replace_feature_matrix[j*m_target_dim+(m_target_dim-i-1)] = tmp;
198 for (i=0; i<m_target_dim/2; i++)
200 tmp = eigenvalues_vector[i];
201 eigenvalues_vector[i] = eigenvalues_vector[m_target_dim-i-1];
202 eigenvalues_vector[m_target_dim-i-1] = tmp;
209 replace_feature_matrix[j*m_target_dim+i] *=
220 wrap_dsyevr(
'V',
'U',N,distance_matrix.
matrix,N,N-m_target_dim+1,N,eigenvalues_vector,eigenvectors,&eigenproblem_status);
222 ASSERT(eigenproblem_status==0);
236 replace_feature_matrix[j*m_target_dim+i] =
249 SG_WARNING(
"Embedding is not consistent (got neg eigenvalues): features %d-%d are wrong",
264 int32_t total_N = distance_matrix.
num_cols;
267 SG_ERROR(
"Number of landmarks (%d) should be greater than 3 for proper triangulation.\n",
272 SG_ERROR(
"Number of landmarks (%d) should be less than total number of vectors (%d).\n",
280 for (i=0; i<lmk_N; i++)
282 for (j=0; j<lmk_N; j++)
283 lmk_dist_matrix[i*lmk_N+j] =
284 distance_matrix[lmk_idxs.
vector[i]*total_N+lmk_idxs.
vector[j]];
291 for (i=0; i<lmk_N; i++)
293 for (j=0; j<lmk_N; j++)
294 mean_sq_dist_vector[i] +=
CMath::sq(lmk_dist_matrix[i*lmk_N+j]);
296 mean_sq_dist_vector[i] /= lmk_N;
304 for (i=0; i<lmk_N; i++)
307 new_feature_matrix[lmk_idxs.
vector[i]*m_target_dim+j] =
308 lmk_feature_matrix[i*m_target_dim+j];
313 for (i=0; i<lmk_N; i++)
321 bool* to_process =
SG_MALLOC(
bool, total_N);
322 for (j=0; j<total_N; j++)
323 to_process[j] =
true;
324 for (j=0; j<lmk_N; j++)
325 to_process[lmk_idxs.
vector[j]] =
false;
333 pthread_t* threads =
SG_MALLOC(pthread_t, num_threads);
334 TRIANGULATION_THREAD_PARAM* parameters =
SG_MALLOC(TRIANGULATION_THREAD_PARAM, num_threads);
336 pthread_attr_init(&attr);
337 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
340 for (t=0; t<num_threads; t++)
342 parameters[t].idx_start = t;
343 parameters[t].idx_stop = total_N;
344 parameters[t].idx_step = num_threads;
345 parameters[t].lmk_N = lmk_N;
346 parameters[t].total_N = total_N;
348 parameters[t].current_dist_to_lmks = current_dist_to_lmks+t*lmk_N;
349 parameters[t].distance_matrix = distance_matrix.
matrix;
350 parameters[t].mean_sq_dist_vector = mean_sq_dist_vector;
351 parameters[t].lmk_idxs = lmk_idxs.
vector;
352 parameters[t].lmk_feature_matrix = lmk_feature_matrix.
matrix;
353 parameters[t].new_feature_matrix = new_feature_matrix;
354 parameters[t].to_process = to_process;
358 for (t=0; t<num_threads; t++)
359 pthread_join(threads[t], NULL);
360 pthread_attr_destroy(&attr);
366 TRIANGULATION_THREAD_PARAM single_thread_param;
367 single_thread_param.idx_start = 0;
368 single_thread_param.idx_stop = total_N;
369 single_thread_param.idx_step = 1;
370 single_thread_param.lmk_N = lmk_N;
371 single_thread_param.total_N = total_N;
373 single_thread_param.current_dist_to_lmks = current_dist_to_lmks;
374 single_thread_param.distance_matrix = distance_matrix.
matrix;
375 single_thread_param.mean_sq_dist_vector = mean_sq_dist_vector;
376 single_thread_param.lmk_idxs = lmk_idxs.
vector;
377 single_thread_param.lmk_feature_matrix = lmk_feature_matrix.
matrix;
378 single_thread_param.new_feature_matrix = new_feature_matrix;
379 single_thread_param.to_process = to_process;
392 TRIANGULATION_THREAD_PARAM* parameters = (TRIANGULATION_THREAD_PARAM*)p;
393 int32_t idx_start = parameters->idx_start;
394 int32_t idx_step = parameters->idx_step;
395 int32_t idx_stop = parameters->idx_stop;
396 const int32_t* lmk_idxs = parameters->lmk_idxs;
397 const float64_t* distance_matrix = parameters->distance_matrix;
398 const float64_t* mean_sq_dist_vector = parameters->mean_sq_dist_vector;
399 float64_t* current_dist_to_lmks = parameters->current_dist_to_lmks;
401 int32_t lmk_N = parameters->lmk_N;
402 int32_t total_N = parameters->total_N;
403 const bool* to_process = parameters->to_process;
404 float64_t* lmk_feature_matrix = parameters->lmk_feature_matrix;
405 float64_t* new_feature_matrix = parameters->new_feature_matrix;
408 for (i=idx_start; i<idx_stop; i+=idx_step)
415 for (k=0; k<lmk_N; k++)
417 current_dist_to_lmks[k] =
418 CMath::sq(distance_matrix[i*total_N+lmk_idxs[k]]) -
419 mean_sq_dist_vector[k];
422 cblas_dgemv(CblasColMajor,CblasNoTrans,
424 -0.5,lmk_feature_matrix,m_target_dim,
425 current_dist_to_lmks,1,
426 0.0,(new_feature_matrix+i*m_target_dim),1);