lunes, 24 de abril de 2017

Algoritmos Genéticos: Búsqueda y Optimización por Selección Natural



Algoritmos Genéticos: Búsqueda y Optimización por Selección Natural




¿Qué son los Algoritmos Genéticos?

En los últimos años, ha habido un alboroto en relación con la Inteligencia Artificial (IA). Las grandes compañías como Google, Apple y Microsoft trabajan activamente en este tema. De hecho, la IA es solo paraguas que cubre muchas metas, acercamientos, herramientas y aplicaciones. Los Algoritmos Genéticos (AG) son solo una de las herramientas inteligentes que buscan a través de muchas soluciones posibles.
El AG es una búsqueda meta-heurística al igual que una técnica de optimización basada en principios presentes en la evolución natural. Pertenece a una clase más larga de algoritmos evolutivas.
El AG mantiene una población de cromosomas—un set de soluciones posibles para el problema. La idea es que la “evolución” encuentre una solución óptima para el problema después de un número de generaciones sucesivas—similar a una selección natural.
El AG imita tres procesos evolutivos: selección, entrecruzamiento cromosómico y mutación.
Tal como la selección natural, el concepto central de la selección AG es la adaptación. Los cromosomas que se adaptan mejor tienen una mayor oportunidad de sobrevivir. La adaptación es una función que mide la calidad de la solución representada por el cromosoma. En esencia, cada cromosoma dentro de la población representa los parámetros de entrada, como el volumen y precio de cambio, cada cromosoma, lógicamente, consistirá de dos elementos. Como los elementos están codificados dentro del cromosoma es otro tema.
Durante la selección, los cromosomas forman parejas de padres para la reproducción. Cadaniño toma características de sus padres. Básicamente, el niño representa una recombinación de características de sus padres: Algunas de las características son tomadas de un padre y otras del otro padre. Adicionalmente a la recombinación, algunas de las características pueden mutar.
Ya que los cromosomas más adecuados producen más niños, cada generación subsecuente será más adecuada. En algún punto, una generación contendrá un cromosoma que representará una solución lo suficientemente buena para nuestro problema.
El AG es poderoso y ampliamente aplicable a problemas complejos. Hay una clase extensa de problemas de optimización que son un tanto difícil de resolver usando técnicas convencionales de optimización. Los algoritmos genéticos son algoritmos eficientes que poseen soluciones aproximadamente óptimas. Las ya bien conocidas aplicaciones incluyen programación, transporte, planificación de ruta, tecnologías de grupo, diseño de plano, entrenamiento de red neural y muchos otros.

Poniendo las Cosas en Práctica

El ejemplo que veremos puede ser considerado el “Hello World” de AG. Este ejemplo fue presentado inicialmente por J. Freeman enSimulating Neural Networks with Mathematica. Yo lo tomé de Genetic Algorithms and Engineering Design por Mitsuo Gen y Runwei Cheng.
El problema simulador del mundo intenta evolucionar una expresión con un algoritmo genético. Inicialmente, el algoritmo debe “adivinar” la frase “ser o no ser” de listas de letras generadas al azar.
“Ya que hay 26 letras posibles para cada una de las 13 locaciones [excluyendo espacios en blanco] en la lista, la posibilidad de que obtengamos la frase correcta puramente al azar es (1/26)^13=4.03038×10-19, lo cual es aproximadamente dos chances en un [trillón]” (Gen & Chong, 1997).
Vamos a definir el problema un poco más aquí al hacer la solución aún más difícil. Asumamos que no estamos limitados a la lengua inglesa, o una frase específica. Podemos terminar lidiando con cualquier alfabeto, o hasta cualquier set de símbolos. No tenemos conocimiento de la lengua. Ni siquiera sabemos si hay algún idioma.
Digamos que nuestro oponente pensó en una frase arbitraria, incluyendo espacios en blanco. Sabemos el largo de la frase y la cantidad de símbolos en el alfabeto. Ese es el único conocimiento que tenemos. Después de cada suposición, nuestro oponente nos dice cuántas letras se encuentran en su lugar.
Cada cromosoma es una secuencia de índices de los símbolos en el alfabeto. Si hablamos del alfabeto inglés, entonces ‘a’ será representada por 0, ‘b’ por 1, ‘c’ por 2, y así sucesivamente. Entonces, por ejemplo, la palabra “ser” será representada como [4, 1].
Vamos a demostrar todos los pasos a través de trozos de código Java, pero el conocimiento enJava no es un requerimiento para entender cada paso.

El Centro del Algoritmo Genético

