Algoritmos para el trazado de funciones (¿adaptable?)


21

Estoy buscando algoritmos para dibujar gráficos 2D estándar para funciones que pueden tener o no singularidades. El propósito es escribir un "Mini-CAS", por lo que no tengo conocimiento a priori de los tipos de funciones que los usuarios quieren graficar.

Este problema es muy antiguo, así que imagino que debe haber algunos algoritmos estándar en la literatura. Por una vez, no tuve mucho éxito para encontrar referencias a través de Google.

Encontré un algoritmo interesante, a saber, este de "YACAS - Libro de algoritmos" llamado "Trazado de función adaptativa".

En resumen:

  • ¿Hay algoritmos estándar?
  • ¿Existe un conjunto de pruebas para las funciones conocidas difíciles de trazar?
  • ¿Cuáles son los papeles interesantes para leer?

2
¿Quizás la pregunta se entendería mejor con "trazado de funciones" en lugar de "dibujo gráfico"? Al principio malinterpreté el título (teoría de grafos).
astrojuanlu

@ Juanlu001 Gracias por la sugerencia. Cambié el título
soegaard

Cuando dices 2D, ¿te refieres a trazar una función de una variable como , o también estás interesado en una función de dos variables ( f ( x , y ) ) que se muestra en 2D con, por ejemplo, diferentes colores / sombras que representan ¿valores diferentes? f(x)f(x,y)
Szabolcs

Bueno, me refería a trazar una función de una variable. Sin embargo, también me gustaría escuchar sobre algoritmos para elegir qué puntos evaluar en una configuración de dos variables también. No estoy tan interesado en escuchar sobre colores y sombras.
soegaard

Para funciones 2D, vea mi pregunta y respuesta aquí . Lo que hice allí fue bastante limitado, y no funcionará tan bien para una función arbitraria. Además, faltan algunos pasos esenciales de la descripción sin los cuales el método no convergerá correctamente: necesitaba insertar un nuevo punto de muestreo en el medio de cada borde de la malla que desaparecería en la próxima retriangulación. (cont.)
Szabolcs

Respuestas:


10

He implementado la rutina de muestreo adaptativo de Mathematica aquí en GitHub (es un solo archivo C, vaya al árbol de origen para el archivo de encabezado). Encontré una descripción de la rutina en un gran libro sobre Mathematica hace mucho tiempo, y he estado usando variaciones en esta implementación desde hace algún tiempo. Básicamente realiza una muestra lineal aproximada sobre el dominio de interés, luego vuelve a refinar regiones de alta curvatura. Es posible que se pierdan algunas características muy definidas, pero en la práctica me parece extremadamente raro. Este archivo también contiene la versión paralela.


1
¿Qué libro es ese? ¿Es el que he vinculado? ¿Sabes qué cambia exactamente en su implementación entre las versiones 5 y 6?
Szabolcs

1
@Szabolcs: No, creo que estaba en la sección 4.1.3 de este libro . La descripción aplica una versión muy antigua de Mathematica. Las versiones más nuevas (tal vez a partir de v6) detectan asíntotas verticales y eliminan las líneas verticales espurias de las tramas. Las nuevas versiones definitivamente hacen un preprocesamiento simbólico sofisticado para lidiar con discontinuidades, regiones indefinidas y cortes de ramas.
Victor Liu

El preprocesamiento simbólico del que habla se denomina "detección de exclusión" en la documentación. Puede desactivarse Exclusions -> Noneocultando la estructura de su función o Plotdefiniéndola como f[x_?NumericQ] := .... Esto no es a lo que me refería cuando pregunté sobre los cambios. Creo que hubo algunos cambios en el algoritmo, ya que v5 y v6 se muestrearon en diferentes puntos. En este momento, no puedo probar en la v5 para comparar de nuevo.
Szabolcs

La "Guía de gráficos de Mathematica" contenía una muy buena discusión del problema. Me gustó especialmente que también se describieran las deficiencias del algoritmo.
soegaard

Ya no puedo encontrar el archivo GitHub, ¿se movió?
Andrei

12

Saber cómo otros CAS hacen esto podría ayudarlo.

f(x)(x(t),y(t))f(x)

  1. Comience con una cuadrícula de puntos regularmente espaciados en el dominio de trazado. (En Mathematica, hay un parámetro para controlar cuántos tomar, llamado PlotPoints).

  2. (x1,f(x1)),(x2,f(x2)),(x3,f(x3))x1+x22x2+x32

  3. Si aún no hemos alcanzado el límite de iteración (establecido MaxRecursionen Mathematica), repita desde el paso 2.

Algo de esto se discute en el libro Mathematica in Action de Stan Wagon, que puedes ver aquí en Google Books .

Implementé este algoritmo antes para tener un mejor control sobre cuántas veces se evaluó mi función costosa de calcular. Aquí está el código de Mathematica para el paso 2:

nd[{points_, values_}] :=
Transpose@{(Drop[points, 1] + Drop[points, -1])/2,
Differences[values]/Differences[points]}

subdivide1d[result_, resolution_, maxAngle_: 10] :=
  Module[
    {deriv, angle, dangle, pos, nf},
    deriv = nd[result\[Transpose]];
    angle = ArcTan[#2] & @@@ deriv;
    dangle = Differences[angle];
    pos = Flatten@Position[dangle, d_ /; Abs[d] > maxAngle/180 Pi];
    pos = Union[pos, pos + 1];
    nf = Nearest[result[[All, 1]]];
    Select[deriv[[pos, 1]], Abs[# - First@nf[#]] > resolution &]
  ]

7

La página web de MathWorld en Gráficos de funciones contiene referencias a varios artículos que parecen ser relevantes en el trazado de funciones adaptativas. Citando la página:

Las buenas rutinas para trazar gráficos utilizan algoritmos adaptativos que trazan más puntos en regiones donde la función varía más rápidamente (Wagon 1991, Math Works 1992, Heck 1993, Wickham-Jones 1994). Tupper (1996) ha desarrollado un algoritmo [...]

Por otro lado, en Google me topé con un papel

www.cs.uic.edu/~wilkinson/Publications/plotfunc.pdf

eso explica cómo elegir correctamente el dominio y otras cosas. Espero que te sean útiles.


1

Encontré este tema y pensé que debería compartir la página de problemas del desarrollador para agregar esto a la biblioteca de Julia Plots.jl. Probamos un montón de técnicas para ver qué daría buenos resultados, comenzando por las notas sobre la implementación de Mathematica. Agregar un poco de poda, una pequeña perturbación para no comenzar exactamente en los puntos finales del intervalo, un límite de recursión y un estimador de error de doble malla fueron necesarios para "hacerlo bien". El hilo también lo señala al código fuente abierto para la implementación. Así que tomó un poco de ajuste, pero agregar esas características lo hizo bastante robusto (según las pruebas, como se muestra en el hilo).

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.