def generate(info, template):
    include_lines = []
    creator_lines = ['// Function creator']

    for i, (category, functions) in enumerate(info['Functions'].items()):
        for j, (function, function_info) in enumerate(functions.items()):
            creator_lines.append('if( func.type() == "{}") {{'.format(function))
            arg_info = function_arguments(function_info)
            include_lines.append('#include <nbla/function/{}.hpp>'.format(info['Names'][function]))

            if len(arg_info['names']) > 0:
                creator_lines.append('    {}Parameter param = func.{}_param();'.format(function, info['Names'][function]))
                args = []
                arg_index = 1
                for arg_name, arg_type in zip(arg_info['names'], arg_info['types']):
                    av = 'arg{}'.format(arg_index)
                    if arg_type == 'repeated int64':
                        creator_lines.append('    std::vector<int> {};'.format(av))
                        creator_lines.append('    for( int i = 0; i < param.{}_size(); i++) {{'.format(arg_name))
                        creator_lines.append('        {}.push_back(param.{}(i));'.format(av, arg_name))
                        creator_lines.append('    }')
                    elif arg_type == 'Shape':
                        creator_lines.append('    std::vector<int> {};'.format(av))
                        creator_lines.append('    {')
                        creator_lines.append('        Shape s = param.{}();'.format(arg_name))
                        creator_lines.append('        for( int i = 0; i < s.dim_size(); i++) {')
                        creator_lines.append('            {}.push_back(s.dim(i));'.format(av))
                        creator_lines.append('        }')
                        creator_lines.append('    }')
                    elif arg_type == 'double':
                        creator_lines.append('    double {} = param.{}();'.format(av, arg_name))
                    elif arg_type == 'float':
                        creator_lines.append('    float {} = param.{}();'.format(av, arg_name))
                    elif arg_type == 'int64':
                        creator_lines.append('    int {} = param.{}();'.format(av, arg_name))
                    elif arg_type == 'bool':
                        creator_lines.append('    bool {} = param.{}();'.format(av, arg_name))
                    elif arg_type == 'string':
                        creator_lines.append('    std::string {} = param.{}();'.format(av, arg_name))
                    args.append(av)
                    arg_index += 1

                creator_lines.append('    nbla::FunctionPtr fp = create_{}(ctx_, {});'.format(function, ' ,'.join(args)))
            else:
                creator_lines.append('    nbla::FunctionPtr fp = create_{}(ctx_);'.format(function))
            creator_lines.append('    return std::make_shared<nbla::CgFunction>(fp);')

            creator_lines.append('}')

    creator_lines.append('// End of function creator')

    function_includes = "\n".join(include_lines)
    function_creator = "\n            ".join(creator_lines)

    return template.format(function_includes=function_includes,
                           function_creator=function_creator)
def generate(info, template):
    definitions = []
    for function, function_info in each_function(info):
        arg_info = function_arguments(function_info)
        function_args = ''
        for arg_name, arg_type in zip(arg_info['names'], arg_info['types']):
            function_args += ', {} {}'.format(utils.type_conv.type_from_proto[
                                              arg_type]['pyx'], arg_name)
        definitions.append(
            'cdef extern from "nbla/function/{}.hpp" namespace "nbla":'.format(info['Names'][function]))
        definitions.append(
            '    shared_ptr[CFunction] create_{}(const CContext&{}) except +'.format(function, function_args))

    return template.format(function_definitions='\n'.join(definitions))