Podemos empezar con la implementación general del algoritmo genético:
public void find() {
   // Initialization
   List population = Stream.generate(supplier)
                              .limit(populationSize)
                              .collect(toList());
   // Iteration
   while (!termination.test(population)) {
       // Selection
       population = selection(population);
       // Crossover
       crossover(population);
       // Mutation
       mutation(population);
   }
}
Este es un set de pasos simples que todo AG debería tener. En el paso inicial, generamos una población inicial de frases. El tamaño de la población está determinada por populationSize. Y como se genera esta frase depende de la implementación del supplier.
Dentro del paso de iteración, evolucionamos la población hasta que se dan las condiciones de término, dentro de la prueba de nudo while. Las condiciones de término pueden incluir el número de generaciones y la pareja perfecta de una de las frases en la población. El termination encapsula una implementación exacta.
Dentro de cada iteración, hacemos los típicos pasos de AG:
  1. Lleva a cabo una selección sobre la población en adecuación de cromosomas.
  2. Produce una nueva “generación” vía la operación de entrecruzamiento.
  3. Lleva a cabo una recombinación de algunas letras en algunas frases.
El centro del algoritmo es muy simple y de dominio agnóstico. Sería el mismo para todo los problemas. Lo que debes ajustar es la implementación de operadores genéticos. Luego, miraremos más de cerca a cada uno de los ya mencionados operadores AG.

Selección

Como ya sabemos, la selección es un proceso hecho para encontrar sucesores para los cromosomas actuales—los cromosomas que sean más adecuados para nuestro problema. Durante la selección, necesitamos asegurar que los cromosomas con mejor adecuación tienen más chance de sobrevivir.
private List selection(List population) {
   final double[] fitnesses = population.stream()
                                        .mapToDouble(fitness)
                                        .toArray();
   final double totalFitness = DoubleStream.of(fitnesses).sum();
   
   double sum = 0;
   final double[] probabilities = new double[fitnesses.length];
   for (int i = 0; i < fitnesses.length; i++) {
       sum += fitnesses[i] / totalFitness;
       probabilities[i] = sum;
   }
   probabilities[probabilities.length - 1] = 1;

   return range(0, probabilities.length).mapToObj(i -> {
       int index = binarySearch(probabilities, random());
       if (index < 0) {
           index = -(index + 1);
       }
       return population.get(index);
   }).collect(toList());
}
La idea de esta implementación es la siguiente: La población es representada como rasgos consecuentes en el eje numérico. La población completa está entre 0 y 1.
Demostración visual de cómo funciona el paso de la selección en nuestro algoritmo genético
El trozo de la serie que toma un cromosoma es proporcional a su adecuación. Esto da como resultado un cromosoma mucho más adecuado el cual toma un trozo más grande. Luego escogemos un número al azar entre 0 y 1 y encontramos una serie que incluye este número. Obviamente, las series más grandes tienen mejor oportunidad de ser seleccionados, por ende, los cromosomas más adecuados tienen mejor oportunidad de sobrevivir..
Ya que no conocemos detalles sobre la función de la adecuación, necesitamos normalizar los valores de adecuación. La función de adecuación es representada por fitness, la cual convierte a un cromosoma en un doble arbitrario que representa la adecuación del cromosoma.
En el código, encontramos una tarifa de adecuación para todos los cromosomas en la población y también encontramos la adecuación total. Dentro del nudo for, ejecutamos una suma acumulativa sobre probabilidades disminuidas por adecuación total. Matemáticamente, esto debería resultar en la variable final teniendo un valor de 1. Debido a la imprecisión del punto flotante, no podemos garantizar eso, así que lo ajustamos a 1 para estar seguros.
Finalmente, por una cantidad de tiempo igual al número de cromosomas entrantes, generamos un número al azar, encontramos una serie que incluya el número y luego seleccionamos el cromosoma correspondiente. Como debes haber notado, el mismo cromosoma puede ser seleccionado muchas veces.

Entrecruzamiento

Ahora necesitamos que los cromosomas se “reproduzcan.”
private void crossover(List population) {
   final int[] indexes = range(0, population.size())
       .filter(i-> random() < crossoverProbability)
       .toArray();

   shuffle(Arrays.asList(indexes));

   for (int i = 0; i < indexes.length / 2; i++) {
       final int index1 = indexes[2 * i];
       final int index2 = indexes[2 * i + 1];
       final T value1 = population.get(index1);
       final T value2 = population.get(index2);
       population.set(index1, crossover.apply(value1, value2));
       population.set(index2, crossover.apply(value2, value1));
   }
}
Con la probabilidad predefinida como crossoverProbability, seleccionamos padres para la reproducción. Los padres que sean seleccionados son mezclados, permitiendo así que se de cualquier combinación. Tomamos parejas de padres y aplicamos el operadorcrossover. Aplicamos el operador dos veces para cada pareja porque necesitamos mantener el mismo tamaño de la población. Los niños reemplazan a los padres en la población.

