Node:Train, Next:, Previous:Mixing Examples, Up:Mixing Examples



Train Example (connections)

This is an example of how to create a runtime system. The Prolog program train.pl will display a route from one train station to another. The C program train.c calls the Prolog code and writes out all the routes found between two stations:

% train.pl

connected(From, From, [From], _):- !.
connected(From, To, [From| Way], Been):-
        (   no_stop(From, Through)
        ;
            no_stop(Through, From)
        ),
        not_been_before(Been, Through),
        connected(Through, To, Way, Been).

no_stop('Stockholm', 'Katrineholm').
no_stop('Stockholm', 'Vasteras').
no_stop('Katrineholm', 'Hallsberg').
no_stop('Katrineholm', 'Linkoping').
no_stop('Hallsberg', 'Kumla').
no_stop('Hallsberg', 'Goteborg').
no_stop('Orebro', 'Vasteras').
no_stop('Orebro', 'Kumla').

not_been_before(Way, _) :- var(Way),!.
not_been_before([Been| Way], Am) :-
        Been \== Am,
        not_been_before(Way, Am).

/* train.c */

#include <stdio.h>
#include <sicstus/sicstus.h>

void write_path(SP_term_ref path)
{
  char *text = NULL;
  SP_term_ref
    tail = SP_new_term_ref(),
    via = SP_new_term_ref();

  SP_put_term(tail,path);

  while (SP_get_list(tail,via,tail))
  {
    if (text)
      printf(" -> ");

    SP_get_string(via, &text);
    printf("%s",text);
  }
  printf("\n");
}

int user_main(int argc, char **argv)
{
  int rval;
  SP_pred_ref pred;
  SP_qid goal;
  SP_term_ref from, to, path;

  /* Initialize Prolog engine. This call looks up SP_PATH in order to
   * find the Runtime Library.  */
  if (SP_FAILURE == SP_initialize(argc, argv, NULL))
    {
      fprintf(stderr, "SP_initialize failed: %s\n", SP_error_message(SP_errno));
      exit(1);
    }

  rval = SP_restore("train.sav");

  if (rval == SP_ERROR || rval == SP_FAILURE)
    {
      fprintf(stderr, "Could not restore \"train.sav\".\n");
      exit(1);
    }

  /* Look up connected/4. */
  if (!(pred = SP_predicate("connected",4,"user")))
    {
      fprintf(stderr, "Could not find connected/4.\n");
      exit(1);
    }

  /* Create the three arguments to connected/4. */
  SP_put_string(from = SP_new_term_ref(), "Stockholm");
  SP_put_string(to = SP_new_term_ref(), "Orebro");
  SP_put_variable(path = SP_new_term_ref());

  /* Open the query. In a development system, the query would look like:
   *
   * | ?- connected('Stockholm','Orebro',X).
   */
  if (!(goal = SP_open_query(pred,from,to,path,path)))
    {
      fprintf(stderr, "Failed to open query.\n");
      exit(1);
    }

  /*
   * Loop through all the solutions.
   */
  while (SP_next_solution(goal)==SP_SUCCESS)
    {
      printf("Path: ");
      write_path(path);
    }

  SP_close_query(goal);

  exit(0);
}

Create the saved-state containing the Prolog code:

% sicstus
SICStus 3.9 (sparc-solaris-5.7): Thu Sep 30 15:20:42 MET DST 1999
Licensed to SICS
| ?- compile(train),save_program('train.sav').
% compiling [...]/train.pl...
% compiled [...]/train.pl in module user, 10 msec 2848 bytes
% [...]/train.sav created in 0 msec

yes
| ?- halt.

Create the executable using the application builder:

% spld --main=user train.c -o train.exe

And finally, run the executable:

% ./train
Path: Stockholm -> Katrineholm -> Hallsberg -> Kumla -> Orebro
Path: Stockholm -> Vasteras -> Orebro