Ejemplo n.º 3
0
def generate(info, func_name, func_name_snakecase, template):

    arg_info = common.function_arguments(info)
    func_arg_variable_defines = '\n'.join(['protected:'] + [
        '{} {}_;'.format(utils.type_conv.type_from_proto[t]['cpp_var'], n)
        for t, n in zip(arg_info['types'], arg_info['names'])
    ])
    func_arg_variable_types = ', '.join(
        [func_name] +
        [utils.type_conv.type_from_proto[t]['cpp'] for t in arg_info['types']])
    func_arg_initializers = ', '.join(
        ['{0}_({0})'.format(n) for n in arg_info['names']])
    func_arg_variables = ', '.join(
        ['ctx_'] + ['{}_'.format(n) for n in arg_info['names']])
    func_args = ', '.join(['const Context &ctx'] + [
        '{} {}'.format(utils.type_conv.type_from_proto[t]['cpp'], n)
        for t, n in zip(arg_info['types'], arg_info['names'])
    ])

    io_info = common.function_io(info)
    template_defines = ', '.join(
        ['typename {}'.format(t) for t in io_info['templates']])
    in_types = ', '.join(
        ['get_dtype<{}>()'.format(t) for t in io_info['input']['types']])
    out_types = ', '.join(
        ['get_dtype<{}>()'.format(t) for t in io_info['output']['types']])
    min_inputs = io_info['input']['min']
    min_outputs = io_info['output']['min']

    base_function_types = ', '.join(
        [utils.type_conv.type_from_proto[t]['cpp'] for t in arg_info['types']])
    base_function_args = ', '.join(['ctx'] +
                                   ['{}'.format(n) for n in arg_info['names']])

    return template.format(func_name=func_name,
                           func_name_upcase=func_name.upper(),
                           template_defines=template_defines,
                           func_args=func_args,
                           func_arg_variable_defines=func_arg_variable_defines,
                           func_arg_variable_types=func_arg_variable_types,
                           func_arg_variables=func_arg_variables,
                           func_arg_initializers=func_arg_initializers,
                           in_types=in_types,
                           out_types=out_types,
                           min_inputs=min_inputs,
                           min_outputs=min_outputs,
                           base_function_types=base_function_types,
                           base_function_args=base_function_args)
def generate(info, template):
    create_functions = []
    if_prefix = ''
    for function, function_info in each_function(info):
        arg_info = function_arguments(function_info)
        create_functions.append(
            '    {}if f.type == "{}":'.format(if_prefix, function))
        args = ['ctx']
        for arg, type in zip(arg_info['names'], arg_info['types']):
            arg_suffix = '.dim' if type == 'Shape' else ''
            args.append('{0}=f.{1}_param.{0}{2}'.format(
                arg, info['Names'][function], arg_suffix))
        create_functions.append('        function = F.{}({})'.format(
            function, ',\n            '.join(args)))
        if_prefix = 'el'
    return template.format(create_functions='\n'.join(create_functions))
Ejemplo n.º 5
0
def generate(info, template):
    create_functions = []
    if_prefix = ''
    for function, function_info in each_function(info):
        arg_info = function_arguments(function_info)
        create_functions.append('    {}if f.type == "{}":'.format(
            if_prefix, function))
        args = ['ctx']
        for arg, type in zip(arg_info['names'], arg_info['types']):
            arg_suffix = '.dim' if type == 'Shape' else ''
            args.append('{0}=f.{1}_param.{0}{2}'.format(
                arg, info['Names'][function], arg_suffix))
        create_functions.append('        function = F.{}({})'.format(
            function, ',\n            '.join(args)))
        if_prefix = 'el'
    return template.format(create_functions='\n'.join(create_functions))
def generate(info, template):
    definitions = []
    for function, function_info in each_function(info):
        arg_info = function_arguments(function_info)
        function_args = ''
        for arg_name, arg_type in zip(arg_info['names'], arg_info['types']):
            function_args += ', {} {}'.format(
                utils.type_conv.type_from_proto[arg_type]['pyx'], arg_name)
        definitions.append(
            'cdef extern from "nbla/function/{}.hpp" namespace "nbla":'.format(
                info['Names'][function]))
        definitions.append(
            '    shared_ptr[CFunction] create_{}(const CContext&{}) except +'.
            format(function, function_args))

    return template.format(function_definitions='\n'.join(definitions))
