We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Port LBFGS from Lua optim
fixes #483 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `torch/nn/functions/thnn/auto.py`
Content:
```
1 from itertools import repeat
2 from collections import defaultdict
3 
4 import torch
5 from torch._thnn.utils import parse_header, THNN_H_PATH
6 from torch.autograd.function import Function, InplaceFunction
7 from torch._thnn import type2backend
8 
9 from . import _all_functions
10 
11 
12 def _make_function_class_criterion(class_name, update_output, update_grad_input, acc_grad_parameters):
13     weight_arg_idx = -1
14     for i, arg in enumerate(update_output.arguments):
15         if arg.name.startswith('weight'):
16             weight_arg_idx = i
17             break
18 
19     buffers_idx = []
20     additional_arg_idx = 0
21     for arg in update_output.arguments[4:]:
22         if not arg.name.startswith('weight') and arg.type == 'THTensor*':
23             buffers_idx.append(additional_arg_idx)
24         additional_arg_idx += 1
25 
26     def __init__(self, *args, **kwargs):
27         Function.__init__(self)
28         self.weight = kwargs.get('weight')
29         self.additional_args = list(args)
30 
31     def forward(self, input, target):
32         self._backend = type2backend[type(input)]
33         self.save_for_backward(input, target)
34         if weight_arg_idx >= 0:
35             insert_idx = weight_arg_idx - 4 # state, input, target, output
36             self.additional_args.insert(insert_idx, self.weight)
37         for idx in buffers_idx:
38             self.additional_args.insert(idx, input.new(1))
39         output = input.new(1)
40         getattr(self._backend, update_output.name)(self._backend.library_state, input, target,
41             output, *self.additional_args)
42         return output
43 
44     def backward(self, grad_output):
45         input, target = self.saved_tensors
46         grad_input = grad_output.new().resize_as_(input).zero_()
47         getattr(self._backend, update_grad_input.name)(self._backend.library_state, input, target,
48             grad_input, *self.additional_args)
49         grad_output_expanded = grad_output.resize_(*repeat(1, grad_input.dim()))
50         grad_input.mul_(grad_output.expand_as(grad_input))
51         return grad_input, None
52 
53     return type(class_name, (Function,), dict(__init__=__init__, forward=forward, backward=backward))
54 
55 
56 def _find_buffers(args, ignored_args):
57     additional_arg_idx = 0
58     buffers = []
59     for arg in args:
60         if arg.name in ignored_args:
61             continue
62         if arg.type == 'THTensor*':
63             buffers.append((additional_arg_idx, arg.name))
64         additional_arg_idx += 1
65     return buffers
66 
67 
68 def _make_function_class(class_name, update_output, update_grad_input, acc_grad_parameters):
69     def has_argument(fn, name):
70         for arg in fn.arguments:
71             if arg.name == name:
72                 return True
73         return False
74     save_output = has_argument(update_grad_input, 'output')
75 
76     param_args = {'weight', 'bias'}
77     ignored_args = {'weight', 'bias', 'gradWeight', 'gradBias', 'output'}
78     expected_params = [arg for arg in update_output.arguments[3:]
79             if arg.name in param_args]
80     buffers = {}
81     buffers['update_output'] = _find_buffers(update_output.arguments[3:],
82             ignored_args)
83     buffers['update_grad_input'] = _find_buffers(
84             update_grad_input.arguments[4:], ignored_args)
85     if acc_grad_parameters is not None:
86         buffers['acc_grad_parameters'] = _find_buffers(
87                 acc_grad_parameters.arguments[3:], ignored_args)
88 
89     # This and __init__ assume that only the last argument can be
90     # an inplace flag
91     is_inplace = update_output.arguments[-1].name == 'inplace'
92 
93     def __init__(self, *args):
94         if is_inplace:
95             InplaceFunction.__init__(self, args[-1])
96         else:
97             Function.__init__(self)
98         self.additional_args = list(args)
99 
100     def _initialize_buffers(self, fn_name):
101         additional_args = self.additional_args
102         for idx, name in buffers[fn_name]:
103             # TODO: some buffers are necessary only for update output and can be
104             # freed right afterwards
105             buffer = self.buffers[name]
106             additional_args = additional_args[:idx] + [buffer] + additional_args[idx:]
107         return tuple(additional_args)
108 
109     def forward(self, input, *params):
110         self._backend = type2backend[type(input)]
111 
112         for param in params:
113             if type(param) != type(input):
114                 raise RuntimeError("input type ({}) doesn't match the type of "
115                         "a parameter tensor ({})".format(torch.typename(input),
116                             torch.typename(param)))
117 
118         # Allocate temporary buffers and insert them into additional_args
119         self.buffers = defaultdict(type(input))
120         additional_args = self._initialize_buffers('update_output')
121 
122         # Fill in optional params with None
123         args = params
124         for i in range(len(params), len(expected_params)):
125             param = expected_params[i]
126             if param.is_optional:
127                 args += (None,)
128             else:
129                 raise ValueError("missing required argument '%s'" % param.name)
130 
131         args += tuple(additional_args)
132 
133         # If the module is working in-place it's output will be set to the
134         # same storage as input, but it's variable won't be dirty.
135         if is_inplace and self.inplace:
136             self.mark_dirty(input)
137             output = input
138             self.save_for_backward(input, *params)
139         else:
140             output = input.new()
141             if save_output:
142                 self.save_for_backward(input, output, *params)
143             else:
144                 self.save_for_backward(input, *params)
145 
146         getattr(self._backend, update_output.name)(self._backend.library_state, input, output, *args)
147         return output
148 
149     def backward(self, grad_output):
150         t = self.saved_tensors
151         if save_output:
152             input, output, params = t[0], t[1], t[2:]
153         else:
154             input, params = t[0], t[1:]
155         grad_params = tuple(None for p in params)
156         grad_input_tuple = (None,)
157 
158         if self.needs_input_grad[0]:
159             additional_args = self._initialize_buffers('update_grad_input')
160             if save_output:
161                 additional_args = (output,) + additional_args
162 
163             grad_input = input.new().resize_as_(input).zero_()
164             params_without_bias = params if len(params) < 2 else params[:1]
165             update_grad_input_fn = getattr(self._backend, update_grad_input.name)
166             gi_args = params_without_bias + additional_args
167             update_grad_input_fn(self._backend.library_state, input, grad_output, grad_input, *gi_args)
168             grad_input_tuple = (grad_input,)
169 
170         if acc_grad_parameters and any(self.needs_input_grad[1:]):
171             additional_args = self._initialize_buffers('acc_grad_parameters')
172             grad_params = tuple(p.new().resize_as_(p).zero_() for p in params)
173             acc_grad_parameters_fn = getattr(self._backend, acc_grad_parameters.name)
174             param_args = grad_params + additional_args + (1,)
175             acc_grad_parameters_fn(self._backend.library_state, input, grad_output, *param_args)
176 
177         return grad_input_tuple + grad_params
178 
179     base_class = Function if not is_inplace else InplaceFunction
180     return type(class_name, (base_class,), dict(__init__=__init__, forward=forward, backward=backward, _initialize_buffers=_initialize_buffers))
181 
182 
183 def _generate_function_classes(scope_dict):
184     function_list = parse_header(THNN_H_PATH)
185     function_by_name = {fn.name: fn for fn in function_list}
186     classes_to_generate = {fn.name.partition('_')[0] for fn in function_list}
187     exceptions = {
188         'SpatialConvolutionMM',
189         'SparseLinear',
190         'TemporalConvolution',
191         'SpatialMaxPooling',
192         'SpatialDilatedMaxPooling',
193         'SpatialMaxUnpooling',
194         'VolumetricMaxPooling',
195         'VolumetricMaxUnpooling',
196         'VolumetricConvolution',
197         'VolumetricConvolutionMM',
198         'TemporalMaxPooling',
199         'BatchNormalization',
200         'LookupTable',
201         'PReLU',
202         'RReLU',
203         'unfolded',
204     }
205     name_remap = {
206         'TemporalConvolution': 'Conv1d',
207         'SpatialDilatedConvolution': 'DilatedConv2d',
208         'SpatialAveragePooling': 'AvgPool2d',
209         'SpatialMaxUnpooling': 'MaxUnpool2d',
210         'SpatialReflectionPadding': 'ReflectionPad2d',
211         'SpatialReplicationPadding': 'ReplicationPad2d',
212         'SpatialFullConvolution': 'ConvTranspose2d',
213         'VolumetricFullConvolution': 'ConvTranspose3d',
214         'VolumetricReplicationPadding': 'ReplicationPad3d',
215         'VolumetricMaxUnpooling': 'MaxUnpool3d',
216         'VolumetricAveragePooling': 'AvgPool3d',
217         'SoftMax': 'Softmax',
218         'LogSoftMax': 'LogSoftmax',
219         'HardTanh': 'Hardtanh',
220         'HardShrink': 'Hardshrink',
221         'SoftPlus': 'Softplus',
222         'SoftShrink': 'Softshrink',
223         'MSECriterion': 'MSELoss',
224         'AbsCriterion': 'L1Loss',
225         'BCECriterion': '_BCELoss',  # TODO: move the glue code into THNN
226         'ClassNLLCriterion': 'NLLLoss',
227         'DistKLDivCriterion': 'KLDivLoss',
228         'SpatialClassNLLCriterion': 'NLLLoss2d',
229         'MultiLabelMarginCriterion': 'MultiLabelMarginLoss',
230         'MultiMarginCriterion': 'MultiMarginLoss',
231         'SmoothL1Criterion': 'SmoothL1Loss',
232         'SoftMarginCriterion': 'SoftMarginLoss',
233     }
234     classes_to_generate -= exceptions
235     for fn in classes_to_generate:
236         update_output = function_by_name[fn + '_updateOutput']
237         update_grad_input = function_by_name[fn + '_updateGradInput']
238         acc_grad_parameters = function_by_name.get(fn + '_accGradParameters')
239         class_name = name_remap.get(fn, fn)
240         # This has to call a function to retain correct references to functions
241         if 'Criterion' in fn:
242             cls = _make_function_class_criterion(class_name, update_output,
243                     update_grad_input, acc_grad_parameters)
244         else:
245             cls = _make_function_class(class_name, update_output,
246                     update_grad_input, acc_grad_parameters)
247         scope_dict[class_name] = cls
248         if not class_name.startswith('_'):
249             _all_functions.append(cls)
250 
251 
252 _generate_function_classes(locals())
253
```
--- 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()

