(builder, node, graph, err)
convert to CoreML Reshape Static Layer:
    https://github.com/apple/coremltools/blob/655b3be5cc0d42c3c4fa49f0f0e4a93a26b3e492/mlmodel/format/NeuralNetwork.proto#L4844
convert to CoreML Reshape Static Layer:
    https://github.com/apple/coremltools/blob/655b3be5cc0d42c3c4fa49f0f0e4a93a26b3e492/mlmodel/format/NeuralNetwork.proto#L4844
convert to CoreML Reshape Static Layer : https : // github . com / apple / coremltools / blob / 655b3be5cc0d42c3c4fa49f0f0e4a93a26b3e492 / mlmodel / format / NeuralNetwork . proto#L4844
def _convert_reshape(builder, node, graph, err):
    '''
    convert to CoreML Reshape Static Layer:
    https://github.com/apple/coremltools/blob/655b3be5cc0d42c3c4fa49f0f0e4a93a26b3e492/mlmodel/format/NeuralNetwork.proto#L4844
    '''
    shape_node = node.inputs[1]
    if shape_node in node.input_tensors:
        output_shape = node.input_tensors[shape_node].astype(np.int64)
    
        # if rank is same, then call rank preserving reshape
        if node.inputs[0] not in graph.shape_dict:
            # If Input shape is not present and output shape is known
            # add reshape static as 
            # TODO: ONNX should be able to infer the shape
            builder.add_reshape_static(
                name=node.name,
                input_name=node.inputs[0],
                output_name=node.outputs[0],
                output_shape=output_shape
            )
            return
    
        len_of_input_shape = builder._get_rank(node.inputs[0])
        if len(output_shape) == len_of_input_shape:
            builder.add_rank_preserving_reshape(
                name=node.name,
                input_name=node.inputs[0],
                output_name=node.outputs[0],
                output_shape=output_shape
            )
        else:
            add_static_reshape = True
            if len_of_input_shape > len(output_shape):
                # Output rank is less than input rank
                # Case when most of the dims size is unchanged
                num_zeros = 0
                num_neg_ones = 0
                for i in output_shape:
                    if i == 0:
                        num_zeros += 1
                    elif i == -1:
                        num_neg_ones += 1

                if num_neg_ones > 1:
                     err.unsupported_op_configuration(builder, node, graph, "Error in ONNX model: At most one dimension of new shape can be -1, found {}".format(num_neg_ones))

                if num_neg_ones + num_zeros == len(output_shape):
                    # Rank of output is less than input
                    # Make Rank equivalent for reshape and then squeeze
                    add_static_reshape = False
                    new_shape = []
                    i = 0
                    for i in range(len(output_shape)):
                        new_shape.append(output_shape[i])
                        if output_shape[i] == -1:
                            break
                    while i < len_of_input_shape-1:
                        new_shape.append(1)
                        i += 1

                    builder.add_rank_preserving_reshape(
                        name=node.name + '_reshape_preserving',
                        input_name=node.inputs[0],
                        output_name=node.outputs[0] + '_reshape_dim_preserved',
                        output_shape=new_shape
                    )

                    squeeze_axes = list(range(len(output_shape) - len_of_input_shape, 0))
                    squeeze_axes.reverse()

                    builder.add_squeeze(
                        name=node.name,
                        input_name=node.outputs[0] + '_reshape_dim_preserved',
                        output_name=node.outputs[0],
                        axes=squeeze_axes
                    )

            if add_static_reshape:
                builder.add_reshape_static(
                    name=node.name,
                    input_name=node.inputs[0],
                    output_name=node.outputs[0],
                    output_shape=output_shape
                )
    else:
        builder.add_reshape_dynamic(
            name=node.name,
            input_names=node.inputs,
            output_name=node.outputs[0],
        )
def _convert_reshape ( builder , node , graph , err ) : shape_node = node . inputs [ 1 ] if shape_node in node . input_tensors : output_shape = node . input_tensors [ shape_node ] . astype ( np . int64 ) # if rank is same, then call rank preserving reshape if node . inputs [ 0 ] not in graph . shape_dict : # If Input shape is not present and output shape is known # add reshape static as  # TODO: ONNX should be able to infer the shape builder . add_reshape_static ( name = node . name , input_name = node . inputs [ 0 ] , output_name = node . outputs [ 0 ] , output_shape = output_shape ) return len_of_input_shape = builder . _get_rank ( node . inputs [ 0 ] ) if len ( output_shape ) == len_of_input_shape : builder . add_rank_preserving_reshape ( name = node . name , input_name = node . inputs [ 0 ] , output_name = node . outputs [ 0 ] , output_shape = output_shape ) else : add_static_reshape = True if len_of_input_shape > len ( output_shape ) : # Output rank is less than input rank # Case when most of the dims size is unchanged num_zeros = 0 num_neg_ones = 0 for i in output_shape : if i == 0 : num_zeros += 1 elif i == - 1 : num_neg_ones += 1 if num_neg_ones > 1 : err . unsupported_op_configuration ( builder , node , graph , "Error in ONNX model: At most one dimension of new shape can be -1, found {}" . format ( num_neg_ones ) ) if num_neg_ones + num_zeros == len ( output_shape ) : # Rank of output is less than input # Make Rank equivalent for reshape and then squeeze add_static_reshape = False new_shape = [ ] i = 0 for i in range ( len ( output_shape ) ) : new_shape . append ( output_shape [ i ] ) if output_shape [ i ] == - 1 : break while i < len_of_input_shape - 1 : new_shape . append ( 1 ) i += 1 builder . add_rank_preserving_reshape ( name = node . name + '_reshape_preserving' , input_name = node . inputs [ 0 ] , output_name = node . outputs [ 0 ] + '_reshape_dim_preserved' , output_shape = new_shape ) squeeze_axes = list ( range ( len ( output_shape ) - len_of_input_shape , 0 ) ) squeeze_axes . reverse ( ) builder . add_squeeze ( name = node . name , input_name = node . outputs [ 0 ] + '_reshape_dim_preserved' , output_name = node . outputs [ 0 ] , axes = squeeze_axes ) if add_static_reshape : builder . add_reshape_static ( name = node . name , input_name = node . inputs [ 0 ] , output_name = node . outputs [ 0 ] , output_shape = output_shape ) else : builder . add_reshape_dynamic ( name = node . name , input_names = node . inputs , output_name = node . outputs [ 0 ] , )