7 return int(val < 0 ? floor(val + 0.5) : ceil(val - 0.5));
30 idum = IA * (idum - k * IQ) - IR * k;
34 double ran = AM * idum;
44 int max_val = a.size() + b.size();
47 std::map<char, int> DA;
50 Eigen::MatrixXi H(a.size() + 2, b.size() + 2);
54 for(
int i = 0; i <= a.size(); ++i) {
56 H(i + 1, 0) = max_val;
59 for(
int j = 0; j <= b.size(); ++j) {
61 H(0, j + 1) = max_val;
67 for(
int i = 1; i <= a.size(); ++i) {
70 for(
int j = 1; j <= b.size(); ++j) {
71 int i1 = DA[b[j - 1]];
74 if(a[i - 1] == b[j - 1]) {
80 H(i + 1, j + 1) =
min(
min(H(i, j) + cost,
83 H(i1, j1) + (i - i1 - 1) + 1 + (j - j1 - 1)));
87 return H(a.size() + 1, b.size() + 1);
92 int gcf(
int i1,
int i2) {
95 while(i1 != i2 && i1 != 1 && i2 != 1) {
115 return std::abs(i1 * (i2 /
gcf(i1, i2)));
120 std::stringstream tstream;
124 while(!tstream.eof()) {
126 std::cerr <<
"WARNING in eigen_vector_from_string. You have more elements in your array, than the value of size you passed. Ignoring any extraneous elements" << std::endl;
133 std::cerr <<
"ERROR in eigen_vector_from_string. Fewer elements in your array than the value of size you passed. Can't handle this. Quitting." << std::endl;
144 double gaussian(
double a,
double x,
double b,
double c) {
145 return a * exp(-((x - b) * (x - b)) / (c * c));
155 if(expon % 2)
return 0.0;
157 double m = pow(sigma, expon);
160 while(expon - 2 > 0) {
174 for(
int i = 0; i <= expon; i++) {
194 long sgn(val < 0 ? -1 : 1);
197 long lim(
max(
long(100),
long(1 / (10 * tol))));
198 for(
long i = 1; i < lim + 1; i++) {
199 tdenom = double(i) / val;
200 tnum = val / double(i);
203 denominator =
round(tdenom);
208 numerator = sgn *
round(tnum);
225 std::stringstream tstr;
234 double tval(val), tdenom, tnum;
236 for(
int ipow = 1; ipow < max_pow + 1; ipow++) {
237 for(
int i = 1; i < lim + 1; i++) {
238 tdenom = double(i) / tval;
239 tnum = tval / double(i);
242 idenom =
round(tdenom);
253 tstr << inum <<
'/' << idenom;
257 tstr <<
"\\sqrt{" << inum;
259 tstr <<
'/' << idenom;
266 tstr <<
'/' << idenom;
267 tstr <<
")^{1/" << ipow <<
"}";
294 return -pow(-number, 1.0 / 3);
298 return pow(number, 1.0 / 3);
308 void poly_fit(Eigen::VectorXcd &xvec, Eigen::VectorXcd &yvec, Eigen::VectorXcd &coeffs,
int degree) {
311 if(xvec.rows() != yvec.rows()) {
312 std::cout <<
"******************************************\n"
313 <<
"ERROR in poly_fit: Dimensions of xvec and \n"
314 <<
"yvec do not match up! Cannot perform a \n"
315 <<
"polynomial fit.\n"
316 <<
"******************************************\n";
320 Eigen::MatrixXcd polymat = Eigen::MatrixXcd::Ones(xvec.rows(), degree + 1);
323 for(
int d = degree; d > 0; d--) {
325 polymat.col(degree - d) = xvec;
327 for(
int m = 0; m < d - 1; m++) {
328 polymat.col(degree - d) = polymat.col(degree - d).cwiseProduct(xvec);
333 Eigen::JacobiSVD<Eigen::MatrixXcd> svd_solver(polymat, Eigen::ComputeThinU | Eigen::ComputeThinV);
334 coeffs = svd_solver.solve(yvec);
349 for(i = 0; i < unique.size(); i++) {
352 if(unique[i].size() != input.
size())
continue;
353 for(j = 0; j < ind_equiv.size(); j++) {
356 for(k = 0; k < ind_equiv[j].size(); k++) {
357 tval = input[ind_equiv[j][k]];
359 for(l = 0; l < ind_equiv[j].size(); l++)
360 tcount +=
int(unique[i][ind_equiv[j][l]] == tval) - int(input[ind_equiv[j][l]] == tval);
365 if(k != ind_equiv[j].size())
368 if(j == ind_equiv.size())
379 for(i = 0; i < unique.size(); i++) {
382 if(unique[i].size() != input.
size())
continue;
383 for(j = 0; j < input.
size(); j++) {
386 for(l = 0; l < input.
size(); l++)
387 tcount +=
int(unique[i][l] == tval) - int(input[l] == tval);
393 if(j == input.
size())
403 if(!series.
size())
return 0;
404 int lcm_val(series[0]);
406 lcm_val =
lcm(lcm_val, series[i]);
418 std::cerr <<
"WARNING in CASM_Global_Definitions::get_prime_factors" << std::endl;
419 std::cerr <<
"You're asking for prime factors of " << target <<
". Returning empty array." << std::endl << std::endl;
420 return factors_array;
425 while(target % factor == 0) {
427 target = target / factor;
432 if(factor_list.
size() > 0) {
438 return factors_array;
448 double tot_cost = 0.0;
450 for(
int i = 0; i < optimal_assignment.size(); i++) {
451 tot_cost += cost_matrix(i, optimal_assignment[i]);
453 if(optimal_assignment.size() == 0)
458 namespace HungarianMethod_impl {
472 int dim = cost_matrix.rows();
476 for(
int i = 0; i < dim; i++) {
477 double row_min = cost_matrix.row(i).minCoeff();
478 if(row_min > _infinity)
480 for(
int j = 0; j < dim; j++) {
481 cost_matrix(i, j) -= row_min;
489 int dim = cost_matrix.rows();
494 for(
int i = 0; i < dim; i++) {
495 for(
int j = 0; j < dim; j++) {
498 for(
int k = 0; k < dim; k++) {
499 if(zero_marks(i, k) == star) {
503 for(
int l = 0; l < dim; l++) {
504 if(zero_marks(l, j) == star) {
509 zero_marks(i, j) = star;
523 for(
int i = 0; i < zero_marks.rows(); i++) {
524 for(
int j = 0; j < zero_marks.cols(); j++) {
525 if(zero_marks(i, j) == -1) {
531 if(col_covered.sum() == zero_marks.rows()) {
539 int prime_zeros(
const Eigen::MatrixXd &cost_matrix, Eigen::VectorXi &row_covered, Eigen::VectorXi &col_covered, Eigen::MatrixXi &zero_marks,
double &
min, Eigen::VectorXi &first_prime_zero,
const double _tol,
const double _infinity) {
556 for(
int i = 0; i < cost_matrix.rows(); i++) {
557 for(
int j = 0; j < cost_matrix.cols(); j++) {
558 if(
almost_zero(cost_matrix(i, j), _tol) && col_covered(j) == 0 && row_covered(i) == 0) {
560 zero_marks(i, j) = prime;
563 bool is_star =
false;
564 for(
int k = 0; k < zero_marks.cols(); k++) {
565 if(zero_marks(i, k) == -1 && !is_star) {
566 row_covered(i) = covered;
567 col_covered(k) = uncovered;
574 first_prime_zero(0) = i;
575 first_prime_zero(1) = j;
588 for(
int i = 0; i < cost_matrix.rows(); i++) {
589 for(
int j = 0; j < cost_matrix.cols(); j++) {
590 if(row_covered(i) == 0 && col_covered(j) == 0 &&
almost_zero(cost_matrix(i, j), _tol)) {
603 for(
int i = 0; i < cost_matrix.rows(); i++) {
604 for(
int j = 0; j < cost_matrix.cols(); j++) {
605 if(row_covered(i) == 0 && col_covered(j) == 0 && cost_matrix(i, j) <
min) {
606 min = cost_matrix(i, j);
617 int alternating_path(
const Eigen::MatrixXd &cost_matrix,
const Eigen::VectorXi &first_prime_zero, Eigen::MatrixXi &zero_marks, Eigen::VectorXi &row_covered, Eigen::VectorXi &col_covered) {
625 Eigen::VectorXi row_path(2 * cost_matrix.rows() - 1);
626 Eigen::VectorXi col_path(2 * cost_matrix.cols() - 1);
634 int path_counter = 1;
638 row_path(0) = first_prime_zero(0);
639 col_path(0) = first_prime_zero(1);
645 bool star_found =
false;
646 bool prime_found =
false;
657 for(
int i = 0; i < zero_marks.rows(); i++) {
658 if(zero_marks(i, col_path(path_counter - 1)) == -1 && !star_found) {
660 row_path(path_counter - 1) = i;
661 col_path(path_counter - 1) = col_path(path_counter - 2);
665 if(i == zero_marks.rows() - 1 && !star_found) {
670 if(star_found && !done) {
671 for(
int j = 0; j < zero_marks.cols(); j++) {
672 if(zero_marks(row_path(path_counter - 1), j) == 1 && !prime_found) {
674 row_path(path_counter - 1) = row_path(path_counter - 2);
675 col_path(path_counter - 1) = j;
687 for(
int i = 0; i < path_counter; i ++)
689 if(i % 2 == 0 && zero_marks(row_path(i), col_path(i)) == 1) {
690 zero_marks(row_path(i), col_path(i)) = -1;
693 else if(zero_marks(row_path(i), col_path(i)) == -1) {
694 zero_marks(row_path(i), col_path(i)) = 0;
696 for(
int i = 0; i < zero_marks.rows(); i++) {
697 for(
int j = 0; j < zero_marks.cols(); j ++) {
698 if(zero_marks(i, j) == 1) {
699 zero_marks(i, j) = 0;
718 for(
int i = 0; i < cost_matrix.rows(); i++) {
719 for(
int j = 0; j < cost_matrix.cols(); j++) {
720 if(row_covered(i) == 1) {
721 cost_matrix(i, j) +=
min;
723 if(col_covered(j) == 0) {
724 cost_matrix(i, j) -=
min;
735 double _infinity = 1E10;
739 int dim = cost_matrix.rows();
743 Eigen::MatrixXi zero_marks = Eigen::MatrixXi::Zero(dim, dim);
745 Eigen::VectorXi row_covered(dim);
746 Eigen::VectorXi col_covered(dim);
752 row_covered.fill(uncovered);
753 col_covered.fill(uncovered);
759 Eigen::VectorXi first_prime_zero(2);
781 int loop_counter = 0;
800 else if(loop_counter > 15) {
807 next_step =
prime_zeros(cost_matrix, row_covered, col_covered, zero_marks, min, first_prime_zero, _tol, _infinity);
811 next_step =
alternating_path(cost_matrix, first_prime_zero, zero_marks, row_covered, col_covered);
815 next_step =
update_costs(row_covered, col_covered, min, cost_matrix);
817 if(next_step == -1) {
818 optimal_assignment.clear();
839 optimal_assignment.assign(cost_matrix.rows(), -1);
841 for(
int i = 0; i < zero_marks.rows(); i++) {
842 for(
int j = 0; j < zero_marks.cols(); j++) {
843 if(zero_marks(i, j) == -1) {
845 optimal_assignment[i] = j;
848 optimal_assignment.clear();
853 if(optimal_assignment.size() == 0 || !
valid_index(optimal_assignment[i])) {
854 optimal_assignment.clear();
int update_costs(const Eigen::VectorXi &row_covered, const Eigen::VectorXi &col_covered, const double min, Eigen::MatrixXd &cost_matrix)
bool almost_zero(const T &val, double tol=TOL)
If T is not integral, use std::abs(val) < tol;.
Index which_unique_combination(const Array< Index > &input, const Array< Index >::X2 &unique, const Array< Index >::X2 &ind_equiv)
Eigen::VectorXd eigen_vector_from_string(const std::string &tstr, const int &size)
int gcf(int i1, int i2)
Find greatest common factor.
void push_back(const T &toPush)
int lcm(int i1, int i2)
Find least common multiple.
double hungarian_method(const Eigen::MatrixXd &cost_matrix, std::vector< Index > &optimal_assignments, const double _tol)
void find_zeros(const Eigen::MatrixXd &cost_matrix, Eigen::MatrixXi &zero_marks, const double _tol)
void poly_fit(Eigen::VectorXcd &xvec, Eigen::VectorXcd &yvec, Eigen::VectorXcd &coeffs, int degree)
double gaussian(double a, double x, double b, double c)
double cuberoot(double number)
int dl_string_dist(const std::string &a, const std::string &b)
Computes the Damerescau-Levenshtein distance – the number of edits (deletions, insertions, transpositions) to go from string 'a' to string 'b'.
void hungarian_method(const Eigen::MatrixXd &cost_matrix_arg, std::vector< Index > &optimal_assignments, const double _tol)
ReturnArray< Array< int > > get_prime_factors(int target)
double gaussian_moment(int expon, double sigma)
EigenIndex Index
For long integer indexing:
IntType nchoosek(IntType n, IntType k)
int alternating_path(const Eigen::MatrixXd &cost_matrix, const Eigen::VectorXi &first_prime_zero, Eigen::MatrixXi &zero_marks, Eigen::VectorXi &row_covered, Eigen::VectorXi &col_covered)
std::string irrational_to_tex_string(double val, int lim, int max_pow=2)
T max(const T &A, const T &B)
T min(const T &A, const T &B)
void nearest_rational_number(double val, long &numerator, long &denominator, double tol=TOL)
int prime_zeros(const Eigen::MatrixXd &cost_matrix, Eigen::VectorXi &row_covered, Eigen::VectorXi &col_covered, Eigen::MatrixXi &zero_marks, double &min, Eigen::VectorXi &first_prime_zero, const double _tol, const double _infinity)
bool check_assignment(const Eigen::MatrixXi &zero_marks, Eigen::VectorXi &col_covered)
void reduce_cost(Eigen::MatrixXd &cost_matrix, double _infinity)
bool valid_index(Index i)