#ifndef SPNBOX_H
#define SPNBOX_H

// Written by Steven Camp in 2009. 

/* 2011 Change: The following change was made in order to ensure UpdateDPData 
   of dp.c is portable (to avoid "segmentation faults" on certain systems)
   "__attribute__ ((packed))" was inserted in the fields of the data structures
   used by UpdateDPData. Note that UpdateDPData assumes that the bytes of one
   field precede immediately the bytes of the next field. The change ensures
   that this assumption is correct. M.V. Iordache, August 2011. */

#include <stdarg.h>
#include "../pnheaders/matrix.h"
#include "../third-party/lp_solve_5.5/lpkit.h"
#include "../pnheaders/pns.h"

typedef struct supervis_r { /* result of supervis */
  matrix Dfm __attribute__ ((packed)); 	//The supervised net output matrix
  matrix Dfp __attribute__ ((packed)); 	//The supervised net input matrix
} supervis_r;

typedef struct ipslv_r {
  REAL *solution; /* called r in Matlab */
  /* number of elements of solution determined from the size of L */
  int kind;
} ipslv_r;

typedef struct ipsolve_r { /*Result of ipsolve*/
  double* res;	//A pointer to an array of doubles containing the solution.
  char* mhow;		//A pointer to a statically-defined result message. DO NOT
								//DEALLOCATE!
} ipsolve_r;

typedef struct ilpadm_r {/*Result of ilpadm*/
  matrix La;		//The new constraint matrix.
  int* ba;			//The new constraint vector, given as a pointer to an integer array.
  matrix R1;		//The transform matrix R1.
  matrix R2;		//The transform matrix R2.
  char* how;		//Overall result message. Statically defined (do not deallocate).
  char** dhow;	//Array of result messages, one for each constraint. The array
								//may be deallocated, but the individual messages should not be.
} ilpadm_r;

/*The type returned by mroadm is identical to the type returned by ilpadm.*/
typedef ilpadm_r mroadm_r;

typedef struct linenf_r 
{/*The values returned from linenf*/
	matrix Dfm;		//The modified Petri net output matrix
	matrix Dfp;		//The modified Petri net input matrix
	int* ms0;			//The modified initial marking
	char* how;		//The overall status message
	char** dhow;	//The status message for each constraint transformation
	matrix Lf;		//Transformed marking constraints
	matrix Cf;		//Transformed Parikh vector constraints
	int* bf;			//Transformed constraint vector
} linenf_r;

typedef struct msplit_r
{
	/*Final Petri net*/
	matrix Df __attribute__ ((packed));
	matrix Dfm __attribute__ ((packed));
	matrix Dfp __attribute__ ((packed));
	/*The transformation matrix for finding the dependent marking
	from the independent marking*/
	matrix Mf __attribute__ ((packed));
	/*Initial and universal marking constraints*/
	matrix L0f __attribute__ ((packed));
	matrix Lf __attribute__ ((packed));
	/*The modified list of independent places and the count.*/
	int* iplf __attribute__ ((packed));
	int ipCountf __attribute__ ((packed));
	/*The lists of transitions that cannot be made live if a
	specified transition is dead, indexed by the specified transition.
	The number of lists is the number of transitions*/
	int **TDf __attribute__ ((packed));
	/*This gives the number of elements in each list above*/
	int* TDfCount __attribute__ ((packed));
} msplit_r;

typedef struct nltrans_r
{
	int* dtr;				//The list of unraisable transitions given as a pointer to an array
	int dtrCount;		//The number of elements in the dtr array
} nltrans_r;

typedef struct pn2acpn_r
{
	//The final Petri net matrices
	matrix Df __attribute__ ((packed));		
	matrix Dmf __attribute__ ((packed));		
	matrix Dpf __attribute__ ((packed));		
	//Modified constraint matrices
	matrix MXF __attribute__ ((packed));		
	matrix L0F __attribute__ ((packed));
	matrix LF __attribute__ ((packed));
	//The new independent place list, given as a pointer to an array of integers
	int *iplf __attribute__ ((packed));
	//The number of independent places (length of the iplf array)
	int iplfCount __attribute__ ((packed));
} pn2acpn_r;

typedef struct pn2eacpn_r
{
	//New Petri net matrices
	matrix Df __attribute__ ((packed));
	matrix Dmf __attribute__ ((packed));
	matrix Dpf __attribute__ ((packed));
	//New constraint matrices
	matrix MXF __attribute__ ((packed));
	matrix L0F __attribute__ ((packed));
	matrix LF __attribute__ ((packed));
	//New independent place list, given as a pointer to an array of integers.
	int *iplf __attribute__ ((packed));
	//Length of the independent place list.
	int iplfCount __attribute__ ((packed));
	/*New list of transitions that are unraisable when a given transition is dead.
	This is a pointer to an array of integer arrays. There is an element for each
	transition. Each array lists the transitions that cannot be raised if the
	transition that array corresponds to is dead.*/
	int **TD __attribute__ ((packed));
	/*The number of elements in each of the arrays in the TD array of arrays.
	This is a pointer to an array of integers, one for each transition, that lists
	the number of elements in the corresponding array in TD.*/
	int *TDCount __attribute__ ((packed));
} pn2eacpn_r;

typedef struct chkcons_r
{
	/*The solution of the ipsolve problem that is done internally.*/
	double* res;
	/*The number of elements in the solution array.*/
	int resCount;
} chkcons_r;

typedef struct reduce_r
{
	/*The new constraint matrix*/
	matrix Lf;
	/*The new constraint vector (an array of integers)*/
	int* Bf;
	/*An array of integers, each one of which is the index of an original transition
	that was kept. 
	Has as many elements as there are rows in Lf.*/
	int* indf;
	/*An integer giving a status message. See "reduce" for meaning.*/
	int how;
} reduce_r;

typedef struct actn_r
{
	/*The input and output matrices of the active subnet, given as a copy of the 
	original subnet with dead	transitions and/or places overwritten with zeroes.*/
	matrix Dma __attribute__ ((packed));
	matrix Dpa __attribute__ ((packed));
	/*The input and output matrices of the active subnet, given as those rows from
	Dma and Dpa that were not overwritten with zeroes.*/
	matrix Dmra __attribute__ ((packed));
	matrix Dpra __attribute__ ((packed));
	/*The list of active transitions. This is a pointer to an array of integers,
	each one of which is the index of a transition that made it into the active
	subnet.*/
	int* TA __attribute__ ((packed));
	/*The number of active transitions, i.e. length of the TA list.*/
	int TACount __attribute__ ((packed));
	/*This flag will be meaninful only if a uniqueness check was done. See actn.*/
	int unique __attribute__ ((packed));
} actn_r;

