6.8.1 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 <stdlib.h>
#include <sicstus/sicstus.h>

static void write_path(SP_term_ref path)
{
  char const *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. The third arg to SP_initialize is
     an option block and can be NULL, for default options. */
  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);
  }
/* train.c */
  /* 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 4.5.0 …
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

| ?- 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


Send feedback on this subject.