diff --git a/quad/computation_graph/src/computation_graph.c b/quad/computation_graph/src/computation_graph.c
index ad122600a051f8649f8cbbbee3e6eab9e728422e..91e778d2592972e436cada267379850a84d15392 100644
--- a/quad/computation_graph/src/computation_graph.c
+++ b/quad/computation_graph/src/computation_graph.c
@@ -1,157 +1,211 @@
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include "computation_graph.h"
-
-#define GRAPH_MAX_DEPTH 20
-#define GRAPH_MAX_INPUTS 20
-
-// Array to store input values for passing to the execute function of each node
-static double exec_input_vals[GRAPH_MAX_INPUTS];
-
-struct computation_graph *create_graph() {
-    struct computation_graph *the_graph = malloc(sizeof(struct computation_graph));
-    the_graph->nodes = malloc(sizeof(struct graph_node));
-    the_graph->n_nodes = 0;
-    the_graph->size = 1;
-    return the_graph;
-}
-
-void reset_node(int node_id) {
-
-}
-
-int graph_set_source(struct computation_graph *graph,
-                     int dest_cntl_id, int dest_input, int src_cntl_id, int src_output) {
-    if (dest_cntl_id >= graph->n_nodes || src_cntl_id >= graph->n_nodes) {
-        return -1;
-    }
-    struct graph_node *dest_node = &graph->nodes[dest_cntl_id];
-    struct graph_node *src_node = &graph->nodes[src_cntl_id];
-    if (dest_input >= dest_node->type->n_inputs || src_output >= src_node->type->n_outputs) {
-        return -1;
-    }
-
-    dest_node->input_srcs[dest_input].controller_id = src_cntl_id;
-    dest_node->input_srcs[dest_input].controller_output = src_output;
-    reset_node(src_cntl_id);
-    return 0;
-}
-
-int graph_add_node(struct computation_graph *graph,
-                   const char* name,
-                   const struct graph_node_type *type,
-                   void *state) {
-    assert(type->n_inputs <= GRAPH_MAX_INPUTS);
-    int new_id = graph->n_nodes;
-    if (new_id >= graph->size) {
-        int new_capacity = graph->n_nodes == 0 ? 1 : graph->n_nodes * 2;
-        struct graph_node *node_arr = realloc(graph->nodes, sizeof(struct graph_node) * new_capacity);
-        if (!node_arr) {
-            return -1;
-        }
-        graph->size = new_capacity;
-        graph->nodes = node_arr;
-    }
-    struct graph_node *new_node = &graph->nodes[new_id];
-    new_node->name = strdup(name);
-    new_node->type = type;
-    new_node->output_values = malloc(type->n_outputs * sizeof(double));
-    new_node->param_values = malloc(type->n_params * sizeof(double));
-    new_node->state = state;
-    new_node->input_srcs = malloc(type->n_inputs * sizeof(struct input_type));
-    int i;
-    for (i = 0; i < type->n_inputs; i++) {
-        new_node->input_srcs[i].controller_id = -1;
-    }
-    graph->n_nodes += 1;
-    return new_id;
-}
-
-int graph_set_param_val(struct computation_graph *graph, int node_id, int param_id, double value) {
-    if (node_id >= graph->n_nodes || param_id >= graph->nodes[node_id].type->n_params) {
-        return -1;
-    }
-    graph->nodes[node_id].param_values[param_id] = value;
-    return 0;
-}
-
-double graph_get_output(const struct computation_graph *graph, int node_id, int output_id) {
-    if (node_id >= graph->n_nodes || output_id >= graph->nodes[node_id].type->n_outputs) {
-        return -1;
-    }
-    return graph->nodes[node_id].output_values[output_id];
-}
-
-void graph_compute_node_rec(struct computation_graph *graph, int node_id, int depth) {
-    if (depth >= GRAPH_MAX_DEPTH) {
-        assert(1 == 0); // TODO :Xil_Assert false
-        return;
-    }
-    if (node_id >= graph->n_nodes) {
-        return;
-    }
-    // TODO: Fix self-reference loop
-    struct graph_node *node = &graph->nodes[node_id];
-    if (node->processed_state == PROCESSED) {
-        return;
-    }
-    int input_id;
-    for (input_id = 0; input_id < node->type->n_inputs; input_id++) {
-        int src_cntl_id = node->input_srcs[input_id].controller_id;
-        if (src_cntl_id != -1) {
-            if (graph->nodes[src_cntl_id].processed_state == UNPROCESSED) {
-                graph_compute_node_rec(graph, src_cntl_id, depth + 1);
-            }
-        }
-    }
-    // Populate the exec_input_vals array for computation
-    for (input_id = 0; input_id < node->type->n_inputs; input_id++) {
-        int src_cntl_id = node->input_srcs[input_id].controller_id;
-        int src_output_id = node->input_srcs[input_id].controller_output;
-        exec_input_vals[input_id] = graph->nodes[src_cntl_id].output_values[src_output_id];
-    }
-    (*node->type->execute)(node->state, node->param_values, exec_input_vals, node->output_values);
-    node->processed_state = PROCESSED;
-}
-
-void graph_compute_node(struct computation_graph *graph, int node_id) {
-    int i;
-    for (i = 0; i < graph->n_nodes; i++) {
-        graph->nodes[i].processed_state = UNPROCESSED;
-    }
-    graph_compute_node_rec(graph, node_id, 0);
-}
-
-int export_dot(const struct computation_graph* graph, FILE* of) {
-    fprintf(of, "digraph G {\n"); // Header
-    fprintf(of, "rankdir=\"LR\"\n"); // Horizontal layout
-
-    // Draw all the nodes and their inputs
-    int i;
-    for (i = 0; i < graph->n_nodes; i++) {
-        struct graph_node *node = &graph->nodes[i];
-        // Create node
-        fprintf(of, "\"%s\"[shape=record\nlabel=\"\n", node->name);
-        fprintf(of, "<f0> %s\n", node->name); // Node name is port 0
-        int j;
-        // Create ports for inputs
-        for (j = 0; j < node->type->n_inputs; j++) {
-            fprintf(of, "|<f%d> --\\>%s\n", j+1, node->type->input_names[j]);
-        }
-        // Create ports for parameters
-        for (j = 0; j < node->type->n_params; j++) {
-            fprintf(of, "|<f%d> [%s=%.3f]\n", j+1+node->type->n_inputs, node->type->param_names[j],node->param_values[j]);
-        }
-        fprintf(of, "\"]\n"); // Close label bracket
-        // Make connections from
-        for (j = 0; j < node->type->n_inputs; j++) {
-            struct graph_node* src_node = &graph->nodes[node->input_srcs[j].controller_id];
-            int output_id = node->input_srcs[j].controller_output;
-            const char* output_name = src_node->type->output_names[output_id];
-            fprintf(of, "\"%s\" -> \"%s\":f%d [label=\"%s=%.3f\"]\n", src_node->name, node->name, j+1, output_name, src_node->output_values[output_id]);
-        }
-    }
-    fprintf(of, "}"); // Close graph
-    return 0;
-}
\ No newline at end of file
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "computation_graph.h"
+
+#define GRAPH_MAX_DEPTH 20
+#define GRAPH_MAX_INPUTS 20
+
+// Array to store input values for passing to the execute function of each node
+static double exec_input_vals[GRAPH_MAX_INPUTS];
+
+struct computation_graph *create_graph() {
+    struct computation_graph *the_graph = malloc(sizeof(struct computation_graph));
+    if (!the_graph) {return NULL;}
+    the_graph->nodes = malloc(sizeof(struct graph_node));
+    if (!the_graph->nodes) { return NULL; }
+    the_graph->n_nodes = 0;
+    the_graph->size = 1;
+    return the_graph;
+}
+
+static void reset_node_rec(struct computation_graph* graph, int node_id, int depth) {
+    if (depth > GRAPH_MAX_DEPTH) {
+        return;
+    }
+    struct graph_node* node = &graph->nodes[node_id];
+    // Don't reset nodes that are already connected to something else
+    // Don't reset nodes that have already been reset or discovered
+    if (node->n_children != 1 || node->processed_state != UNPROCESSED) {
+        return;
+    }
+    node->processed_state = DISCOVERED;
+    int input_id;
+    for (input_id = 0; input_id < node->type->n_inputs; input_id++) {
+        int src_node_id = node->input_srcs[input_id].controller_id;
+        if (src_node_id != -1) {
+            reset_node_rec(graph, src_node_id, depth + 1);
+        }
+    }
+    // Reset this node
+    if (node->type->reset != NULL) {
+        node->type->reset(node->state);
+    }
+    node->processed_state = PROCESSED;
+}
+
+int reset_node(struct computation_graph* graph, int node_id) {
+    if (node_id >= graph->n_nodes) {
+        return -1;
+    }
+    int i;
+    for (i = 0; i < graph->n_nodes; i++) {
+        graph->nodes[i].processed_state = UNPROCESSED;
+    }
+    reset_node_rec(graph, node_id, 0);
+    return 0;
+}
+
+int graph_set_source(struct computation_graph *graph,
+                     int dest_node_id, int dest_input, int src_node_id, int src_output) {
+    if (dest_node_id >= graph->n_nodes || src_node_id >= graph->n_nodes) {
+        return -1;
+    }
+    struct graph_node *dest_node = &graph->nodes[dest_node_id];
+    struct graph_node *src_node = &graph->nodes[src_node_id];
+    if (dest_input >= dest_node->type->n_inputs || src_output >= src_node->type->n_outputs) {
+        return -1;
+    }
+
+    // If a previous source exists, remove one from its children count
+    int prev_src_id = dest_node->input_srcs[dest_input].controller_id;
+    if (prev_src_id != -1) {
+        graph->nodes[prev_src_id].n_children -= 1;
+    }
+    src_node->n_children += 1; // Count destination node as a child
+    dest_node->input_srcs[dest_input].controller_id = src_node_id;
+    dest_node->input_srcs[dest_input].controller_output = src_output;
+    reset_node(graph, src_node_id);
+    return 0;
+}
+
+int graph_add_node(struct computation_graph *graph,
+                   const char* name,
+                   const struct graph_node_type *type,
+                   void *state) {
+    assert(type->n_inputs <= GRAPH_MAX_INPUTS);
+    int new_id = graph->n_nodes;
+    if (new_id >= graph->size) {
+        int new_capacity = graph->n_nodes == 0 ? 1 : graph->n_nodes * 2;
+        struct graph_node *node_arr = realloc(graph->nodes, sizeof(struct graph_node) * new_capacity);
+        if (!node_arr) {
+            return -1;
+        }
+        graph->size = new_capacity;
+        graph->nodes = node_arr;
+    }
+    struct graph_node *new_node = &graph->nodes[new_id];
+    new_node->name = strdup(name);
+    new_node->type = type;
+    new_node->state = state;
+    new_node->n_children = 0;
+    new_node->output_values = malloc(type->n_outputs * sizeof(double));
+    new_node->param_values = malloc(type->n_params * sizeof(double));
+    new_node->input_srcs = malloc(type->n_inputs * sizeof(struct input_type));
+    // Check that malloc succeeded in every case which memory was requested
+    if ((type->n_outputs && !new_node->output_values) ||
+        (type->n_params && !new_node->param_values) ||
+        (type->n_inputs && !new_node->input_srcs)) {
+        return -1;
+    }
+    int i;
+    for (i = 0; i < type->n_inputs; i++) {
+        new_node->input_srcs[i].controller_id = -1;
+    }
+    graph->n_nodes += 1;
+    // Reset block upon creation
+    if (new_node->type->reset != NULL) {
+        new_node->type->reset(new_node->state);
+    }
+    return new_id;
+}
+
+int graph_set_param_val(struct computation_graph *graph, int node_id, int param_id, double value) {
+    if (node_id >= graph->n_nodes || param_id >= graph->nodes[node_id].type->n_params) {
+        return -1;
+    }
+    graph->nodes[node_id].param_values[param_id] = value;
+    return 0;
+}
+
+double graph_get_output(const struct computation_graph *graph, int node_id, int output_id) {
+    if (node_id >= graph->n_nodes || output_id >= graph->nodes[node_id].type->n_outputs) {
+        return 0;
+    }
+    return graph->nodes[node_id].output_values[output_id];
+}
+
+void graph_compute_node_rec(struct computation_graph *graph, int node_id, int depth) {
+    if (depth >= GRAPH_MAX_DEPTH) {
+        assert(1 == 0); // TODO :Xil_Assert false
+        return;
+    }
+    if (node_id >= graph->n_nodes) {
+        return;
+    }
+    struct graph_node *node = &graph->nodes[node_id];
+    if (node->processed_state != UNPROCESSED) {
+        return;
+    }
+    node->processed_state = DISCOVERED;
+    int input_id;
+    for (input_id = 0; input_id < node->type->n_inputs; input_id++) {
+        int src_cntl_id = node->input_srcs[input_id].controller_id;
+        if (src_cntl_id != -1) {
+            graph_compute_node_rec(graph, src_cntl_id, depth + 1);
+        }
+    }
+    // Populate the exec_input_vals array for computation
+    for (input_id = 0; input_id < node->type->n_inputs; input_id++) {
+        int src_cntl_id = node->input_srcs[input_id].controller_id;
+        int src_output_id = node->input_srcs[input_id].controller_output;
+        if (src_cntl_id != -1) {
+            exec_input_vals[input_id] = graph->nodes[src_cntl_id].output_values[src_output_id];
+        }
+    }
+    if (node->type->execute != NULL) {
+        (*node->type->execute)(node->state, node->param_values, exec_input_vals, node->output_values);
+    }
+    node->processed_state = PROCESSED;
+}
+
+void graph_compute_node(struct computation_graph *graph, int node_id) {
+    int i;
+    for (i = 0; i < graph->n_nodes; i++) {
+        graph->nodes[i].processed_state = UNPROCESSED;
+    }
+    graph_compute_node_rec(graph, node_id, 0);
+}
+
+int export_dot(const struct computation_graph* graph, FILE* of) {
+    fprintf(of, "digraph G {\n"); // Header
+    fprintf(of, "rankdir=\"LR\"\n"); // Horizontal layout
+
+    // Draw all the nodes and their inputs
+    int i;
+    for (i = 0; i < graph->n_nodes; i++) {
+        struct graph_node *node = &graph->nodes[i];
+        // Create node
+        fprintf(of, "\"%s\"[shape=record\nlabel=\"\n", node->name);
+        fprintf(of, "<f0> %s\n", node->name); // Node name is port 0
+        int j;
+        // Create ports for inputs
+        for (j = 0; j < node->type->n_inputs; j++) {
+            fprintf(of, "|<f%d> --\\>%s\n", j+1, node->type->input_names[j]);
+        }
+        // Create ports for parameters
+        for (j = 0; j < node->type->n_params; j++) {
+            fprintf(of, "|<f%d> [%s=%.3f]\n", j+1+node->type->n_inputs, node->type->param_names[j],node->param_values[j]);
+        }
+        fprintf(of, "\"]\n"); // Close label bracket
+        // Make connections from
+        for (j = 0; j < node->type->n_inputs; j++) {
+            struct graph_node* src_node = &graph->nodes[node->input_srcs[j].controller_id];
+            int output_id = node->input_srcs[j].controller_output;
+            const char* output_name = src_node->type->output_names[output_id];
+            fprintf(of, "\"%s\" -> \"%s\":f%d [label=\"%s=%.3f\"]\n", src_node->name, node->name, j+1, output_name, src_node->output_values[output_id]);
+        }
+    }
+    fprintf(of, "}"); // Close graph
+    return 0;
+}
diff --git a/quad/computation_graph/src/computation_graph.h b/quad/computation_graph/src/computation_graph.h
index 301187cf4ee8b59c5c01f921e856a03e89fb4732..bf30a70c2cdb791e8183314fa55abb61223fe0b5 100644
--- a/quad/computation_graph/src/computation_graph.h
+++ b/quad/computation_graph/src/computation_graph.h
@@ -1,68 +1,103 @@
-#ifndef __COMPUTATION_GRAPH_H__
-#define __COMPUTATION_GRAPH_H__
-
-#include <stdio.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;
-    const char* const* output_names;
-    const char* const* param_names;
-    int n_inputs;
-    int n_outputs;
-    int n_params;
-    execute_node_t execute;
-    reset_node_t reset;
-};
-
-// Declares an instance of a node
-struct graph_node {
-    const char *name;
-    const struct graph_node_type* type;
-    double *output_values;
-    double *param_values;
-    void *state;
-    int processed_state;
-    struct input_type {
-        int controller_id;
-        int controller_output;
-    } *input_srcs;
-};
-
-struct computation_graph *create_graph();
-
-int graph_set_source(struct computation_graph *graph, int dest_cntl, int dest_input, int src_cntl, int src_output);
-
-int graph_add_node(struct computation_graph *graph,
-                   const char *name,
-                   const struct graph_node_type *type,
-                   void *state);
-
-double graph_get_output(const struct computation_graph *graph, int node_id, int output_id);
-
-int graph_set_param_val(struct computation_graph *graph, int node_id, int param_id, double value);
-
-void graph_compute_node(struct computation_graph *graph, int node_id);
-
-int export_dot(const struct computation_graph* graph, FILE* of);
-
-#endif // __COMPUTATION_GRAPH_H__
+#ifndef __COMPUTATION_GRAPH_H__
+#define __COMPUTATION_GRAPH_H__
+
+#include <stdio.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;
+    const char* const* output_names;
+    const char* const* param_names;
+    int n_inputs;
+    int n_outputs;
+    int n_params;
+    execute_node_t execute;
+    reset_node_t reset;
+};
+
+// Declares an instance of a node
+struct graph_node {
+    const char *name;
+    const struct graph_node_type* type;
+    double *output_values;
+    double *param_values;
+    int n_children;
+    void *state;
+    int processed_state;
+    struct input_type {
+        int controller_id;
+        int controller_output;
+    } *input_srcs;
+};
+
+/*
+ * 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);
+
+/*
+ * 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);
+
+/*
+ * Computes the node given by node_id.
+ * To do so, computes all nodes which are ancestors of node_id in topological order, with
+ * the final computation being node_id itself.
+ */
+void graph_compute_node(struct computation_graph *graph, int node_id);
+
+/*
+ * Writes a graphical representation of the given graph to <of> in the DOT language
+ */
+int export_dot(const struct computation_graph* graph, FILE* of);
+
+#endif // __COMPUTATION_GRAPH_H__
diff --git a/quad/computation_graph/src/main.c b/quad/computation_graph/src/main.c
index 025781d9a66f87bb6ac22a996e8b5af9fb384bc9..2f0784f8978e851fb01eff7d42cf4c4fc589da43 100644
--- a/quad/computation_graph/src/main.c
+++ b/quad/computation_graph/src/main.c
@@ -4,34 +4,38 @@
 #include "node_mult.h"
 #include "node_constant.h"
 #include "node_gain.h"