/*The type of data returned by actn and tactn are identical. Create a tactn_r
type just for consistency's sake.*/
typedef actn_r tactn_r;

typedef struct issiph_r
{
	/*An array of flags, one for each proposed siphon, set for each one that was
	a siphon.*/
	int* flag;
	/*This flag will be set if any of the proposed siphons were NOT siphons.*/
	int flx;
} issiph_r;

typedef struct asiph_r
{
	/*The modified list of known active siphons - those that were given and
	those that were added by the asiph procedure. Given as a matrix with a row
	for each place and a column for each siphon. An element will be nonzero if
	the corresponding place is a part of the corresponding siphon.*/
	matrix MS __attribute__ ((packed));
	/*The list of active siphons added by the asiph procedure. Same format as MS.*/
	matrix NMS __attribute__ ((packed));
} asiph_r;

typedef struct admcon_r
{
	/*A flag vector and its length.*/
	int *l __attribute__ ((packed));
	int lCount __attribute__ ((packed));
	/*A flag. If set, we found an admissible constraint.*/
	int how __attribute__ ((packed));
} admcon_r;

typedef struct dp_r
{
	/*The supervising marking constraint matrix and vector*/
	matrix Lf;
	int *Bf;
	/*The supervising initial marking constraint matrix and vector*/
	matrix L0f;
	int *B0f;
	/*The status message*/
	char* how;
} dp_r;

/*Functions to free return structures. Implemented in deallocation.c*/
void DeallocateSupervis(supervis_r *data);
void DeallocateIpslv(ipslv_r *data);
void DeallocateIpsolve(ipsolve_r *data);
void DeallocateIlpadm(ilpadm_r *data);
void DeallocateMroadm(mroadm_r *data);
void DeallocateLinenf(linenf_r *data);
void DeallocateMsplit(msplit_r *data);
void DeallocateNltrans(nltrans_r *data);
void DeallocatePn2acpn(pn2acpn_r *data);
void DeallocatePn2eacpn(pn2eacpn_r *data);
void DeallocateChkcons(chkcons_r *data);
void DeallocateReduce(reduce_r *data);
void DeallocateActn(actn_r *data);
void DeallocateTactn(tactn_r *data);
void DeallocateIssiph(issiph_r *data);
void DeallocateAsiph(asiph_r *data);
void DeallocateAdmcon(admcon_r *data);
void DeallocateDp(dp_r *data);

/*Constants returned in by functions to indicate the nature of the result.*/
#define HOW_ERROR			  "error"
#define HOW_OK				  "OK"
#define HOW_UNBOUNDED		"unbounded"
#define HOW_INFEASIBLE	"infeasible"
#define HOW_NOTSOLVED		"not solved"
#define HOW_IMPOSSIBLE  "impossible"
#define HOW_FAILED			"failed"

/*A constant used by ipsolve to check the result.*/
#define HOW_MAX_ERROR		1e-10

#define INF 1E30  // a large number used for "infinity"

/*Verbosity thresholds - these define the minimum verbosity level needed before
various spnbox functions will print output.*/
#define VRB_CHKCONS			4
#define VRB_REDUCE			3
#define VRB_DP					1
#define VRB_ILPADM			2
#define VRB_MROADM			2
#define VRB_ASIPH				3
#define VRB_MAX					10

/*Constants used to change the behavior of the vector display functions.*/
#define DISPLAY_INTS		0
#define DISPLAY_MATRIX	1
#define DISPLAY_OFFSET	2

/*Options for dp.*/
#define DP_OPT_WRITELOG			4
#define DP_OPT_ENFORCELIVE	8
#define DP_OPT_APPENDLOGS		16

msplit_r msplit(matrix* Dm, matrix* Dp, int* mask, matrix* M, matrix* L0, matrix* L, int* ipl, int ipCount, int* dpl, int dpCount, int** TD, int* TDCount);
/*MSPLIT - split transitions to make a Petri net PT-ordinary.
Original Matlab Usage:
[DF, DFM, DFP] = msplit(DM, DP)

[DF, DFM, DFP] = msplit(DM, DP, mask)

[DF, DFM, DFP, MF, L0F, LF, iplf, TDf] = msplit(DM, DP, mask, M, L0, L, ipl, dpl, TD)

* DM, DP are the input and output incidence matrices (D- and D+). 
* mask: mask(i) ~= 0 only if transition i is desired to be split.
* Returns the updated incidence matrices.
* The last five parameters are optional. See DP code for meaning. 
  Their updated values are given as output.

As for DF = DFP - DFM, transitions in the replacement sequence of 
split transitions are in the last columns. The original columns
are not reordered. If the incidence matrices are m by n, the 
first m rows and n columns of DF, DFM and DFN correspond to the
places and transitions of the net (DM, DP). The remaining rows
and columns correspond to the places and transitions resulted
through transition split.
Used in DP.

Usage In C:
msplit_r msplit(matrix *Dm, matrix *Dp, int *mask, matrix *M, matrix *L0, 
matrix *L, int *ipl, int ipCount, int *dpl, int dpCount, int **TD, int *TDCount)
Parameters have the same meaning and usage as in Matlab with the following
differences and notes:
* Mask: Integer array. Same as "mask" in matlab. Not required. If not present
  Mask is assumed to be all 1's.
* ipl, ipCount: Pointer to an integer array and the number of elements in the
  array, respectively. Same as ipl in Matlab. Not required. If not present,
	defaults to an array containing the index of each place in the net. This also
	forces dpl to default to empty. Note that the sum of ipCount and dpCount must
	be the same as the total number of places in the Petri net.
* dpl, dpCount: Pointer to an integer array and the number of elements in the
	array, respectively. Same as dpl in Matlab. See ipl, ipCount for defaults.

Written for Matlab by Marian V. Iordache, marianiordache@letu.edu.
Converted to C by Stephen Camp, stephencamp@letu.edu.*/