def generate(info, func_name, func_name_snakecase, template):

    arg_info = common.function_arguments(info)
    func_arg_variables = ', '.join(
        ['ctx'] + ['{}'.format(n) for n in arg_info['names']])
    func_args = ', '.join(['const Context &ctx'] + ['{} {}'.format(utils.type_conv.type_from_proto[
                          t]['cpp'], n) for t, n in zip(arg_info['types'], arg_info['names'])])

    io_info = common.function_io(info)
    template_defines = ', '.join(['typename {}'.format(t)
                                  for t in io_info['templates']])
    templates = ', '.join(io_info['templates'])

    return template.format(func_name=func_name,
                           func_name_snakecase=func_name_snakecase,
                           func_name_upcase=func_name.upper(),
                           templates=templates,
                           template_defines=template_defines,
                           func_args=func_args,
                           func_arg_variables=func_arg_variables)
def generate(info, template):
    definitions = []
    for function, function_info in each_function(info):
        arg_info = function_arguments(function_info)
        function_args1 = ''
        function_args2 = ''
        store_args = ['    info.args = {}']
        for arg_name, arg_type in zip(arg_info['names'], arg_info['types']):
            function_args1 += ', {} {}'.format(utils.type_conv.type_from_proto[
                                               arg_type]['pyx'], arg_name)
            function_args2 += ', {}'.format(arg_name)
            store_args.append("    info.args['{0}'] = {0}".format(arg_name))
        definitions.append('def {}(CContext ctx{}):'.format(
            function, function_args1))
        definitions.append('    info = Info()')
        definitions += store_args
        definitions.append('    info.type_name = \'{}\''.format(function))
        definitions.append('    f = Function.create(create_{}(ctx{}), info)'.format(
            function, function_args2))
        definitions.append('    return f')
    return template.format(function_definitions='\n'.join(definitions))
def generate(info, func_name, func_name_snakecase, template):

    arg_info = common.function_arguments(info)
    func_arg_variable_defines = '\n'.join(['protected:'] + ['{} {}_;'.format(utils.type_conv.type_from_proto[
                                          t]['cpp_var'], n) for t, n in zip(arg_info['types'], arg_info['names'])])
    func_arg_variable_types = ', '.join(
        [func_name] + [utils.type_conv.type_from_proto[t]['cpp'] for t in arg_info['types']])
    func_arg_initializers = ', ' + ', '.join(['{0}_({0})'.format(n) for n in arg_info['names']])
    func_arg_variables = ', '.join(
        ['ctx_'] + ['{}_'.format(n) for n in arg_info['names']])
    func_args = ', '.join(['const Context &ctx'] + ['{} {}'.format(utils.type_conv.type_from_proto[
                          t]['cpp'], n) for t, n in zip(arg_info['types'], arg_info['names'])])

    io_info = common.function_io(info)
    template_defines = ', '.join(['typename {}'.format(t)
                                  for t in io_info['templates']])
    in_types = ', '.join(['get_dtype<{}>()'.format(t)
                          for t in io_info['input']['types']])
    out_types = ', '.join(['get_dtype<{}>()'.format(t)
                           for t in io_info['output']['types']])
    min_inputs = io_info['input']['min']
    min_outputs = io_info['output']['min']

    base_function_types = ', '.join([utils.type_conv.type_from_proto[t]['cpp'] for t in arg_info['types']])
    base_function_args = ', '.join(['ctx'] + ['{}'.format(n) for n in arg_info['names']])

    return template.format(func_name=func_name,
                           func_name_upcase=func_name.upper(),
                           template_defines=template_defines,
                           func_args=func_args,
                           func_arg_variable_defines=func_arg_variable_defines,
                           func_arg_variable_types=func_arg_variable_types,
                           func_arg_variables=func_arg_variables,
                           func_arg_initializers=func_arg_initializers,
                           in_types=in_types,
                           out_types=out_types,
                           min_inputs=min_inputs,
                           min_outputs=min_outputs,
                           base_function_types=base_function_types,
                           base_function_args=base_function_args)