Mutación

Finalmente, llevamos a cabo la recombinación de las características.
private void mutation(List population) {
   for (int i = 0; i < population.size(); i++) {
       if (random() < mutationProbability) {
           population.set(i, mutation.apply(population.get(i)));
       }
   }
}
Con la probabilidad mutationProbabilitypredefinida, llevamos a cabo la “mutación” en los cromosomas. La mutación como tal es definida como mutation.

Configuración de Algoritmo de Problema-Específico

Ahora echemos un vistazo a qué tipo de parámetros de problema específico necesitamos proveer para nuestra implementación genérica.
private BiFunction crossover;
private double crossoverProbability;
private ToDoubleFunction fitness;
private Function mutation;
private double mutationProbability;
private int populationSize = 100;
private Supplier supplier;
private Predicate> termination;
Los parámetros, respectivamente, son: 1. Operador de entrecruzamiento 2. Probabilidad de entrecruzamiento 3. Función de adecuación 4. Operador de mutación 5. Probabilidad de mutación 6. Tamaño de la población 7. Proveedor de cromosomas para la población inicial 8. Función de término
Aquí está la configuración de nuestro problema:
new GeneticAlgorithm()
   .setCrossover(this::crossover)
   .setCrossoverProbability(0.25)
   .setFitness(this::fitness)
   .setMutation(this::mutation)
   .setMutationProbability(0.05)
   .setPopulationSize(100)
   .setSupplier(() -> supplier(expected.length))
   .setTermination(this::termination)
   .find()

Operador de Entrecruzamiento y Probabilidad

private char[] crossover(char[] value1, char[] value2) {
   final int i = (int) round(random() * value1.length);
   final char[] result = new char(value1.length);
   System.arraycopy(value1, 0, result, 0, i);
   System.arraycopy(value2, i, result, i, value2.length - i);
   return result;
}
La probabilidad de entrecruzamiento es 0.25, así que esperamos que en promedio, 25 por ciento de los cromosomas sean seleccionados para el entrecruzamiento. Llevamos a cabo un simple procedimiento, para el entrecruzamiento de un par de cromosomas. Generamos un número al azar n para la selección [0..length], dónde length es el largo del cromosoma. Ahora unimos la pareja seleccionada tomando el primer símbolo n de uno de los cromosomas y el resto de los símbolos después del segundo.

Función Adecuada

private double fitness(char[] value) {
   return range(0, value.length)
       .filter(i -> value[i] == expected[i])
       .count();
}
La función adecuada simplemente cuenta el número de combinaciones entre la frase clave y el cromosoma dado.

Operador de Mutación y Probabilidad

private char[] mutation(char[] value) {
   final char[] result = Arrays.copyOf(value, value.length);
   for (int i = 0; i < 2; i++) {
       int letter = (int) round(random() * (ALPHABET.length - 1));
       int location = (int) round(random() * (value.length - 1));
       result[location] = ALPHABET[letter];
   }
   return result;
}
La operación de mutación se ejecuta independientemente en cada cromosoma. La probabilidad de mutación es de 0.05, así que esperamos que, en promedio cinco por ciento de la población sea mutada. Mutamos al escoger una posición de letra al azar y reemplazar su valor con una letra al azar del alfabeto. Lo hacemos dos veces por cada cromosoma mutado.

Proveedor

private char[] supplier(int length) {
   final char[] result = new char(length);
   for (int i = 0; i < length; i++) {
       int letter = (int) round(random() * (ALPHABET.length - 1));
       result[i] = ALPHABET[letter];
   }
   return result;
}
El proveedor genera frases al azar tomando letras del alfabeto igualmente al azar. Cada frase tiene un largo constante predefinido.

Función de Término

private boolean termination(Collection chars) {
   count++;
   final Optional result = chars.stream()
       .filter(value -> round(fitness(value)) == expected.length)
       .findAny();
   if (result.isPresent()) {
       System.out.println("Count: " + count);
       System.out.println(result.get());
       return true;
   }
   final boolean terminated = count == 3000;
   if (terminated) {
       chars.forEach(System.out::println);
   }
   return terminated;
}
La función término cuenta el número de llamadas y regresos true, si hay ya una pareja exacta, o si la cuenta de la generación llega a 3,000.

Ejecución