ilpadm_r ilpadm(matrix* L, int* b, matrix* D, int TucCount, int* Tuc, int TuoCount, int* Tuo, int* m0);
/*ILP_ADM - transformation to admissible constraints based on linear integer programming
Original Matlab usage:
[La, ba, R1, R2, how, dhow] = ilp_adm(L, b, D, Tuc, Tuo, m0, vrb)

The function transforms a marking constraint L*m <= b to an admissible 
marking constraint (R1 + R2*L)*m <= R2*(b+1). If the transformation is
possible for the given initial marking, 'ok' is returned in a variable
how; else 'impossible' is returned; similarly, dhow{i} is 'ok' if the
transformation of the constraint i of Lm <= b was possible.

L - the constraint matrix. Required.
b - the constraint vector. Defaults to zeros.
D   - the incidence matrix. Required.
TucCount - the number of uncontrollable transitions.
Tuc - the uncontrollable transitions (e.g. for Tuc = [2, 5], the second and the fifth columns of D correspond to uncontrollable transitions). 
          Either Tuc or Tuo must point to a valid array of column numbers.
TuoCount - the number of unobservable transitions. Ignored if Tuo is null.
Tuo - the unobservable transitions. Either Tuc or Tuo must point to a valid array of column numbers.
m0  - the initial marking
vrb - use vrb = 0 to suppress messages. Default is vrb = 1.
 
Use m0 = [] or only the first five arguments if the initial marking is not of interest. 

Usage in C:
ilpadm_r ilpadm(matrix* L, int* b, matrix* D, int TucCount, int* Tuc, int TuoCount, 
int* Tuo, int* m0);
The parameters have the same meaning as in Matlab with the following notes and
exceptions:
* b is an integer array, used as in matlab. If not present defaults to all zeroes.
* TucCount, Tuc. The number of elements in and an array of integers containing 
  the list of uncontrollable transition indices, respectively. Not required.
	Same as Tuc in Matlab.
* TuoCount, Tuo. The same as Tuc but for unobservable transitions. Same as Tuo
  in Matlab.
* The vrb parameter from Matlab has been dispensed with. ilpadm now uses the 
  program-wide verbosity level.

Written for Matlab by Marian V. Iordache, marianiordache@letu.edu. 
Converted to C by Stephen Camp, stephencamp@letu.edu.*/

mroadm_r mroadm(matrix* L, int* B, matrix* D, int* Tuc, int TucCount, int* Tuo, int TuoCount, int* m0);
/*
MRO_ADM - transformation to admissible constraints based on matrix row
          operations

[La, ba, R1, R2, how, dhow] = mro_adm(L, b, D, Tuc, Tuo, m0, vrb)

The function transforms a marking constraint L*places <= b to an admissible 
marking constraint (R1 + R2*L)*places <= R2*(b+1). If the transformation is
possible for the given initial marking, 'ok' is returned in a variable
how; else 'impossible' is returned; similarly, dhow{i} is 'ok' if the
transformation of the constraint i of Lm <= b was possible.

D   - the incidence matrix
Tuc - the uncontrollable transitions (e.g. for Tuc = [2, 5], the second and 
      the fifth columns of D correspond to uncontrollable transitions
Tuo - the unobservable transitions
m0  - the initial marking
vrb - use vrb = 0 to suppress messages. Default is vrb = 1.

Use m0 = [] or only the first five arguments if the initial marking is
not of interest.
Usage in C:
mroadm_r mroadm(matrix* L, int* B, matrix* D, int* Tuc, int TucCount, int* Tuo, 
int TuoCount, int* m0);
The parameters have the same meaning as in Matlab with the same notes and
exceptions as for ilpadm.

Written for Matlab by Marian V. Iordache, marianiordache@letu.edu
Converted to C by Stephen Camp, stephencamp@letu.edu
*/

supervis_r supervis(matrix* PlantIn, matrix* PlantOut, matrix* L);
/* supervis_r supervis(const matrix PlantIn, const matrix PlantOut, const matrix L)

 This function creates the structure that enforces L*M >= b, where M is 
 the marking. The constant b is not specified, since the same structure 
 may enforce any inequality  L*M >= b, for any b, given an L; b results
 from the initial marking: Mo for the original places, where L*Mo >= b,
 and L*Mo - b for the control places.

 The function returns the structure that corresponds to the supervised
 Petri net.

 This is the approach in the papers by Moody and Yamalidou.

 Written for Matlab by Marian V. Iordache, marianiordache@letu.edu
 Converted to C by Stephen Camp, stephencamp@letu.edu
 */

ipsolve_r ipsolve(matrix* L, double* B, double* f, short int *IntList, double *ub, double *lb, short int *ctype);
/* ipsolve - Interface to the Mixed Integer Program Solver LP_SOLVE
Original Usage in Matlab:
[res, how] = ipsolve(L, B, f, intlist, ub, lb, ctype)
The function minimizes f'*x subject to Lx >= B and lb <= x <= ub.
x(i) is an integer if intlist(i) is not zero. 
The first two parameters are required. All parameters after that can be given as null pointers to use the default values.
If ctype is given, the inequality constraints are interpreted as follows:
 L(i,:)x <= B(i) for ctype(i) = -1
 L(i,:)x  = B(i) for ctype(i) =  0
 L(i,:)x >= B(i) for ctype(i) =  1
 
The function returns in res the optimal solution, and in how the 
termination type ('ok', 'not solved', 'unbounded', 'infeasible'). 
When the problem is infeasible or not solved, res is an empty 
vector. When the problem is unbounded, res is a feasible solution.

To find a feasible solution to a set of constraints, use f = [] or
set to 0 all elements of f.
 
Default values: if intlist not given, all variables considered to
be integers; if ub not given, all upper bounds are infinity; if 
lb not given, all lower bounds are 0; if ctype not given, the
constraints are Lx >= B.

Another integer program solver is SOLVE_IP.

Usage in C:
ipsolve_r ipsolve(matrix* L, double* B, double* f, short int *IntList, double *ub, double *lb, short int *ctype)
All parameters have the same meaning as in Matlab. B, f, IntList, ub, and lb are
all pointers that should point to the first element of an array of the appropriate
length or be given as a null pointer.

This interface to the LP_SOLVE package has been 
written by Marian V. Iordache, marianiordache@letu.edu.
It was converted to C by Stephen Camp, stephencamp@letu.edu.*/
/*Most complete C syntax (all optional parameters included): ipsolve_r ipsolve(int numberOfArguments, matrix *L, double *B, double *f, short *IntList, double *ub, double *lb, short *ctype)
All parameters after the first three are optional.*/

ipslv_r ipslv(REAL* f, REAL** L, REAL* b, int m, int n, int* intlist, REAL* ub, REAL* lb, int* ctype);
/* This is the interface of ipsolve to LPSOLVE.
m: the number of rows of L; n: the number of columns of L; See ipsolve
for the meaning of the remaining parameters. */
		 
int disq2disj(pns* plant1, matrix *L, matrix* H, pns* plant2, matrix* L_star);
/* disq2disj - Convert Q_Disjunctive Constraints to Disjunctive Constraints
   i.e. Convert from L*m + H*q <=b to L*m <=b
   
   Original Usage in Matlab:
   [Nstar, L_star]=composeNstar(plant, L, H)

   Written for Matlab by Feng Zhu, fzhu@nd.edu
   Converted to C by Po Wu, pwu1@nd.edu */

