#include"../../pnheaders/pns.h"

int main() {
  int i;

  /* Declaring pn objects */

  pns pn_p, pn_s, pn;

  /* Petri nets can be initialized using the incidence matrix */

  /* This will be used for the incidence matrix of one pn */

  int Dp[] = {  1,  1, -1,  1,  0,  0,\
	        0,  0,  1,  0, -1,  0,\
	        0, -1,  1,  0,  0, -1,\
               -1,  0,  0,  0,  1,  0,\
	        0,  0,  0, -1,  0,  1};

  int mp[] = { 1, 1, 1, 1, 1}; /* The initial marking */

  /* These will be used for the input and output matrices of another pn */

  int Is[] = {  0,  1,  0,  0,\
		0,  0,  1,  0,\
		0,  0,  0,  1,\
		1,  0,  0,  0};

  int Os[] = {  0,  0,  1,  0,\
		0,  0,  0,  1,\
		1,  0,  0,  0,\
		0,  1,  0,  0};

  int ms[] = {0, 0, 1, 1}; /* The initial marking */

  struct placelist *plist;
  arcs* alist;
  char *str;

  /* Here is how the pn objects are created */

  /* The following creates a pn of 5 places, 6 transitions, incidence 
     matrix Dp, and initial marking mp */
  pn_p = createpn("pnum tnum D m0", 5, 6, Dp, mp); 

  /* Here the input and output matrices are used to initialize the pn */
  pn_s = createpn("pnum tnum I O m0", 4, 4, Is, Os, ms);

  /* This creates a pn object without transition arcs */
  pn = createpn("pnum tnum", 3, 5);

  /* GetMatrixEl and SetMatrixEl can be used to read or write the elements
     of a matrix. */

  /* For instance, arcs could be added by changing the value of the input 
     and output matrices of the pn */

  SetMatrixEl(&pn.out, 0, 2, 1); /* add arc from p0 to t2 of weight 1 */
  SetMatrixEl(&pn.out, 0, 4, 1); /* add arc from p0 to t4 of weight 1 */
  SetMatrixEl(&pn.out, 2, 4, 1); /* add arc from p2 to t4 of weight 1 */
  SetMatrixEl(&pn.in, 1, 3, 1); /* add arc from t3 to p1 of weight 1 */
  SetMatrixEl(&pn.in, 1, 0, 2); /* add arc from t0 to p1 of weight 2 */

  /* For instance, to check whether there is an arc from t1 to p2: */
  i = GetMatrixEl(&pn.in, 2, 1);
  if(i)
    fprintf(stderr, "\nThe arc (t1, p2) has the weight %d.\n", i);
  else
    fprintf(stderr, "\nThere is no arc from t1 to p2.\n");

  /* To display in text format a Petri net object use displaypn */

  fprintf(stderr, "\n** PN_P *************************************\n");
  displaypn(pn_p, stderr); /* displays pn_p */
  fprintf(stderr, "\n** PN_S *************************************\n");
  displaypn(pn_s, stderr); /* displays pn_s */
  fprintf(stderr, "\n** PN *************************************\n");
  displaypn(pn, stderr); /* displays pn */

  /* Properties of the pn objects can be set or changed with updatepn */

  updatepn(&pn, "place_name", 0, "start_p");
  /* The line above associates the name "start_p" with the place 0 */

  updatepn(&pn, "trans_name", 0, "tr0");
  /* The line above associates the name "tr0" with the transition 0 */

  updatepn(&pn, "select", 1, "f1"); /*select function 'f1' for place 1*/

  updatepn(&pn, "segment", 0, "i++;");/*code segment 'i++' for place 0*/

  /* Text transmitted by means of createpn/updatepn is copied to the 
     corresponding items of the pns object; thus it should be 
     deallocated, when applicable. For instance: */

  str = tcalloc(strlen("f1(i, j);")+1, sizeof(char));
  strcpy(str, "f1(i, j);");
  updatepn(&pn, "segment", 1, str);
  /* Now, str may be freed, since its content has been copied */
  free(str);

  /* Flags are set as follows. */

  updatepn(&pn, "unobservable", 0);/*marks transition 0 unobservable*/

  updatepn(&pn, "live uncontrollable uncontrollable", 0, 0, 2);
  /* The line above sets the "live" and "uncontrollable" flags of 
     transition 0 and the uncontrollable flag of transition 2 */

  /* Arcs are added similarly (using createpn or updatepn). Here is
     an example. */

  plist = tmalloc(sizeof(struct placelist));
  plist->place = 1;
  plist->next = tmalloc(sizeof(*plist));
  plist->next->place = 2;
  plist->next->next = 0;

  alist = tmalloc(sizeof(arcs));
  alist->in_place = 0;
  alist->out_places = plist;
  alist->condition = tcalloc(strlen("j == i || z == 0.1")+1, sizeof(char));
  strcpy(alist->condition, "j == i || z == 0.1");
  alist->next = 0;

  updatepn(&pn, "arcs", 0, alist); /* arc list associated with transition 0 */ 

  /* The line above updates the arc_list item of the pns object as well as the 
     input & output matrices. */ 

  /* Note the absence of the lines of code deallocating alist. The object alist is
     placed in the pns object, it is not copied. Thus, alist is deallocated when 
     the pns object is deallocated with the function deallocpn. */ 

  /* To deallocate a pn object use deallocpn */

  deallocpn(&pn_p); 
  deallocpn(&pn_s); 
  deallocpn(&pn); 

  return 0;
}