def generate(info, template):
    definitions = []
    for function, function_info in each_function(info):
        arg_info = function_arguments(function_info)
        function_args1 = ''
        function_args2 = ''
        store_args = ['    info.args = {}']
        for arg_name, arg_type in zip(arg_info['names'], arg_info['types']):
            function_args1 += ', {} {}'.format(
                utils.type_conv.type_from_proto[arg_type]['pyx'], arg_name)
            function_args2 += ', {}'.format(arg_name)
            store_args.append("    info.args['{0}'] = {0}".format(arg_name))
        definitions.append('def {}(CContext ctx{}):'.format(
            function, function_args1))
        definitions.append('    info = Info()')
        definitions += store_args
        definitions.append('    info.type_name = \'{}\''.format(function))
        definitions.append(
            '    f = Function.create(create_{}(ctx{}), info)'.format(
                function, function_args2))
        definitions.append('    return f')
    return template.format(function_definitions='\n'.join(definitions))
Ejemplo n.º 11
0
def generate(info, func_name, func_name_snakecase, template):

    arg_info = common.function_arguments(info)
    func_arg_variables = ', '.join(['ctx'] +
                                   ['{}'.format(n) for n in arg_info['names']])
    func_args = ', '.join(['const Context &ctx'] + [
        '{} {}'.format(utils.type_conv.type_from_proto[t]['cpp'], n)
        for t, n in zip(arg_info['types'], arg_info['names'])
    ])

    io_info = common.function_io(info)
    template_defines = ', '.join(
        ['typename {}'.format(t) for t in io_info['templates']])
    templates = ', '.join(io_info['templates'])

    return template.format(func_name=func_name,
                           func_name_snakecase=func_name_snakecase,
                           func_name_upcase=func_name.upper(),
                           templates=templates,
                           template_defines=template_defines,
                           func_args=func_args,
                           func_arg_variables=func_arg_variables)
Ejemplo n.º 12
0
def generate(info, template):
    function_args = []
    function_arg_definitions = []

    for i, (category, functions) in enumerate(info['Functions'].items()):
        function_args.append('')
        function_args.append('    // {} functions'.format(category))
        for j, (function, function_info) in enumerate(functions.items()):
            arg_info = function_arguments(function_info)
            if len(arg_info['names']) > 0:
                function_args.append('    {}Parameter {}_param = {};'.format(
                    function, info['Names'][function], (i + 1) * 1000 + j + 1))
                function_arg_definitions.append('')
                function_arg_definitions.append(
                    'message {}Parameter {{'.format(function))
                for k, (t, n) in enumerate(
                        zip(arg_info['types'], arg_info['names'])):
                    function_arg_definitions.append('  {} {} = {};'.format(
                        t, n, k + 1))
                function_arg_definitions.append('}')

    return template.format(
        function_args='\n'.join(function_args),
        function_arg_definitions='\n'.join(function_arg_definitions))
def generate(info, template):
    function_args = []
    function_arg_definitions = []

    for i, (category, functions) in enumerate(info['Functions'].items()):
        function_args.append('')
        function_args.append('    // {} functions'.format(category))
        for j, (function, function_info) in enumerate(functions.items()):
            arg_info = function_arguments(function_info)
            if len(arg_info['names']) > 0:
                function_args.append('    {}Parameter {}_param = {};'.format(function,
                                                                             info['Names'][
                                                                                 function],
                                                                             (i + 1) * 1000 + j + 1))
                function_arg_definitions.append('')
                function_arg_definitions.append(
                    'message {}Parameter {{'.format(function))
                for k, (t, n) in enumerate(zip(arg_info['types'], arg_info['names'])):
                    function_arg_definitions.append(
                        '  {} {} = {};'.format(t, n, k + 1))
                function_arg_definitions.append('}')

    return template.format(function_args='\n'.join(function_args),
                           function_arg_definitions='\n'.join(function_arg_definitions))
