Prolog: enlazando un sistema experto con PHP

Prolog enlazando PHP

Hoy traigo cómo enlazar proyectos web en PHP con partes hechas en Prolog. No he encontrado casi información en Internet, así que aquí estoy compartiendo algo sobre esto. Este es un simple HOWTO para tratar las respuestas, o muchos de los casos que puedes tener en ataques a Prolog desde PHP.

La idea general es que tenemos uno o varios programas en ficheros .pl. Estos ficheros a su vez se pueden autoincluir unos en otros con sentencias del estilo include o import como en otros lenguajes. Además, también estos ficheros .pl se pueden generar automáticamente desde otras fuentes de datos. Esta dinamicidad de la parte programada en Prolog es una de las cosas más interesantes. Es decir, los programas en Prolog pueden cambiarse a si mismos, tema muy interesante en Inteligencia Artificial. Esto es, los programas en Prolog pueden aprender sobre la marcha, además de que, la base de conocimiento puede nutrirse de muchos datos externos también sobre la marcha.

Todo esto no es nada nuevo, los sistemas expertos se vienen construyendo desde los 60 si mal no recuerdo. No te pienses que te estoy contando nada nuevo. En las décadas de los 70-80-90 aparecieron varios lenguajes relacionados con la IA como LISP, Prolog, Haskell.. Y últimamente están tomando mucho protagonismo, ya que la potencia actual de los ordenadores da pie a muy buenos resultados combinando estas cosas. Así que vamos al grano con el script.

Show me the code

<html>
    <head>
        <title>JnjSite.com: Usando Prolog desde PHP</title>
    </head>
<body>
<h1><a href="/">Usando Prolog desde PHP</a></h1>
<?php
    $defaultMain = 'persona(maria).'.PHP_EOL
        .'persona(pepe).'.PHP_EOL
        .PHP_EOL
        .'edad(pepe, 22).'.PHP_EOL
        .'edad(maria, 23).'.PHP_EOL
        .PHP_EOL
        ."escribeEdades([]) :- write('No hay mas información sobre edades.'), nl.".PHP_EOL
        .'escribeEdades([Primera|Personas]) :-'.PHP_EOL
        ." edad(Primera, X), write(Primera), write(' tiene de edad '), write(X), nl, escribeEdades(Personas).".PHP_EOL
        .''.PHP_EOL
        .'main :-'.PHP_EOL
        ." write('¡Hola Mundo!'), nl,".PHP_EOL
        .' findall(X, persona(X), Personas),'.PHP_EOL
        .' escribeEdades(Personas).'.PHP_EOL;

    // If intializing..
    if (!file_exists('index.pl')) {
        file_put_contents('index.pl', $defaultMain);
    }

    // If updating..
    if (isset($_POST['program'])) {
        file_put_contents('index.pl', $_POST['program']);
    }

    if (isset($_POST['query'])) {
        // If executing query..
        $query = $_POST['query'];
    } else {
        // If executing main..
        $query = "main.";
    }
    $lastLine = exec('swipl -s index.pl -g "'.$query.'" -t halt.', $output, $returnValue);

?>

<h2>Resultado de consultar ?- <?= $query ?></h2>
<div style="border: 1px dashed black; width: 90%; padding-left: 12px; padding-right: 12px;">
    <pre><?php
    foreach ($output as $line) {
        echo $line.'<br>';
    }
    ?></pre>
    <?php //var_dump($output) ?>
    <p>Valor de retorno: <?= $returnValue ?> <?php
    if($returnValue == 0) echo 'true';
    elseif($returnValue == 1) echo 'false';
    elseif($returnValue == 2) echo 'error';
    ?> - Última línea: <?= $lastLine ?></p>
</div>

<h2>Hacer consulta simple</h2>
<form method="post">
?- <input type="text" style="width: 75%;" name="query">
<input type="submit" value="Consultar"><br>
<small>Por ejemplo:<br>
¿Pepe es una persona? <strong>persona(pepe).</strong><br>
¿Cuál es la edad de pepe? <strong>edad(pepe, X), write(X).</strong><br>
¿Cuáles son todas las personas? <strong>findall(X, persona(X), Personas), write(Personas).</strong></small>
</form>

<h2>Programa completo</h2>
<form method="post">
<textarea style="min-height: 200px; width: 100%;" name="program"><?= file_get_contents('index.pl'); ?></textarea>
<input type="submit" value="Actualizar">
</form>

</body>
</html>

Este código lo pones en un directorio en una web, dentro de un fichero index.php y debes de ver algo parecido a esto:

Prolog enlazando PHP

Unas explicaciones

La idea general es que tenemos un index.php con el programa en PHP. Este fichero index.php lanza ataques a un fichero index.pl que se autogenera si no existe. En la sección de Programa completo puedes editar este programa Prolog. Cada vez que le des a Actualizar guardará tus cambios y consultará Prolog haciendo la consulta ?- main.

En Hacer consulta simple puedes lanzar consultas específicas sobre algo en concreto. El ataque en cuestión se lanza con la línea PHP que marco en negrita en el index.php, se hace con la función exec. Los valores devueltos por pantalla y el valor de retorno de la ejecución son la clave para saber si la consulta ha dado true (0), false (1), error (2), y qué respuesta ha dado la obtenemos por salida estándar, por pantalla.

Es curioso como se resolvería la pregunta: ¿Cuáles son todas las personas? En este caso, para tratar estos datos desde PHP, cogiendo la salida por pantalla, debemos sacarlos como lista separada por comas por pantalla. ¡Ojo! También tenemos en Prolog instrucciones para leer o escribir de ficheros, que puede ser una opción a tener en cuenta, aunque más lenta que pasar por pantalla.

Compartir..

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

cinco × 4 =

2 ideas sobre “Prolog: enlazando un sistema experto con PHP”