+#include "tests.h"
 
 int main() {
-    struct computation_graph *graph = create_graph();
+//    struct computation_graph *graph = create_graph();
+//
+//    int const1 = graph_add_node_const(graph, "Const 2");
+//    graph_set_param_val(graph, const1, CONST_SET, 2);
+//    int const2 = graph_add_node_const(graph, "Const 1");
+//    graph_set_param_val(graph, const2, CONST_SET, 3);
+//
+//    int add1_id = graph_add_node_add(graph, "Add");
+//    graph_set_source(graph, add1_id, ADD_SUMMAND1, const1, CONST_VAL);
+//    graph_set_source(graph, add1_id, ADD_SUMMAND2, const2, CONST_VAL);
+//
+//    int gain1_id = graph_add_node_gain(graph, "Gain");
+//    graph_set_param_val(graph, gain1_id, GAIN_GAIN, 3);
+//    graph_set_source(graph, gain1_id, GAIN_INPUT, add1_id, ADD_SUM);
+//
+//    int mult1_id = graph_add_node_mult(graph, "Mult");
+//    graph_set_source(graph, mult1_id, MULT_MULTIPLICAND2, gain1_id, GAIN_RESULT);
+//    graph_set_source(graph, mult1_id, MULT_MULTIPLICAND1, const1, CONST_VAL);
+//
+//    graph_compute_node(graph, mult1_id);
 
-    int const1 = graph_add_node_const(graph, "Const 2");
-    graph_set_param_val(graph, const1, CONST_SET, 2);
-    int const2 = graph_add_node_const(graph, "Const 1");
-    graph_set_param_val(graph, const2, CONST_SET, 3);
+//    FILE* dot_fp;
+//    dot_fp = fopen("..\\comp_graph.dot", "w");
+//    export_dot(graph, dot_fp);
+//    fclose(dot_fp);
+//    printf("Sum is %f\n", graph_get_output(graph, mult1_id, GAIN_RESULT));
 
-    int add1_id = graph_add_node_add(graph, "Add");
-    graph_set_source(graph, add1_id, ADD_SUMMAND1, const1, CONST_VAL);
-    graph_set_source(graph, add1_id, ADD_SUMMAND2, const2, CONST_VAL);
-
-    int gain1_id = graph_add_node_gain(graph, "Gain");
-    graph_set_param_val(graph, gain1_id, GAIN_GAIN, 3);
-    graph_set_source(graph, gain1_id, GAIN_INPUT, add1_id, ADD_SUM);
-
-    int mult1_id = graph_add_node_mult(graph, "Mult");
-    graph_set_source(graph, mult1_id, MULT_MULTIPLICAND2, gain1_id, GAIN_RESULT);
-    graph_set_source(graph, mult1_id, MULT_MULTIPLICAND1, const1, CONST_VAL);
-
-    graph_compute_node(graph, mult1_id);
-
-    FILE* dot_fp;
-    dot_fp = fopen("..\\comp_graph.dot", "w");
-    export_dot(graph, dot_fp);
-    fclose(dot_fp);
-    printf("Sum is %f\n", graph_get_output(graph, mult1_id, GAIN_RESULT));
+    int success = graph_run_tests();
+    printf("Success: %s", success == 0 ? "Yes" : "No");
     fflush(stdout);
     return 0;
 }