```

diff --git a/torch/nn/functions/thnn/auto.py b/torch/nn/functions/thnn/auto.py
--- a/torch/nn/functions/thnn/auto.py
+++ b/torch/nn/functions/thnn/auto.py
@@ -185,6 +185,7 @@
     function_by_name = {fn.name: fn for fn in function_list}
     classes_to_generate = {fn.name.partition('_')[0] for fn in function_list}
     exceptions = {
+        'Linear',
         'SpatialConvolutionMM',
         'SparseLinear',
         'TemporalConvolution',

{"golden_diff": "diff --git a/torch/nn/functions/thnn/auto.py b/torch/nn/functions/thnn/auto.py\n--- a/torch/nn/functions/thnn/auto.py\n+++ b/torch/nn/functions/thnn/auto.py\n@@ -185,6 +185,7 @@\n     function_by_name = {fn.name: fn for fn in function_list}\n     classes_to_generate = {fn.name.partition('_')[0] for fn in function_list}\n     exceptions = {\n+        'Linear',\n         'SpatialConvolutionMM',\n         'SparseLinear',\n         'TemporalConvolution',\n", "issue": "Port LBFGS from Lua optim\nfixes #483 \n", "before_files": [{"content": "from itertools import repeat\nfrom collections import defaultdict\n\nimport torch\nfrom torch._thnn.utils import parse_header, THNN_H_PATH\nfrom torch.autograd.function import Function, InplaceFunction\nfrom torch._thnn import type2backend\n\nfrom . import _all_functions\n\n\ndef _make_function_class_criterion(class_name, update_output, update_grad_input, acc_grad_parameters):\n    weight_arg_idx = -1\n    for i, arg in enumerate(update_output.arguments):\n        if arg.name.startswith('weight'):\n            weight_arg_idx = i\n            break\n\n    buffers_idx = []\n    additional_arg_idx = 0\n    for arg in update_output.arguments[4:]:\n        if not arg.name.startswith('weight') and arg.type == 'THTensor*':\n            buffers_idx.append(additional_arg_idx)\n        additional_arg_idx += 1\n\n    def __init__(self, *args, **kwargs):\n        Function.__init__(self)\n        self.weight = kwargs.get('weight')\n        self.additional_args = list(args)\n\n    def forward(self, input, target):\n        self._backend = type2backend[type(input)]\n        self.save_for_backward(input, target)\n        if weight_arg_idx >= 0:\n            insert_idx = weight_arg_idx - 4 # state, input, target, output\n            self.additional_args.insert(insert_idx, self.weight)\n        for idx in buffers_idx:\n            self.additional_args.insert(idx, input.new(1))\n        output = input.new(1)\n        getattr(self._backend, update_output.name)(self._backend.library_state, input, target,\n            output, *self.additional_args)\n        return output\n\n    def backward(self, grad_output):\n        input, target = self.saved_tensors\n        grad_input = grad_output.new().resize_as_(input).zero_()\n        getattr(self._backend, update_grad_input.name)(self._backend.library_state, input, target,\n            grad_input, *self.additional_args)\n        grad_output_expanded = grad_output.resize_(*repeat(1, grad_input.dim()))\n        grad_input.mul_(grad_output.expand_as(grad_input))\n        return grad_input, None\n\n    return type(class_name, (Function,), dict(__init__=__init__, forward=forward, backward=backward))\n\n\ndef _find_buffers(args, ignored_args):\n    additional_arg_idx = 0\n    buffers = []\n    for arg in args:\n        if arg.name in ignored_args:\n            continue\n        if arg.type == 'THTensor*':\n            buffers.append((additional_arg_idx, arg.name))\n        additional_arg_idx += 1\n    return buffers\n\n\ndef _make_function_class(class_name, update_output, update_grad_input, acc_grad_parameters):\n    def has_argument(fn, name):\n        for arg in fn.arguments:\n            if arg.name == name:\n                return True\n        return False\n    save_output = has_argument(update_grad_input, 'output')\n\n    param_args = {'weight', 'bias'}\n    ignored_args = {'weight', 'bias', 'gradWeight', 'gradBias', 'output'}\n    expected_params = [arg for arg in update_output.arguments[3:]\n            if arg.name in param_args]\n    buffers = {}\n    buffers['update_output'] = _find_buffers(update_output.arguments[3:],\n            ignored_args)\n    buffers['update_grad_input'] = _find_buffers(\n            update_grad_input.arguments[4:], ignored_args)\n    if acc_grad_parameters is not None:\n        buffers['acc_grad_parameters'] = _find_buffers(\n                acc_grad_parameters.arguments[3:], ignored_args)\n\n    # This and __init__ assume that only the last argument can be\n    # an inplace flag\n    is_inplace = update_output.arguments[-1].name == 'inplace'\n\n    def __init__(self, *args):\n        if is_inplace:\n            InplaceFunction.__init__(self, args[-1])\n        else:\n            Function.__init__(self)\n        self.additional_args = list(args)\n\n    def _initialize_buffers(self, fn_name):\n        additional_args = self.additional_args\n        for idx, name in buffers[fn_name]:\n            # TODO: some buffers are necessary only for update output and can be\n            # freed right afterwards\n            buffer = self.buffers[name]\n            additional_args = additional_args[:idx] + [buffer] + additional_args[idx:]\n        return tuple(additional_args)\n\n    def forward(self, input, *params):\n        self._backend = type2backend[type(input)]\n\n        for param in params:\n            if type(param) != type(input):\n                raise RuntimeError(\"input type ({}) doesn't match the type of \"\n                        \"a parameter tensor ({})\".format(torch.typename(input),\n                            torch.typename(param)))\n\n        # Allocate temporary buffers and insert them into additional_args\n        self.buffers = defaultdict(type(input))\n        additional_args = self._initialize_buffers('update_output')\n\n        # Fill in optional params with None\n        args = params\n        for i in range(len(params), len(expected_params)):\n            param = expected_params[i]\n            if param.is_optional:\n                args += (None,)\n            else:\n                raise ValueError(\"missing required argument '%s'\" % param.name)\n\n        args += tuple(additional_args)\n\n        # If the module is working in-place it's output will be set to the\n        # same storage as input, but it's variable won't be dirty.\n        if is_inplace and self.inplace:\n            self.mark_dirty(input)\n            output = input\n            self.save_for_backward(input, *params)\n        else:\n            output = input.new()\n            if save_output:\n                self.save_for_backward(input, output, *params)\n            else:\n                self.save_for_backward(input, *params)\n\n        getattr(self._backend, update_output.name)(self._backend.library_state, input, output, *args)\n        return output\n\n    def backward(self, grad_output):\n        t = self.saved_tensors\n        if save_output:\n            input, output, params = t[0], t[1], t[2:]\n        else:\n            input, params = t[0], t[1:]\n        grad_params = tuple(None for p in params)\n        grad_input_tuple = (None,)\n\n        if self.needs_input_grad[0]:\n            additional_args = self._initialize_buffers('update_grad_input')\n            if save_output:\n                additional_args = (output,) + additional_args\n\n            grad_input = input.new().resize_as_(input).zero_()\n            params_without_bias = params if len(params) < 2 else params[:1]\n            update_grad_input_fn = getattr(self._backend, update_grad_input.name)\n            gi_args = params_without_bias + additional_args\n            update_grad_input_fn(self._backend.library_state, input, grad_output, grad_input, *gi_args)\n            grad_input_tuple = (grad_input,)\n\n        if acc_grad_parameters and any(self.needs_input_grad[1:]):\n            additional_args = self._initialize_buffers('acc_grad_parameters')\n            grad_params = tuple(p.new().resize_as_(p).zero_() for p in params)\n            acc_grad_parameters_fn = getattr(self._backend, acc_grad_parameters.name)\n            param_args = grad_params + additional_args + (1,)\n            acc_grad_parameters_fn(self._backend.library_state, input, grad_output, *param_args)\n\n        return grad_input_tuple + grad_params\n\n    base_class = Function if not is_inplace else InplaceFunction\n    return type(class_name, (base_class,), dict(__init__=__init__, forward=forward, backward=backward, _initialize_buffers=_initialize_buffers))\n\n\ndef _generate_function_classes(scope_dict):\n    function_list = parse_header(THNN_H_PATH)\n    function_by_name = {fn.name: fn for fn in function_list}\n    classes_to_generate = {fn.name.partition('_')[0] for fn in function_list}\n    exceptions = {\n        'SpatialConvolutionMM',\n        'SparseLinear',\n        'TemporalConvolution',\n        'SpatialMaxPooling',\n        'SpatialDilatedMaxPooling',\n        'SpatialMaxUnpooling',\n        'VolumetricMaxPooling',\n        'VolumetricMaxUnpooling',\n        'VolumetricConvolution',\n        'VolumetricConvolutionMM',\n        'TemporalMaxPooling',\n        'BatchNormalization',\n        'LookupTable',\n        'PReLU',\n        'RReLU',\n        'unfolded',\n    }\n    name_remap = {\n        'TemporalConvolution': 'Conv1d',\n        'SpatialDilatedConvolution': 'DilatedConv2d',\n        'SpatialAveragePooling': 'AvgPool2d',\n        'SpatialMaxUnpooling': 'MaxUnpool2d',\n        'SpatialReflectionPadding': 'ReflectionPad2d',\n        'SpatialReplicationPadding': 'ReplicationPad2d',\n        'SpatialFullConvolution': 'ConvTranspose2d',\n        'VolumetricFullConvolution': 'ConvTranspose3d',\n        'VolumetricReplicationPadding': 'ReplicationPad3d',\n        'VolumetricMaxUnpooling': 'MaxUnpool3d',\n        'VolumetricAveragePooling': 'AvgPool3d',\n        'SoftMax': 'Softmax',\n        'LogSoftMax': 'LogSoftmax',\n        'HardTanh': 'Hardtanh',\n        'HardShrink': 'Hardshrink',\n        'SoftPlus': 'Softplus',\n        'SoftShrink': 'Softshrink',\n        'MSECriterion': 'MSELoss',\n        'AbsCriterion': 'L1Loss',\n        'BCECriterion': '_BCELoss',  # TODO: move the glue code into THNN\n        'ClassNLLCriterion': 'NLLLoss',\n        'DistKLDivCriterion': 'KLDivLoss',\n        'SpatialClassNLLCriterion': 'NLLLoss2d',\n        'MultiLabelMarginCriterion': 'MultiLabelMarginLoss',\n        'MultiMarginCriterion': 'MultiMarginLoss',\n        'SmoothL1Criterion': 'SmoothL1Loss',\n        'SoftMarginCriterion': 'SoftMarginLoss',\n    }\n    classes_to_generate -= exceptions\n    for fn in classes_to_generate:\n        update_output = function_by_name[fn + '_updateOutput']\n        update_grad_input = function_by_name[fn + '_updateGradInput']\n        acc_grad_parameters = function_by_name.get(fn + '_accGradParameters')\n        class_name = name_remap.get(fn, fn)\n        # This has to call a function to retain correct references to functions\n        if 'Criterion' in fn:\n            cls = _make_function_class_criterion(class_name, update_output,\n                    update_grad_input, acc_grad_parameters)\n        else:\n            cls = _make_function_class(class_name, update_output,\n                    update_grad_input, acc_grad_parameters)\n        scope_dict[class_name] = cls\n        if not class_name.startswith('_'):\n            _all_functions.append(cls)\n\n\n_generate_function_classes(locals())\n", "path": "torch/nn/functions/thnn/auto.py"}], "after_files": [{"content": "from itertools import repeat\nfrom collections import defaultdict\n\nimport torch\nfrom torch._thnn.utils import parse_header, THNN_H_PATH\nfrom torch.autograd.function import Function, InplaceFunction\nfrom torch._thnn import type2backend\n\nfrom . import _all_functions\n\n\ndef _make_function_class_criterion(class_name, update_output, update_grad_input, acc_grad_parameters):\n    weight_arg_idx = -1\n    for i, arg in enumerate(update_output.arguments):\n        if arg.name.startswith('weight'):\n            weight_arg_idx = i\n            break\n\n    buffers_idx = []\n    additional_arg_idx = 0\n    for arg in update_output.arguments[4:]:\n        if not arg.name.startswith('weight') and arg.type == 'THTensor*':\n            buffers_idx.append(additional_arg_idx)\n        additional_arg_idx += 1\n\n    def __init__(self, *args, **kwargs):\n        Function.__init__(self)\n        self.weight = kwargs.get('weight')\n        self.additional_args = list(args)\n\n    def forward(self, input, target):\n        self._backend = type2backend[type(input)]\n        self.save_for_backward(input, target)\n        if weight_arg_idx >= 0:\n            insert_idx = weight_arg_idx - 4 # state, input, target, output\n            self.additional_args.insert(insert_idx, self.weight)\n        for idx in buffers_idx:\n            self.additional_args.insert(idx, input.new(1))\n        output = input.new(1)\n        getattr(self._backend, update_output.name)(self._backend.library_state, input, target,\n            output, *self.additional_args)\n        return output\n\n    def backward(self, grad_output):\n        input, target = self.saved_tensors\n        grad_input = grad_output.new().resize_as_(input).zero_()\n        getattr(self._backend, update_grad_input.name)(self._backend.library_state, input, target,\n            grad_input, *self.additional_args)\n        grad_output_expanded = grad_output.resize_(*repeat(1, grad_input.dim()))\n        grad_input.mul_(grad_output.expand_as(grad_input))\n        return grad_input, None\n\n    return type(class_name, (Function,), dict(__init__=__init__, forward=forward, backward=backward))\n\n\ndef _find_buffers(args, ignored_args):\n    additional_arg_idx = 0\n    buffers = []\n    for arg in args:\n        if arg.name in ignored_args:\n            continue\n        if arg.type == 'THTensor*':\n            buffers.append((additional_arg_idx, arg.name))\n        additional_arg_idx += 1\n    return buffers\n\n\ndef _make_function_class(class_name, update_output, update_grad_input, acc_grad_parameters):\n    def has_argument(fn, name):\n        for arg in fn.arguments:\n            if arg.name == name:\n                return True\n        return False\n    save_output = has_argument(update_grad_input, 'output')\n\n    param_args = {'weight', 'bias'}\n    ignored_args = {'weight', 'bias', 'gradWeight', 'gradBias', 'output'}\n    expected_params = [arg for arg in update_output.arguments[3:]\n            if arg.name in param_args]\n    buffers = {}\n    buffers['update_output'] = _find_buffers(update_output.arguments[3:],\n            ignored_args)\n    buffers['update_grad_input'] = _find_buffers(\n            update_grad_input.arguments[4:], ignored_args)\n    if acc_grad_parameters is not None:\n        buffers['acc_grad_parameters'] = _find_buffers(\n                acc_grad_parameters.arguments[3:], ignored_args)\n\n    # This and __init__ assume that only the last argument can be\n    # an inplace flag\n    is_inplace = update_output.arguments[-1].name == 'inplace'\n\n    def __init__(self, *args):\n        if is_inplace:\n            InplaceFunction.__init__(self, args[-1])\n        else:\n            Function.__init__(self)\n        self.additional_args = list(args)\n\n    def _initialize_buffers(self, fn_name):\n        additional_args = self.additional_args\n        for idx, name in buffers[fn_name]:\n            # TODO: some buffers are necessary only for update output and can be\n            # freed right afterwards\n            buffer = self.buffers[name]\n            additional_args = additional_args[:idx] + [buffer] + additional_args[idx:]\n        return tuple(additional_args)\n\n    def forward(self, input, *params):\n        self._backend = type2backend[type(input)]\n\n        for param in params:\n            if type(param) != type(input):\n                raise RuntimeError(\"input type ({}) doesn't match the type of \"\n                        \"a parameter tensor ({})\".format(torch.typename(input),\n                            torch.typename(param)))\n\n        # Allocate temporary buffers and insert them into additional_args\n        self.buffers = defaultdict(type(input))\n        additional_args = self._initialize_buffers('update_output')\n\n        # Fill in optional params with None\n        args = params\n        for i in range(len(params), len(expected_params)):\n            param = expected_params[i]\n            if param.is_optional:\n                args += (None,)\n            else:\n                raise ValueError(\"missing required argument '%s'\" % param.name)\n\n        args += tuple(additional_args)\n\n        # If the module is working in-place it's output will be set to the\n        # same storage as input, but it's variable won't be dirty.\n        if is_inplace and self.inplace:\n            self.mark_dirty(input)\n            output = input\n            self.save_for_backward(input, *params)\n        else:\n            output = input.new()\n            if save_output:\n                self.save_for_backward(input, output, *params)\n            else:\n                self.save_for_backward(input, *params)\n\n        getattr(self._backend, update_output.name)(self._backend.library_state, input, output, *args)\n        return output\n\n    def backward(self, grad_output):\n        t = self.saved_tensors\n        if save_output:\n            input, output, params = t[0], t[1], t[2:]\n        else:\n            input, params = t[0], t[1:]\n        grad_params = tuple(None for p in params)\n        grad_input_tuple = (None,)\n\n        if self.needs_input_grad[0]:\n            additional_args = self._initialize_buffers('update_grad_input')\n            if save_output:\n                additional_args = (output,) + additional_args\n\n            grad_input = input.new().resize_as_(input).zero_()\n            params_without_bias = params if len(params) < 2 else params[:1]\n            update_grad_input_fn = getattr(self._backend, update_grad_input.name)\n            gi_args = params_without_bias + additional_args\n            update_grad_input_fn(self._backend.library_state, input, grad_output, grad_input, *gi_args)\n            grad_input_tuple = (grad_input,)\n\n        if acc_grad_parameters and any(self.needs_input_grad[1:]):\n            additional_args = self._initialize_buffers('acc_grad_parameters')\n            grad_params = tuple(p.new().resize_as_(p).zero_() for p in params)\n            acc_grad_parameters_fn = getattr(self._backend, acc_grad_parameters.name)\n            param_args = grad_params + additional_args + (1,)\n            acc_grad_parameters_fn(self._backend.library_state, input, grad_output, *param_args)\n\n        return grad_input_tuple + grad_params\n\n    base_class = Function if not is_inplace else InplaceFunction\n    return type(class_name, (base_class,), dict(__init__=__init__, forward=forward, backward=backward, _initialize_buffers=_initialize_buffers))\n\n\ndef _generate_function_classes(scope_dict):\n    function_list = parse_header(THNN_H_PATH)\n    function_by_name = {fn.name: fn for fn in function_list}\n    classes_to_generate = {fn.name.partition('_')[0] for fn in function_list}\n    exceptions = {\n        'Linear',\n        'SpatialConvolutionMM',\n        'SparseLinear',\n        'TemporalConvolution',\n        'SpatialMaxPooling',\n        'SpatialDilatedMaxPooling',\n        'SpatialMaxUnpooling',\n        'VolumetricMaxPooling',\n        'VolumetricMaxUnpooling',\n        'VolumetricConvolution',\n        'VolumetricConvolutionMM',\n        'TemporalMaxPooling',\n        'BatchNormalization',\n        'LookupTable',\n        'PReLU',\n        'RReLU',\n        'unfolded',\n    }\n    name_remap = {\n        'TemporalConvolution': 'Conv1d',\n        'SpatialDilatedConvolution': 'DilatedConv2d',\n        'SpatialAveragePooling': 'AvgPool2d',\n        'SpatialMaxUnpooling': 'MaxUnpool2d',\n        'SpatialReflectionPadding': 'ReflectionPad2d',\n        'SpatialReplicationPadding': 'ReplicationPad2d',\n        'SpatialFullConvolution': 'ConvTranspose2d',\n        'VolumetricFullConvolution': 'ConvTranspose3d',\n        'VolumetricReplicationPadding': 'ReplicationPad3d',\n        'VolumetricMaxUnpooling': 'MaxUnpool3d',\n        'VolumetricAveragePooling': 'AvgPool3d',\n        'SoftMax': 'Softmax',\n        'LogSoftMax': 'LogSoftmax',\n        'HardTanh': 'Hardtanh',\n        'HardShrink': 'Hardshrink',\n        'SoftPlus': 'Softplus',\n        'SoftShrink': 'Softshrink',\n        'MSECriterion': 'MSELoss',\n        'AbsCriterion': 'L1Loss',\n        'BCECriterion': '_BCELoss',  # TODO: move the glue code into THNN\n        'ClassNLLCriterion': 'NLLLoss',\n        'DistKLDivCriterion': 'KLDivLoss',\n        'SpatialClassNLLCriterion': 'NLLLoss2d',\n        'MultiLabelMarginCriterion': 'MultiLabelMarginLoss',\n        'MultiMarginCriterion': 'MultiMarginLoss',\n        'SmoothL1Criterion': 'SmoothL1Loss',\n        'SoftMarginCriterion': 'SoftMarginLoss',\n    }\n    classes_to_generate -= exceptions\n    for fn in classes_to_generate:\n        update_output = function_by_name[fn + '_updateOutput']\n        update_grad_input = function_by_name[fn + '_updateGradInput']\n        acc_grad_parameters = function_by_name.get(fn + '_accGradParameters')\n        class_name = name_remap.get(fn, fn)\n        # This has to call a function to retain correct references to functions\n        if 'Criterion' in fn:\n            cls = _make_function_class_criterion(class_name, update_output,\n                    update_grad_input, acc_grad_parameters)\n        else:\n            cls = _make_function_class(class_name, update_output,\n                    update_grad_input, acc_grad_parameters)\n        scope_dict[class_name] = cls\n        if not class_name.startswith('_'):\n            _all_functions.append(cls)\n\n\n_generate_function_classes(locals())\n", "path": "torch/nn/functions/thnn/auto.py"}]}