Ahora estamos listos para probar nuestro algoritmo. Si lo ejecutas varias veces, notarás que no todas las ejecuciones son exitosas. En cada oportunidad, el número de iteraciones será diferente. Esto se debe a una naturaleza de probabilidad del algoritmo. El algoritmo tiene varios puntos donde se puede mejorar. Puedes jugar con entrecruzamiento y probabilidades de mutación.
Bajar el número a una solución estable pero lenta. Un número más pequeño de cromosomas se verá afectado por operadores genéticos, por tanto, más iteraciones serán requeridas para la solución.
Aumentar los números acelerará el algoritmo, pero también hará que la solución sea inestable. Los cromosomas adecuados no solo serán preservados, pero también se verán afectados por los operadores genéticos. Por este motivo, perderán sus “buenos” genes.
Es importante encontrar un buen balance. Aumentar el número de iteraciones le dará al algoritmo más oportunidades para encontrar una solución pero, por otra parte, tomará más tiempo. También aplicar métodos diferentes de entrecruzamiento y mutación. Una buena selección de estos operadores mejorará drásticamente la calidad de la solución.

¿Qué sigue?

Hemos cubierto solo la punta del iceberg. Tomamos un ejemplo que tiene solo una entrada y ésta puede ser presentada, fácilmente, como un cromosoma. Los operadores genéticos son simples.
Es muy interesante tomar un problema de la vida real y aplicar el algoritmo genético a éste. Descubrirás diferentes acercamientos al codificar entradas de data reales, al igual que diferentes implementaciones de entrecruzamiento y mutación.
Si un problema puede ser expresado a través de un set de parámetros que tenemos que adivinar para optimizar una métrica, podemos establecer rápidamente un AG que podemos usar para resolverlo.
Uno de los problemas más interesantes es enseñar redes neuronales artificiales. Podemos establecer los parámetros optimizados para ser fuerzas sinapsis y para que la métrica adecuada sea el porcentaje de entradas por el cual nuestras redes neurales hayan dado la respuesta correcta. Después de eso, nos podemos relajar y dejar que nuestras redes neurales evolucionen en la solución ideal que deseamos. O al menos hasta que tengamos algo lo suficientemente bueno, porque la evolución toma tiempo.

El articulo original lo puede ver en el siguiente enlace:

https://www.toptal.com/algorithms/algoritmos-gen%C3%A9ticos-b%C3%BAsqueda-y-optimizaci%C3%B3n-por-selecci%C3%B3n-natural/es

domingo, 16 de abril de 2017

Introducción A PHP 7: Qué Hay De Nuevo Y Qué Se Ha Ido


Introducción A PHP 7: Qué Hay De Nuevo Y Qué Se Ha Ido



Uno de los eventos más emocionantes en el 2015 en el mundo de PHP fue el lanzamiento de PHP 7;10 años después del lanzamiento de la última versión principal, PHP 5. Con un gran paso adelante, PHP 7 introduce un montón de nuevas características y actualizaciones de rendimiento.
Sin embargo, también elimina la funcionalidad antigua, obsoleta, que introduce algunos pausas de compatibilidad, lo que hace más difícil para las aplicaciones más antiguas migrar a la nueva versión. Esta guía debe servir como un recorrido rápido sobre qué esperar si planeas mover sus aplicaciones existentes, o construir otras nuevas, encima de PHP 7.

Pero Espera, ¿ A Dónde Fue PHP 6?

Si no has estado trabajando con PHP últimamente, puedes preguntarte qué pasó con PHP 6, ¿por qué el salto de PHP 5 a PHP 7? Bueno, larga historia corta, PHP 6 fue un fracaso. La característica principal de la versión 6 era el soporte nativo de caracteres Unicode, ya que PHP se utiliza principalmente en el desarrollo web y la web necesita Unicode, por lo que el movimiento para traer Unicode a PHP tenía sentido.
La idea era traer un soporte completo para Unicode al núcleo mismo. Habría traído capacidades extendidas al lenguaje: desde la habilidad de usar emojis tontos, como nombres de variables y de funciones, hasta poderosas funciones internacionales de cuerdas. Por ejemplo, cuando otro idioma utiliza letras mayúsculas y minúsculas de manera diferente al inglés, o cuando un nombre en caracteres chinos necesita ser convertido al inglés.
PHP 6 era ambicioso, pero basura. Así es como terminamos con PHP 7, saltando la versión 6 en el proceso.
PHP 6 era ambicioso, pero basura. Así es como terminamos con PHP 7, saltando la versión 6 en el proceso.
Desafortunadamente, este ambicioso plan resultó ser un mayor problema de lo previsto. La mayor parte de la base de código tenía que ser portada para soportar Unicode tanto para las extensiones principales como para las importantes, lo que resultó tedioso y complicado. Esto frenó el desarrollo de otras características en el lenguaje, frustrando a muchos desarrolladores de PHP en el proceso. Se presentaron obstáculos adicionales, lo que resultó en menos interés en el desarrollo de un soporte nativo de Unicode, lo que finalmente llevó al abandono del proyecto.
Dado que los recursos, tales como libros y artículos, se habían escrito para PHP 6 y su soporte Unicode, la nueva versión sería renombrada PHP 7 para evitar la confusión.
De todos modos, suficiente sufrimiento del pasado triste, vamos a ver lo que PHP 7 trae a la fiesta.