def generate(info, template):
    lines = []
    if_prefix = ''
    for function, function_info in each_function(info):
        arg_info = function_arguments(function_info)
        lines.append('    {}if function[\'type\'] == "{}":'.format(
            if_prefix, function))
        arg_prefix = 'f.{}_param'.format(info['Names'][function])

        for arg, arg_type in zip(arg_info['names'], arg_info['types']):
            if arg_type in ['float', 'double', 'int64', 'string']:
                lines.append(
                    '        {0}.{1} = function[\'args\'][\'{1}\']'.format(arg_prefix, arg))
            elif arg_type == 'bool':
                lines.append(
                    '        if function[\'args\'][\'{}\']:'.format(arg))
                lines.append(
                    '            {0}.{1} = True'.format(arg_prefix, arg))
                lines.append('        else:')
                lines.append(
                    '            {0}.{1} = False'.format(arg_prefix, arg))
                pass
            elif arg_type == 'Shape':
                lines.append('        {0}.{1}.dim.extend(function[\'args\'][\'{1}\'])'.format(
                    arg_prefix, arg))
            elif arg_type == 'repeated int64':
                lines.append(
                    '        {0}.{1}.extend(function[\'args\'][\'{1}\'])'.format(arg_prefix, arg))
            else:
                print('Unknown argument type [{}]'.format(arg_type))
                raise 'Unknown argument type [{}]'.format(arg_type)

            arg_suffix = '.dim' if type == 'Shape' else ''
        lines.append('        pass')
        if_prefix = 'el'
    return template.format(create_function_args='\n'.join(lines))
Ejemplo n.º 15
0
def generate(info, template):
    apis = []
    for function, function_info in each_function(info):
        io_info = function_io(function_info)
        arg_info = function_arguments(function_info)

        desc = function_info['description']

        variadic = False
        desc.append('Args:')
        for a_n, a_info in function_info['input'].items():
            a_type = '~nnabla.Variable'
            if 'Options' in a_info:
                if 'Variadic' in a_info['Options']:
                    variadic = True
            name = a_n
            if variadic:
                name = '*inputs'
            if 'Options' in a_info:
                desc.append('    {}({}): [{}] {}'.format(
                    name, a_type, a_info['Options'], a_info['Description']))
            else:
                desc.append('    {}({}): {}'.format(name, a_type,
                                                    a_info['Description']))

        if 'argument' in function_info:
            for a_n, a_info in function_info['argument'].items():

                a_type = a_info['Type']
                if a_type == 'Shape':
                    a_type = ':obj:`tuple` of :obj:`int`'
                elif a_type == 'int64':
                    a_type = 'int'
                elif a_type == 'double':
                    a_type = 'float'

                if variadic:
                    desc.append('    **param({}): [name={}] {}'.format(
                        a_type, a_n, a_info['Description']))
                else:
                    desc.append('    {}({}): {}'.format(
                        a_n, a_type, a_info['Description']))

        desc.append('')
        desc.append('Returns:')

        for o_n, o_info in function_info['output'].items():
            desc.append('    ~nnabla.Variable: {}'.format(
                o_info['Description']))

        desc.append('')

        description = '\n    '.join(desc)

        if io_info['input']['repeat']:
            apis.append(
                generate_repeated_inputs(info, function, io_info, arg_info,
                                         description))
            continue

        args1 = []
        args2 = []
        args3 = []
        args3_optional = []
        optional_code = []
        set_default_values = []

        for i, n in enumerate(io_info['input']['names']):
            if i < io_info['input']['min']:
                args1.append(n)
                args3.append(n)
            else:
                args1.append('{} = None'.format(n))
                args3_optional.append(n)

        for n, d in zip(arg_info['names'], arg_info['defaults']):
            args2.append(n)
            if d is None:
                args1.append(n)
            else:
                if d.__class__.__name__ == "DefaultRHS":
                    args1.append('{}=None'.format(n))
                    set_default_values.append('    if {} is None:'.format(n))
                    set_default_values.append('        {} = {}'.format(
                        n, d.rhs))
                else:
                    args1.append('{}={}'.format(n, repr(d)))

        if len(args1) > 0:
            args1 = ', ' + ', '.join(args1)
        else:
            args1 = ''
        if len(args2) > 0:
            args2 = ', ' + ', '.join(args2)
        else:
            args2 = ''
        if len(args3_optional) > 0:
            optional_code.append('    inputs = ({})'.format(', '.join(args3)))
            for a in args3_optional:
                optional_code.append('    if {} is not None:'.format(a))
                optional_code.append('        inputs += ({}, )'.format(a))
            args3 = '*inputs'
        else:
            args3 = ','.join(args3)
        if args3:
            args3 += ', '

        apis.append('')
        apis.append('')
        apis.append('@function_api')
        apis.append('def {}(ctx{}, n_outputs=-1, outputs=None):'.format(
            info['Names'][function], args1))
        apis.append('    r"""{}'.format(description))
        apis.append('    """')
        apis.append('')
        apis += optional_code
        apis += set_default_values
        apis.append(
            '    return F.{}(ctx{})({}n_outputs=n_outputs, auto_forward=get_auto_forward(), outputs=outputs)'
            .format(function, args2, args3))
    return template.format(function_apis='\n'.join(apis))
