code: """
   Copyright (C) 2018-2020 Intel Corporation
  
   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 numpy as np
  
  from mo.middle.passes.fusing.decomposition import convert_scale_shift_to_mul_add, convert_batch_norm
  from mo.utils.ir_engine.compare_graphs import compare_graphs
  from mo.utils.unittest.graph import build_graph
  
  nodes_attributes = {
      'placeholder_1': {'shape': None, 'type': 'Parameter', 'kind': 'op', 'op': 'Parameter'},
      'placeholder_1_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None},
      'placeholder_2': {'shape': None, 'type': 'Parameter', 'kind': 'op', 'op': 'Parameter'},
      'placeholder_2_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None},
      # ScaleShift layer
      'scaleshift_1': {'type': 'ScaleShift', 'kind': 'op', 'op': 'ScaleShift', 'axis': 0},
      'const_scaleshift_1_w': {'value': None, 'shape': None, 'kind': 'op'},
      'scaleshift_1_w': {'value': None, 'shape': None, 'kind': 'data'},
      'const_scaleshift_1_b': {'value': None, 'shape': None, 'kind': 'op'},
      'scaleshift_1_b': {'value': None, 'shape': None, 'kind': 'data'},
      'scaleshift_1_data': {'value': None, 'shape': None, 'kind': 'data'},
      # Mul and Add operations
      'mul_1': {'type': None, 'value': None, 'kind': 'op', 'op': 'Mul'},
      'const_mul_1_w': {'value': None, 'shape': None, 'kind': 'op'},
      'mul_1_w': {'value': None, 'shape': None, 'kind': 'data'},
      'mul_1_data': {'value': None, 'shape': None, 'kind': 'data'},
      'add_1': {'type': None, 'kind': 'op', 'op': 'Add'},
      'const_add_1_w': {'value': None, 'shape': None, 'kind': 'op'},
      'add_1_w': {'value': None, 'shape': None, 'kind': 'data'},
      'add_1_data': {'value': None, 'shape': None, 'kind': 'data'},
      # Mul and Add operations
      'mul_2': {'type': None, 'kind': 'op', 'op': 'Mul'},
      'const_mul_2_w': {'value': None, 'shape': None, 'kind': 'op'},
      'mul_2_w': {'value': None, 'shape': None, 'kind': 'data'},
      'mul_2_data': {'value': None, 'shape': None, 'kind': 'data'},
      'add_2': {'type': None, 'kind': 'op', 'op': 'Add'},
      'const_add_2_w': {'value': None, 'shape': None, 'kind': 'op'},
      'add_2_w': {'value': None, 'shape': None, 'kind': 'data'},
      'add_2_data': {'value': None, 'shape': None, 'kind': 'data'},
      # Reshape
      'placeholder_2/Reshape_': {'type': 'Reshape', 'kind': 'op', 'op': 'Reshape'},
      'placeholder_2/Reshape_data': {'value': None, 'shape': None, 'kind': 'data'},
      'placeholder_2/Reshape_const': {'type': 'Const', 'kind': 'op', 'op': 'Const', 'value': None},
      'placeholder_2/Reshape_const_data': {'kind': 'data', 'value': None, 'shape': None},
      # BatchNorm operation
      'bn_op': {'type': None, 'kind': 'op', 'op': 'BatchNorm', 'can_be_fused': True},
      'const_bn_const': {'value': None, 'shape': None, 'kind': 'op'},
      'bn_const': {'value': None, 'shape': None, 'kind': 'data'},
      'const_bn_beta': {'value': None, 'shape': None, 'kind': 'op'},
      'bn_beta': {'value': None, 'shape': None, 'kind': 'data'},
      'const_bn_mean': {'value': None, 'shape': None, 'kind': 'op'},
      'bn_mean': {'value': None, 'shape': None, 'kind': 'data'},
      'const_bn_var': {'value': None, 'shape': None, 'kind': 'op'},
      'bn_var': {'value': None, 'shape': None, 'kind': 'data'},
      'bn_data': {'value': None, 'shape': None, 'kind': 'data'},
      # Concat1 operation
      'concat': {'type': 'Concat', 'kind': 'op', 'op': 'Concat'},
      'concat_data': {'value': None, 'shape': None, 'kind': 'data'},
      'op_output': {'kind': 'op', 'op': 'Result'}
  }
  
  
  class ScaleShiftToMulAdd(unittest.TestCase):
      # ScaleShift -> Mul
      def test_scaleshift_to_mul_1(self):
          graph = build_graph(nodes_attributes,
                              [('placeholder_1', 'placeholder_1_data'),
                               ('placeholder_1_data', 'scaleshift_1'),
                               ('const_scaleshift_1_w', 'scaleshift_1_w'),
                               ('scaleshift_1_w', 'scaleshift_1'),
                               ('scaleshift_1', 'scaleshift_1_data'),
                               ('scaleshift_1_data', 'op_output')
                               ],
                              {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])},
                               'scaleshift_1_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
                               'scaleshift_1_data': {}
                               })
  
          graph_ref = build_graph(nodes_attributes,
                                  [('placeholder_1', 'placeholder_1_data'),
                                   ('placeholder_1_data', 'mul_1'),
                                   ('const_mul_1_w', 'mul_1_w'),
                                   ('mul_1_w', 'mul_1'),
                                   ('mul_1', 'scaleshift_1_data'),
                                   ('scaleshift_1_data', 'op_output')
                                   ],
                                  {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])},
                                   'const_mul_1_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
                                   'mul_1_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
                                   'mul_1': {'can_be_fused': True},
                                   'scaleshift_1_data': {}
                                   })
  
          graph.graph['layout'] = 'NHWC'
          convert_scale_shift_to_mul_add(graph)
          graph.clean_up()
          (flag, resp) = compare_graphs(graph, graph_ref, 'placeholder_1')
          self.assertTrue(flag, resp)
  
      # ScaleShift  2 inputs-> Mul
      def test_scaleshift2_to_mul(self):
          graph = build_graph(nodes_attributes,
                              [('placeholder_1', 'placeholder_1_data'),
                               ('placeholder_2', 'placeholder_2_data'),
                               ('placeholder_1_data', 'scaleshift_1'),
                               ('placeholder_2_data', 'scaleshift_1'),
                               ('scaleshift_1', 'scaleshift_1_data'),
                               ('scaleshift_1_data', 'op_output')
                               ],
                              {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])},
                               'placeholder_2_data': {'shape': np.array([1, 227])},
                               'scaleshift_1_data': {}
                               })
  
          graph_ref = build_graph(nodes_attributes,
                                  [('placeholder_1', 'placeholder_1_data'),
                                   ('placeholder_2', 'placeholder_2_data'),
                                   ('placeholder_2_data', 'placeholder_2/Reshape_'),
                                   ('placeholder_2/Reshape_const', 'placeholder_2/Reshape_const_data'),
                                   ('placeholder_2/Reshape_const_data', 'placeholder_2/Reshape_'),
                                   ('placeholder_2/Reshape_', 'placeholder_2/Reshape_data'),
                                   ('placeholder_1_data', 'mul_1'),
                                   ('placeholder_2/Reshape_data', 'mul_1'),
                                   ('mul_1', 'scaleshift_1_data'),
                                   ('scaleshift_1_data', 'op_output')
                                   ],
                                  {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])},
                                   'placeholder_2_data': {'shape': np.array([1, 227])},
                                   'placeholder_2/Reshape_const': {'value': np.array([1, 227, 1, 1]), 'shape': [4]},
                                   'placeholder_2/Reshape_const_data': {'value': np.array([1, 227, 1, 1]), 'shape': [4]},
                                   'placeholder_2/Reshape_data': {'shape': np.array([1, 227, 1, 1])},
                                   'mul_1': {'can_be_fused': True},
                                   'scaleshift_1_data': {}
                                   })
  
          graph.graph['layout'] = 'NHWC'
          convert_scale_shift_to_mul_add(graph)
          graph.clean_up()
          (flag, resp) = compare_graphs(graph, graph_ref, 'placeholder_1')
          self.assertTrue(flag, resp)
  
      # ScaleShift  2 inputs-> Mul (axis = 1)
      def test_scaleshift2_axis1_to_mul(self):
          graph = build_graph(nodes_attributes,
                              [('placeholder_1', 'placeholder_1_data'),
                               ('placeholder_2', 'placeholder_2_data'),
                               ('placeholder_1_data', 'scaleshift_1'),
                               ('placeholder_2_data', 'scaleshift_1'),
                               ('scaleshift_1', 'scaleshift_1_data'),
                               ('scaleshift_1_data', 'op_output')
                               ],
                              {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])},
                               'placeholder_2_data': {'shape': np.array([227])},
                               'scaleshift_1': {'axis': 1},
                               'scaleshift_1_data': {}
                               })
  
          graph_ref = build_graph(nodes_attributes,
                                  [('placeholder_1', 'placeholder_1_data'),
                                   ('placeholder_2', 'placeholder_2_data'),
                                   ('placeholder_2_data', 'placeholder_2/Reshape_'),
                                   ('placeholder_2/Reshape_const', 'placeholder_2/Reshape_const_data'),
                                   ('placeholder_2/Reshape_const_data', 'placeholder_2/Reshape_'),
                                   ('placeholder_2/Reshape_', 'placeholder_2/Reshape_data'),
                                   ('placeholder_1_data', 'mul_1'),
                                   ('placeholder_2/Reshape_data', 'mul_1'),
                                   ('mul_1', 'scaleshift_1_data'),
                                   ('scaleshift_1_data', 'op_output')
                                   ],
                                  {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])},
                                   'placeholder_2_data': {'shape': np.array([227])},
                                   'placeholder_2/Reshape_const': {'value': np.array([1, 227, 1, 1]), 'shape': [4]},
                                   'placeholder_2/Reshape_const_data': {'value': np.array([1, 227, 1, 1]), 'shape': [4]},
                                   'placeholder_2/Reshape_data': {'shape': np.array([1, 227, 1, 1])},
                                   'mul_1': {'can_be_fused': True},
                                   'scaleshift_1_data': {}
                                   })
  
          graph.graph['layout'] = 'NHWC'
          convert_scale_shift_to_mul_add(graph)
          graph.clean_up()
          (flag, resp) = compare_graphs(graph, graph_ref, 'placeholder_1')
          self.assertTrue(flag, resp)
  
      # ScaleShift -> Mul (Zero biases)
      def test_scaleshift_to_mul_2(self):
          graph = build_graph(nodes_attributes,
                              [('placeholder_1', 'placeholder_1_data'),
                               ('placeholder_1_data', 'scaleshift_1'),
                               ('const_scaleshift_1_w', 'scaleshift_1_w'),
                               ('const_scaleshift_1_b', 'scaleshift_1_b'),
                               ('scaleshift_1_w', 'scaleshift_1'),
                               ('scaleshift_1_b', 'scaleshift_1'),
                               ('scaleshift_1', 'scaleshift_1_data'),
                               ('scaleshift_1_data', 'op_output')
                               ],
                              {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])},
                               'scaleshift_1_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
                               'scaleshift_1_b': {'shape': np.array([3]), 'value': np.array([0, 0, 0])},
                               'scaleshift_1_data': {}
                               })
  
          graph_ref = build_graph(nodes_attributes,
                                  [('placeholder_1', 'placeholder_1_data'),
                                   ('placeholder_1_data', 'mul_1'),
                                   ('const_mul_1_w', 'mul_1_w'),
                                   ('mul_1_w', 'mul_1'),
                                   ('mul_1', 'scaleshift_1_data'),
                                   ('scaleshift_1_data', 'op_output')
                                   ],
                                  {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])},
                                   'const_mul_1_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
                                   'mul_1_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
                                   'mul_1': {'can_be_fused': True},
                                   'scaleshift_1_data': {}
                                   })
  
          graph.graph['layout'] = 'NHWC'
          convert_scale_shift_to_mul_add(graph)
          graph.clean_up()
          (flag, resp) = compare_graphs(graph, graph_ref, 'placeholder_1')
          self.assertTrue(flag, resp)
  
      # ScaleShift -> Mul->Add
      def test_scaleshift_to_mul_add(self):
          graph = build_graph(nodes_attributes,
                              [('placeholder_1', 'placeholder_1_data'),
                               ('placeholder_1_data', 'scaleshift_1'),
                               ('const_scaleshift_1_w', 'scaleshift_1_w'),
                               ('const_scaleshift_1_b', 'scaleshift_1_b'),
                               ('scaleshift_1_w', 'scaleshift_1'),
                               ('scaleshift_1_b', 'scaleshift_1'),
                               ('scaleshift_1', 'scaleshift_1_data'),
                               ('scaleshift_1_data', 'op_output')
                               ],
                              {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])},
                               'scaleshift_1_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
                               'scaleshift_1_b': {'shape': np.array([3]), 'value': np.array([3, 2, 1])},
                               'scaleshift_1_data': {}
                               })
  
          graph_ref = build_graph(nodes_attributes,
                                  [('placeholder_1', 'placeholder_1_data'),
                                   ('placeholder_1_data', 'mul_1'),
                                   ('const_mul_1_w', 'mul_1_w'),
                                   ('mul_1_w', 'mul_1'),
                                   ('mul_1', 'mul_1_data'),
                                   ('mul_1_data', 'add_1'),
                                   ('const_add_1_w', 'add_1_w'),
                                   ('add_1_w', 'add_1'),
                                   ('add_1', 'scaleshift_1_data'),
                                   ('scaleshift_1_data', 'op_output')
                                   ],
                                  {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])},
                                   'const_mul_1_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
                                   'mul_1_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
                                   'const_add_1_w': {'shape': np.array([3]), 'value': np.array([3, 2, 1])},
                                   'add_1_w': {'shape': np.array([3]), 'value': np.array([3, 2, 1])},
                                   'mul_1_data': {'shape': np.array([1, 227, 227, 3])},
                                   'add_1': {'can_be_fused': True},
                                   'mul_1': {'can_be_fused': True},
                                   'scaleshift_1_data': {}
                                   })
  
          graph.graph['layout'] = 'NHWC'
          convert_scale_shift_to_mul_add(graph)
          graph.clean_up()
          (flag, resp) = compare_graphs(graph, graph_ref, 'placeholder_1')
          self.assertTrue(flag, resp)
  
      # ScaleShift -> None (Zero weights and biases)
      def test_scaleshift_to_nothing(self):
          graph = build_graph(nodes_attributes,
                              [('placeholder_1', 'placeholder_1_data'),
                               ('placeholder_1_data', 'scaleshift_1'),
                               ('const_scaleshift_1_w', 'scaleshift_1_w'),
                               ('const_scaleshift_1_b', 'scaleshift_1_b'),
                               ('scaleshift_1_w', 'scaleshift_1'),
                               ('scaleshift_1_b', 'scaleshift_1'),
                               ('scaleshift_1', 'scaleshift_1_data'),
                               ('scaleshift_1_data', 'op_output')
                               ],
                              {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])},
                               'scaleshift_1_w': {'shape': np.array([3]), 'value': np.array([1, 1, 1])},
                               'scaleshift_1_b': {'shape': np.array([3]), 'value': np.array([0, 0, 0])},
                               'scaleshift_1_data': {'shape': np.array([1, 227, 227, 3])}
                               }, nodes_with_edges_only=True)
  
          graph_ref = build_graph(nodes_attributes,
                                  [('placeholder_1', 'placeholder_1_data'),
                                   ('placeholder_1_data', 'op_output')
                                   ],
                                  {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])}}
                                  ,nodes_with_edges_only=True)
  
          graph.graph['layout'] = 'NHWC'
          convert_scale_shift_to_mul_add(graph)
          graph.clean_up()
          (flag, resp) = compare_graphs(graph, graph_ref, 'placeholder_1')
          self.assertTrue(flag, resp)
  
      # ScaleShift -> ScaleShift (can_be_fused=False)
      def test_scaleshift_can_be_fused(self):
          graph = build_graph(nodes_attributes,
                              [('placeholder_1', 'placeholder_1_data'),
                               ('placeholder_1_data', 'scaleshift_1'),
                               ('const_scaleshift_1_w', 'scaleshift_1_w'),
                               ('const_scaleshift_1_b', 'scaleshift_1_b'),
                               ('scaleshift_1_w', 'scaleshift_1'),
                               ('scaleshift_1_b', 'scaleshift_1'),
                               ('scaleshift_1', 'scaleshift_1_data'),
                               ('scaleshift_1_data', 'op_output')
                               ],
                              {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])},
                               'scaleshift_1_w': {'shape': np.array([3]), 'value': np.array([1, 1, 1])},
                               'scaleshift_1_b': {'shape': np.array([3]), 'value': np.array([0, 0, 0])},
                               'scaleshift_1': {'can_be_fused': False},
                               'scaleshift_1_data': {'shape': np.array([1, 227, 227, 3])}
                               })
  
          graph_ref = build_graph(nodes_attributes,
                                  [('placeholder_1', 'placeholder_1_data'),
                                   ('placeholder_1_data', 'scaleshift_1'),
                                   ('const_scaleshift_1_w', 'scaleshift_1_w'),
                                   ('const_scaleshift_1_b', 'scaleshift_1_b'),
                                   ('scaleshift_1_w', 'scaleshift_1'),
                                   ('scaleshift_1_b', 'scaleshift_1'),
                                   ('scaleshift_1', 'scaleshift_1_data'),
                                   ('scaleshift_1_data', 'op_output')
                                   ],
                                  {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])},
                                   'const_scaleshift_1_w': {'shape': np.array([3]), 'value': np.array([1, 1, 1])},
                                   'scaleshift_1_w': {'shape': np.array([3]), 'value': np.array([1, 1, 1])},
                                   'const_scaleshift_1_b': {'shape': np.array([3]), 'value': np.array([0, 0, 0])},
                                   'scaleshift_1_b': {'shape': np.array([3]), 'value': np.array([0, 0, 0])},
                                   'scaleshift_1': {'can_be_fused': False},
                                   'scaleshift_1_data': {'shape': np.array([1, 227, 227, 3])}
                                   })
  
          convert_scale_shift_to_mul_add(graph)
          graph.clean_up()
  
          (flag, resp) = compare_graphs(graph, graph_ref, 'scaleshift_1_data')
          self.assertTrue(flag, resp)
  
  
  class BatchNormDecomposition(unittest.TestCase):
      def test_bn_decomposition_1(self):
          graph = build_graph(nodes_attributes,
                              [('placeholder_1', 'placeholder_1_data'),
                               ('placeholder_1_data', 'bn_op'),
                               ('const_bn_const', 'bn_const'),
                               ('const_bn_beta', 'bn_beta'),
                               ('const_bn_mean', 'bn_mean'),
                               ('const_bn_var', 'bn_var'),
                               ('bn_const', 'bn_op'),
                               ('bn_beta', 'bn_op'),
                               ('bn_mean', 'bn_op'),
                               ('bn_var', 'bn_op'),
                               ('bn_op', 'bn_data'),
                               ('concat', 'concat_data'),
                               ('bn_data', 'concat'),
                               ('concat_data', 'op_output')
                               ],
                              {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])},
                               'bn_op': {'eps': 1.2},
                               'bn_const': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
                               'bn_beta': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
                               'bn_mean': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
                               'bn_var': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
                               'bn_data': {'shape': np.array([1, 227, 227, 3])},
                               'concat_data': {}
                               }, nodes_with_edges_only=True)
  
          graph_ref = build_graph(nodes_attributes,
                                  [('placeholder_1', 'placeholder_1_data'),
                                   ('placeholder_1_data', 'mul_1'),
                                   ('const_mul_1_w', 'mul_1_w'),
                                   ('mul_1_w', 'mul_1'),
                                   ('mul_1', 'mul_1_data'),
                                   ('mul_1_data', 'add_1'),
                                   ('const_add_1_w', 'add_1_w'),
                                   ('add_1_w', 'add_1'),
                                   ('add_1', 'add_1_data'),
                                   ('add_1_data', 'mul_2'),
                                   ('const_mul_2_w', 'mul_2_w'),
                                   ('mul_2_w', 'mul_2'),
                                   ('mul_2', 'mul_2_data'),
                                   ('mul_2_data', 'add_2'),
                                   ('const_add_2_w', 'add_2_w'),
                                   ('add_2_w', 'add_2'),
                                   ('add_2', 'add_2_data'),
                                   ('concat', 'concat_data'),
                                   ('add_2_data', 'concat'),
                                   ('concat_data', 'op_output')
                                   ],
                                  {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])},
                                   'const_mul_1_w': {'shape': np.array([3]),
                                               'value': np.array([0.67419986, 0.55901699, 0.48795004])},
                                   'mul_1_w': {'shape': np.array([3]),
                                               'value': np.array([0.67419986, 0.55901699, 0.48795004])},
                                   'const_mul_2_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
                                   'mul_2_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
                                   'const_add_1_w': {'shape': np.array([3]),
                                               'value': np.array([-0.67419986, -1.11803399, -1.46385011])},
                                   'add_1_w': {'shape': np.array([3]),
                                               'value': np.array([-0.67419986, -1.11803399, -1.46385011])},
                                   'const_add_2_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
                                   'add_2_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
                                   'add_2_data': {'shape': np.array([1, 227, 227, 3])},
                                   'mul_1': {'can_be_fused': True},
                                   'mul_2': {'can_be_fused': True},
                                   'add_1': {'can_be_fused': True},
                                   'add_2': {'can_be_fused': True},
                                   'concat_data': {}
                                   }, nodes_with_edges_only=True)
  
          graph.graph['layout'] = 'NHWC'
          convert_batch_norm(graph)
          graph.clean_up()
  
          (flag, resp) = compare_graphs(graph, graph_ref, 'concat_data')
          self.assertTrue(flag, resp)
  
      # 'can_be_fused': False for BatchNorm
      def test_bn_decomposition_2(self):
          graph = build_graph(nodes_attributes,
                              [('placeholder_1', 'placeholder_1_data'),
                               ('placeholder_1_data', 'bn_op'),
                               ('const_bn_const', 'bn_const'),
                               ('const_bn_beta', 'bn_beta'),
                               ('const_bn_mean', 'bn_mean'),
                               ('const_bn_var', 'bn_var'),
                               ('bn_const', 'bn_op'),
                               ('bn_beta', 'bn_op'),
                               ('bn_mean', 'bn_op'),
                               ('bn_var', 'bn_op'),
                               ('bn_op', 'bn_data'),
                               ('concat', 'concat_data'),
                               ('bn_data', 'concat'),
                               ('concat_data', 'op_output')
                               ],
                              {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])},
                               'bn_op': {'eps': 1.2, 'can_be_fused': False},
                               'bn_const': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
                               'bn_beta': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
                               'bn_mean': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
                               'bn_var': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
                               'bn_data': {'shape': np.array([1, 227, 227, 3])},
                               'concat_data': {}
                               })
  
          graph_ref = build_graph(nodes_attributes,
                                  [('placeholder_1', 'placeholder_1_data'),
                                   ('placeholder_1_data', 'mul_1'),
                                   ('const_mul_1_w', 'mul_1_w'),
                                   ('mul_1_w', 'mul_1'),
                                   ('mul_1', 'mul_1_data'),
                                   ('mul_1_data', 'add_1'),
                                   ('const_add_1_w', 'add_1_w'),
                                   ('add_1_w', 'add_1'),
                                   ('add_1', 'add_1_data'),
                                   ('add_1_data', 'mul_2'),
                                   ('const_mul_2_w', 'mul_2_w'),
                                   ('mul_2_w', 'mul_2'),
                                   ('mul_2', 'mul_2_data'),
                                   ('mul_2_data', 'add_2'),
                                   ('const_add_2_w', 'add_2_w'),
                                   ('add_2_w', 'add_2'),
                                   ('add_2', 'add_2_data'),
                                   ('concat', 'concat_data'),
                                   ('add_2_data', 'concat'),
                                   ('concat_data', 'op_output')
                                   ],
                                  {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])},
                                   'const_mul_1_w': {'shape': np.array([3]),
                                               'value': np.array([0.67419986, 0.55901699, 0.48795004])},
                                   'mul_1_w': {'shape': np.array([3]),
                                               'value': np.array([0.67419986, 0.55901699, 0.48795004])},
                                   'const_mul_2_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
                                   'mul_2_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
                                   'const_add_1_w': {'shape': np.array([3]),
                                               'value': np.array([-0.67419986, -1.11803399, -1.46385011])},
                                   'add_1_w': {'shape': np.array([3]),
                                               'value': np.array([-0.67419986, -1.11803399, -1.46385011])},
                                   'const_add_2_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
                                   'add_2_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
                                   'add_2_data': {'shape': np.array([1, 227, 227, 3])},
                                   'mul_1': {'can_be_fused': False},
                                   'mul_2': {'can_be_fused': False},
                                   'add_1': {'can_be_fused': False},
                                   'add_2': {'can_be_fused': False},
                                   'concat_data': {}
                                   })
  
          graph.graph['layout'] = 'NHWC'
          convert_batch_norm(graph)
          graph.clean_up()
  
          (flag, resp) = compare_graphs(graph, graph_ref, 'concat_data')
          self.assertTrue(flag, resp) """
   Copyright (C) 2018-2020 Intel Corporation
  
   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
  from argparse import Namespace
  
  import numpy as np
  
  from extensions.back.InterpolateReshape import InterpolateReshapeWA, InterpolateConcat
  from mo.utils.ir_engine.compare_graphs import compare_graphs
  from mo.utils.unittest.graph import build_graph, result, regular_op_with_shaped_data, valued_const_with_data, connect, \
      connect_data
  
  nodes = {
      **regular_op_with_shaped_data('placeholder', [1, 3, 30, 40], {'type': 'Parameter'}),
      **valued_const_with_data('out_shape', np.array([60, 160])),
  
      **regular_op_with_shaped_data('interpolate', [1, 3, 60, 160], {'type': 'Interpolate', 'axes': [2, 3]}),
  
      **regular_op_with_shaped_data('shape', [4], {'type': 'ShapeOf'}),
      **valued_const_with_data('indices', np.array([2, 3])),
      **valued_const_with_data('axis', np.array(0)),
      **regular_op_with_shaped_data('gather', [2], {'type': 'Gather'}),
  
      **valued_const_with_data('multiplier', np.array([2, 4])),
      **regular_op_with_shaped_data('mul', [2], {'type': 'Multiply'}),
  
      **regular_op_with_shaped_data('placeholder_1', [1, 3, 60, 160], {'type': 'Parameter'}),
      **regular_op_with_shaped_data('concat', [1, 7, 60, 160], {'type': 'Concat', 'axis': 1}),
  
      **result(),
  }
  
  
  class TestInterpolateReshapeWA(unittest.TestCase):
      def test_interpolate_reshape_graph_comparison(self):
          graph = build_graph(nodes, [
              *connect('placeholder', '0:interpolate'),
              *connect('out_shape', '1:interpolate'),
              *connect('interpolate', 'output'),
          ], nodes_with_edges_only=True)
          InterpolateReshapeWA().find_and_replace_pattern(graph)
          graph.graph['cmd_params'] = Namespace(keep_shape_ops=True)
          graph.clean_up()
          graph_ref = build_graph(nodes, [
              *connect('placeholder', '0:interpolate'),
              *connect_data('placeholder', 'shape'),
              *connect('shape', '0:gather'),
              *connect('indices', '1:gather'),
              *connect('axis', '2:gather'),
              *connect('gather', '0:mul'),
              *connect('multiplier', '1:mul'),
              *connect('mul', '1:interpolate'),
              *connect('interpolate', 'output'),
          ], nodes_with_edges_only=True)
          (flag, resp) = compare_graphs(graph, graph_ref, 'output', check_op_attrs=True)
          self.assertTrue(flag, resp)
  
  
  class TestInterpolateConcat(unittest.TestCase):
      def test_interpolate_concat_reshape_graph_comparison(self):
          graph = build_graph(nodes, [
              *connect('placeholder', '0:interpolate'),
              *connect('out_shape', '1:interpolate'),
              *connect('interpolate', '0:concat'),
              *connect('placeholder_1', '1:concat'),
              *connect('concat', 'output'),
          ], nodes_with_edges_only=True)
          InterpolateConcat().find_and_replace_pattern(graph)
          graph.graph['cmd_params'] = Namespace(keep_shape_ops=True)
          graph.clean_up()
          graph_ref = build_graph(nodes, [
              *connect('placeholder', '0:interpolate'),
              *connect('placeholder_1', 'shape'),
              *connect('shape', '0:gather'),
              *connect('indices', '1:gather'),
              *connect('axis', '2:gather'),
              *connect('gather', '1:interpolate'),
              *connect('interpolate', '0:concat'),
              *connect_data('placeholder_1', '1:concat'),
              *connect('concat', 'output'),
          ], nodes_with_edges_only=True)
          (flag, resp) = compare_graphs(graph, graph_ref, 'output', check_op_attrs=True)
          self.assertTrue(flag, resp)
  
apis: numpy.array
apis: numpy.array