// Fills the cost matrix, *cost, with respect to Sakoe & Chiba band constraint |i-j| < ks -- O(k*n) void fill_cost_matrix_with_sakoe_chiba_constraint(const double *x, const double *y, int n, int m, int n_dimensions, int distance_selector, double warping_penalty, double *cost, int sakoe_chiba_band_parameter) { double (*dist)(const double *, const double *, const int); dist = distance_function(distance_selector); int i, j; // Fill cost matrix with infinities first for (i = 0; i < n*m; i++) cost[i] = INFINITY; // Initialise cost[0] = (*dist)(&x[0], &y[0], n_dimensions); for (i=1; i<min2(n, sakoe_chiba_band_parameter+1); i++) cost[i*m] = (*dist)(&x[i*n_dimensions], &y[0], n_dimensions) + cost[(i-1)*m] + warping_penalty; for (j=1; j<min2(m, sakoe_chiba_band_parameter+1); j++) cost[j] = (*dist)(&x[0], &y[j*n_dimensions], n_dimensions) + cost[(j-1)] + warping_penalty; // Fill only the columns that satisfy |i-j| <= sakoe_chiba_band_parameter for (i=1; i<n; i++) for (j=max2(i-sakoe_chiba_band_parameter, 1); j<min2(m, i+sakoe_chiba_band_parameter+1); j++) cost[i*m+j] = (*dist)(&x[i*n_dimensions], &y[j*n_dimensions], n_dimensions) + min3(cost[(i-1)*m+j] + warping_penalty, cost[(i-1)*m+(j-1)], cost[i*m+(j-1)] + warping_penalty); }
/// Returns the number of elements in the range ptrdiff_t distance() const { ptrdiff_t n = 0; m_r.for_each_cancelable(distance_function(n)); return n; }
int main() { Point<float> a(1.125, 1.125, 1.125); Point<float> b(2.125 * a); float m = 2.; std::cout << b << " + " << a << " = " << b + a << std::endl; std::cout << b << " - " << a << " = " << b - a << std::endl; std::cout << b << " * " << a << " = " << b*a << std::endl; std::cout << a << " / " << b << " = " << a / b << std::endl; std::cout << b << " / " << m << " = " << b / m << std::endl; std::cout << m << " * " << b << " = " << m*b << std::endl; std::cout << "Distance between " << b << " and " << a << " is " << distance_function(a, b) << "." << std::endl; return 0; }
// Fills the cost matrix, *cost, without any constraints - O(nm) void fill_cost_matrix_unconstrained(const double *x, const double *y, int n, int m, int n_dimensions, int distance_selector, const double warping_penalty, double *cost) { double (*dist)(const double *, const double *, const int); dist = distance_function(distance_selector); int i, j; cost[0] = (*dist)(&x[0], &y[0], n_dimensions); for (i=1; i<n; i++) cost[i*m] = (*dist)(&x[i*n_dimensions], &y[0], n_dimensions) + cost[(i-1)*m] + warping_penalty; for (j=1; j<m; j++) cost[j] = (*dist)(&x[0], &y[j*n_dimensions], n_dimensions) + cost[(j-1)] + warping_penalty; for (i=1; i<n; i++) for (j=1; j<m; j++) cost[i*m+j] = (*dist)(&x[i*n_dimensions], &y[j*n_dimensions], n_dimensions) + min3(cost[(i-1)*m+j]+warping_penalty, cost[(i-1)*m+(j-1)], cost[i*m+(j-1)]+warping_penalty); }
// Fills arbitrarily constrained matrix // The constraint is specified by boolean array *constraint_matrix void fill_constrained_cost_matrix(const double *x, const double *y, int n, int m, int n_dimensions, int distance_selector, double *cost, const char *constraint_matrix) { double (*dist)(const double *, const double *, const int); dist = distance_function(distance_selector); int i, j; // Fill cost matrix with infinities first for (i = 0; i < n*m; i++) cost[i] = INFINITY; // Initialise cost[0] = (*dist)(&x[0], &y[0], n_dimensions); for (i=1; i<n; i++) { if (!constraint_matrix[i*m]) continue; cost[i*m] = (*dist)(&x[i*n_dimensions], &y[0], n_dimensions) + cost[(i-1)*m]; } for (j=1; j<m; j++) { if (!constraint_matrix[j]) continue; cost[j] = (*dist)(&x[0], &y[j*n_dimensions], n_dimensions) + cost[(j-1)]; } for (i=1; i<n; i++) { for (j=1; j<m; j++) { if (!constraint_matrix[i*m+j]) continue; cost[i*m+j] = (*dist)(&x[i*n_dimensions], &y[j*n_dimensions], n_dimensions) + min3(cost[(i-1)*m+j], cost[(i-1)*m+(j-1)], cost[i*m+(j-1)]); } } }
// Fills the cost matrix, *cost, using slanted band constraint. // this is similar to sakoe & chiba constraint but is generalised for sequences with unequal lengths // based on the implementation of similar constraint in R // The implementation expects len(x) >= len(y), otherwise bad things happen. Python side makes sure this is // called correctly void fill_cost_matrix_with_slanted_band_constraint(const double *x, const double *y, int n, int m, int n_dimensions, int distance_selector, double warping_penalty, double *cost, int width) { double (*dist)(const double *, const double *, const int); dist = distance_function(distance_selector); double slant = (double) m / (double) n; int i, j; int i_times_slant; // Fill cost matrix with infinities first for (i = 0; i < n*m; i++) cost[i] = INFINITY; // Initialise cost[0] = (*dist)(&x[0], &y[0], n_dimensions); // abs(j - i*slant) should always be less than or equal to width for (i=1; i < n && (int)(i*slant) < width+1; i++) cost[i*m] = (*dist)(&x[i*n_dimensions], &y[0], n_dimensions) + cost[(i-1)*m] + warping_penalty; // i=0 below, so abs(j) <= width for (j=1; j<min2(m, (int)width+1); j++) cost[j] = (*dist)(&x[0], &y[j*n_dimensions], n_dimensions) + cost[(j-1)] + warping_penalty; // Fill only the columns that satisfy |i-j| <= width for (i=1; i<n; i++) { i_times_slant = (int) ceil(i * slant); for (j=max2(i_times_slant-width, 1); j<min2(m, i_times_slant+(int)width+1); j++) { cost[i*m+j] = (*dist)(&x[i*n_dimensions], &y[j*n_dimensions], n_dimensions) + min3(cost[(i-1)*m+j] + warping_penalty, cost[(i-1)*m+(j-1)], cost[i*m+(j-1)] + warping_penalty); } } }
// Fill cost matrix constrained by Itakura Paralellogram void fill_cost_matrix_with_itakura_constraint(const double *x, const double *y, int n, int m, int n_dimensions, int distance_selector, double warping_penalty, double *cost) { double (*dist)(const double *, const double *, const int); dist = distance_function(distance_selector); int i, j; // Fill cost matrix with infinities first for (i = 0; i < n*m; i++) cost[i] = INFINITY; // Initialise cost[0] = (*dist)(&x[0], &y[0], n_dimensions); for (i=1; i<n; i++) { if (!itakura_constraint(i, 0, n, m)) continue; cost[i*m] = (*dist)(&x[i*n_dimensions], &y[0], n_dimensions) + cost[(i-1)*m] + warping_penalty; } for (j=1; j<m; j++) { if (!itakura_constraint(0,j,n,m)) continue; cost[j] = (*dist)(&x[0], &y[j*n_dimensions], n_dimensions) + cost[(j-1)] + warping_penalty; } for (i=1; i<n; i++) { for (j=1; j<m; j++) { if (!itakura_constraint(i,j,n,m)) continue; cost[i*m+j] = (*dist)(&x[i*n_dimensions], &y[j*n_dimensions], n_dimensions) + min3(cost[(i-1)*m+j] + warping_penalty, cost[(i-1)*m+(j-1)], cost[i*m+(j-1)] + warping_penalty); } } }