# Path: src/server.py
# class ParameterServer(object):
#     """
#     A server of variables, consists of slots
#     each slot contains variables of one module, thus
#     each slot can have zero, one or more variables.
#     """
#     
#     def __init__(self):
#         self._slots = list()
#         self._optimizer = None
# 
#     def issue_movingvar_slot(self, shape, momen):
#         slot = MovingVariableSlot(shape, momen)
#         self._slots.append(slot)
#         return slot
# 
#     def issue_var_slot(self, val, trainable):
#         slot = VariableSlot(val, trainable)
#         self._slots.append(slot)
#         return slot
#     
#     def set_optimizer(self, name, *args, **kwargs):
#         optimizer = optimizer_factory(
#             name, *args, **kwargs)
#         self._optimizer = optimizer
# 
#     def apply_optimizer(self):
#         for slot in self._slots:
#             self._optimizer.apply(slot)
#         self._optimizer.finalize_step()
#     
#     def save(self, file_name):
#         with open(file_name, 'wb') as f:
#             pickle.dump(
#                 [self._slots, self._optimizer], f, protocol = -1)
#         
#     def load(self, file_name, *args, **kwargs):
#         with open(file_name, 'rb') as f:
#             slots, self._optimizer = \
#                 pickle.load(f, *args, **kwargs)
#         assert len(slots) == len(self._slots)
#         for i, slot in enumerate(self._slots):
#             slot.load(slots[i])
# 
# Path: src/graph.py
# class DAG(object):
#     def __init__(self):
#         self._node_pool = dict()
#         # key : val = Ptr : Node
# 
#     def register_for_slot(self, name, server, *args):
#         # Step 1, extract dependencies from arguments
#         dep_parsed = parse_for(ptr, *args)
#         dep_list, parameters = dep_parsed
# 
#         # Step 2, Get shapes from dependencies
#         dep_nodes = list()
#         dep_shapes = list()
#         for i in range(len(dep_list)):
#             node = self._node_pool[dep_list[i]]
#             dep_shapes.append(node.out_shape())
#             dep_nodes.append(node)
# 
#         # Step 3, Create module, wrap by a node, add to pool
#         module = module_class_factory(name)(
#             server, *(dep_shapes + parameters))
#         new_ptr = ptr()
#         new_node = Node(module, *dep_nodes)
#         self._node_pool[new_ptr] = new_node
#         return new_ptr   
#     
#     def get_module(self, ptr):
#         return self._node_pool[ptr].get_module()
# 
#     def forward_to_leaf(self, fetches, feed):
#         fetch = fetches + [self._leaf]
#         return self.forward(fetch, feed)
#     
#     def forward(self, fetches, feed):
#         assert type(fetches) is list,\
#         'Fetches must be a list'
# 
#         forward_id = object()
#         vals = list()
#         for ptr in feed:
#             node = self._node_pool[ptr]
#             node.set_feed(feed[ptr])
#         for ptr in fetches:
#             node = self._node_pool[ptr]
#             vals.append(node.forward(forward_id))
#         return vals
#     
#     def set_closure(self, ptr):
#         self._leaf = ptr
#         leaf_node = self._node_pool[self._leaf]
#         leaf_node.inc_counter(ptr)
#     
#     def backward(self):
#         leaf_node = self._node_pool[self._leaf]
#         leaf_node.backward(1.0, self._leaf)


from src.server import ParameterServer
from src.graph import DAG
import src.sugar as sugar

class Net(object):
    # Sugar syntax
    def __init__(self):
        self._server = ParameterServer()
        self._finalized = False

# Path: src/server.py
# class ParameterServer(object):
#     """
#     A server of variables, consists of slots
#     each slot contains variables of one module, thus
#     each slot can have zero, one or more variables.
#     """
#     
#     def __init__(self):
#         self._slots = list()
#         self._optimizer = None
# 
#     def issue_movingvar_slot(self, shape, momen):
#         slot = MovingVariableSlot(shape, momen)
#         self._slots.append(slot)
#         return slot
# 
#     def issue_var_slot(self, val, trainable):
#         slot = VariableSlot(val, trainable)
#         self._slots.append(slot)
#         return slot
#     
#     def set_optimizer(self, name, *args, **kwargs):
#         optimizer = optimizer_factory(
#             name, *args, **kwargs)
#         self._optimizer = optimizer
# 
#     def apply_optimizer(self):
#         for slot in self._slots:
#             self._optimizer.apply(slot)
#         self._optimizer.finalize_step()
#     
#     def save(self, file_name):
#         with open(file_name, 'wb') as f:
#             pickle.dump(
#                 [self._slots, self._optimizer], f, protocol = -1)
#         
#     def load(self, file_name, *args, **kwargs):
#         with open(file_name, 'rb') as f:
#             slots, self._optimizer = \
#                 pickle.load(f, *args, **kwargs)
#         assert len(slots) == len(self._slots)
#         for i, slot in enumerate(self._slots):
#             slot.load(slots[i])
# 
# Path: src/graph.py
# class DAG(object):
#     def __init__(self):
#         self._node_pool = dict()
#         # key : val = Ptr : Node
# 
#     def register_for_slot(self, name, server, *args):
#         # Step 1, extract dependencies from arguments
#         dep_parsed = parse_for(ptr, *args)
#         dep_list, parameters = dep_parsed
# 
#         # Step 2, Get shapes from dependencies
#         dep_nodes = list()
#         dep_shapes = list()
#         for i in range(len(dep_list)):
#             node = self._node_pool[dep_list[i]]
#             dep_shapes.append(node.out_shape())
#             dep_nodes.append(node)
# 
#         # Step 3, Create module, wrap by a node, add to pool
#         module = module_class_factory(name)(
#             server, *(dep_shapes + parameters))
#         new_ptr = ptr()
#         new_node = Node(module, *dep_nodes)
#         self._node_pool[new_ptr] = new_node
#         return new_ptr   
#     
#     def get_module(self, ptr):
#         return self._node_pool[ptr].get_module()
# 
#     def forward_to_leaf(self, fetches, feed):
#         fetch = fetches + [self._leaf]
#         return self.forward(fetch, feed)
#     
#     def forward(self, fetches, feed):
#         assert type(fetches) is list,\
#         'Fetches must be a list'
# 
#         forward_id = object()
#         vals = list()
#         for ptr in feed:
#             node = self._node_pool[ptr]
#             node.set_feed(feed[ptr])
#         for ptr in fetches:
#             node = self._node_pool[ptr]
#             vals.append(node.forward(forward_id))
#         return vals
#     
#     def set_closure(self, ptr):
#         self._leaf = ptr
#         leaf_node = self._node_pool[self._leaf]
#         leaf_node.inc_counter(ptr)
#     
#     def backward(self):
#         leaf_node = self._node_pool[self._leaf]
#         leaf_node.backward(1.0, self._leaf)


# Path: src/net.py
from src.server import ParameterServer
from src.graph import DAG
import src.sugar as sugar


class Net(object):
    # Sugar syntax
    def __init__(self):
        self._server = ParameterServer()
        self._finalized = False

        self._dagraph = DAG()