prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Bug: Reshape() with -1 fails
  When calling the chainer function Reshape() with a -1 value (e.g. Reshape((-1, 10, 10))) I get an error: 
  
  ```
  InvalidType: Expect: prod(in_types[0].shape) == prod((-1, 10, 10))
  Actual: 2800 != -100
  ```
  
  The cupy function reshape does support -1 arguments, so the error seems to be just the check in chainer's Reshape. The problematic check is:
     _type_check_prod(in_types[0].shape) == _type_check_prod(self.shape)
  
  If a -1 argument is present, it should instead check if the size of in_types[0] is divisible by the product of the axis-lengths that are not -1. 
  
  I would send a PR but I'm not exactly clear on the correct usage of type_check.expect, and had some issues with it in the past. Should be simple enough to fix though.
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `chainer/functions/array/reshape.py`
  Content:
  ```
  1 import numpy
  2 
  3 from chainer import function
  4 from chainer.utils import type_check
  5 
  6 
  7 _type_check_prod = type_check.Variable(numpy.prod, 'prod')
  8 
  9 
  10 class Reshape(function.Function):
  11 
  12     """Reshapes an input array without copy."""
  13 
  14     def __init__(self, shape):
  15         self.shape = shape
  16 
  17     def check_type_forward(self, in_types):
  18         type_check.expect(
  19             in_types.size() == 1,
  20             _type_check_prod(in_types[0].shape) ==
  21             _type_check_prod(self.shape)
  22         )
  23 
  24     def forward(self, x):
  25         return x[0].reshape(self.shape),
  26 
  27     def backward(self, x, gy):
  28         return gy[0].reshape(x[0].shape),
  29 
  30 
  31 def reshape(x, shape):
  32     """Reshapes an input variable without copy.
  33 
  34     Args:
  35         x (~chainer.Variable): Input variable.
  36         shape (tuple of ints): Target shape.
  37 
  38     Returns:
  39         ~chainer.Variable: Variable that holds a reshaped version of the input
  40             variable.
  41 
  42     """
  43     return Reshape(shape)(x)
  44
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/chainer/functions/array/reshape.py b/chainer/functions/array/reshape.py
  --- a/chainer/functions/array/reshape.py
  +++ b/chainer/functions/array/reshape.py
  @@ -1,10 +1,12 @@
  -import numpy
  -
   from chainer import function
   from chainer.utils import type_check
   
   
  -_type_check_prod = type_check.Variable(numpy.prod, 'prod')
  +def _count_unknown_dims(shape):
  +    cnt = 0
  +    for dim in shape:
  +        cnt += dim < 0
  +    return cnt
   
   
   class Reshape(function.Function):
  @@ -12,15 +14,32 @@
       """Reshapes an input array without copy."""
   
       def __init__(self, shape):
  +        cnt = _count_unknown_dims(shape)
  +        assert cnt == 0 or cnt == 1
  +
           self.shape = shape
   
       def check_type_forward(self, in_types):
           type_check.expect(
               in_types.size() == 1,
  -            _type_check_prod(in_types[0].shape) ==
  -            _type_check_prod(self.shape)
           )
   
  +        x_type, = in_types
  +
  +        cnt = _count_unknown_dims(self.shape)
  +        if cnt == 0:
  +            type_check.expect(
  +                type_check.prod(x_type.shape) == type_check.prod(self.shape))
  +        else:
  +            known_size = 1
  +            for s in self.shape:
  +                if s > 0:
  +                    known_size *= s
  +            size_var = type_check.Variable(known_size,
  +                                           'known_size(=%d)' % known_size)
  +            type_check.expect(
  +                type_check.prod(x_type.shape) % size_var == 0)
  +
       def forward(self, x):
           return x[0].reshape(self.shape),
  
verification_info: {"golden_diff": "diff --git a/chainer/functions/array/reshape.py b/chainer/functions/array/reshape.py\n--- a/chainer/functions/array/reshape.py\n+++ b/chainer/functions/array/reshape.py\n@@ -1,10 +1,12 @@\n-import numpy\n-\n from chainer import function\n from chainer.utils import type_check\n \n \n-_type_check_prod = type_check.Variable(numpy.prod, 'prod')\n+def _count_unknown_dims(shape):\n+    cnt = 0\n+    for dim in shape:\n+        cnt += dim < 0\n+    return cnt\n \n \n class Reshape(function.Function):\n@@ -12,15 +14,32 @@\n     \"\"\"Reshapes an input array without copy.\"\"\"\n \n     def __init__(self, shape):\n+        cnt = _count_unknown_dims(shape)\n+        assert cnt == 0 or cnt == 1\n+\n         self.shape = shape\n \n     def check_type_forward(self, in_types):\n         type_check.expect(\n             in_types.size() == 1,\n-            _type_check_prod(in_types[0].shape) ==\n-            _type_check_prod(self.shape)\n         )\n \n+        x_type, = in_types\n+\n+        cnt = _count_unknown_dims(self.shape)\n+        if cnt == 0:\n+            type_check.expect(\n+                type_check.prod(x_type.shape) == type_check.prod(self.shape))\n+        else:\n+            known_size = 1\n+            for s in self.shape:\n+                if s > 0:\n+                    known_size *= s\n+            size_var = type_check.Variable(known_size,\n+                                           'known_size(=%d)' % known_size)\n+            type_check.expect(\n+                type_check.prod(x_type.shape) % size_var == 0)\n+\n     def forward(self, x):\n         return x[0].reshape(self.shape),\n", "issue": "Bug: Reshape() with -1 fails\nWhen calling the chainer function Reshape() with a -1 value (e.g. Reshape((-1, 10, 10))) I get an error: \n\n```\nInvalidType: Expect: prod(in_types[0].shape) == prod((-1, 10, 10))\nActual: 2800 != -100\n```\n\nThe cupy function reshape does support -1 arguments, so the error seems to be just the check in chainer's Reshape. The problematic check is:\n   _type_check_prod(in_types[0].shape) == _type_check_prod(self.shape)\n\nIf a -1 argument is present, it should instead check if the size of in_types[0] is divisible by the product of the axis-lengths that are not -1. \n\nI would send a PR but I'm not exactly clear on the correct usage of type_check.expect, and had some issues with it in the past. Should be simple enough to fix though.\n\n", "before_files": [{"content": "import numpy\n\nfrom chainer import function\nfrom chainer.utils import type_check\n\n\n_type_check_prod = type_check.Variable(numpy.prod, 'prod')\n\n\nclass Reshape(function.Function):\n\n    \"\"\"Reshapes an input array without copy.\"\"\"\n\n    def __init__(self, shape):\n        self.shape = shape\n\n    def check_type_forward(self, in_types):\n        type_check.expect(\n            in_types.size() == 1,\n            _type_check_prod(in_types[0].shape) ==\n            _type_check_prod(self.shape)\n        )\n\n    def forward(self, x):\n        return x[0].reshape(self.shape),\n\n    def backward(self, x, gy):\n        return gy[0].reshape(x[0].shape),\n\n\ndef reshape(x, shape):\n    \"\"\"Reshapes an input variable without copy.\n\n    Args:\n        x (~chainer.Variable): Input variable.\n        shape (tuple of ints): Target shape.\n\n    Returns:\n        ~chainer.Variable: Variable that holds a reshaped version of the input\n            variable.\n\n    \"\"\"\n    return Reshape(shape)(x)\n", "path": "chainer/functions/array/reshape.py"}], "after_files": [{"content": "from chainer import function\nfrom chainer.utils import type_check\n\n\ndef _count_unknown_dims(shape):\n    cnt = 0\n    for dim in shape:\n        cnt += dim < 0\n    return cnt\n\n\nclass Reshape(function.Function):\n\n    \"\"\"Reshapes an input array without copy.\"\"\"\n\n    def __init__(self, shape):\n        cnt = _count_unknown_dims(shape)\n        assert cnt == 0 or cnt == 1\n\n        self.shape = shape\n\n    def check_type_forward(self, in_types):\n        type_check.expect(\n            in_types.size() == 1,\n        )\n\n        x_type, = in_types\n\n        cnt = _count_unknown_dims(self.shape)\n        if cnt == 0:\n            type_check.expect(\n                type_check.prod(x_type.shape) == type_check.prod(self.shape))\n        else:\n            known_size = 1\n            for s in self.shape:\n                if s > 0:\n                    known_size *= s\n            size_var = type_check.Variable(known_size,\n                                           'known_size(=%d)' % known_size)\n            type_check.expect(\n                type_check.prod(x_type.shape) % size_var == 0)\n\n    def forward(self, x):\n        return x[0].reshape(self.shape),\n\n    def backward(self, x, gy):\n        return gy[0].reshape(x[0].shape),\n\n\ndef reshape(x, shape):\n    \"\"\"Reshapes an input variable without copy.\n\n    Args:\n        x (~chainer.Variable): Input variable.\n        shape (tuple of ints): Target shape.\n\n    Returns:\n        ~chainer.Variable: Variable that holds a reshaped version of the input\n            variable.\n\n    \"\"\"\n    return Reshape(shape)(x)\n", "path": "chainer/functions/array/reshape.py"}]}