int disj2normal(pns* plant, matrix *L, int *b, int *LB, int *UB, matrix *Dm, matrix *Dp, matrix *LD, int *CD, int *m1);
/* disj2normal - Convert Disjunctive Constraints to Normal Constraints
   get new Dm Dp LD(from matrix L) CD(from int* b) m1(from int* m0) label0
   with supervisor enforcing
   L*m disjunctively less than or equal to b, 
   which means all rows of L*m <=b are disjunctive constraints.

   Original Usage in Matlab:
   [pn_cl, pn_supervis]=disj_supervis(plant,L,b,LB,UB)
   
   Written for Matlab by Feng Zhu, fzhu@nd.edu
   Converted to C by Po Wu, pwu1@nd.edu */

int disj2pn(pns *bin, matrix* ld, int* cd, matrix* D, matrix* m0m, int* plant_label, matrix* l, int c, int lb, int ub, int bin_current, int bin_total);
/* disj2pn - Convert disjunctive constraints into small PN to compose later

   Written for Matlab by Feng Zhu, fzhu@nd.edu
   Converted to C by Po Wu, pwu1@nd.edu */

int tree2spec(pns* plant1, expression2 *root, char *type, pns* plant2, matrix
*L, int **b);
/* TREE2SPEC - convert the original propositions and plant to 
               the new constraints and plant that can be used in LINENF.
               Depending on the types of propositions, there are 2 types
               of conversion methods. For method 'state', the propositions
               in the expression should have the form [l b lb ub]. For
               method 'dynamic',the propositions in the expression should 
               have the form [l h c lb ub]
   Written by Feng Zhu, fzhu1@nd.edu
   Converted to C by Po Wu, pwu1@nd.edu */


int satisfied_expr(expression2 *expr);
/* Returns 1 if the expression is satisfied at the initial marking. Otherwise,
   it returns 0. Written by Po Wu. Placed in tree2spec.c. The test file is
   test-lintree.c. */


linenf_r linenf(matrix* Dm, matrix* Dp, matrix* L, int* b, int* m0, matrix* F, matrix* C, int TucCount, int* Tuc, int TuoCount, int* Tuo);
/* LINENF - Linear Inequality Enforcement
This function creates the supervisor enforcing 

             L*m + F*q + C*v <= b                                 (1)

where m is the Petri net marking, v is the firing vector and q is a  
vector of the size of the firing vector. The meaning of the inequali-
ties is as follows. Let tj be an enabled transition at the marking m,
m[tj>m', v' the firing vector after firing tj, and q be such that all
its elements are 0 except for q(j) = 1. The transition tj may fire if
the two conditions below are met:
 1) L*m' + C*v' <= b
 2) (1) holds true

The function returns the structure that corresponds to the supervised
Petri net, and the initial marking of the supervised Petri net (ms0),
(the argument m0 specifies the initial marking of the plant Petri net.)
The initial firing vector v0 is assumed to be 0. The Matlab syntax is:

[Df^-, Df^+, ms0] = linenf(pn, L, b, F, C)

The last four arguments of the function are optional. This means that if
an argument is not of interest, it may be set to [] and that the following
forms can also be used:

[Df^-, Df^+, ms0] = linenf(pn, L, b)
[Df^-, Df^+, ms0] = linenf(pn, L, b, F)
[Df^-, Df^+, ms0] = linenf(pn, L, b, F, C)

Alternative formats are:

[Df^-, Df^+, ms0] = linenf(D^-, D^+, L, b, m0, F, C)
[Df^-, Df^+, ms0] = linenf(D^-, D^+, L, b, m0, F, C, Tuc, Tuo)

where D^- and  D^+ specify the incidence matrices and Tuc and Tuo the
uncontrollable and unobservable transitions. For instance, Tuc = [3 4] 
means that t3 and t4 (where the indices correspond to the incidence matrix)
are uncontrollable. 

When presented with uncontrollable and/or unobservable transitions, 
additional outputs are of interest:

[Df^-, Df^+, ms0, how, dhow] = linenf(...)
 
The function first transforms the constraints such that they are admissible, 
and then enforces them; if the transformation succeeded, how = 'ok', else 
how = 'not solved'. dhow{i} stores the status of constraint i: 'ok' or 
'not solved'. 
 
When the initial marking m0 is not given (that is m0 = []/pn.m0 = []), the 
following output format is of interest

[Df^-, Df^+, ms0, how, dhow, Lf, Cf, bf] = linenf(...)

The additional outputs allow to compute the initial marking ms0 of the
supervised system as a function of the marking m0 of the plant:
ms0 = bf - Lf*m0 - Cf*v0

Written by Marian V. Iordache, marianiordache@letu.edu
Converted to C by Stephen Camp, stephencamp@letu.edu*/

int* isadm(matrix* Dm, matrix* Dp, matrix* L, int* b, int* m0, matrix* F, matrix* C, int TucCount, int* Tuc, int TuoCount, int* Tuo);
/*
ISADM - Checks whether a set of constraints is admissible based
on reachability analysis.

A constraint is considered to be admissible if its enforcement
under the assumption that all transitions are controllable and
observable does not attempt to inhibit uncontrollable transitions 
and does not detect unobservable transitions. An admissible cons-
traint must also be satisfied by the initial marking.

In the formats
[v] = isadm(pnobj, L, b)
[v] = isadm(pnobj, L, F, b)
[v] = isadm(pnobj, L, F, C, b)

the coverability graph of the closed-loop is computed to check whether 
 L*m <= b  or
 L*m + F*q <= b  or
 L*m + F*q + C*v <= b  
is admissible; Dm and Dp are the incidence matrices, Tuc and Tuo
are the sets of uncontrollable and unobservable transitions, and m0 
is the initial marking. The return value is a vector such that 
v(i) = 0 if L(i,:)*m <= b(i) is inadmissible, v(i) = 1 if the 
constraint is admissible, and v(i) = -1 if admissibility couldn't be
decided. v(i) = -1 may happen when the controller part of the closed-
loop is unbounded. 

If it is desired to check whether the constraint is admissible for 
all initial markings, set pnobj.m0 = []. The admissibility check in
this case is very fast (no coverability graph is computed.)

When the coverability graph of the plant is available (see PNCGRAPH),
the following formats can be used

[v] = isadm(pnobj, L, b, graph)
[v] = isadm(pnobj, L, F, b, graph)

The disadvantage of using a precomputed plant coverability graph is that
it is more likely to have a v(i) equal to -1.

Usage in C:
linenf_r linenf(matrix* Dm, matrix* Dp, matrix* L, int* b, int* m0, matrix* F, matrix* C, int TucCount, int* Tuc, int TuoCount, int* Tuo)
All parameters have the same names as their counterparts in Matlab. Parameters
in matlab that were vectors are passed in C as array pointers. The variable-length
vectors Tuc and Tuo are given in two parts, an integer (TucCount/TuoCount) specifying
the length of the array followed by a pointer (Tuc/Tuo) to the first element of the
array. The form of the function call making use of a pnobj structure is no longer
valid.

See LINENF and PNCGRAPH.

Written for Matlab by Marian V. Iordache, marianiordach@letu.edu.
Converted to C by Stephen Camp, stephencamp@letu.edu.
*/