Batalla De Rendimiento, PHP 7 vs. PHP 5

Con prácticamente todas las actualizaciones, se esperan mejoras de rendimiento menores. Sin embargo, esta vez PHP trae una mejora significativa sobre versiones anteriores que hacen el funcionamiento escarpado una de las características más atractivas de PHP 7. Esto viene como parte del proyecto “PHPNG”, que aborda los componentes internos del propio motor Zend.
Mediante la refactorización de estructuras de datos internas y la adición de un paso intermedio para codificar la compilación en forma de un árbol de sintaxis abstracto (AST), el resultado es un rendimiento superior y una asignación de memoria más eficiente. Los números mismos parecen muy prometedores; Los Benchmarks realizados en aplicaciones del mundo real muestran que PHP 7 es dos veces más rápido que PHP 5.6 en promedio y que resulta en un 50% menos de consumo de memoria durante las solicitudes, convirtiendo a PHP 7 en un fuerte rival para el compilador HHVM JIT de Facebook. Echa un vistazo a este infográfico de Zend representando el rendimiento de algunos comunes CMS y Frameworks.
PHP 7 se ve y se siente familiar, pero está ajustado para el rendimiento. El refinado Motor Zend y las ganancias de rendimiento resultantes hacen una gran diferencia.
PHP 7 se ve y se siente familiar, pero está ajustado para el rendimiento. El refinado Motor Zend y las ganancias de rendimiento resultantes hacen una gran diferencia.
La disminución en el consumo de memoria también permite a las máquinas más pequeñas manejar mejor las solicitudes junto con la oportunidad de construir micro servicios alrededor de PHP. Los cambios internos, en particular la implementación de AST, también abren posibilidades de optimizaciones futuras que podrían empujar aún más el rendimiento. Se está considerando una nueva implementación interna de un compilador JIT para futuras versiones.

PHP 7 Azúcar Sintáctica

PHP 7 viene con nuevas características de sintaxis. Aunque no amplían las capacidades del propio lenguaje, proporcionan una forma mejor o más fácil de hacer que tu código sea más agradable para escribir y más cómodo para a los ojos.

Declaraciones De Importación De Grupo

Ahora, podemos agrupar las declaraciones de importación para las clases que se originan desde el mismo espacio de nombres en la línea de ‘uso.’ Esto debería ayudar a alinear las declaraciones de una manera significativa o simplemente guardar algunos bytes en tus archivos.
use Framework\Module\Foo;
use Framework\Module\Bar;
use Framework\Module\Baz;
Con PHP 7 podemos usar:
use Framework\Module\{Foo, Bar, Baz};
O si preferimos un estilo multi-linear:
use Framework\Module{
   Foo,
   Bar,
   Baz
};

Operador Coalescente Nulo

Esto resuelve un problema común en la programación PHP, donde queremos asignar un valor a una variable de otra variable, si esta última está realmente configurada; de lo contrario proporcionarle un valor diferente a esta. Se utiliza comúnmente cuando trabajamos con la entrada proporcionada por el usuario.
Pre-PHP 7:
if (isset($foo)) {
   $bar = $foo;
} else {
   $bar = 'default'; // we would give $bar the value 'default' if $foo is NULL
}
Después de PHP 7:
 
$bar = $foo ?? 'default';
Esto también puede estar encadenado con un número de variables:
$bar = $foo ?? $baz ?? 'default';

Operador De Nave Espacial

El operador de la nave espacial <=> permite una comparación de tres vías entre dos valores, no solo indicando si son iguales, sino también cuál es mayor, sobre la desigualdad devolviendo 1,0 o -1.
Aquí podemos tomar diferentes acciones dependiendo de cómo los valores difieren:
switch ($bar <=> $foo) {
   case 0:
       echo '$bar and $foo are equal';
   case -1:
       echo '$foo is bigger';
   case 1:
       echo '$bar is bigger';
}
Los valores comparados pueden ser enteros, flotantes, cadenas o incluso matrices. Consulta la documentación para tener una idea de cómo se comparan los diferentes valores entre sí.

Nuevas Funciones En PHP 7

Pero, por supuesto, PHP 7 también aporta nuevas y emocionantes funcionalidades.

Tipos De Parámetros Escalares Y Sugerencias De Tipo De Retorno

