void hsyncnet::process(const double order, const solve_type solver, const bool collect_dynamic, hsyncnet_analyser & analyser) { unsigned int number_neighbors = 0; unsigned int current_number_clusters = std::numeric_limits<unsigned int>::max(); double radius = 0.0; double current_time = 0.0; while(current_number_clusters > number_clusters) { create_connections(radius, false); sync_dynamic current_dynamic; simulate_dynamic(order, 0.1, solver, collect_dynamic, current_dynamic); sync_dynamic::const_iterator last_state_dynamic = current_dynamic.cend() - 1; analyser.push_back(*(last_state_dynamic)); hsyncnet_cluster_data clusters; analyser.allocate_sync_ensembles(0.05, clusters); current_number_clusters = clusters.size(); number_neighbors++; if (number_neighbors >= oscillator_locations->size()) { radius = radius * 0.1 + radius; } else { radius = average_neighbor_distance(oscillator_locations, number_neighbors); } } }
double hsyncnet::calculate_radius(const double radius, const std::size_t amount_neighbors) const { double next_radius = 0.0; if (amount_neighbors >= oscillator_locations->size()) { next_radius = radius * m_increase_persent + radius; } else { next_radius = average_neighbor_distance(oscillator_locations, amount_neighbors); } return next_radius; }
void hsyncnet::process(const double order, const solve_type solver, const bool collect_dynamic, hsyncnet_analyser & analyser) { std::size_t number_neighbors = m_initial_neighbors; std::size_t current_number_clusters = m_oscillators.size(); if (current_number_clusters <= m_number_clusters) { return; /* Nothing to process, amount of objects is less than required amount of clusters. */ } double radius = average_neighbor_distance(oscillator_locations, number_neighbors); std::size_t increase_step = (std::size_t) round(oscillator_locations->size() * m_increase_persent); if (increase_step < 1) { increase_step = DEFAULT_INCREASE_STEP; } sync_dynamic current_dynamic; do { create_connections(radius, false); simulate_dynamic(order, 0.1, solver, collect_dynamic, current_dynamic); if (collect_dynamic) { if (analyser.empty()) { store_state(*(current_dynamic.begin()), analyser); } store_state(*(current_dynamic.end() - 1), analyser); } else { m_time += DEFAULT_TIME_STEP; } hsyncnet_cluster_data clusters; current_dynamic.allocate_sync_ensembles(0.05, clusters); current_number_clusters = clusters.size(); number_neighbors += increase_step; radius = calculate_radius(radius, number_neighbors); } while(current_number_clusters > m_number_clusters); if (!collect_dynamic) { store_state(*(current_dynamic.end() - 1), analyser); } }
void manifold_sculpting_embed(RandomAccessIterator begin, RandomAccessIterator end, DenseMatrix& data, IndexType target_dimension, const Neighbors& neighbors, DistanceCallback callback, IndexType max_iteration, ScalarType squishing_rate) { /* Step 1: Get initial distances to each neighbor and initial * angles between the point Pi, each neighbor Nij, and the most * collinear neighbor of Nij. */ ScalarType initial_average_distance; SparseMatrix distances_to_neighbors = neighbors_distances_matrix(begin, end, neighbors, callback, initial_average_distance); SparseMatrixNeighborsPair angles_and_neighbors = angles_matrix_and_neighbors(neighbors, data); /* Step 2: Optionally preprocess the data using PCA * (skipped for now). */ ScalarType no_improvement_counter = 0, normal_counter = 0; ScalarType current_multiplier = squishing_rate; ScalarType learning_rate = initial_average_distance; ScalarType best_error = DBL_MAX, current_error, point_error; /* Step 3: Do until no improvement is made for some period * (or until max_iteration number is reached): */ while (((no_improvement_counter++ < max_number_of_iterations_without_improvement) || (current_multiplier > multiplier_treshold)) && (normal_counter++ < max_iteration)) { /* Step 3a: Scale the data in non-preserved dimensions * by a factor of squishing_rate. */ data.bottomRows(data.rows() - target_dimension) *= squishing_rate; while (average_neighbor_distance(data, neighbors) < initial_average_distance) { data.topRows(target_dimension) /= squishing_rate; } current_multiplier *= squishing_rate; /* Step 3b: Restore the previously computed relationships * (distances to neighbors and angles to ...) by adjusting * data points in first target_dimension dimensions. */ /* Start adjusting from a random point */ IndexType start_point_index = std::rand() % data.cols(); std::deque<IndexType> points_to_adjust; points_to_adjust.push_back(start_point_index); ScalarType steps_made = 0; current_error = 0; std::set<IndexType> adjusted_points; while (!points_to_adjust.empty()) { IndexType current_point_index = points_to_adjust.front(); points_to_adjust.pop_front(); if (adjusted_points.count(current_point_index) == 0) { DataForErrorFunc error_func_data = { distances_to_neighbors, angles_and_neighbors.first, neighbors, angles_and_neighbors.second, adjusted_points, initial_average_distance }; adjust_point_at_index(current_point_index, data, target_dimension, learning_rate, error_func_data, point_error); current_error += point_error; /* Insert all neighbors into deque */ std::copy(neighbors[current_point_index].begin(), neighbors[current_point_index].end(), std::back_inserter(points_to_adjust)); adjusted_points.insert(current_point_index); } } if (steps_made > data.cols()) learning_rate *= learning_rate_grow_factor; else learning_rate *= learning_rate_shrink_factor; if (current_error < best_error) { best_error = current_error; no_improvement_counter = 0; } } data.conservativeResize(target_dimension, Eigen::NoChange); data.transposeInPlace(); }