nltrans_r nltrans(matrix* D, int* UnraisableTransitions, int urtCount);
/*
NLTRANS - Find all transitions that cannot be made live

Usage in Matlab:
[nlt] = nltrans(D)

[nlt] = nltrans(D^-, D^+, X)

nlt is a vector, nlt(i) = 0 if t_i can be made live.

X is a vector indicating transitions which cannot be made live for 
other reasons. E.g. X = [1, 3, 6] indicates the transitions t_1, t_3
and t_6.

Usage in C:
nltrans_r nltrans(matrix* D, int* UnraisableTransitions, int urtCount)
D is the same as D in Matlab. The function no longer accepts separate D+ and D-
matrices. X in Matlab corresponds to the array pointer UnraisableTransitions.
UnraisableTransitions should be the pointer to the array containing the
transitions to be assumed unraisable, and urtCount should be set to the number
of elements in the array.

Written by Marian V. Iordache, marianiordache@letu.edu.
Converted to C by Stephen Camp, stephencamp@letu.edu
*/

pn2acpn_r pn2acpn(matrix* Dm, matrix* Dp, int* Mask, matrix* MX, matrix* L0, matrix* L, int *ipl, int ipCount, int* dpl, int dpCount);
/*
PN2ACPN - Transforms a Petri net to an asymmetric choice Petri net

Matlab Usage:
[Df, Dmf, Dpf] = pn2acpn(D)

[Df, Dmf, Dpf] = pn2acpn(Dm, Dp)

[Df, Dmf, Dpf] = pn2acpn(Dm, Dp, mask)

[Df, Dmf, Dpf, MF, L0F, LF, iplf] = pn2acpn(Dm, Dp, mask, M, L0, L, ipl, dpl)

mask is an optional argument: mask(i) = 1 if the place i is 
in the set M of the technical report. (M in the tech. report has 
a different meaning than M in the TLE program.)
 
The last four parameters are optional. See TLE code for meaning. 
Their updated values are given as output.

If called before the first iteration, take LF = MF, as the computation 
of LF does not consider this case!

See MSPLIT.

C Usage:
pn2acpn_r pn2acpn(matrix* Dm, matrix* Dp, int* Mask, matrix* MX, matrix* L0, 
matrix* L, int *ipl, int ipCount, int* dpl, int dpCount)
Dm and Dp are the same as in Matlab. The function no longer accepts a single
incidence matrix D. The variable-length vectors ipl and dpl in Matlab should
be passed as a pointer to the integer array followed by the length of the
array.

Written by Marian V. Iordache, marianiordach@letu.edu
M. Iordache -- Sep. 4, 2000
revised on Oct. 24, 2001

Converted to C by Stephen Camp, stephencamp@letu.edu
Stephen Camp -- Jun. 18, 2009
*/

pn2eacpn_r pn2eacpn(matrix* Dm, matrix* Dp, int* Mask, matrix* MX, matrix* L0, matrix* L, int *ipl, int ipCount, int* dpl, int dpCount, int** TD, int* TDCount);
/*
PN2EACPN - Transforms a Petri net to an extended asymmetric choice Petri net

Matlab Usage:
[Df, Dmf, Dpf] = pn2eacpn(D)

[Df, Dmf, Dpf] = pn2eacpn(Dm, Dp)

[Df, Dmf, Dpf] = pn2eacpn(Dm, Dp, mask)

[Df, Dmf, Dpf, MF, L0F, LF, iplf, TDf] = pn2eacpn(Dm, Dp, mask, M, L0, L, ipl, dpl, TD)

mask is an optional argument: mask(i) = 1 if the place i is 
in the set M of the technical report. (M in the tech. report has 
a different meaning than M in the DP program.)
 
The last five parameters are optional. See DP code for meaning. 
Their updated values are given as output. In particular, TD{t} lists  
transitions that cannot be made live when t is dead (including t itself).
TD will typically be an underestimate of the total set. If not given,
TD is computed here (this computation takes time). The output TDf is so
that this computation may not be repeated again in the next iterations.
The use of TD differentiates PN2EACPN from PN2ACPN.

If called before the first iteration, take LF = MF, as the computation 
of LF does not consider this case!

See MSPLIT.

C Usage:
pn2eacpn_r pn2eacpn(matrix* Dm, matrix* Dp, int* Mask, matrix* MX, matrix* L0, 
matrix* L, int *ipl, int ipCount, int* dpl, int dpCount, int** TD, int* TDCount)
Dm and Dp are the same as in Matlab. The function no longer accepts a single
incidence matrix D. The variable-length vectors ipl and dpl in Matlab should
be passed as a pointer to the integer array followed by the length of the
array.


Written for Matlab by Marian V. Iordache
Original Matlab code extended the Matlab pn2acpn code written on
M. Iordache -- Sep. 4, 2000
and revised on Oct. 24, 2001

This is the extension for extended asymmetric choice nets;
M. Iordache, July 2003

Converted to C by Stephen Camp, StephenCamp@letu.edu.
Matlab code was under construction at time of conversion to C.
Stephen Camp, June 2009
*/

chkcons_r chkcons(matrix* L0, int* B0, matrix* l0, int b0);
/*
Matlab Usage:
res = chk_con2(L,B,l,b)

Checks consistency of the set of constraints Lx >= B and lx< b, 
where x should be a nonnegative integer vector. 
'l' is expected to be a 1-D vector.

If the system is consistent, the function returns a feasible 
solution. So 'res' is a nonnegative integer vector x such
that Lx >= B and lx < b. If res is empty, then the constraint 
lx >= b is redundant for Lx >= B.

C Usage:
chkcons_r chkcons(matrix* L0, int* B0, matrix* l0, int b0)
The parameters have the same names and meanings as in Matlab. Either the pair L0
& l0 or the pair B0 and b0 is required. Both pairs can be given. If B0 is a null
pointer, the value of b0 is ignored.

The C implementation of chkcons currently is an implementation of CHK_CON2.M 
from the original Matlab package.

CHK_CON2 is the old version of CHK_CONS. It is expected to be
slower than CHK_CONS. However, CHK_CON2 is simpler, and so it
may be more reliable. 

The C implementation may be changed to implement the newer CHK_CON.M sometime in the future.

Written by Marian V. Iordache, marianiordache@letu.edu.
Converted to C by Stephen Camp, stephencamp@letu.edu.
*/