PHP 7 extiende las declaraciones de tipos anteriores de parámetros en métodos (clases, interfaces y matrices) añadiendo los cuatro tipos escalares; Integers (int), Floats (float), Booleans (bool) y Strings (string) como posibles tipos de parámetro.
Además, podemos especificar opcionalmente qué tipo de métodos y funciones devuelven. Los tipos soportados son * bool *, * int *, * float *, * string *, * array *, * callable *, nombre de * Clase * o * Interface *, * self * y * parent * (para métodos de clase)
Clase Calculadora
{
  // Declaramos que los parámetros proporcionados son del tipo entero
  Función Pública addTwoInts (int $ x, int $ y): int {
         Retorno $ x + $ y; // También decimos explícitamente que este método devolverá un entero
  }
}
Las declaraciones de tipo permiten la construcción de aplicaciones más robustas y evitan pasar y devolver valores erróneos de las funciones. Otros beneficios incluyen analizadores de código estático e IDEs, que proporcionan una mejor visión de la base de código si faltan los DocBlocks.
Dado que PHP es un lenguaje de tipificación débil, ciertos valores para los tipos de parámetro y de retorno se emitirán en función del contexto. Si pasamos el valor “3” en una función que tiene un parámetro declarado de tipo int, el intérprete lo aceptará como un entero y no lanzará ningún error. Si no deseas esto, puede habilitar modo estrictoañadiendo una directiva dedeclarar.
Declarar (tipos_estrictos = 1);
Esto se establece en una base por archivo, ya que una opción global dividiría los repositorios de código en aquellos que están construidos con rigor global en y aquellos que no lo son, resultando en un comportamiento inesperado cuando combinamos código de ambos.

Excepciones Del Motor

Con la adición de excepciones del motor, los errores fatales que podrían haber resultado en la terminación del Script se pueden capturar y manejar fácilmente.
Errores como llamar a un método inexistente no terminará el Script, sino que lanzarán una excepción que puede ser manejada por un bloque de prueba de captura, lo que mejora el manejo de errores para sus aplicaciones. Esto es importante para ciertos tipos de aplicaciones, servidores y Daemons, ya que los errores fatales requerirían que se reiniciaran. Las pruebas en PHPUnit también deberían ser más útiles, ya que los errores fatales eliminan toda la serie de pruebas. Las excepciones, en lugar de errores, se manejarían por caso de prueba.
La adición de excepciones de motor a PHP 7 ayuda a prevenir la terminación de scripts y mejora el error handling.
PHP 7 se ve y se siente familiar, pero está ajustado para el rendimiento. El refinado Motor Zend y las ganancias de rendimiento resultantes hacen una gran diferencia.
PHP 7 añade una serie de nuevas clases de excepción basadas en el tipo de errores que se pueden encontrar. Con el fin de mantener la compatibilidad entre versiones, se ha añadido una nueva interfaz Throwable que se puede implementar a partir de excepciones de motor y de usuario. Esto era necesario para evitar excepciones del motor para extender la clase de excepción de base, lo que resulta en antiguas excepciones de captura de código que no existían antes.
Antes de PHP 7 esto habría terminado el script con un error fatal:
try
{
   thisFunctionDoesNotEvenExist();
}
catch (\EngineException $e) {
   //
Clean things up and log error
   echo
$e->getMessage();
}

Clases Anónimas

Las clases anónimas son primos de funciones anónimas que podrías usar en una instancia simple a corto plazo. Las clases anónimas se pueden crear y utilizar fácilmente como un objeto normal. Aquí hay un ejemplo de los documentos.
Pre-PHP 7
php
class
MyLogger {
 public function log($msg) {
 
   print_r($msg . "\n");
 }
}
 
$pusher->setLogger(
new MyLogger() );
Con clase anónima:
php
$pusher->setLogger(new class {
 public
function log($msg) {
   print_r($msg
. "\n");
 }
});
Las clases anónimas son útiles en las pruebas unitarias, particularmente en pruebas de objetos y servicios. Esto nos ayuda a evitar las pesadas bibliotecas y los marcos replica la creación de un objeto simple que proporciona la interfaz que queremos imitar.

Funciones CSPRNG

Se agregaron dos nuevas funciones para generar cadenas y números enteros criptográficamente seguros.
random_bytes(int
$len);
Devuelve una cadena aleatoria con longitud $len.
php
random_int(int
$min, int $max);
Devuelve un número entre $min$max.

Sintaxis de Escape de Codepoint Unicode

A diferencia de muchos otros lenguajes, antes de PHP 7, PHP no tenía una manera de escapar de un código Unicode en literales de cadena,. Esta funcionalidad agrega la secuencia de escape `\ u ‘para producir dichos caracteres usando su código de código UTF-8. Esto es mejor que insertar los caracteres directamente, permitiendo un mejor manejo de los caracteres invisibles, así como los caracteres que tienen la misma representación gráfica, pero difieren en el significado.
echo "\u{1F602}"; // outputs 😂‚
Ten en cuenta que esto rompe el código existente con la secuencia `\ u ‘porque cambia el comportamiento.

