#ifndef __COMPUTATION_GRAPH_H__ #define __COMPUTATION_GRAPH_H__ #include <stdio.h> #include <math.h> typedef void (*execute_node_t)(void *state, const double* params, const double *inputs, double *outputs); typedef void (*reset_node_t)(void *state); enum node_processed_state { UNPROCESSED, DISCOVERED, PROCESSED }; struct computation_graph { int n_nodes; int size; struct graph_node *nodes; }; // Declares a node type struct graph_node_type { const char* const* input_names; // Array of strings corresponding to the inputs const char* const* output_names; // Array of strings corresponding to the outputs const char* const* param_names; // Array of strings corresponding to the parameters int n_inputs; // Number of inputs int n_outputs; // Number of outputs int n_params; // Number of parameters execute_node_t execute; // Function describing how to produce outputs reset_node_t reset; // Reset this node. Called upon (re)connection size_t state_size; // Size of the state struct for this type int type_id; // A unique ID for this node type }; // Holds a tuple for defining the source of a node. Includes the node ID and its output ID struct node_src { int controller_id; int controller_output; }; // Declares an instance of a node struct graph_node { const char *name; // Name of this node instance const struct graph_node_type* type; // Type of this node double *output_values; // Computed output values double *param_values; // Values of parameters set for this node int n_children; // The number of connected children void *state; // Pointer to the state instance int processed_state; // State of the node with respecct to the graph traversal struct node_src *input_srcs; // Array of tuples indicating the source for each input to this node int updated; // 1 if this node has had an input or parameter change }; /* * Creates an empty computation graph * May return NULL on failure */ struct computation_graph *create_graph(); /* * Defines which node's output gets its value passed into the input of a different node. * Will call reset for each node which was previously orphaned, but is now connected to the graph * dest_node_id: The ID of the node to which the input belongs * dest_input: The ID of the input for node dest_cntl to pass the value into * src_node_id: The node ID where the value is coming from * src_output: The ID of the output on <src_node_id> where the value comes from * Returns 0 for success */ int graph_set_source(struct computation_graph *graph, int dest_node_id, int dest_input, int src_node_id, int src_output); /* * Returns the source node/output pair of a node's input. The mirror of graph_set_source. * Returns a node ID of -1 if the requested node or input does not exist */ struct node_src graph_get_source(struct computation_graph *graph, int node_id, int input_id); /* * Creates a new node with the given data, and adds it to the graph. * Returns a negative integer upon failure. * Otherwise returns a positive integer which is the ID of the new node */ int graph_add_node(struct computation_graph *graph, const char *name, const struct graph_node_type *type, void *state); /* * Returns the value at the output of the requested node for the requested output. * Returns 0 if the given node or output IDs are invalid */ double graph_get_output(const struct computation_graph *graph, int node_id, int output_id); /* * Sets a parameter given by param_id on node node_id to the given value * Returns 0 upon success */ int graph_set_param_val(struct computation_graph *graph, int node_id, int param_id, double value); /* * Returns the value of the param at param_id for the given node * Will return NaN if the given node or parameter IDs are not valid */ double graph_get_param_val(const struct computation_graph *graph, int node_id, int param_id); /* * Computes the nodes given by node_id. * To do so, computes all nodes which are ancestors of each given node_id in topological order, with * the final computation being node_id itself. */ void graph_compute_nodes(struct computation_graph *graph, int* node_ids, int n_nodes); /* * Writes a graphical representation of the given graph to <of> in the DOT language */ int export_dot(const struct computation_graph* graph, FILE* of, int print_outputs); #endif // __COMPUTATION_GRAPH_H__