reduce_r reduce(matrix* L0, int* B0);
/*
Matlab usage:
[Lf, Bf, ind, how] = reduce(L,B)

This function removes redundant constraints of Lx>=B, where x 
is a nonnegative integer vector. 'ind' stores the indices of 
the rows that were kept. The variable how is set to 1 if 
redundant constraints have been found.

See also CHK_CONS, IP_SOLVE.

C Usage:
reduce_r reduce(matrix* L0, int* B0)
L0 and B0 are L and B, respectively, from the Matlab version.

Written for Matlab by Marian V. Iordache, marianiordache@letu.edu.
Converted to C by Stephen Camp, stephencamp@letu.edu.
*/

actn_r actn(matrix* Dm, matrix* Dp, int* X, int XCount, matrix *Dcm, matrix *Dcp, int update, int checkUnique);
/*
ACTN - The active subnet of a Petri net
Matlab usage:
[Dma, Dpa, Dmra, Dpra] = actn(Dm, Dp)

[Dma, Dpa, Dmra, Dpra] = actn(Dm, Dp, X)

This function computes the maximal subnet of the Petri net 
structure which can be made live and does not contain  
transitions in X. In contrast, the function PART only removes  
source places and the transitions thus detected as impossible
to be made live. This is the difference between the active 
subnet produced by ACTN and that of PART. 

For convenience, the outcome is produced as matrices of the 
same size as (Dm, Dp): (Dma, Dpa) and also at reduced size: 
(Dmra, Dpra), where 'm' stands for '-' and 'p' for '+'.

[Dma, Dpa, Dmra, Dpra] = actn(Dm, Dp, X, Dma, Dpa, upd)

In this format ACTN only makes an update, if upd is not zero.
The update is done as follows: the transitions of the active
subnet are found based on the current Dma and Dpa. Then the 
places of the active subnet are found. 

See also NLTRANS. 

C Usage:
actn_r actn(matrix* Dm, matrix* Dp, int* X, int XCount, matrix *Dcm, matrix *Dcp, int update, int checkUnique)
Parameters have the same names as in Matlab with a few exceptions. The variable-length
vector X is passed as the pointer to the integer array (X) followed by the number of
elements in the array (XCount). The additional parameter, checkUnique, should be
nonzero if the user wants to run a uniqueness check. Note that the uniqueness check
is time-consuming. If the check is not run, the value if "unique" in the result
structure will be set to 0 regardless of the actual state of the result.

Written for Matlab by Marian V. Iordache, marianiordache@letu.edu.
Converted to C by Stephen Camp, stephencamp@letu.edu.
*/

tactn_r tactn(matrix* Dm, matrix* Dp, int* IncludeT, int IncludeTCount, int* ExcludeT, int ExcludeTCount, matrix *Dcm, matrix *Dcp, int checkUnique);
/*
TACTN - Computes a T-minimal active subnet of a Petri net

Matlab usage:

[Dma, Dpa, Dmra, Dpra, TA] = tactn(Dm, Dp, T, Z)
[Dma, Dpa, Dmra, Dpra, TA, unique] = tactn(Dm, Dp, T, Z)

This function computes a subnet of the Petri net structure (Dm, Dp), 
such that
(a) the subnet can be made live
(b) it contains the transitions in T and no transitions in Z
(c) there is no other subnet satisfying (a) and (b) and having less 
    transitions.

 -  (Dma, Dpa) and (Dmra, Dpra) are incidence matrix representations
    of the computed subnet.
 -  TA is the set of transitions of the subnet.
 -  unique = 1 if there is a unique subnet satisfying (a), (b) and (c).

When no subnet satisfying (a) and (b) exists, the procedure yields a 
subnet such that
(a) the subnet can be made live
(b) it does not contain the transitions in Z
(c) there is no other subnet satisfying (a) and (b) and having more 
    transitions in T.

 -  unique = 1 if there is a unique subnet satisfying (a), (b) and (c).

The function can be employed to do only an update in the following format

[Dma, Dpa, Dmra, Dpra] = tactn(Dm, Dp, T, Z, Dma, Dpa)

In this format only an update is made: the transitions of the
active subnet are found based only on the former subnet given 
by Dma and Dpa.

For convenience, the outcome is produced as matrices of the 
same size as (Dm, Dp): (Dma, Dpa) and also at reduced size: 
(Dmra, Dpra), where 'm' stands for '-' and 'p' for '+'.

The default values for T and Z are T - the total set of transitions
and Z - empty. Therefore the following simplified formats can be used:

[Dma, Dpa, Dmra, Dpra] = tactn(Dm, Dp)

[Dma, Dpa, Dmra, Dpra] = tactn(Dm, Dp, T)

When only two arguments are used, TACTN is equivalent to ACTN: it 
computes the maximal active subnet.

See also ACTN and NLTRANS. 

C Usage:
tactn_r tactn(matrix* Dm, matrix* Dp, int* IncludeT, int IncludeTCount, int* ExcludeT, int ExcludeTCount, matrix *Dcm, matrix *Dcp, int checkUnique)

Parameters have the same names as in Matlab with a few exceptions. IncludeT and
ExcludeT replace the variable-length vectors T and Z. They should be given as 
the pointer to the integer array (IncludeT or ExcludeT) followed by the number of
elements in the array (IncludeTCount or ExcludeTCount). The additional parameter,
checkUnique, should be nonzero if the user wants to run a uniqueness check. Note 
that the uniqueness check is time-consuming. If the check is not run, the value 
of "unique" in the result structure will be set to 0 regardless of the actual 
state of the result.

Written for Matlab by Marian V. Iordache, marianiordache@letu.edu

Marian V. Iordache, Sep. 5, 2000.
Revised on Oct. 24, 2001, and enhanced in February 2002.

Converted to C by Stephen Camp, stephencamp@letu.edu.
*/

