text: # Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #     http://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  
  import unittest
  import paddle
  import numpy as np
  from op_test import OpTest
  import paddle.fluid as fluid
  from paddle.fluid import Program, program_guard, core
  
  SEED = 2020
  
  
  def fc_refer(matrix, with_bias, with_relu=False):
      in_n, in_c, in_h, in_w = matrix.input.shape
      w_i, w_o = matrix.weights.shape
  
      x_data = np.reshape(matrix.input, [in_n, in_c * in_h * in_w])
      w_data = np.reshape(matrix.weights, [w_i, w_o])
      b_data = np.reshape(matrix.bias, [1, w_o])
      result = None
  
      if with_bias:
          result = np.dot(x_data, w_data) + b_data
      else:
          result = np.dot(x_data, w_data)
  
      if with_relu:
          return np.maximum(result, 0)
      else:
          return result
  
  
  class MatrixGenerate:
      def __init__(self, mb, ic, oc, h, w, bias_dims=2):
          self.input = np.random.random((mb, ic, h, w)).astype("float32")
          self.weights = np.random.random((ic * h * w, oc)).astype("float32")
          if bias_dims == 2:
              self.bias = np.random.random((1, oc)).astype("float32")
          else:
              self.bias = np.random.random((oc)).astype("float32")
  
  
  class TestFCOp(OpTest):
      def config(self):
          self.with_bias = True
          self.with_relu = True
          self.matrix = MatrixGenerate(1, 10, 15, 3, 3, 2)
  
      def setUp(self):
          self.op_type = "fc"
          self.config()
  
          if self.with_bias:
              self.inputs = {
                  'Input': self.matrix.input,
                  'W': self.matrix.weights,
                  'Bias': self.matrix.bias
              }
          else:
              self.inputs = {'Input': self.matrix.input, 'W': self.matrix.weights}
  
          if self.with_relu:
              activation_type = "relu"
          else:
              activation_type = ""
          self.attrs = {'use_mkldnn': False, 'activation_type': activation_type}
  
          self.outputs = {
              'Out': fc_refer(self.matrix, self.with_bias, self.with_relu)
          }
  
      def test_check_output(self):
          self.check_output()
  
  
  class TestFCOpNoBias1(TestFCOp):
      def config(self):
          self.with_bias = False
          self.with_relu = False
          self.matrix = MatrixGenerate(2, 8, 10, 1, 1, 2)
  
  
  class TestFCOpNoBias2(TestFCOp):
      def config(self):
          self.with_bias = False
          self.with_relu = False
          self.matrix = MatrixGenerate(4, 5, 6, 2, 2, 1)
  
  
  class TestFCOpNoBias4(TestFCOp):
      def config(self):
          self.with_bias = False
          self.with_relu = False
          self.matrix = MatrixGenerate(1, 32, 64, 3, 3, 1)
  
  
  class TestFCOpWithBias1(TestFCOp):
      def config(self):
          self.with_bias = True
          self.with_relu = False
          self.matrix = MatrixGenerate(3, 8, 10, 2, 1, 2)
  
  
  class TestFCOpWithBias2(TestFCOp):
      def config(self):
          self.with_bias = True
          self.with_relu = True
          self.matrix = MatrixGenerate(4, 5, 6, 2, 2, 1)
  
  
  class TestFCOpWithBias3(TestFCOp):
      def config(self):
          self.with_bias = True
          self.with_relu = True
          self.matrix = MatrixGenerate(1, 64, 32, 3, 3, 1)
  
  
  class TestFCOpWithPadding(TestFCOp):
      def config(self):
          self.with_bias = True
          self.with_relu = True
          self.matrix = MatrixGenerate(1, 4, 3, 128, 128, 2)
  
  
  class TestFcOp_NumFlattenDims_NegOne(unittest.TestCase):
      def test_api(self):
          def run_program(num_flatten_dims):
              paddle.seed(SEED)
              startup_program = Program()
              main_program = Program()
  
              with program_guard(main_program, startup_program):
                  input = np.random.random([2, 2, 25]).astype("float32")
                  x = fluid.layers.data(
                      name="x",
                      shape=[2, 2, 25],
                      append_batch_size=False,
                      dtype="float32")
  
                  out = paddle.static.nn.fc(x=x,
                                            size=1,
                                            num_flatten_dims=num_flatten_dims)
  
              place = fluid.CPUPlace() if not core.is_compiled_with_cuda(
              ) else fluid.CUDAPlace(0)
              exe = fluid.Executor(place=place)
              exe.run(startup_program)
              out = exe.run(main_program, feed={"x": input}, fetch_list=[out])
  
          res_1 = run_program(-1)
          res_2 = run_program(2)
          self.assertTrue(np.array_equal(res_1, res_2))
  
  
  class TestFCOpError(unittest.TestCase):
      def test_errors(self):
          with program_guard(Program(), Program()):
              input_data = np.random.random((2, 4)).astype("float32")
  
              def test_Variable():
                  # the input type must be Variable
                  fluid.layers.fc(input=input_data, size=1)
  
              self.assertRaises(TypeError, test_Variable)
  
              def test_input_list():
                  # each of input(list) must be Variable
                  fluid.layers.fc(input=[input_data], size=1)
  
              self.assertRaises(TypeError, test_input_list)
  
              def test_type():
                  # dtype must be float32 or float64
                  x2 = fluid.layers.data(name='x2', shape=[4], dtype='int32')
                  fluid.layers.fc(input=x2, size=1)
  
              self.assertRaises(TypeError, test_type)
  
              # The input dtype of fc can be float16 in GPU, test for warning
              x3 = fluid.layers.data(name='x3', shape=[4], dtype='float16')
              fluid.layers.fc(input=x3, size=1)
  
  
  if __name__ == "__main__":
      unittest.main()
  