コード例 #1
0
import seamless
from seamless.core import macro_mode_on
from seamless.core import context, cell, \
  macro, path

def run_macro(ctx):
    ctx.mycell = cell()

with macro_mode_on():
    ctx = context(toplevel=True)
    ctx.macro = macro({})
    ctx.macro.code.cell().set(run_macro)
    ctx.a = cell().set(1)
    p = path(ctx.macro.ctx).mycell
    ctx.a.connect(p)
    ctx.aa = cell()
    p.connect(ctx.aa)

ctx.compute()
print(ctx.macro.ctx.mycell.value)
print(ctx.aa.value)
ctx.a.set(None)
ctx.compute()
print(ctx.macro.ctx.mycell.value)
print(ctx.aa.value)
コード例 #2
0
ファイル: pin-as.py プロジェクト: sjdv1982/seamless
    ctx.tf.result.connect(ctx.result)

    ctx.macro = macro({
        "header": "str",
        "code_": {
            "celltype": "str",
            "as": "code",
        },
    })
    def run(ctx, code, header):
        ctx.result = cell("str").set("MACRO: " + header + code)
    ctx.macro.code.set(run)
    ctx.code.connect(ctx.macro.code_)
    ctx.header.connect(ctx.macro.header)
    ctx.result2 = cell("str")    
    mctx = path(ctx.macro.ctx)
    mctx.result.connect(ctx.result2)

    ctx.reactor = reactor({
        "header": "input",
        "code_": {
            "io": "input",
            "as": "code",
        },
        "result": "output"
    })
    ctx.code.connect(ctx.reactor.code_)
    ctx.header.connect(ctx.reactor.header)
    ctx.reactor.code_start.cell().set("")
    ctx.reactor.code_update.cell().set(
        "PINS.result.set('REACTOR: ' + PINS.header.value + PINS.code.value)"
コード例 #3
0
def top(ctx, elision_, elision_chunksize, graph, lib_module_dict,
        lib_codeblock, inp, keyorder, has_uniform):
    ctx.lib_module_dict = cell("plain").set(lib_module_dict)
    ctx.lib_codeblock = cell("plain").set(lib_codeblock)
    ctx.main_code = cell("python").set(lib_module_dict["map_dict"]["main"])
    ctx.lib_module = cell("plain").set({
        "type": "interpreted",
        "language": "python",
        "code": lib_codeblock
    })
    ctx.graph = cell("plain").set(graph)
    ctx.elision = cell("bool").set(elision_)
    ctx.elision_chunksize = cell("int").set(elision_chunksize)
    ctx.has_uniform = cell("bool").set(has_uniform)

    if has_uniform:
        ctx.uniform = cell("mixed")

    macro_params = {
        'elision_': {
            'celltype': 'bool'
        },
        'elision_chunksize': {
            'celltype': 'int'
        },
        'graph': {
            'celltype': 'plain'
        },
        'lib_module_dict': {
            'celltype': 'plain'
        },
        'lib_codeblock': {
            'celltype': 'plain'
        },
        'lib': {
            'celltype': 'plain',
            'subcelltype': 'module'
        },
        'inp': {
            'celltype': 'plain'
        },
        'keyorder': {
            'celltype': 'plain'
        },
        'has_uniform': {
            'celltype': 'bool'
        },
    }
    ctx.top = macro(macro_params)
    m = ctx.top
    m.allow_elision = elision_

    ctx.main_code.connect(m.code)
    ctx.elision.connect(m.elision_)
    ctx.elision_chunksize.connect(m.elision_chunksize)
    ctx.has_uniform.connect(m.has_uniform)
    ctx.graph.connect(m.graph)
    ctx.lib_module_dict.connect(m.lib_module_dict)
    ctx.lib_codeblock.connect(m.lib_codeblock)
    ctx.lib_module.connect(m.lib)
    m.inp.cell().set(inp)
    m.keyorder.cell().set(keyorder)
    result_path = path(m.ctx).result
    ctx.result = cell("mixed", hash_pattern={"*": "#"})
    result_path.connect(ctx.result)

    input_cells = {}
    if has_uniform:
        uniform_path = path(m.ctx).uniform
        ctx.uniform.connect(uniform_path)
        input_cells = {ctx.uniform: uniform_path}
    ctx._get_manager().set_elision(macro=m,
                                   input_cells=input_cells,
                                   output_cells={
                                       ctx.result: result_path,
                                   })
コード例 #4
0
def map_dict_nested(ctx, elision, elision_chunksize, graph, inp, keyorder, *,
                    lib_module_dict, lib_codeblock, lib, has_uniform):
    from seamless.core import cell, macro, context, path, transformer
    assert len(inp) == len(keyorder)
    length = len(inp)
    #print("NEST", length, keyorder[0])

    if elision and elision_chunksize > 1 and length > elision_chunksize:
        merge_subresults = lib_module_dict["helper"]["merge_subresults_dict"]
        ctx.lib_module_dict = cell("plain").set(lib_module_dict)
        ctx.lib_codeblock = cell("plain").set(lib_codeblock)
        ctx.main_code = cell("python").set(lib_module_dict["map_dict"]["main"])
        ctx.lib_module = cell("plain").set({
            "type": "interpreted",
            "language": "python",
            "code": lib_codeblock
        })
        ctx.graph = cell("plain").set(graph)
        ctx.elision = cell("bool").set(elision)
        ctx.elision_chunksize = cell("int").set(elision_chunksize)
        ctx.has_uniform = cell("bool").set(has_uniform)
        chunk_index = 0

        macro_params = {
            'elision_': {
                'celltype': 'bool'
            },
            'elision_chunksize': {
                'celltype': 'int'
            },
            'graph': {
                'celltype': 'plain'
            },
            "lib_module_dict": {
                'celltype': 'plain'
            },
            "lib_codeblock": {
                'celltype': 'plain'
            },
            "lib": {
                'celltype': 'plain',
                'subcelltype': 'module'
            },
            'inp': {
                'celltype': 'plain'
            },
            'has_uniform': {
                'celltype': 'bool'
            },
            'keyorder': {
                'celltype': 'plain'
            },
        }

        if has_uniform:
            ctx.uniform = cell("mixed")
        subresults = {}
        chunksize = elision_chunksize
        while chunksize * elision_chunksize < length:
            chunksize *= elision_chunksize
        for n in range(0, length, chunksize):
            chunk_keyorder = keyorder[n:n + chunksize]
            chunk_inp = {k: inp[k] for k in chunk_keyorder}
            chunk_index += 1
            subresult = cell("checksum")

            m = macro(macro_params)
            m.allow_elision = True

            setattr(ctx, "m{}".format(chunk_index), m)
            ctx.main_code.connect(m.code)
            ctx.elision.connect(m.elision_)
            ctx.elision_chunksize.connect(m.elision_chunksize)
            ctx.has_uniform.connect(m.has_uniform)
            ctx.graph.connect(m.graph)
            ctx.lib_module_dict.connect(m.lib_module_dict)
            ctx.lib_codeblock.connect(m.lib_codeblock)
            ctx.lib_module.connect(m.lib)
            m.inp.cell().set(chunk_inp)
            m.keyorder.cell().set(chunk_keyorder)
            subr = "subresult{}".format(chunk_index)
            setattr(ctx, subr, subresult)
            subresults[subr] = subresult
            result_path = path(m.ctx).result
            result_path.connect(subresult)
            input_cells = {}
            if has_uniform:
                uniform_path = path(m.ctx).uniform
                ctx.uniform.connect(uniform_path)
                input_cells = {ctx.uniform: uniform_path}

            ctx._get_manager().set_elision(macro=m,
                                           input_cells=input_cells,
                                           output_cells={
                                               subresult: result_path,
                                           })

        transformer_params = {}
        for subr in subresults:
            transformer_params[subr] = {"io": "input", "celltype": "checksum"}
        transformer_params["result"] = {"io": "output", "celltype": "checksum"}
        ctx.merge_subresults = transformer(transformer_params)
        ctx.merge_subresults.code.cell().set(merge_subresults)
        tf = ctx.merge_subresults
        for subr, c in subresults.items():
            c.connect(getattr(tf, subr))

        ctx.all_subresults = cell("plain")
        tf.result.connect(ctx.all_subresults)

        # ctx.all_subresults has the correct checksum, but there is no valid conversion
        #  (because it is unsafe).
        # Use a macro to do it
        ctx.get_result = macro(
            {"result_checksum": {
                "io": "input",
                "celltype": "checksum"
            }})
        get_result = lib_module_dict["helper"]["get_result_dict"]
        ctx.get_result.code.cell().set(get_result)
        ctx.all_subresults.connect(ctx.get_result.result_checksum)
        p = path(ctx.get_result.ctx).result
        ctx.result = cell("mixed", hash_pattern={"*": "#"})
        p.connect(ctx.result)

    else:
        lib.map_dict(ctx, graph, inp, has_uniform, elision)
    return ctx
コード例 #5
0
ファイル: macro3.py プロジェクト: xeTaiz/seamless
""")
    ctx.macro_code.connect(ctx.macro.code)
    ctx.tfx = transformer({
        "x0": "input",
        "x": "output"
    })
    ctx.tfx.code.cell().set("x = x0 + '!'")
    ctx.macro.ctx.x0.connect(ctx.tfx.x0)
    ctx.x = cell("text")
    ctx.tfx.x.connect(ctx.macro.ctx.x_link)
    ctx.tfx.x.connect(ctx.x)
    ctx.y = cell("text")
    ctx.macro.ctx.y.connect(ctx.y)
    ctx.e = cell("json")
    ctx.e2 = cell("json")
    p_d = path(ctx.macro.ctx).d
    p_d.connect(ctx.e)
    p_tf2 = path(ctx.macro.ctx).tf2
    ctx.e.connect(p_tf2.e)
    p_tf2.e2.connect(ctx.e2)
    ctx.z = cell("text").set("z")
    ctx.z_link = link(ctx.z)
    ctx.z_link.connect(ctx.macro.ctx.z)
    ctx.q = cell("text")
    ctx.macro.ctx.q_link.connect(ctx.q)
    ctx.macro.ctx.q.connect(ctx.macro.ctx.qq)
    ctx.r = cell("text")
    ctx.r_link = link(ctx.r)
    ctx.macro.ctx.r_link.connect(ctx.r_link)
    ctx.r.connect(ctx.macro.ctx.rr_link)
コード例 #6
0
ファイル: map_dict_chunk.py プロジェクト: sjdv1982/seamless
def map_dict_chunk(ctx, chunksize, graph, inp, keyorder, has_uniform, elision,
                   lib_module_dict):
    #print("map_dict_chunk", inp)
    from seamless.core import Cell as CoreCell
    from seamless.core import cell, context, macro, path, transformer
    from seamless.core.structured_cell import StructuredCell
    from seamless.core.HighLevelContext import HighLevelContext
    from seamless.core.unbound_context import UnboundContext
    import math

    pseudo_connections = []
    ctx.sc_data = cell("mixed")
    ctx.sc_buffer = cell("mixed")
    inpkeys = keyorder
    nchunks = math.ceil(len(inpkeys) / chunksize)
    ctx.sc = StructuredCell(
        data=ctx.sc_data,
        buffer=ctx.sc_buffer,
        inchannels=[(n + 1, ) for n in range(nchunks)],
        outchannels=[()],
    )

    if has_uniform:
        ctx.uniform = cell("mixed")

    first = True
    for n in range(nchunks):
        pos = chunksize * n
        hc = HighLevelContext(graph)

        subctx = "subctx_" + str(n + 1)
        setattr(ctx, subctx, hc)

        if first:
            if not hasattr(hc, "inp"):
                raise TypeError(
                    "map_dict_chunk context must have a cell called 'inp'")
        hci = hc.inp

        if has_uniform:
            if first:
                if not hasattr(hc, "uniform"):
                    raise TypeError(
                        "map_dict_chunk context must have a cell called 'uniform'"
                    )
                if isinstance(hc.uniform, StructuredCell):
                    raise TypeError(
                        "map_dict_chunk context has a cell called 'uniform', but its celltype must be mixed, not structured"
                    )
                if not isinstance(hc.uniform, CoreCell):
                    raise TypeError(
                        "map_dict_chunk context must have an attribute 'uniform' that is a cell, not a {}"
                        .format(type(hc.uniform)))
            ctx.uniform.connect(hc.uniform)
            con = ["..uniform"], ["ctx", subctx, "uniform"]
            pseudo_connections.append(con)

        if first:
            if isinstance(hci, StructuredCell):
                raise TypeError(
                    "map_dict_chunk context has a cell called 'inp', but its celltype must be mixed, not structured"
                )
            if not isinstance(hci, CoreCell):
                raise TypeError(
                    "map_dict_chunk context must have an attribute 'inp' that is a cell, not a {}"
                    .format(type(hci)))
            if hci.celltype != "mixed":
                raise TypeError(
                    "map_dict_chunk context has a cell called 'inp', but its celltype must be mixed, not {}"
                    .format(hci.celltype))

        con = ["..inp"], ["ctx", subctx, "inp"]
        pseudo_connections.append(con)

        inputchunk = {k: inp[k] for k in inpkeys[pos:pos + chunksize]}
        #print("CHUNK", list(inputchunk.keys()))

        chunk_ctx = context()
        setattr(ctx, "chunk_%d" % (n + 1), chunk_ctx)
        chunk_ctx.inputchunk_deep = cell("mixed", hash_pattern={"*": "#"})
        chunk_ctx.inputchunk_deep.set(inputchunk)
        chunk_ctx.inputchunk_deep2 = cell("plain")
        chunk_ctx.inputchunk_deep.connect(chunk_ctx.inputchunk_deep2)
        chunk_ctx.inputchunk_checksum = cell("checksum")
        chunk_ctx.inputchunk_deep2.connect(chunk_ctx.inputchunk_checksum)

        # chunk_ctx.inputchunk_checksum has the correct checksum, but there is no valid conversion
        #  (because it is unsafe).
        # Use a macro to do it
        chunk_ctx.get_inputchunk = macro(
            {"inputchunk_checksum": {
                "io": "input",
                "celltype": "checksum"
            }})
        get_inputchunk = lib_module_dict["helper"]["get_inputchunk_dict"]
        chunk_ctx.get_inputchunk.code.cell().set(get_inputchunk)
        chunk_ctx.inputchunk_checksum.connect(
            chunk_ctx.get_inputchunk.inputchunk_checksum)
        p = path(chunk_ctx.get_inputchunk.ctx).inputchunk
        chunk_ctx.inputchunk = cell("mixed", hash_pattern={"*": "#"})
        p.connect(chunk_ctx.inputchunk)

        if first:
            if not hasattr(hc, "result"):
                raise TypeError(
                    "map_dict_chunk context must have a cell called 'result'")
            if isinstance(hc.result, StructuredCell):
                raise TypeError(
                    "map_dict_chunk context has a cell called 'result', but its celltype must be mixed, not structured"
                )
            if not isinstance(hc.result, CoreCell):
                raise TypeError(
                    "map_dict_chunk context must have an attribute 'result' that is a cell, not a {}"
                    .format(type(hc.result)))

        chunk_ctx.inputchunk.connect(hci)
        chunk_ctx.result = cell("mixed", hash_pattern={"*": "#"})
        chunk_ctx.result_deep = cell("checksum")
        hc.result.connect(chunk_ctx.result)
        chunk_ctx.result.connect(chunk_ctx.result_deep)
        chunk_ctx.result_deep.connect(ctx.sc.inchannels[(n + 1, )])
        con = ["ctx", subctx, "result"], ["..result"]
        pseudo_connections.append(con)
        first = False

    ctx.subresults = cell("plain")
    ctx.sc.outchannels[()].connect(ctx.subresults)

    merge_subresults = lib_module_dict["helper"]["merge_subresults_chunk"]
    ctx.merge_subresults = transformer({
        "subresults": {
            "io": "input",
            "celltype": "plain"
        },
        "result": {
            "io": "output",
            "celltype": "plain"
        }
    })
    ctx.merge_subresults.code.cell().set(merge_subresults)
    ctx.subresults.connect(ctx.merge_subresults.subresults)
    ctx.result_deep = cell("plain")
    ctx.merge_subresults.result.connect(ctx.result_deep)

    # ctx.result_deep has the correct checksum, but there is no valid conversion
    #  (because it is unsafe).
    # Use a macro to do it
    ctx.get_result = macro(
        {"result_checksum": {
            "io": "input",
            "celltype": "checksum"
        }})
    get_result = lib_module_dict["helper"]["get_result_dict"]
    ctx.get_result.code.cell().set(get_result)
    ctx.result_deep.connect(ctx.get_result.result_checksum)
    p = path(ctx.get_result.ctx).result
    ctx.result = cell("mixed", hash_pattern={"*": "#"})
    p.connect(ctx.result)

    if not elision:
        ctx._pseudo_connections = pseudo_connections
コード例 #7
0
ファイル: macro3.py プロジェクト: sjdv1982/seamless
 ctx.macro_code.connect(ctx.macro.code)
 ctx.tfx = transformer({"x0": "input", "x": "output"})
 ctx.tfx.code.cell().set("x = x0 + '!'")
 ctx.tfx_x0 = cell("text")
 ctx.tfx_x0.connect(ctx.tfx.x0)
 ctx.macro.ctx.x0.connect(ctx.tfx_x0)
 ctx.x = cell("text")
 ctx.tfxx = cell("text")
 ctx.tfx.x.connect(ctx.tfxx)
 ctx.tfxx.connect(ctx.macro.ctx.x_unilink)
 ctx.tfx.x.connect(ctx.x)
 ctx.y = cell("text")
 ctx.macro.ctx.y.connect(ctx.y)
 ctx.e = cell("plain")
 ctx.e2 = cell("plain")
 p_d = path(ctx.macro.ctx).d
 p_d.connect(ctx.e)
 p_tf2e = path(ctx.macro.ctx).tf2e
 p_tf2e2 = path(ctx.macro.ctx).tf2e2
 ctx.e.connect(p_tf2e)
 p_tf2e2.connect(ctx.e2)
 ctx.z = cell("text").set("z")
 ctx.z_unilink = unilink(ctx.z)
 ctx.z_unilink.connect(ctx.macro.ctx.z)
 ctx.q = cell("text")
 ctx.macro.ctx.q_unilink.connect(ctx.q)
 ctx.subq = cell("text")
 ctx.macro.ctx.q.connect(ctx.subq)
 ctx.subq.connect(ctx.macro.ctx.qq)
 ctx.r = cell("text")
 ctx.r_unilink = unilink(ctx.r)
コード例 #8
0
ファイル: macro3.py プロジェクト: sjdv1982/seamless
     "x": "output"
 })
 ctx.tfx.code.cell().set("x = x0 + '!'")
 ctx.tfx_x0 = cell("text")
 ctx.tfx_x0.connect(ctx.tfx.x0)
 ctx.macro.ctx.x0.connect(ctx.tfx_x0)
 ctx.x = cell("text")
 ctx.tfxx = cell("text")
 ctx.tfx.x.connect(ctx.tfxx)
 ctx.tfxx.connect(ctx.macro.ctx.x_link)
 ctx.tfx.x.connect(ctx.x)
 ctx.y = cell("text")
 ctx.macro.ctx.y.connect(ctx.y)
 ctx.e = cell("plain")
 ctx.e2 = cell("plain")
 p_d = path(ctx.macro.ctx).d
 p_d.connect(ctx.e)
 p_tf2e = path(ctx.macro.ctx).tf2e
 p_tf2e2 = path(ctx.macro.ctx).tf2e2
 ctx.e.connect(p_tf2e)
 p_tf2e2.connect(ctx.e2)
 ctx.z = cell("text").set("z")
 ctx.z_link = link(ctx.z)
 ctx.z_link.connect(ctx.macro.ctx.z)
 ctx.q = cell("text")
 ctx.macro.ctx.q_link.connect(ctx.q)
 ctx.subq = cell("text")
 ctx.macro.ctx.q.connect(ctx.subq)
 ctx.subq.connect(ctx.macro.ctx.qq)
 ctx.r = cell("text")
 ctx.r_link = link(ctx.r)
コード例 #9
0
def map_list_N_nested(ctx,
                      elision_chunksize,
                      inp_prefix,
                      graph,
                      inp,
                      *,
                      map_list_N_nested_code,
                      macro_code_lib_code,
                      macro_code_lib0=None):
    global macro_code_lib
    if macro_code_lib0 is not None:
        macro_code_lib = macro_code_lib0
    from seamless.core import cell, macro, context, path, transformer
    first_k = list(inp.keys())[0]
    length = len(inp[first_k])
    print("NEST", length, inp[first_k][0])
    first_k = first_k[len(inp_prefix):]
    for k0 in inp:
        k = k0[len(inp_prefix):]
        if len(inp[k0]) != length:
            err = "all cells in inp must have the same length, but '{}' has length {} while '{}' has length {}"
            raise ValueError(err.format(k, len(inp[k0]), first_k, length))

    if length > elision_chunksize:
        merge_subresults = """def merge_subresults(**subresults):
            result = []
            for k in sorted(subresults.keys()):
                v = subresults[k]
                result += v
            return result"""
        ctx.macro_code = cell("python").set(map_list_N_nested_code)
        ctx.macro_code_lib_code = cell("plain").set(macro_code_lib_code)
        ctx.macro_code_lib = cell("plain").set({
            "type": "interpreted",
            "language": "python",
            "code": macro_code_lib_code
        })
        ctx.graph = cell("plain").set(graph)
        ctx.inp_prefix = cell("str").set(inp_prefix)
        ctx.elision_chunksize = cell("int").set(elision_chunksize)
        chunk_index = 0

        macro_params = {
            'inp_prefix': {
                'celltype': 'str'
            },
            'elision_chunksize': {
                'celltype': 'int'
            },
            'graph': {
                'celltype': 'plain'
            },
            'inp': {
                'celltype': 'plain'
            },
            "map_list_N_nested_code": {
                'celltype': 'python'
            },
            "macro_code_lib": {
                'celltype': 'plain',
                'subcelltype': 'module'
            },
            "macro_code_lib_code": {
                'celltype': 'plain'
            },
        }

        subresults = {}
        chunksize = elision_chunksize
        while chunksize * elision_chunksize < length:
            chunksize *= elision_chunksize
        for n in range(0, length, chunksize):
            chunk_inp = {}
            for k in inp:
                chunk_inp[k] = inp[k][n:n + chunksize]
            chunk_index += 1
            subresult = cell("checksum")
            """ # The following will work, but make it un-elidable

            setattr(ctx, "chunk_%d" % chunk_index, context())
            chunk_ctx = getattr(ctx, "chunk_%d" % chunk_index)
            macro_code_lib.map_list_N(chunk_ctx, inp_prefix, graph, chunk_inp)  #
            """

            m = macro(macro_params)
            elision = {"macro": m, "input_cells": {}, "output_cells": {}}
            m.allow_elision = True

            setattr(ctx, "m{}".format(chunk_index), m)
            ctx.macro_code.connect(m.code)
            ctx.inp_prefix.connect(m.inp_prefix)
            ctx.elision_chunksize.connect(m.elision_chunksize)
            ctx.graph.connect(m.graph)
            ctx.macro_code.connect(m.map_list_N_nested_code)
            ctx.macro_code_lib.connect(m.macro_code_lib)
            ctx.macro_code_lib_code.connect(m.macro_code_lib_code)
            m.inp.cell().set(chunk_inp)
            subr = "subresult{}".format(chunk_index)
            setattr(ctx, subr, subresult)
            subresults[subr] = subresult
            result_path = path(m.ctx).result
            result_path.connect(subresult)
            elision["output_cells"][subresult] = result_path
            ctx._get_manager().set_elision(**elision)

        transformer_params = {}
        for subr in subresults:
            transformer_params[subr] = {"io": "input", "celltype": "checksum"}
        transformer_params["result"] = {"io": "output", "celltype": "checksum"}
        ctx.merge_subresults = transformer(transformer_params)
        ctx.merge_subresults.code.cell().set(merge_subresults)
        tf = ctx.merge_subresults
        for subr, c in subresults.items():
            c.connect(getattr(tf, subr))

        ctx.all_subresults = cell("plain")
        tf.result.connect(ctx.all_subresults)

        # ctx.all_subresults has the correct checksum, but there is no valid conversion
        #  (because it is unsafe).
        # Use a macro to do it

        ctx.get_result = macro(
            {"result_checksum": {
                "io": "input",
                "celltype": "checksum"
            }})
        get_result = """def get_result(ctx, result_checksum):
            ctx.result = cell("mixed", hash_pattern={"!": "#"})
            ctx.result.set_checksum(result_checksum)"""
        ctx.get_result.code.cell().set(get_result)
        ctx.all_subresults.connect(ctx.get_result.result_checksum)
        p = path(ctx.get_result.ctx).result
        ctx.result = cell("mixed", hash_pattern={"!": "#"})
        p.connect(ctx.result)

    else:
        macro_code_lib.map_list_N(ctx, inp_prefix, graph, inp)
    return ctx