Los Generadores Se Actualizan

Generadores en PHP obtienen también algunas características adicionales agradables. Ahora, los generadores tienen una instrucción de retorno que puede usarse para permitir que produzca un valor final después de la iteración. Esto se puede utilizar para comprobar que el generador se ha ejecutado sin errores y permite que el código que llamó al generador maneje varios escenarios de manera adecuada.
Además, los generadores pueden devolver y rendir expresiones de otros generadores. Esto les permite dividir las operaciones complejas en unidades más simples y modulares.
function genA() {
   yield 2;
   yield 3;
   yield 4;
}
 
function genB() {
   yield 1;
   yield from genA(); // 'genA' Se llama aquí e itera
sobre
   yield 5;
   return 'success'; // Este es un resultado final que
podemos comprobar más tarde
}
 
foreach (genB() as $val) {
   echo "\n $val"; // Esto emitirá los
valores 1 a 5 para}
 
$genB()->getReturn(); // Esto debería devolver el "éxito"
cuando no hay errores.

Expectativas

Las expectativas son una mejora de la función de afirmar () mientras se mantiene la compatibilidad hacia atrás. Permiten aserciones de costo cero en el código de producción y proporcionan la posibilidad de lanzar excepciones personalizadas cuando la afirmación falla, lo cual puede ser útil durante el desarrollo.
Afirmar () se convierte en una construcción de lenguaje en PHP 7. Las aserciones deben usarse para propósitos de depuración sólo en entornos de desarrollo y pruebas. Para configurar su comportamiento, se nos proporcionan dos nuevas directivas.
  • zend.afirmación - 1: generar y ejecutar código (modo de desarrollo) (valor por defecto) - 0: genera el código pero salta a su alrededor en tiempo de ejecución - -1: no genera código que lo convierte en coste cero (modo de producción)
  • afirmación.excepción - 1: lanzar cuando la aserción falla, lanzando el objeto proporcionado como excepción o lanzando un nuevo objeto * ErrorAfirmación * si no se proporcionó la excepción - 0: usa o genera un * Throwable * como se describió anteriormente, pero solo genera una advertencia basada en ese objeto en lugar de lanzarla (compatible con el comportamiento de PHP 5)

Preparación Para Pasar de PHP 5 a PHP 7

La introducción de un lanzamiento importante brinda la oportunidad de cambiar/actualizar las funcionalidades más antiguas o incluso eliminarlas si se consideran demasiado viejas o han quedado obsoletas durante algún tiempo. Tales cambios pueden introducir interrupciones en compatibilidad en aplicaciones más antiguas.
Otro problema que surge de esta versión, es que las bibliotecas y los marcos importantes de los que dependes pueden no haber sido actualizados para soportar la última versión. El equipo de PHP ha intentado hacer los nuevos cambios lo más atrasados ​​posible y permitir que la migración a la nueva versión sea lo más sencilla posible. Las aplicaciones más nuevas y más actualizadas deberían encontrar más fácil pasar a la nueva versión, mientras que las aplicaciones más antiguas pueden tener que decidir si los beneficios superan el costo, posiblemente eligiendo no actualizar.
La mayoría de los descansos son menores y se pueden mitigar fácilmente, mientras que otros pueden requerir más esfuerzo y tiempo. Básicamente, si tenías advertencias de obsoletos en tu aplicación antes de instalar PHP 7 probablemente obtendrás errores que romperán la aplicación hasta que se resuelva. Fuiste advertido, ¿verdad?

Antiguos SAPIs y extensiones

Lo más importante, las SAPIs viejas y desaprobadas fueron eliminadas como la extensión mysql (pero no deberías estar usando esto en primer lugar, ¿verdad?). Para obtener una lista completa de extensiones y destacados eliminado puedes comprobar este RFCs aquí y aquí.
Además, otros SAPIs están siendo portados a PHP 7.
Cargas de SAPIs y extensiones viejas fueron eliminadas de PHP 7.Estamos prediciendo que no se perderán.
Cargas de SAPIs y extensiones viejas fueron eliminadas de PHP 7.Estamos prediciendo que no se perderán..

Sintaxis de variable uniforme

Esta actualización hizo algunos cambios a favor de la coherencia para las construcciones de variable- variable. Esto permite expresiones más avanzadas con variables, pero introduce cambios en el comportamiento en algunos otros casos, como se muestra a continuación.
                       //
old meaning
           // new meaning
$$foo['bar']['baz']
    ${$foo['bar']['baz']}
    ($$foo)['bar']['baz']
$foo->$bar['baz']
      $foo->{$bar['baz']}
      ($foo->$bar)['baz']