issiph_r issiph(matrix *Dm, matrix *Dp, void *PlaceSet, int MultiplePlaceSets);
/*
IS_SIPH - checks whether a set of places is a siphon

[flag, flx] = is_siph(Dm, Dp, S)

S - a set of places represented as a column of zeros and ones
    S is allowed to be a matrix, in which case each of the columns
    is verified

Dm, Dp - the incidence matrices

flag = (S == siphon)
flx  = sum(flag == 0) (i.e. flx is nonzero if a column of S is not a siphon)

C Usage:
issiph_r issiph(matrix *Dm, matrix *Dp, void *PlaceSet, int MultiplePlaceSets)
The parameter S in Matlab is equivalent to the parameter PlaceSet in C.
If MultiplePlaceSets is nonzero, PlaceSet is interpreted as a pointer to a matrix
formated as described above. Otherwise, PlaceSet is interpreted as a pointer
to an integer array, where each integer is a flag as described above.

Written for Matlab by Marian V. Iordache, marianiordache@letu.edu.
Converted to C by Stephen Camp, stephencamp@letu.edu.
*/

asiph_r asiph(matrix *Dm, matrix *Dp, int* list, int listCount, matrix *PS, matrix *Dma, matrix *Dpa);
/*
ASIPH - find minimal active siphons: direct implementation

[MS, NMS] = asiph(D)

[MS, NMS] = asiph(D^-,D^+,list,PAS, Dma, Dpa)

[MS, NMS] = asiph(D^-,D^+,list,PAS, Dma, Dpa, verb)

'list' is an optional argument that should specify a subset of 
{1, ..., m}, where m is the number of rows of the incidence matrix. 
When 'list is used, only act. siphons that include one or more of the
places from 'list' are returned. This feature allows the program to
run faster. However note that in this case the result is the set of
smallest act. siphons that include the places from the list; this includes
the set of minimal act. siphons that contain places from list, but it may 
include other act. siphons as well. Therefore the 3rd argument is useful
when it is known (from theoretical considerations) that all returned 
act. siphons are minimal. This is the case in SDP. If list = [], the
program sets it to the default value list = 1:m.

The columns of PAS are already known active siphons. Dma and Dpa are
the incidence matrices of the active subnet.

When Dma and Dpa are omitted, the maximal active subnet is assumed.

MS is the updated PAS, and NMS the new minimal active siphons. 

verb (default is 1) stands for verbosity. If verb = 1, the program will
display some information about its progress.

See also MSIPH, SIPH2, MINSIPH

Written for Matlab by Marian V. Iordache, marianiordache@letu.edu
Converted to C by Stephen Camp, stephencamp@letu.edu

lst feature is not yet fully implemented! (the case when a source place 
appears in the list has not been considered).

C Usage:
Parameters are the same and have the same meanings as in Matlab, except that
PAS in the Matlab version is PS in the C version. list is passed as a pointer
to an integer array containing the indices in the list followed by a single
integer, listCount, that should be set to the length of the list.
*/

/*These are the parameters for a call to admcon.*/
typedef struct admcon_p
{
	/*The place flag array indicating which places are part of the siphon.*/
	int* siphon;	
	/*The input and output matrices of the Petri net as well as the incidence
	matrix of the target petri net.*/
	matrix Dm, Dp, DI;
	/*The lists of indendent, dependent, original places, and active places.*/
	int *ipl, *dpl, *opl, *apl;
	int ipCount, dpCount, opCount, apCount;
	/*The list of transitions that resulted from the transition split.*/
	int *ntr;
	int ntCount;
	/*The transformation matrix fron independent to dependent marking.*/
	matrix M;
	/*The lists of unobservable and uncontrollable transitions.*/
	int *Tuc, *Tuo;
	int TucCount, TuoCount;
	int skipParamCheck;
} admcon_p;

admcon_r admcon(admcon_p *params);
/*ADMCON - A procedure to find admissible constraints for siphon control

[a, how] = admcon(s_list, Dm, Dp, ipl, dpl, opl, apl, ntr, M, Tuc, Tuo, Di)

s_list: s_list(i) = 1 if place i is in the siphon, else 0. (Place i 
has the index i in the incidence matrix D.)

Dm and Dp: the input and output incidence matrices of the Petri net
(places -> rows and transitions -> columns.)

ipl, dpl, opl: the set of independent, dependent and original places.

apl: the set of places of the active subnet.

ntr: the set of new transitions (those resulted through transition split).

M: the matrix expressing the marking of dpl in terms of that of ipl.

Tuc, Tuo: the sets of the uncontrollable and unobservable transitions
of the original (target) Petri net. 

Di: the incidence matrix of the target Petri net; Tuc, Tuo are specified
with respect to Di.

For unspecified arguments, use the empty array [].

a - is a vector such that a'*m >= 1 is admissible.
 
how - is set to 0 if no admissible constraint could be found.

Written for Matlab by Marian V. Iordache, marianiordache@letu.edu.
Converted to C by Stephen Camp, stephencamp@letu.edu.

C Usage:
The admcon function takes a pointer to a structure of type admcon_p, which
contains parts for all the parameters required by admcon, followed by one
additional parameter, skipParamCheck. If skipParamCheck is nonzero, admcon will
endeavor to speed its operations slightly by skipping the parameter check
routines. Note that the calling routine must take responsibility for properly
formatting all parameters.

The parameters have the same names and meanings except for Matlab s_list, which
is equivalent to C siphon.
siphon should point to an array of integers, one for each place in Dm/Dp.
Dm, Dp, and DI have the same usage and meaning in C and Matlab.
The lists of indices ipl, dpl, opl, apl, ntr, Tuc, and Tuo should be given as
pointers to arrays of integers. For each array, there is also a count variable,
which should be set to the length of the array. No arrays should contain
duplicate elements or indices to transitions.

Dm, Dp, DI, and at least one of Tuc or Tuo is required.
If the dependent and independent place lists are present, their counts must sum
to the total number of places represented by Dm/Dp. Further, if M is present, its
size must be appropriate (same number of rows as there are dependent places, same
number of columns as there are independent places).*/

char* avpr(void *vector, int length, int mode, char* chr, int option);
/*
AVPR - Transforms a vector in a string to be used for displaying
equations/inequalities.

[str] = avpr(x)

Use the format below to specify the variable name in var (default name 
is 'm'). 

[str] = avpr(x,var)

Use the format below to generate a tex description with indices

[str] = avpr(x,var,1)

Written for Matlab by Marian V. Iordache, marianiordache@letu.edu.
Converted to C by Stephen Camp, stephencamp@letu.edu.

C Usage: Parameters have the same meaning and names as in Matlab.
If chr is a null pointer it will default to m, as in Matlab.
Use mode = DISPLAY_MATRIX for vector a pointer to a matrix. length is ignored.
Use mode = DISPLAY_INTS for vector a pointer to an array of integers.
Or the DISPLAY_OFFSET flag with the DISPLAY_MATRIX or DISPLAY_INTS to build a
string that displays vector indices as if they began at 1 rather than zero. This
will produce the same output as Matlab.
The function returns a pointer to a static buffer that it owns. This buffer is
overwritten every time the function is called. The caller should use or copy the
buffer immediately after calling the function.*/