diff --git a/quad/computation_graph/src/node_accumulator.c b/quad/computation_graph/src/node_accumulator.c
new file mode 100644
index 0000000000000000000000000000000000000000..8556ac8cc50047a5691bdf6282c45a08458fe269
--- /dev/null
+++ b/quad/computation_graph/src/node_accumulator.c
@@ -0,0 +1,39 @@
+#include "node_accumulator.h"
+#include <stdlib.h>
+
+static struct accum_state {
+    double accumulated;
+};
+
+static void accum_nodes(void *state, const double* params, const double *inputs, double *outputs) {
+    struct accum_state* my_state = (struct accum_state*)state;
+    my_state->accumulated += inputs[ACCUM_IN];
+    outputs[ACCUMULATED] = my_state->accumulated;
+}
+
+static void reset(void *state) {
+    ((struct accum_state*)state)->accumulated = 0;
+}
+
+
+static const char* const in_names[2] = {"Accumulator in"};
+static const char* const out_names[1] = {"Accumulated"};
+static const char* const param_names[0] = {};
+const struct graph_node_type node_accum_type = {
+        .input_names = in_names,
+        .output_names = out_names,
+        .param_names = param_names,
+        .n_inputs = 1,
+        .n_outputs = 1,
+        .n_params = 0,
+        .execute = accum_nodes,
+        .reset = reset
+};
+
+int graph_add_node_accum(struct computation_graph *graph, const char* name) {
+    struct accum_state* node_state = malloc(sizeof(struct accum_state));
+    if (sizeof(struct accum_state) && !node_state) {
+        return -1; // malloc failed
+    }
+    return graph_add_node(graph, name, &node_accum_type, node_state);
+}
diff --git a/quad/computation_graph/src/node_accumulator.h b/quad/computation_graph/src/node_accumulator.h
new file mode 100644
index 0000000000000000000000000000000000000000..c9e04db7cb37fa064e841359953dd4e35b902474
--- /dev/null
+++ b/quad/computation_graph/src/node_accumulator.h
@@ -0,0 +1,16 @@
+#ifndef __NODE_ACCUMULATOR_H__
+#define __NODE_ACCUMULATOR_H__
+#include "computation_graph.h"
+
+int graph_add_node_accum(struct computation_graph *graph, const char* name);
+
+const extern struct graph_node_type node_accum_type;
+
+enum graph_node_accum_inputs {
+    ACCUM_IN,
+};
+
+enum graph_node_accum_outputs {
+    ACCUMULATED
+};
+#endif // __NODE_ACCUMULATOR_H__
\ No newline at end of file
diff --git a/quad/computation_graph/src/tests.c b/quad/computation_graph/src/tests.c
new file mode 100644
index 0000000000000000000000000000000000000000..8118914cf89dea3a085ccdd0c939b56f9e1a1307
--- /dev/null
+++ b/quad/computation_graph/src/tests.c
@@ -0,0 +1,143 @@
+//
+// Created by dawehr on 2/9/2017.
+//
+
+#include "tests.h"
+#define GRAPH_TEST_EPS 0.00001
+
+static int nequal(double val1, double val2) {
+    if (fabs(val1 - val2) < GRAPH_TEST_EPS) {
+        return 0;
+    }
+    return -1;
+}
+
+int graph_run_tests() {
+    int success = 0;
+    success |= graph_test_one_add();
+    success |= graph_test_circular_runs();
+    success |= graph_test_circular_resets();
+    success |= graph_test_accumulator();
+    success |= graph_test_single_run();
+    success |= graph_test_reset_rules();
+    success |= graph_test_self_loop();
+    return success;
+}
+
+int graph_test_one_add() {
+    struct computation_graph *graph = create_graph();
+    int block = graph_add_node_add(graph, "Add");
+    int cblock3 = graph_add_node_const(graph, "3");
+    graph_set_param_val(graph, cblock3, CONST_SET, 3);
+    int cblock4 = graph_add_node_const(graph, "4");
+    graph_set_param_val(graph, cblock4, CONST_SET, 4);
+    graph_set_source(graph, block, ADD_SUMMAND1, cblock3, CONST_VAL);
+    graph_set_source(graph, block, ADD_SUMMAND2, cblock4, CONST_VAL);
+    graph_compute_node(graph, block);
+    double result = graph_get_output(graph, block, ADD_SUM);
+    return nequal(result, 7);
+}
+
+
+int graph_test_circular_runs() {
+    struct computation_graph *graph = create_graph();
+    int gain1 = graph_add_node_gain(graph, "gain1");
+    int gain2 = graph_add_node_gain(graph, "gain2");
+    graph_set_source(graph, gain2, GAIN_INPUT, gain1, GAIN_RESULT);
+    graph_set_source(graph, gain1, GAIN_INPUT, gain2, GAIN_RESULT);
+    graph_compute_node(graph, gain2);
+    // If no infinite loop, then success. Value is undefined for circular graphs
+    return 0;
+}
+
+int graph_test_circular_resets() {
+    struct computation_graph *graph = create_graph();
+    int acum1 = graph_add_node_accum(graph, "accumulator1");
+    int acum2 = graph_add_node_accum(graph, "accumulator2");
+    graph_set_source(graph, acum2, ACCUM_IN, acum1, ACCUMULATED);
+    graph_set_source(graph, acum1, ACCUM_IN, acum2, ACCUMULATED);
+    return 0; // Passes if no infinite loop
+}
+
+// Tests the accumulator block, thereby testing reset and state changes
+int graph_test_accumulator() {
+    struct computation_graph *graph = create_graph();
+    int cblock = graph_add_node_const(graph, "const");
+    int acum_b = graph_add_node_accum(graph, "accumulator");
+    graph_set_source(graph, acum_b, ACCUM_IN, cblock, CONST_VAL);
+
+    graph_set_param_val(graph, cblock, CONST_SET, 3);
+    graph_compute_node(graph, acum_b);
+    graph_set_param_val(graph, cblock, CONST_SET, 8);
+    graph_compute_node(graph, acum_b);
+    graph_set_param_val(graph, cblock, CONST_SET, -2);
+    graph_compute_node(graph, acum_b);
+
+    double result = graph_get_output(graph, acum_b, ACCUMULATED);
+    if (nequal(result, 9)) {
+        printf("graph_test_accumulator failed on step 1, equals %f\n", result);
+        return -1;
+    }
+
+    // Test reset on source set
+    int gain_b = graph_add_node_gain(graph, "Gain");
+    graph_set_param_val(graph, gain_b, GAIN_GAIN, 1);
+    graph_set_source(graph, gain_b, GAIN_INPUT, acum_b, ACCUMULATED);
+    graph_compute_node(graph, gain_b);
+    result = graph_get_output(graph, gain_b, GAIN_RESULT);
+    if (nequal(result, -2)) {
+        printf("graph_test_accumulator failed on step 2\n");
+        return -2;
+    }
+    return 0;
+}
+
+// Tests that a block will only execute once per compute,
+// even if its output is connected to multiple inputs
+int graph_test_single_run() {
+    struct computation_graph *graph = create_graph();
+    int acum_b = graph_add_node_accum(graph, "accumulator");
+    int add_block = graph_add_node_add(graph, "Add");
+    int cblock = graph_add_node_const(graph, "const");
+    graph_set_param_val(graph, cblock, CONST_SET, 2);
+
+
+    graph_set_source(graph, acum_b, ACCUM_IN, cblock, CONST_VAL);
+    graph_set_source(graph, add_block, ADD_SUMMAND1, acum_b, ACCUMULATED);
+    graph_set_source(graph, add_block, ADD_SUMMAND2, acum_b, ACCUMULATED);
+
+    graph_compute_node(graph, add_block);
+    double result = graph_get_output(graph, add_block, ADD_SUM);
+    return nequal(result, 4);
+}
+
+// Tests that upon connection of a second child, a block will not reset
+int graph_test_reset_rules() {
+    struct computation_graph *graph = create_graph();
+    int cblock = graph_add_node_const(graph, "5");
+    graph_set_param_val(graph, cblock, CONST_SET, 5);
+    int acum_b = graph_add_node_accum(graph, "accumulator");
+    int gain1 = graph_add_node_gain(graph, "gain1");
+    graph_set_param_val(graph, gain1, GAIN_GAIN, 1);
+
+    graph_set_source(graph, gain1, GAIN_INPUT, acum_b, ACCUMULATED);
+    graph_set_source(graph, acum_b, ACCUM_IN, cblock, CONST_VAL);
+    graph_compute_node(graph, gain1);
+    // state of acum_b is now 5
+
+    int gain2 = graph_add_node_gain(graph, "gain2");
+    graph_set_param_val(graph, gain2, GAIN_GAIN, 1);
+    // Connect gain 2, and accumulator should not get reset
+    graph_set_source(graph, gain2, GAIN_INPUT, acum_b, ACCUMULATED);
+    graph_compute_node(graph, gain2);
+    double result = graph_get_output(graph, gain2, GAIN_RESULT);
+    return nequal(result, 10);
+}
+
+int graph_test_self_loop() {
+    struct computation_graph *graph = create_graph();
+    int gain1 = graph_add_node_gain(graph, "gain1");
+    graph_set_source(graph, gain1, GAIN_INPUT, gain1, GAIN_RESULT);
+    graph_compute_node(graph, gain1);
+    return 0;
+}
\ No newline at end of file
diff --git a/quad/computation_graph/src/tests.h b/quad/computation_graph/src/tests.h
new file mode 100644
index 0000000000000000000000000000000000000000..9452bb525fc8984e927d5de96259588c6718498b
--- /dev/null
+++ b/quad/computation_graph/src/tests.h
@@ -0,0 +1,32 @@
+//
+// Created by dawehr on 2/9/2017.
+//
+
+#ifndef COMPUTATION_GRAPH_TESTS_H
+#define COMPUTATION_GRAPH_TESTS_H
+
+#include "computation_graph.h"
+#include "node_add.h"
+#include "node_mult.h"
+#include "node_constant.h"
+#include "node_gain.h"
+#include "node_accumulator.h"
+#include <math.h>
+
+int graph_run_tests();
+
+int graph_test_one_add();
+
+int graph_test_circular_runs();
+
+int graph_test_circular_resets();
+
+int graph_test_self_loop();
+
+int graph_test_accumulator();
+
+int graph_test_single_run();
+
+int graph_test_reset_rules();
+
+#endif //COMPUTATION_GRAPH_TESTS_H