Ejemplo n.º 16
0
def generate(info, template):
    include_lines = []
    creator_lines = ['// Function creator']

    for i, (category, functions) in enumerate(info['Functions'].items()):
        for j, (function, function_info) in enumerate(functions.items()):
            creator_lines.append(
                'if( func.type() == "{}") {{'.format(function))
            arg_info = function_arguments(function_info)
            include_lines.append('#include <nbla/function/{}.hpp>'.format(
                info['Names'][function]))

            if len(arg_info['names']) > 0:
                creator_lines.append(
                    '    {}Parameter param = func.{}_param();'.format(
                        function, info['Names'][function]))
                args = []
                arg_index = 1
                for arg_name, arg_type in zip(arg_info['names'],
                                              arg_info['types']):
                    av = 'arg{}'.format(arg_index)
                    if arg_type == 'repeated int64':
                        creator_lines.append(
                            '    std::vector<int> {};'.format(av))
                        creator_lines.append(
                            '    for( int i = 0; i < param.{}_size(); i++) {{'.
                            format(arg_name))
                        creator_lines.append(
                            '        {}.push_back(param.{}(i));'.format(
                                av, arg_name))
                        creator_lines.append('    }')
                    elif arg_type == 'Shape':
                        creator_lines.append(
                            '    std::vector<int> {};'.format(av))
                        creator_lines.append('    {')
                        creator_lines.append(
                            '        Shape s = param.{}();'.format(arg_name))
                        creator_lines.append(
                            '        for( int i = 0; i < s.dim_size(); i++) {')
                        creator_lines.append(
                            '            {}.push_back(s.dim(i));'.format(av))
                        creator_lines.append('        }')
                        creator_lines.append('    }')
                    elif arg_type == 'double':
                        creator_lines.append(
                            '    double {} = param.{}();'.format(av, arg_name))
                    elif arg_type == 'float':
                        creator_lines.append(
                            '    float {} = param.{}();'.format(av, arg_name))
                    elif arg_type == 'int64':
                        creator_lines.append('    int {} = param.{}();'.format(
                            av, arg_name))
                    elif arg_type == 'bool':
                        creator_lines.append(
                            '    bool {} = param.{}();'.format(av, arg_name))
                    elif arg_type == 'string':
                        creator_lines.append(
                            '    std::string {} = param.{}();'.format(
                                av, arg_name))
                    args.append(av)
                    arg_index += 1

                creator_lines.append(
                    '    nbla::FunctionPtr fp = create_{}(ctx_, {});'.format(
                        function, ' ,'.join(args)))
            else:
                creator_lines.append(
                    '    nbla::FunctionPtr fp = create_{}(ctx_);'.format(
                        function))
            creator_lines.append(
                '    return std::make_shared<nbla::CgFunction>(fp);')

            creator_lines.append('}')

    creator_lines.append('// End of function creator')

    function_includes = "\n".join(include_lines)
    function_creator = "\n            ".join(creator_lines)

    return template.format(function_includes=function_includes,
                           function_creator=function_creator)
