Me encuentro con el mismo problema pero con una función trigonométrica diferente y con la ventaja añadida de que sólo consideramos $-b<x<b$ : $f(x) = a \cdot cos(arcsin(\frac{x}{b}))$
Hay múltiples formas de llegar hasta aquí, pero finalmente acabamos como describes buscando un $x$ donde la derivada de la función de distancia es $$x + f'(x) (f(x)-y1)) -x1 = 0$$ con $(x_1,y_1)$ siendo el punto cuya distancia buscamos. Esta ecuación es la derivada de la función de distancia D anterior. Ahora para sustituir y resolver esto.
Primero determinamos $$f'(x) = \frac{-a^2x}{b^2 f(x)}$$
Entonces sustituimos
$$x + \frac{-a^2x}{b^2 a \cdot cos(arcsin(\frac{x}{b}))} (a \cdot cos(arcsin(\frac{x}{b}))-y_1) -x_1 = 0$$ y "simplificar" a
$$x + \frac{y_1ax-a^2x \cdot cos(arcsin(\frac{x}{b}))}{b^2 \cdot cos(arcsin(\frac{x}{b}))} -x_1 = 0$$
$$x \cdot cos(arcsin(\frac{x}{b}))+ \frac{y_1a}{b^2}x-\frac{a^2 \cdot cos(arcsin(\frac{x}{b}))}{b^2}x -x_1 \cdot cos(arcsin(\frac{x}{b})) = 0$$
$$(x -\frac{a^2}{b^2}x -x_1) \cdot cos(arcsin(\frac{x}{b})) = -\frac{y_1a}{b^2}x$$
En este punto podemos utilizar el hecho de que $cos(arcsin(x)) = \sqrt{1-x^2}$ y cuadrar ambos lados: $$(x -\frac{a^2}{b^2}x -x_1)^2 \cdot (1-(\frac{x}{b})^2) = (-\frac{y_1a}{b^2}x)^2$$
Creo que no hace falta que te diga que al resolver esto se obtiene un polinomio absolutamente delicioso cuyo grado resulta ser 4. Esto significa que obtendremos cuatro raíces cuando hayamos terminado, y entonces tendremos que validar cuál de ellas es realmente la verdadera $x$ que estábamos buscando. Matemáticamente, esto es lo máximo que pude conseguir. Wolfram Alpha (wolframalpha.com) cuando le das el polinomio cuártico genérico ( $ax^4+bx^3...$ ) de hecho te da las cuatro ecuaciones para las cuatro raíces, pero son terriblemente largas y en nuestro caso, esas $a, b, c...$ por supuesto, abreviar términos que a su vez consisten en sumas y diferencias que implican la $a$ y $b$ en nuestro original $f$ .
Sin embargo, un callejón sin salida matemático no era una opción para mí, ya que mi programa necesita un valor para esto. Por si alguien se encuentra alguna vez en la misma situación, quería mencionar las soluciones que encontré para llegar a un resultado. Mi programa está en python, pero espero que lo que sea que estés trabajando ofrezca implementaciones de los mismos enfoques:
-
Aprovechamos nuestro conocimiento de que la función de distancia siempre tiene exactamente un mínimo. Utiliza un algoritmo minimizador para aproximar el mínimo de la función de distancia D. Lo he implementado con scipy.optimize.minimize_scalar . Esto funcionó, pero ejecutar este minimizador para 12000 puntos lleva un tiempo, así que busqué una opción mejor.
optimize.minimize_scalar(
dist_to_vitelline,
args=(x1,y1,a,b),
bounds=(-b,b),
method="Bounded"
)
def dist_to_vitelline(x0,x1,y1,a,b):
return np.sqrt((y1-a * np.cos(np.arcsin((x0 / b))))2+(x1-x0)2)
-
En su lugar, nos adentramos en nuestro análisis anterior y utilizamos un algoritmo para encontrar la raíz de la derivada de la función de distancia. Scipy ofrece una función especializada para ello, optimizar.root_scalar . Esto fue un poco más rápido (¿quizás 10 veces más o menos?) y tal vez pueda acelerarse aún más especificando method='newton'
y también suministrando la segunda derivada de la función de distancia como argumento adicional fprime=dxdx_dist_to_vitelline
.
optimize.root_scalar(
dx_dist_to_vitelline,
args=(x1,x2,a,b),
bracket=(-b,b),
x0=x1
)
def dx_dist_to_vitelline(x0,x1,y1,a,b):
fx0 = a np.cos(np.arcsin(x0/b))
dx_fx0 = (a2 / b2) (-1 x0 / fx0)
return x0 + dx_fx0 (fx0 - y1) - x1