Algoritmo para encontrar los extremos de una función unimodal
Un algoritmo de búsqueda ternario [1] es una técnica en informática para encontrar el mínimo o máximo de una función unimodal .
La función
Supongamos que estamos buscando un máximo de y que sabemos que el máximo se encuentra en algún punto entre y . Para que el algoritmo sea aplicable, debe haber algún valor tal que![{\displaystyle f(x)}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
![{\displaystyle A}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
![{\displaystyle B}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
![{\displaystyle x}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
- para todos con , tenemos , y
![{\displaystyle a,b}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
![{\displaystyle A\leq a<b\leq x}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
![{\displaystyle f(a)<f(b)}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
- para todos con , tenemos .
![{\displaystyle a,b}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
![{\displaystyle x\leq a<b\leq B}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
![{\displaystyle f(a)>f(b)}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
Algoritmo
Sea una función unimodal en algún intervalo . Tome dos puntos cualesquiera y en este segmento: . Entonces hay tres posibilidades:![{\displaystyle f(x)}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
![{\displaystyle [l;r]}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
![{\ Displaystyle m_ {1}}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
![{\ Displaystyle m_ {2}}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
![{\displaystyle l<m_{1}<m_{2}<r}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
- si , entonces el máximo requerido no se puede ubicar en el lado izquierdo – . Esto significa que tiene sentido buscar el máximo solo en el intervalo
![{\ Displaystyle f (m_ {1}) <f (m_ {2})}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
![{\displaystyle [l;m_{1}]}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
![{\displaystyle [m_{1};r]}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
- si , que la situación es similar a la anterior, hasta la simetría. Ahora, el máximo requerido no puede estar en el lado derecho – , así que vaya al segmento
![{\ Displaystyle f (m_ {1})> f (m_ {2})}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
![{\displaystyle [m_{2};r]}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
![{\displaystyle [l;m_{2}]}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
- si , entonces la búsqueda debe realizarse en , pero este caso se puede atribuir a cualquiera de los dos anteriores (para simplificar el código). Tarde o temprano, la longitud del segmento será un poco menor que una constante predeterminada y el proceso podrá detenerse.
![{\ Displaystyle f (m_ {1}) = f (m_ {2})}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
![{\displaystyle [m_{1};m_{2}]}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
puntos de elección y : ![{\ Displaystyle m_ {1}}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
![{\ Displaystyle m_ {2}}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
![{\displaystyle m_{1}=l+(rl)/3}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
![{\displaystyle m_{2}=r-(rl)/3}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
- Orden de tiempo de ejecución
![{\displaystyle T(n)=T(2n/3)+1=\Theta (\log n)}](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
Algoritmo recursivo
def ternary_search ( f , izquierda , derecha , precisión_absoluta ) -> float : """Izquierda y derecha son los límites actuales; el máximo está entre ellos. """ if abs ( derecha - izquierda ) < precisión_absoluta : return ( izquierda + derecha ) / 2 tercio_izquierdo = ( 2 * izquierda + derecha ) / 3 tercio_derecho = ( izquierda + 2 * derecha ) / 3 si f ( tercero_izquierdo ) < f ( tercero_derecho ): devuelve búsqueda_ternaria ( f , tercio_izquierdo , derecha , precisión_absoluta ) más : devuelve búsqueda_ternaria ( f , izquierda , tercio_derecho , precisión_absoluta )
Algoritmo iterativo
def ternary_search ( f , izquierda , derecha , precisión_absoluta ) -> float : """Encontrar el máximo de la función unimodal f() dentro de [izquierda, derecha]. Para encontrar el mínimo, invierta la declaración if/else o invierta la comparación. " "" mientras que abs ( derecha - izquierda ) >= precisión_absoluta : tercio_izquierdo = izquierda + ( derecha - izquierda ) / 3 tercio_derecho = derecha - ( derecha - izquierda ) / 3 si f ( tercero_izquierdo ) < f ( tercero_derecho ): izquierda = tercio_izquierdo más : derecha = tercio_derecho # Izquierda y derecha son los límites actuales; el máximo está entre ellos retorno ( izquierda + derecha ) / 2
Ver también
Referencias
- ^ "Búsqueda ternaria". cp-algoritmos.com . Consultado el 21 de agosto de 2023 .