#include <ccv.h>
#include <nnc/ccv_nnc.h>
#include <nnc/ccv_nnc_easy.h>
#include <sys/time.h>
#include <ctype.h>
int main(int argc, char** argv)
{
ccv_nnc_init();
ccv_nnc_symbolic_graph_t* graph = ccv_nnc_symbolic_graph_new();
// Input tensor
ccv_nnc_tensor_symbol_t a = ccv_nnc_tensor_symbol_new(graph, ONE_CPU_TENSOR(223, 223, 3), "a");
ccv_nnc_tensor_t* tensor_a = ccv_nnc_tensor_new(0, ONE_CPU_TENSOR(223, 223, 3), 0);
// conv1
ccv_nnc_tensor_symbol_t conv1w = ccv_nnc_tensor_symbol_new(graph, ONE_CPU_TENSOR(64, 7, 7, 3), "conv1w");
ccv_nnc_tensor_symbol_t conv1b = ccv_nnc_tensor_symbol_new(graph, ONE_CPU_TENSOR(64), "conv1b");
ccv_nnc_tensor_symbol_t b[9];
b[0] = ccv_nnc_tensor_symbol_new(graph, ccv_nnc_tensor_auto, "b0");
ccv_nnc_graph_exec_symbol_t conv1 = ccv_nnc_graph_exec_symbol_new(graph, CMD_CONVOLUTION_FORWARD(64, 7, 7, 3), TENSOR_SYMBOL_LIST(a, conv1w, conv1b), TENSOR_SYMBOL_LIST(b[0]), "conv1");
ccv_nnc_graph_exec_symbol_set_hint(graph, conv1, HINT((2, 2), (3, 3)));
// max1
b[1] = ccv_nnc_tensor_symbol_new(graph, ccv_nnc_tensor_auto, "b1");
ccv_nnc_graph_exec_symbol_t max1 = ccv_nnc_graph_exec_symbol_new(graph, ccv_nnc_cmd(CCV_NNC_MAX_POOL_FORWARD, 0, CMD_GENERIC(2, 2, 64), 0), TENSOR_SYMBOL_LIST(b[0]), TENSOR_SYMBOL_LIST(b[1]), "max1");
ccv_nnc_graph_exec_symbol_set_hint(graph, max1, HINT((2, 2)));
ccv_nnc_graph_exec_symbol_concat(graph, conv1, max1);
b[2] = ccv_nnc_tensor_symbol_new(graph, ccv_nnc_tensor_auto, "b2");
ccv_nnc_graph_exec_symbol_t relu1 = ccv_nnc_graph_exec_symbol_new(graph, ccv_nnc_cmd(CCV_NNC_RELU_FORWARD, 0, ccv_nnc_cmd_auto, 0), TENSOR_SYMBOL_LIST(b[1]), TENSOR_SYMBOL_LIST(b[2]), "relu1");
ccv_nnc_graph_exec_symbol_concat(graph, max1, relu1);
// conv2(x3)
b[3] = ccv_nnc_tensor_symbol_new(graph, ccv_nnc_tensor_auto, "b3");
ccv_nnc_tensor_symbol_t conv2w[3];
conv2w[0] = ccv_nnc_tensor_symbol_new(graph, ONE_CPU_TENSOR(64, 3, 3, 64), "conv2w");
ccv_nnc_tensor_symbol_t conv2b[3];
conv2b[0] = ccv_nnc_tensor_symbol_new(graph, ONE_CPU_TENSOR(64), "conv2b");
ccv_nnc_graph_exec_symbol_t conv2[3];
conv2[0] = ccv_nnc_graph_exec_symbol_new(graph, CMD_CONVOLUTION_FORWARD(64, 3, 3, 64), TENSOR_SYMBOL_LIST(b[2], conv2w[0], conv2b[0]), TENSOR_SYMBOL_LIST(b[3]), "conv2");
ccv_nnc_graph_exec_symbol_concat(graph, relu1, conv2[0]);
ccv_nnc_graph_exec_symbol_t relu2[3];
b[4] = ccv_nnc_tensor_symbol_new(graph, ccv_nnc_tensor_auto, "b4");
relu2[0] = ccv_nnc_graph_exec_symbol_new(graph, ccv_nnc_cmd(CCV_NNC_RELU_FORWARD, 0, ccv_nnc_cmd_auto, 0), TENSOR_SYMBOL_LIST(b[3]), TENSOR_SYMBOL_LIST(b[4]), "relu2");
ccv_nnc_graph_exec_symbol_concat(graph, conv2[0], relu2[0]);
int i;
for (i = 1; i < 3; i++)
{
b[3 + i * 2] = ccv_nnc_tensor_symbol_new(graph, ccv_nnc_tensor_auto, "bn");
conv2w[i] = ccv_nnc_tensor_symbol_new(graph, ONE_CPU_TENSOR(64, 3, 3, 64), "conv2wn");
conv2b[i] = ccv_nnc_tensor_symbol_new(graph, ONE_CPU_TENSOR(64), "conv2bn");
conv2[i] = ccv_nnc_graph_exec_symbol_new(graph, CMD_CONVOLUTION_FORWARD(64, 3, 3, 64), TENSOR_SYMBOL_LIST(b[2 + i * 2], conv2w[i], conv2b[i]), TENSOR_SYMBOL_LIST(b[3 + i * 2]), "conv2n");
ccv_nnc_graph_exec_symbol_concat(graph, relu2[i - 1], conv2[i]);
b[4 + i * 2] = ccv_nnc_tensor_symbol_new(graph, ccv_nnc_tensor_auto, "bn");
relu2[i] = ccv_nnc_graph_exec_symbol_new(graph, ccv_nnc_cmd(CCV_NNC_RELU_FORWARD, 0, ccv_nnc_cmd_auto, 0), TENSOR_SYMBOL_LIST(b[3 + i * 2]), TENSOR_SYMBOL_LIST(b[4 + i * 2]), "relu2n");
ccv_nnc_graph_exec_symbol_concat(graph, conv2[i], relu2[i]);
}
/*
ccv_nnc_graph_t* run_graph = 0;
ccv_nnc_tensor_arena_t* tensor_arena = 0;
ccv_nnc_graph_exec_arena_t* graph_exec_arena = 0;
ccv_nnc_symbolic_graph_compile(graph, TENSOR_SYMBOL_LIST(a), TENSOR_LIST(tensor_a), GRAPH_EXEC_SYMBOL_LIST(conv1), GRAPH_EXEC_SYMBOL_LIST(relu2[2]), &run_graph, &tensor_arena, &graph_exec_arena);
ccv_nnc_graph_free(run_graph);
ccv_nnc_tensor_arena_free(tensor_arena);
ccv_nnc_graph_exec_arena_free(graph_exec_arena);
*/
ccv_nnc_symbolic_graph_backward(graph, GRAPH_EXEC_SYMBOL_LIST(conv1), GRAPH_EXEC_SYMBOL_LIST(relu2[2]), TENSOR_SYMBOL_LIST(b[8]), TENSOR_SYMBOL_LIST(conv1w));
ccv_nnc_symbolic_graph_free(graph);
ccv_nnc_tensor_free(tensor_a);
return 0;
}