def generate(info, template):
    apis = []
    for function, function_info in each_function(info):
        io_info = function_io(function_info)
        arg_info = function_arguments(function_info)

        desc = function_info['description']

        variadic = False
        desc.append('Args:')
        for a_n, a_info in function_info['input'].items():
            a_type = '~nnabla.Variable'
            if 'Options' in a_info:
                if 'Variadic' in a_info['Options']:
                    variadic = True
            name = a_n
            if variadic:
                name = '*inputs'
            if 'Options' in a_info:
                desc.append('    {}({}): [{}] {}'.format(
                    name, a_type, a_info['Options'], a_info['Description']))
            else:
                desc.append('    {}({}): {}'.format(
                    name, a_type, a_info['Description']))

        if 'argument' in function_info:
            for a_n, a_info in function_info['argument'].items():

                a_type = a_info['Type']
                if a_type == 'Shape':
                    a_type = ':obj:`tuple` of :obj:`int`'
                elif a_type == 'int64':
                    a_type = 'int'
                elif a_type == 'double':
                    a_type = 'float'

                if variadic:
                    desc.append(
                        '    **param({}): [name={}] {}'.format(a_type, a_n, a_info['Description']))
                else:
                    desc.append('    {}({}): {}'.format(
                        a_n, a_type, a_info['Description']))

        desc.append('')
        desc.append('Returns:')

        for o_n, o_info in function_info['output'].items():
            desc.append('    ~nnabla.Variable: {}'.format(
                o_info['Description']))

        desc.append('')

        description = '\n    '.join(desc)

        if io_info['input']['repeat']:
            apis.append(generate_repeated_inputs(
                info, function, io_info, arg_info, description))
            continue

        args1 = []
        args2 = []
        args3 = []
        args3_optional = []
        optional_code = []
        set_default_values = []

        for i, n in enumerate(io_info['input']['names']):
            if i < io_info['input']['min']:
                args1.append(n)
                args3.append(n)
            else:
                args1.append('{} = None'.format(n))
                args3_optional.append(n)

        for n, d in zip(arg_info['names'], arg_info['defaults']):
            args2.append(n)
            if d is None:
                args1.append(n)
            else:
                if d.__class__.__name__ == "DefaultRHS":
                    args1.append('{}=None'.format(n))
                    set_default_values.append('    if {} is None:'.format(n))
                    set_default_values.append(
                        '        {} = {}'.format(n, d.rhs))
                else:
                    args1.append('{}={}'.format(n, repr(d)))

        if len(args1) > 0:
            args1 = ', ' + ', '.join(args1)
        else:
            args1 = ''
        if len(args2) > 0:
            args2 = ', ' + ', '.join(args2)
        else:
            args2 = ''
        if len(args3_optional) > 0:
            optional_code.append('    inputs = ({})'.format(', '.join(args3)))
            for a in args3_optional:
                optional_code.append('    if {} is not None:'.format(a))
                optional_code.append('        inputs += ({}, )'.format(a))
            args3 = '*inputs'
        else:
            args3 = ','.join(args3)
        if args3:
            args3 += ', '

        apis.append('')
        apis.append('')
        apis.append('@function_api')
        apis.append('def {}(ctx{}, n_outputs=-1, outputs=None):'.format(
            info['Names'][function], args1))
        apis.append('    r"""{}'.format(description))
        apis.append('    """')
        apis.append('')
        apis += optional_code
        apis += set_default_values
        apis.append('    return F.{}(ctx{})({}n_outputs=n_outputs, auto_forward=get_auto_forward(), outputs=outputs)'.format(
            function, args2, args3))
    return template.format(function_apis='\n'.join(apis))