char* fvpr(void* vector, int length, int mode, int option);
/*FVPR - Transforms a vector in a string

[str] = fvpr(x)

Use the format below to print finite sets

[str] = fvpr(x,2)

Written for Matlab by Marian V. Iordache, marianiordache@letu.edu.
Converted to C by Stephen Camp, stephencamp@letu.edu.
C Usage: Parameters have the same meaning and names as in Matlab.
Use mode = DISPLAY_MATRIX for vector a pointer to a matrix. length is ignored.
Use mode = DISPLAY_INTS for vector a pointer to an array of integers.
Or the DISPLAY_OFFSET flag with the DISPLAY_MATRIX or DISPLAY_INTS to add 1 to
each value before displaying it. When fvpr is used to display vectors
containing lists of indices, this will effectively shift all the indices up
by one, displaying them as if they began at 1 rather than at 0. This will generate the same output as Matlab when used in these circumstances.
The function returns a pointer to a static buffer that it owns. This buffer is
overwritten every time the function is called. The caller should use or copy the
buffer immediately after calling the function.*/

typedef struct dp_p
{
	/*Dm and Dp are the incidence matrices of the Petri net.*/
	matrix Dm; 
	matrix Dp;
	
	/*Tuc/Tuo and their counts are the lists of uncontrollable and unobservable
	transitions.*/
	int *Tuc, *Tuo; 
	int TucCount, TuoCount;
	
	/*IncludeT and ExcludeT and their counts are the lists of transitions to 
	include and exclude	in and from T-liveness enforcement.*/
	int *IncludeT, *ExcludeT;
	int IncludeCount, ExcludeCount;	
	
	/*The marking constraints and initial marking constraints.*/
	int *B, *B0;
	matrix L, L0;
	
	int option;
} dp_p;

dp_r dp(dp_p* params);

/*
Matlab Usage:
DP - Create a Petri net supervisor for deadlock prevention

By selecting the appropriate option, this function generates a supervisor for
 - global-deadlock prevention (default option)
 - liveness enforcement
 - T-liveness enforcement
 
The format is as follows:

[L, b, L0, b0, how] = dp(pn, T, L, B, L0, B0, opt)

where the simpler formats

[L, b, L0, b0, how] = dp(pn)
[L, b, L0, b0, how] = dp(pn, T)
[L, b, L0, b0, how] = dp(pn, T, L, B)
[L, b, L0, b0, how] = dp(pn, T, L, B, L0, B0)

can also be used. pn is a Petri net object generated with GETPN. T is
the set of transitions to be made live in the case of T-liveness enforcement.
By default T equals the total set of transitions. L and B specify marking 
constraints already enforced. L0 and B0 specify initial-marking constraints. 
opt represents the options input:
opt = 8*l+4*k+2*i+j, where j = (0)/1 turns (OFF)/ON displaying 
messages (default is 1); k = (0)/1 turns (OFF)/ON printing log files 
(default is ON); l = 0(1) for deadlock prevention/((T-)liveness enforcement).

The output are (admissible) constraints that are to be enforced on 
the marking vector. For all initial marking vectors Mo such
that L*Mo >= b and L0*Mo >= b0, the Petri net supervised
with the constraints (L,b) (see LINENF) is live. 

'how' is set to 'impossible' if deadlock cannot be avoided
in the given Petri net. Otherwise 'how' is set to 'ok'.

Other formats are:

[L, b, L0, b0, how] = dp(D)
[L, b, L0, b0, how] = dp(D^-, D^+)
[L, b, L0, b0, how] = dp(D^-, D^+, Tuc, Tuo)
[L, b, L0, b0, how] = dp(D^-, D^+, Tuc, Tuo, T)
[L, b, L0, b0, how] = dp(D^-, D^+, Tuc, Tuo, T, L, B)
[L, b, L0, b0, how] = dp(D^-, D^+, Tuc, Tuo, T, L, B, L0, B0)
[L, b, L0, b0, how] = dp(D^-, D^+, Tuc, Tuo, T, L, b, L0, b0, opt)

The input are the incidence matrices of the Petri net that 
is to be supervised; rows correspond to places and columns
to transitions. The optional arguments Tuc and Tuo list the 
uncontrollable and unobservable transitions, specified by 
their column number in the incidence matrix. 

Written for Matlab by Marian V. Iordache, marianiordache@letu.edu
Converted to C by Stephen Camp, stephencamp@letu.edu

Marian V. Iordache, March 1999

Revised on September 2000 and January 2002.
Converted to C in July 2009.

Other changes:

On July 1, 2002: corrected the problem causing dp to write incomplete
                 data in the log file dp.dat.
On July 2, 2003: replaced the transformation to AC nets by transformation 
                 to EAC-nets
								 
C Usage: The C version of Dp takes a pointer to a structure of type dp_p,
containing all the same parameters that were passed to the original Matlab
implementation.
Arrays of indices, such as Tuc and Tuo, should be provided by setting the
pointers in the structure to point to integer arrays containing the indices
and setting the corresponding count integers to the length of the index lists.
*/

int gcdv(matrix *m, int row, int column);
/*
GCDV  greatest common divisor of a vector/matrix. Uses GCD.

Written by Marian V. Iordache

C Usage:
If m is a null pointer, the function returns the gcd of the row and column
numbers. Otherwise:
If row is nonnegative the function returns the gcd of the given row, ignoring 
the column number.
If row is negative but column is positive, the function returns the gcd of the
given column, ignoring the row number.
If both row and column are negative, the function returns the gcd of every
element in the matrix.
If both row and column are positive the function fails with an error.*/

matrix invar(matrix* A);
/*
INVAR - Positive invariant computation.

INVAR(A) returns a matrix whose columns give the minimal support positive
invariants of a matrix A, i.e., it returns a basis for the solutions to
Ax = 0, x >= 0.

The matlab version of INVAR is a modification of INVAR1. INVAR works with 
integers only! In Matlab, INVAR1 is called if A is not an integer matrix.

The solution is based on an algorithm by Martinez and Silva.

In Matlab, INVAR is a slight modification of INVAR1; INVAR1 has been written by 
John O. Moody.


C Usage:
INVAR1 has not been implemented in C. INVAR takes a pointer to a matrix as its
only parameter and returns the solution matrix. Since the pntool matrix type
does not support non-integer matrices, nothing has been implemented to deal with
them.
Converted to C by Stephen Camp, stephencamp@letu.edu.
*/

#endif
