FunctionMinkowskiDistance
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © RicardoSantos

//@version=5

// @description Method for Minkowski Distance, 
// The Minkowski distance or Minkowski metric is a metric in a normed vector space
// which can be considered as a generalization of both the Euclidean distance and 
// the Manhattan distance. 
// It is named after the German mathematician Hermann Minkowski.
// reference: https://en.wikipedia.org/wiki/Minkowski_distance
library("FunctionMinkowskiDistance")

// @function Minkowsky Distance for single points.
// @param point_ax float, x value of point a.
// @param point_ay float, y value of point a.
// @param point_bx float, x value of point b.
// @param point_by float, y value of point b.
// @param p_value float, p value, default=1.0(1: manhatan, 2: euclidean), does not support chebychev. 
// @returns float
export double (float point_ax, float point_ay, float point_bx, float point_by, float p_value=1.0) => //{
    //sum the vector diference:
    float _sum = math.pow(math.abs(point_ax - point_bx), p_value) + math.pow(math.abs(point_ay - point_by), p_value)
    //root it:
    math.pow(_sum, (1.0 / p_value))
//{ usage:
p = input.float(1.0)
md1 = double(10, 10, 20, 20, 1)
md2 = double(10, 10, 20, 20, 2)
mdx = double(10, 10, 20, 20, p)

h = ta.valuewhen(high >= ta.highest(10), high, 0)
b = ta.valuewhen(high >= ta.highest(10), bar_index, 0)
mdn = double(h, b, close, bar_index, p)

plot(series=md1, title="MD1 - Manhattan D", color=color.blue)
plot(series=md2, title="MD2 - Euclidean", color=color.red)
plot(series=mdx, title="MDX - input: p", color=color.navy)
plot(series=mdn, title="MDN - distance to when higher high", color=color.purple)
//{ reference:
//      https://www.cs.indiana.edu/~predrag/classes/2010springi211/week3_w.pdf
//      https://www.geeksforgeeks.org/minkowski-distance-python/
//      https://towardsdatascience.com/importance-of-distance-metrics-in-machine-learning-modelling-e51395ffe60d
//}}}

// @function Minkowsky Distance for N dimensions.
// @param point_x float array, point x dimension attributes.
// @param point_y float array, point y dimension attributes.
// @param p_value float, p value, default=1.0(1: manhatan, 2: euclidean), does not support chebychev. 
// @returns float
export ndim (float[] point_x, float[] point_y, float p_value=1.0) => //{
    int _size_x = array.size(point_x)
    int _size_y = array.size(point_y)
    //
    switch
        (_size_x < 1) => runtime.error('FunctionMinkowskiDistance -> array(): invalid size array.')
        (_size_x != _size_y) => runtime.error('FunctionMinkowskiDistance -> array(): invalid size array.')
    //
    //sum the vector diference:
    float _sum = 0.0
    for _i = 0 to (_size_x - 1)
        float _xi = array.get(point_x, _i)
        float _yi = array.get(point_y, _i)
        _sum += math.pow(math.abs(_xi - _yi), p_value)
    //root it:
    math.pow(_sum, (1.0 / p_value))
//{ usage:
// point_x = array.from(10.0)
// point_y = array.from(20.0)
// point_x = array.from(10.0, 10.0)
// point_y = array.from(20.0, 20)
point_x = array.from(10.0, 2, 4, -1, 0, 9, 1)
point_y = array.from(14.0, 7, 11, 5, 2, 2, 18)
nd = ndim(point_x, point_y, p)

plot(series=nd, title="ND - multiple dimension distance", color=color.yellow)
//{ reference:
//      https://www.mikulskibartosz.name/minkowski-distance-explained/
//      https://www.statology.org/minkowski-distance-in-r/
//}}}

