prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Add a class to generate an MLP
  <!---
  Please label your issue with `new_task_module`.
  -->
  
  ### Suggested Name
  <!---
  -->
  MlpGenerator
  
  ### Task Description
  <!---
  A clear and concise description of the machine learning task to be added, its problem statement and learning outcome.
  -->
  Add a class named MlpGenerator. Create a superclass that would be inherited by CnnGenerator and MlpGenerator.
  
  
  </issue>
  <code>
  [start of autokeras/constant.py]
  1 class Constant:
  2     # Data
  3 
  4     VALIDATION_SET_SIZE = 0.08333
  5 
  6     # Searcher
  7 
  8     MAX_MODEL_NUM = 1000
  9     BETA = 2.576
  10     KERNEL_LAMBDA = 0.1
  11     T_MIN = 0.0001
  12     N_NEIGHBOURS = 8
  13     MAX_MODEL_SIZE = (1 << 25)
  14     MAX_LAYER_WIDTH = 4096
  15     MAX_LAYERS = 100
  16 
  17     # Model Defaults
  18 
  19     DENSE_DROPOUT_RATE = 0.5
  20     CONV_DROPOUT_RATE = 0.25
  21     CONV_BLOCK_DISTANCE = 2
  22     DENSE_BLOCK_DISTANCE = 1
  23     MODEL_LEN = 3
  24     MODEL_WIDTH = 64
  25 
  26     # ModelTrainer
  27 
  28     DATA_AUGMENTATION = True
  29     MAX_ITER_NUM = 200
  30     MIN_LOSS_DEC = 1e-4
  31     MAX_NO_IMPROVEMENT_NUM = 5
  32     MAX_BATCH_SIZE = 128
  33     LIMIT_MEMORY = False
  34     SEARCH_MAX_ITER = 200
  35 
  36     # text preprocessor
  37 
  38     EMBEDDING_DIM = 100
  39     MAX_SEQUENCE_LENGTH = 400
  40     MAX_NB_WORDS = 5000
  41     EXTRACT_PATH = "glove/"
  42     # Download file name
  43     FILE_PATH = "glove.zip"
  44     PRE_TRAIN_FILE_LINK = "http://nlp.stanford.edu/data/glove.6B.zip"
  45     PRE_TRAIN_FILE_NAME = "glove.6B.100d.txt"
  46
  [end of autokeras/constant.py]
  [start of autokeras/nn/generator.py]
  1 from autokeras.constant import Constant
  2 from autokeras.nn.graph import Graph
  3 from autokeras.nn.layers import StubBatchNormalization, StubConv, StubDropout, StubPooling, StubDense, StubFlatten, \
  4     StubReLU, StubGlobalPooling
  5 
  6 
  7 class CnnGenerator:
  8     def __init__(self, n_output_node, input_shape):
  9         self.n_output_node = n_output_node
  10         self.input_shape = input_shape
  11         if len(self.input_shape) > 4:
  12             raise ValueError('The input dimension is too high.')
  13         if len(self.input_shape) < 2:
  14             raise ValueError('The input dimension is too low.')
  15 
  16     def generate(self, model_len=Constant.MODEL_LEN, model_width=Constant.MODEL_WIDTH):
  17         pooling_len = int(model_len / 4)
  18         graph = Graph(self.input_shape, False)
  19         temp_input_channel = self.input_shape[-1]
  20         output_node_id = 0
  21         for i in range(model_len):
  22             output_node_id = graph.add_layer(StubReLU(), output_node_id)
  23             output_node_id = graph.add_layer(StubConv(temp_input_channel, model_width, kernel_size=3), output_node_id)
  24             output_node_id = graph.add_layer(StubBatchNormalization(model_width), output_node_id)
  25             temp_input_channel = model_width
  26             if pooling_len == 0 or ((i + 1) % pooling_len == 0 and i != model_len - 1):
  27                 output_node_id = graph.add_layer(StubPooling(), output_node_id)
  28 
  29         output_node_id = graph.add_layer(StubGlobalPooling(), output_node_id)
  30         output_node_id = graph.add_layer(StubDropout(Constant.CONV_DROPOUT_RATE), output_node_id)
  31         output_node_id = graph.add_layer(StubDense(graph.node_list[output_node_id].shape[0], model_width),
  32                                          output_node_id)
  33         output_node_id = graph.add_layer(StubReLU(), output_node_id)
  34         graph.add_layer(StubDense(model_width, self.n_output_node), output_node_id)
  35         return graph
  36
  [end of autokeras/nn/generator.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/autokeras/constant.py b/autokeras/constant.py
  --- a/autokeras/constant.py
  +++ b/autokeras/constant.py
  @@ -18,9 +18,12 @@
   
       DENSE_DROPOUT_RATE = 0.5
       CONV_DROPOUT_RATE = 0.25
  +    MLP_DROPOUT_RATE = 0.25
       CONV_BLOCK_DISTANCE = 2
       DENSE_BLOCK_DISTANCE = 1
       MODEL_LEN = 3
  +    MLP_MODEL_LEN = 3
  +    MLP_MODEL_WIDTH = 5
       MODEL_WIDTH = 64
   
       # ModelTrainer
  diff --git a/autokeras/nn/generator.py b/autokeras/nn/generator.py
  --- a/autokeras/nn/generator.py
  +++ b/autokeras/nn/generator.py
  @@ -2,12 +2,22 @@
   from autokeras.nn.graph import Graph
   from autokeras.nn.layers import StubBatchNormalization, StubConv, StubDropout, StubPooling, StubDense, StubFlatten, \
       StubReLU, StubGlobalPooling
  +from abc import abstractmethod
   
   
  -class CnnGenerator:
  +class NetworkGenerator:
       def __init__(self, n_output_node, input_shape):
           self.n_output_node = n_output_node
           self.input_shape = input_shape
  +
  +    @abstractmethod
  +    def generate(self, model_len, model_width):
  +        pass
  +
  +
  +class CnnGenerator(NetworkGenerator):
  +    def __init__(self, n_output_node, input_shape):
  +        super(CnnGenerator, self).__init__(n_output_node, input_shape)
           if len(self.input_shape) > 4:
               raise ValueError('The input dimension is too high.')
           if len(self.input_shape) < 2:
  @@ -33,3 +43,28 @@
           output_node_id = graph.add_layer(StubReLU(), output_node_id)
           graph.add_layer(StubDense(model_width, self.n_output_node), output_node_id)
           return graph
  +
  +
  +class MlpGenerator(NetworkGenerator):
  +    def __init__(self, n_output_node, input_shape):
  +        super(MlpGenerator, self).__init__(n_output_node, input_shape)
  +        if len(self.input_shape) > 1:
  +            raise ValueError('The input dimension is too high.')
  +
  +    def generate(self, model_len=Constant.MLP_MODEL_LEN, model_width=Constant.MLP_MODEL_WIDTH):
  +        if type(model_width) is list and not len(model_width) == model_len:
  +            raise ValueError('The length of \'model_width\' does not match \'model_len\'')
  +        elif type(model_width) is int:
  +            model_width = [model_width] * model_len
  +
  +        graph = Graph(self.input_shape[0], False)
  +        output_node_id = 0
  +        n_nodes_prev_layer = self.input_shape[0]
  +        for width in model_width:
  +            output_node_id = graph.add_layer(StubDense(n_nodes_prev_layer, width), output_node_id)
  +            output_node_id = graph.add_layer(StubDropout(Constant.MLP_DROPOUT_RATE), output_node_id)
  +            output_node_id = graph.add_layer(StubReLU(), output_node_id)
  +            n_nodes_prev_layer = width
  +
  +        graph.add_layer(StubDense(n_nodes_prev_layer, self.n_output_node), output_node_id)
  +        return graph
  
verification_info: {"golden_diff": "diff --git a/autokeras/constant.py b/autokeras/constant.py\n--- a/autokeras/constant.py\n+++ b/autokeras/constant.py\n@@ -18,9 +18,12 @@\n \n     DENSE_DROPOUT_RATE = 0.5\n     CONV_DROPOUT_RATE = 0.25\n+    MLP_DROPOUT_RATE = 0.25\n     CONV_BLOCK_DISTANCE = 2\n     DENSE_BLOCK_DISTANCE = 1\n     MODEL_LEN = 3\n+    MLP_MODEL_LEN = 3\n+    MLP_MODEL_WIDTH = 5\n     MODEL_WIDTH = 64\n \n     # ModelTrainer\ndiff --git a/autokeras/nn/generator.py b/autokeras/nn/generator.py\n--- a/autokeras/nn/generator.py\n+++ b/autokeras/nn/generator.py\n@@ -2,12 +2,22 @@\n from autokeras.nn.graph import Graph\n from autokeras.nn.layers import StubBatchNormalization, StubConv, StubDropout, StubPooling, StubDense, StubFlatten, \\\n     StubReLU, StubGlobalPooling\n+from abc import abstractmethod\n \n \n-class CnnGenerator:\n+class NetworkGenerator:\n     def __init__(self, n_output_node, input_shape):\n         self.n_output_node = n_output_node\n         self.input_shape = input_shape\n+\n+    @abstractmethod\n+    def generate(self, model_len, model_width):\n+        pass\n+\n+\n+class CnnGenerator(NetworkGenerator):\n+    def __init__(self, n_output_node, input_shape):\n+        super(CnnGenerator, self).__init__(n_output_node, input_shape)\n         if len(self.input_shape) > 4:\n             raise ValueError('The input dimension is too high.')\n         if len(self.input_shape) < 2:\n@@ -33,3 +43,28 @@\n         output_node_id = graph.add_layer(StubReLU(), output_node_id)\n         graph.add_layer(StubDense(model_width, self.n_output_node), output_node_id)\n         return graph\n+\n+\n+class MlpGenerator(NetworkGenerator):\n+    def __init__(self, n_output_node, input_shape):\n+        super(MlpGenerator, self).__init__(n_output_node, input_shape)\n+        if len(self.input_shape) > 1:\n+            raise ValueError('The input dimension is too high.')\n+\n+    def generate(self, model_len=Constant.MLP_MODEL_LEN, model_width=Constant.MLP_MODEL_WIDTH):\n+        if type(model_width) is list and not len(model_width) == model_len:\n+            raise ValueError('The length of \\'model_width\\' does not match \\'model_len\\'')\n+        elif type(model_width) is int:\n+            model_width = [model_width] * model_len\n+\n+        graph = Graph(self.input_shape[0], False)\n+        output_node_id = 0\n+        n_nodes_prev_layer = self.input_shape[0]\n+        for width in model_width:\n+            output_node_id = graph.add_layer(StubDense(n_nodes_prev_layer, width), output_node_id)\n+            output_node_id = graph.add_layer(StubDropout(Constant.MLP_DROPOUT_RATE), output_node_id)\n+            output_node_id = graph.add_layer(StubReLU(), output_node_id)\n+            n_nodes_prev_layer = width\n+\n+        graph.add_layer(StubDense(n_nodes_prev_layer, self.n_output_node), output_node_id)\n+        return graph\n", "issue": "Add a class to generate an MLP\n<!---\r\nPlease label your issue with `new_task_module`.\r\n-->\r\n\r\n### Suggested Name\r\n<!---\r\n-->\r\nMlpGenerator\r\n\r\n### Task Description\r\n<!---\r\nA clear and concise description of the machine learning task to be added, its problem statement and learning outcome.\r\n-->\r\nAdd a class named MlpGenerator. Create a superclass that would be inherited by CnnGenerator and MlpGenerator.\r\n\n", "before_files": [{"content": "class Constant:\n    # Data\n\n    VALIDATION_SET_SIZE = 0.08333\n\n    # Searcher\n\n    MAX_MODEL_NUM = 1000\n    BETA = 2.576\n    KERNEL_LAMBDA = 0.1\n    T_MIN = 0.0001\n    N_NEIGHBOURS = 8\n    MAX_MODEL_SIZE = (1 << 25)\n    MAX_LAYER_WIDTH = 4096\n    MAX_LAYERS = 100\n\n    # Model Defaults\n\n    DENSE_DROPOUT_RATE = 0.5\n    CONV_DROPOUT_RATE = 0.25\n    CONV_BLOCK_DISTANCE = 2\n    DENSE_BLOCK_DISTANCE = 1\n    MODEL_LEN = 3\n    MODEL_WIDTH = 64\n\n    # ModelTrainer\n\n    DATA_AUGMENTATION = True\n    MAX_ITER_NUM = 200\n    MIN_LOSS_DEC = 1e-4\n    MAX_NO_IMPROVEMENT_NUM = 5\n    MAX_BATCH_SIZE = 128\n    LIMIT_MEMORY = False\n    SEARCH_MAX_ITER = 200\n\n    # text preprocessor\n\n    EMBEDDING_DIM = 100\n    MAX_SEQUENCE_LENGTH = 400\n    MAX_NB_WORDS = 5000\n    EXTRACT_PATH = \"glove/\"\n    # Download file name\n    FILE_PATH = \"glove.zip\"\n    PRE_TRAIN_FILE_LINK = \"http://nlp.stanford.edu/data/glove.6B.zip\"\n    PRE_TRAIN_FILE_NAME = \"glove.6B.100d.txt\"\n", "path": "autokeras/constant.py"}, {"content": "from autokeras.constant import Constant\nfrom autokeras.nn.graph import Graph\nfrom autokeras.nn.layers import StubBatchNormalization, StubConv, StubDropout, StubPooling, StubDense, StubFlatten, \\\n    StubReLU, StubGlobalPooling\n\n\nclass CnnGenerator:\n    def __init__(self, n_output_node, input_shape):\n        self.n_output_node = n_output_node\n        self.input_shape = input_shape\n        if len(self.input_shape) > 4:\n            raise ValueError('The input dimension is too high.')\n        if len(self.input_shape) < 2:\n            raise ValueError('The input dimension is too low.')\n\n    def generate(self, model_len=Constant.MODEL_LEN, model_width=Constant.MODEL_WIDTH):\n        pooling_len = int(model_len / 4)\n        graph = Graph(self.input_shape, False)\n        temp_input_channel = self.input_shape[-1]\n        output_node_id = 0\n        for i in range(model_len):\n            output_node_id = graph.add_layer(StubReLU(), output_node_id)\n            output_node_id = graph.add_layer(StubConv(temp_input_channel, model_width, kernel_size=3), output_node_id)\n            output_node_id = graph.add_layer(StubBatchNormalization(model_width), output_node_id)\n            temp_input_channel = model_width\n            if pooling_len == 0 or ((i + 1) % pooling_len == 0 and i != model_len - 1):\n                output_node_id = graph.add_layer(StubPooling(), output_node_id)\n\n        output_node_id = graph.add_layer(StubGlobalPooling(), output_node_id)\n        output_node_id = graph.add_layer(StubDropout(Constant.CONV_DROPOUT_RATE), output_node_id)\n        output_node_id = graph.add_layer(StubDense(graph.node_list[output_node_id].shape[0], model_width),\n                                         output_node_id)\n        output_node_id = graph.add_layer(StubReLU(), output_node_id)\n        graph.add_layer(StubDense(model_width, self.n_output_node), output_node_id)\n        return graph\n", "path": "autokeras/nn/generator.py"}]}