$foo->$bar['baz']()
    $foo->{$bar['baz']}()
    ($foo->$bar)['baz']()
Foo::$bar['baz']()
     Foo::{$bar['baz']}()
     (Foo::$bar)['baz']()
Esto rompería el comportamiento de las aplicaciones que accedían a valores como éste. Por otro lado, puede hacer algunas cosas limpias como esto :.
//
Nested ()
foo()();
// Calls the return of foo()
$foo->bar()();
 
//
IIFE syntax like JavaScript
(function()
{
   //
Function body
})();
 
//
Nested ::
$foo::$bar::$baz

Etiquetas De Estilo Antiguo Eliminadas

Las etiquetas de apertura / cierre `` <% …%> ,<% = …%> , ... </ script> `se eliminan y ya no son válidas. Sustituirlas por los válidos debería ser fácil, pero ¿qué estás haciendo con ellos de todos modos, raro?

Nombres No Válidos Para Clases, Interfaces Y Rasgos

Como resultado de las adiciones, como las clases de tipo de parámetro y retorno, las interfaces y los rasgos ya no pueden tener los siguientes nombres:
- bool - int - float - string - nulo - verdadero - falso
Estos causan roturas a las aplicaciones existentes y las bibliotecas que las utilizan, pero deben ser fáciles de arreglar. Además, aunque no causan ningún error y son válidos, no deben utilizarse los siguientes, ya que están reservados para uso futuro:

-recurso

objecto - mixto - numérico
Abstenerse de usarlos debería ahorrarte el trabajo de cambiarlos en el futuro. Para una lista completa de cambios que romperían la compatibilidad, comprueba este documento.
También puedes utilizar php7cc, que verifica tu código y puede detectar posibles problemas que puedan surgir si te mudas a PHP 7. Pero, por supuesto, no hay mejor manera que instalar PHP 7 y comprobarlo por ti mismo. ## Potenciales Problemas de Compatibilidad con PHP ### PHP 7 Compatibilidad de Infraestructura
Una gran cantidad de servicios de hosting han comenzado a añadir soporte para PHP 7. Esta es una buena noticia para los proveedores de alojamiento compartido, ya que las ganancias de rendimiento les permitirá aumentar el número de sitios web de los clientes en su hardware, reduciendo sus gastos operativos y aumentando sus márgenes. En cuanto a los propios clientes, no deben esperar demasiado de un impulso en estas condiciones, pero para ser justos, el alojamiento compartido no es una opción orientada al rendimiento de todos modos.
Por otro lado, los servicios que ofrecen los servidores privados virtuales o servidores dedicados obtendrán los beneficios completos de este golpe de rendimiento. Algunos servicios de PaaS como Heroku soportaban PHP 7 desde el principio, pero otros servicios, como AWS Beanstalk y OpenShift de Oracle, están rezagados. Consulta el sitio web de tu proveedor PaaS para ver si PHP 7 ya está soportado, o si el soporte viene en un futuro próximo. Por supuesto, los proveedores IaaS te permiten tomar el control del hardware e instalar PHP 7 (o compilar si es más a tu gusto). Los paquetes de PHP 7 ya están disponibles para los principales entornos IaaS.

PHP 7 Compatibilidad de Software

Además de la compatibilidad de infraestructura, también debes tener en cuenta posibles problemas de compatibilidad de software. Los sistemas de gestión de contenidos populares como WordPress, Joomla y Drupal han añadido soporte para PHP 7 con sus últimas versiones. Los marcos importantes como Symfony y Laravel también disfrutan de un apoyo total. Sin embargo, es hora de una palabra de precaución. Este soporte no se extiende a código de terceros en forma de complementos, plugins, paquetes o lo que sea que ru CMS o framework los llame. Pueden sufrir problemas de compatibilidad y es tu responsabilidad asegurarte de que todo esté listo para PHP 7.
Para los repositorios activos y mantenidos, esto no debería ser un problema. Sin embargo, los repositorios antiguos y sin mantenimiento que carecen de soporte de PHP 7 podrían hacer que tu aplicación entera no fuese utilizable.

El futuro de PHP

La versión de PHP 7 eliminó el código antiguo y obsoleto y allanó el camino para nuevas características y actualizaciones de rendimiento en el futuro. Además, se espera que PHP obtenga optimizaciones de rendimiento adicionales pronto. A pesar de tener algunas pausas de compatibilidad con versiones anteriores, la mayoría de los problemas son fáciles de resolver. Las bibliotecas y los frameworks ahora están migrando su código a PHP 7 haciendo disponible así las últimas versiones. Quiero incentivarte a probar y ver los resultados por ti mismo. Tal vez tu aplicación ya es compatible y espera para usar y beneficiarte de, PHP 7.

El articulo original lo puede encontrar en el siguiente enlace: