#include #include #ifndef PNS_H_ #define PNS_H_ /* TYPES */ typedef struct PnsIndexArray { size_t count, size; size_t* indices; } PnsIndexArray; typedef struct PnsNode { PnsIndexArray prev, next; } PnsNode; typedef struct PnsIndexList { size_t index; struct PnsIndexList* next; } PnsIndexList; typedef struct PnsNodeArray { size_t count, size; PnsNode* nodes; PnsIndexList* reusable; } PnsNodeArray; typedef struct PnsNet { PnsNodeArray transitions, places; size_t* initial_token_counts; } PnsNet; typedef struct PnsTransitionView { size_t count; PnsIndexList* transitions; } PnsTransitionView; typedef struct PnsTransitionList { size_t count; PnsIndexList* transitions; } PnsTransitionList; typedef struct PnsFireChanges { PnsTransitionList added, removed; } PnsFireChanges; typedef struct PnsFireInfo { size_t count; PnsIndexList* transitions; } PnsFireInfo; typedef struct PnsFireState { PnsFireInfo active, added, removed; } PnsFireState; typedef struct PnsCountArray { size_t size; size_t* counts; } PnsCountArray; typedef struct PnsState { PnsCountArray tokens, calls; PnsFireState fire, unfire; } PnsState; /* FUNCTIONS */ /** Net **/ /*** Default Operations ***/ /// Initialize `net` void pnsCreateNet(PnsNet* net); /// Make a (deep) copy of `net` void pnsCloneNet(PnsNet* net_clone, const PnsNet* net); /// Load a net into `net` from a u32 array and return if it was successful bool pnsLoadNet(PnsNet* net, size_t count, const uint32_t* values); /// Destroy `net` void pnsDestroyNet(PnsNet* net); /// Calculate the number of required u32 values for serializing size_t pnsNet_serializeSize(const PnsNet* net); /// Serialize `net` into a u32 array void pnsNet_serialize(const PnsNet* net, uint32_t* values); /*** Edit Operations ***/ /**** Core Operations ****/ /// Add a new place to `net` and return its ID size_t pnsNet_addPlace(PnsNet* net); /// Add a new transition to `net` and return its ID size_t pnsNet_addTransition(PnsNet* net); /// Remove place `pid` from `net` void pnsNet_removePlace(PnsNet* net, size_t pid); /// Remove transition `tid` from `net` void pnsNet_removeTransition(PnsNet* net, size_t tid); /// Create a new connection from place `pid` of transition `tid` and return if it was successful bool pnsNet_connectPlaceToTransition(PnsNet* net, size_t pid, size_t tid); /// Create a new connection from transition `tid` to place `pid` and return if it was successful bool pnsNet_connectTransitionToPlace(PnsNet* net, size_t tid, size_t pid); /// Remove the connection from place `pid` to transition `tid` void pnsNet_disconnectPlaceToTransition(PnsNet* net, size_t pid, size_t tid); /// Remove the connection from transition `tid` to place `pid` void pnsNet_disconnectTransitionToPlace(PnsNet* net, size_t tid, size_t pid); /// Increase the initial token count of the place `pid` by `count` size_t pnsNet_addInitialTokens(PnsNet* net, size_t pid, size_t count); /**** Utility Operations ****/ /// Add a new place to `net`, connect it to the specified transitions, and return its ID size_t pnsNet_addConnectedPlace(PnsNet* net, size_t input_count, const size_t* input_tids, size_t output_count, const size_t* output_tids); /// Add a new transition to `net`, connect it to the specified places, and return its ID size_t pnsNet_addConnectedTransition(PnsNet* net, size_t input_count, const size_t* input_pids, size_t output_count, const size_t* output_pids); /// Duplicate a place, sharing all input and output transitions size_t pnsNet_duplicatePlace(PnsNet* net, size_t pid); /// Duplicate a transition, sharing all input and output places size_t pnsNet_duplicateTransition(PnsNet* net, size_t tid); /** State **/ /*** Default Operations ***/ /// Initialize `state` void pnsCreateState(PnsState* state, const PnsNet* net); /// Make a (deep) copy of a `state` (based on the same net) void pnsCloneState(PnsState* state_clone, const PnsState* state, const PnsNet* net); /// Load a new state into `state` from a u32 array and return if it was successful bool pnsLoadState(PnsState* state, const PnsNet* net, size_t count, const uint32_t* values); /// Destroy `state` void pnsDestroyState(PnsState* state); /* Simulation Operations */ /// Get a view of currently available transitions as a linked list /// Using the view after further simulation might lead to undefined behavior PnsTransitionView pnsState_transitions(const PnsState* state); PnsTransitionView pnsState_transitions_backward(const PnsState* state); /// Get lists of newly added and removed transitions as linked lists and reset the cached changes /// Lists must be destroyed manually, either by fully iterating over them or by calling the destructor PnsFireChanges pnsState_changedTransitions(PnsState* state); PnsFireChanges pnsState_changedTransitions_backward(PnsState* state); /// Remove all transition changes /// Caution: Only use after querying the current transitions directly and manually synchronizing your local state void pnsState_cleanChanges(PnsState* state); void pnsState_cleanChanges_backward(PnsState* state); /// Fire the transition /// Caution: Ensure to only call valid transitions /// (queried using the methods transitions or managed yourself using addedTransitions and removedTransitions) void pnsState_fire(PnsState* state, const PnsNet* net, size_t tid); void pnsState_fire_backward(PnsState* state, const PnsNet* net, size_t tid); /*** Refresh Operations ***/ /// Refreshes Petri net state after edits void pnsState_refresh(PnsState* state, const PnsNet* net); /** Transition View **/ /// Get the next value in the `view` and update count and the next element bool pnsTransitionView_next(PnsTransitionView* view, size_t* tid); /** Transition List **/ /// Destroy `list` void pnsDestroyTransitionList(PnsTransitionList* list); /// Get the next value in the `list` and update count and the next element /// Also destroys the next list element bool pnsTransitionList_next(PnsTransitionList* list, size_t* tid); #endif