Exemplo n.º 1
0
def test_no_input_ports_to_json(tmpdir):
    """Test the edge case of exporting a model to JSON when it has a node with no input ports"""

    mod = Model(id="ABCD")
    mod_graph = Graph(id="abcd_example")
    mod.graphs.append(mod_graph)

    input_node = Node(id="input0")
    input_node.parameters.append(Parameter(id="input_level", value=10.0))
    op1 = OutputPort(id="out_port")
    op1.value = "input_level"
    input_node.output_ports.append(op1)
    mod_graph.nodes.append(input_node)

    tmpfile = f"{tmpdir}/test.json"
    mod.to_json_file(tmpfile)

    # FIXME: Doesn't seem like we have any methods for deserialization. Just do some quick and dirty checks
    # This should really be something like assert mod_graph == deserialized_mod_graph
    import json

    with open(tmpfile) as f:
        data = json.load(f)
    print(data)

    assert (data["ABCD"]["graphs"]["abcd_example"]["nodes"]["input0"]
            ["parameters"]["input_level"]["value"] == 10.0)

    mod_graph2 = load_mdf(tmpfile)

    print(mod_graph2)
    assert mod_graph2.graphs[0].nodes[0].parameters[0].value == 10.0
Exemplo n.º 2
0
def test_graph_inputs():
    r"""Test whether we can retrieve graph input node\ports via the inputs property."""
    mod = Model(id="ABCD")
    mod_graph = Graph(id="abcd_example")
    mod.graphs.append(mod_graph)

    input_node = Node(id="input0")
    input_node.parameters.append(Parameter(id="input_level", value=10.0))
    op1 = OutputPort(id="out_port")
    op1.value = "input_level"
    input_node.output_ports.append(op1)
    mod_graph.nodes.append(input_node)
Exemplo n.º 3
0
def simple_model_mdf():
    """
    A simple MDF model with two nodes. Input node has an input port with no receiving edge but it is not used
    because the output port uses a parameter instead.
    """
    mod = Model(id="Simple")
    mod_graph = Graph(id="simple_example")
    mod.graphs.append(mod_graph)

    input_node = Node(id="input_node")
    input_node.parameters.append(Parameter(id="input_level", value=0.5))
    op1 = OutputPort(id="out_port")
    op1.value = "input_level"
    input_node.output_ports.append(op1)
    mod_graph.nodes.append(input_node)

    processing_node = Node(id="processing_node")
    mod_graph.nodes.append(processing_node)

    processing_node.parameters.append(Parameter(id="lin_slope", value=0.5))
    processing_node.parameters.append(Parameter(id="lin_intercept", value=0))
    processing_node.parameters.append(Parameter(id="log_gain", value=3))

    ip1 = InputPort(id="input_port1")
    processing_node.input_ports.append(ip1)

    f1 = Parameter(
        id="linear_1",
        function="linear",
        args={"variable0": ip1.id, "slope": "lin_slope", "intercept": "lin_intercept"},
    )
    f2 = Parameter(
        id="logistic_1",
        function="logistic",
        args={"variable0": f1.id, "gain": "log_gain", "bias": 0, "offset": 0},
    )
    processing_node.parameters.append(f1)
    processing_node.parameters.append(f2)
    processing_node.output_ports.append(OutputPort(id="output_1", value="logistic_1"))

    e1 = Edge(
        id="input_edge",
        parameters={"weight": 0.55},
        sender=input_node.id,
        sender_port=op1.id,
        receiver=processing_node.id,
        receiver_port=ip1.id,
    )

    mod_graph.edges.append(e1)

    return mod
Exemplo n.º 4
0
def test_include_metadata_to_json(tmpdir):
    """
    Test for serialization
    """

    mod = Model(id="ABCD", metadata={"info": "model_test"})
    mod_graph = Graph(
        id="abcd_example",
        metadata={"info": {
            "graph_test": {
                "environment_x": "xyz"
            }
        }})
    mod.graphs.append(mod_graph)

    input_node = Node(id="input0", metadata={"color": ".8 0 .8"})
    input_node.parameters.append(Parameter(id="input_level", value=10.0))
    op1 = OutputPort(id="out_port", metadata={"info": "value at OutputPort"})
    op1.value = "input_level"
    input_node.output_ports.append(op1)
    mod_graph.nodes.append(input_node)

    tmpfile = f"{tmpdir}/test.json"
    mod_graph.to_json_file(tmpfile)

    # FIXME: Doesn't seem like we have any methods for deserialization. Just do some quick and dirty checks
    # This should really be something like assert mod_graph == deserialized_mod_graph
    import json

    with open(tmpfile) as f:
        data = json.load(f)

    assert data["abcd_example"]["metadata"] == {
        "info": {
            "graph_test": {
                "environment_x": "xyz"
            }
        }
    }
    assert data["abcd_example"]["nodes"]["input0"]["metadata"] == {
        "color": ".8 0 .8"
    }
    assert data["abcd_example"]["nodes"]["input0"]["output_ports"]["out_port"][
        "metadata"] == {
            "info": "value at OutputPort"
        }
Exemplo n.º 5
0
    def create_simple_node(graph, id_, sender=None):
        n = Node(id=id_)
        graph.nodes.append(n)

        ip1 = InputPort(id="input_port1", shape="(1,)")
        n.input_ports.append(ip1)

        n.output_ports.append(OutputPort(id="output_1", value=ip1.id))

        if sender is not None:
            simple_connect(sender, n, graph)

        return n
Exemplo n.º 6
0
def create_example_node(node_id: str, graph: Graph) -> Node:
    """
    Create a simple example node with Input inside a graph

    Args:
        node_id: The unique id for the first node in the graph.
        graph: The graph to add the example node.

    Returns:
        The node (with id=node_id) created in the graph.
    """

    a = Node(id=node_id)
    graph.nodes.append(a)

    a.parameters = {"logistic_gain": 3, "slope": 0.5, "intercept": 0}
    ip1 = InputPort(id="input_port1", shape="(1,)")
    a.input_ports.append(ip1)

    f1 = Function(
        id="logistic_1",
        function="logistic",
        args={
            "variable0": ip1.id,
            "gain": "logistic_gain",
            "bias": 0,
            "offset": 0
        },
    )
    a.functions.append(f1)
    f2 = Function(
        id="linear_1",
        function="linear",
        args={
            "variable0": f1.id,
            "slope": "slope",
            "intercept": "intercept"
        },
    )
    a.functions.append(f2)
    a.output_ports.append(OutputPort(id="output_1", value="linear_1"))

    return a
Exemplo n.º 7
0
def main():
    mod = Model(id="Simple")
    mod_graph = Graph(id="simple_example")
    mod.graphs.append(mod_graph)

    input_node = Node(id="input_node")
    input_node.parameters.append(Parameter(id="input_level", value=0.5))
    op1 = OutputPort(id="out_port")
    op1.value = "input_level"
    input_node.output_ports.append(op1)
    mod_graph.nodes.append(input_node)

    processing_node = Node(id="processing_node")
    mod_graph.nodes.append(processing_node)

    processing_node.parameters.append(Parameter(id="lin_slope", value=0.5))
    processing_node.parameters.append(Parameter(id="lin_intercept", value=0))
    processing_node.parameters.append(Parameter(id="log_gain", value=3))
    ip1 = InputPort(id="input_port1")
    processing_node.input_ports.append(ip1)

    f1 = Parameter(
        id="linear_1",
        function="linear",
        args={"variable0": ip1.id, "slope": "lin_slope", "intercept": "lin_intercept"},
    )
    f2 = Parameter(
        id="logistic_1",
        function="logistic",
        args={"variable0": f1.id, "gain": "log_gain", "bias": 0, "offset": 0},
    )
    processing_node.parameters.append(f1)
    processing_node.parameters.append(f2)

    processing_node.output_ports.append(OutputPort(id="output_1", value="logistic_1"))

    e1 = Edge(
        id="input_edge",
        parameters={"weight": 0.55},
        sender=input_node.id,
        sender_port=op1.id,
        receiver=processing_node.id,
        receiver_port=ip1.id,
    )

    mod_graph.edges.append(e1)

    print(mod)

    print("------------------")
    print(mod.to_json())

    new_file = mod.to_json_file("%s.json" % mod.id)
    new_file = mod.to_yaml_file("%s.yaml" % mod.id)

    if "-run" in sys.argv:
        verbose = True
        # verbose = False
        from modeci_mdf.execution_engine import EvaluableGraph

        from modelspec.utils import FORMAT_NUMPY, FORMAT_TENSORFLOW

        format = FORMAT_TENSORFLOW if "-tf" in sys.argv else FORMAT_NUMPY
        eg = EvaluableGraph(mod_graph, verbose=verbose)
        eg.evaluate(array_format=format)

    if "-graph" in sys.argv:
        mod.to_graph_image(
            engine="dot",
            output_format="png",
            view_on_render=False,
            level=1,
            filename_root="simple",
            only_warn_on_fail=True,  # Makes sure test of this doesn't fail on Windows on GitHub Actions
        )
        mod.to_graph_image(
            engine="dot",
            output_format="png",
            view_on_render=False,
            level=3,
            filename_root="simple_3",
            only_warn_on_fail=True,  # Makes sure test of this doesn't fail on Windows on GitHub Actions
        )
Exemplo n.º 8
0
def main():
    mod = Model(id="abc_conditions")
    mod_graph = Graph(id="abc_conditions_example")
    mod.graphs.append(mod_graph)

    input_node = Node(id="input0")
    input_node.parameters.append(Parameter(id="input_level", value=0.0))
    input_node.parameters.append(Parameter(id="count_0", value="count_0 + 1"))
    op1 = OutputPort(id="out_port")
    op1.value = "input_level"
    input_node.output_ports.append(op1)
    mod_graph.nodes.append(input_node)

    def create_simple_node(graph, id_, sender=None):
        n = Node(id=id_)
        graph.nodes.append(n)

        ip1 = InputPort(id="input_port1", shape="(1,)")
        n.input_ports.append(ip1)

        n.output_ports.append(OutputPort(id="output_1", value=ip1.id))

        if sender is not None:
            simple_connect(sender, n, graph)

        return n

    a = create_simple_node(mod_graph, "A", input_node)
    a.parameters.append(Parameter(id="count_A", value="count_A + 1"))

    b = create_simple_node(mod_graph, "B", a)
    b.parameters.append(Parameter(id="count_B", value="count_B + 1"))

    c = create_simple_node(mod_graph, "C", a)

    c.parameters.append(Parameter(id="count_C", value="count_C+ 1"))

    cond_i = Condition(type="BeforeNCalls", dependencies=input_node.id, n=1)
    cond_a = Condition(type="Always")
    cond_b = Condition(type="EveryNCalls", dependencies=a.id, n=2)
    cond_c = Condition(type="EveryNCalls", dependencies=a.id, n=3)
    cond_term = Condition(
        type="And",
        dependencies=[
            Condition(type="AfterNCalls", dependencies=c.id, n=2),
            Condition(type="JustRan", dependencies=a.id),
        ],
    )

    mod_graph.conditions = ConditionSet(
        node_specific={
            input_node.id: cond_i,
            a.id: cond_a,
            b.id: cond_b,
            c.id: cond_c
        },
        termination={"environment_state_update": cond_term},
    )

    mod.to_json_file(
        os.path.join(os.path.dirname(__file__), "%s.json" % mod.id))
    mod.to_yaml_file(
        os.path.join(os.path.dirname(__file__), "%s.yaml" % mod.id))

    print_summary(mod_graph)

    import sys

    if "-run" in sys.argv:
        verbose = True
        # verbose = False
        from modeci_mdf.execution_engine import EvaluableGraph
        from modelspec.utils import FORMAT_NUMPY, FORMAT_TENSORFLOW

        format = FORMAT_TENSORFLOW if "-tf" in sys.argv else FORMAT_NUMPY
        eg = EvaluableGraph(mod_graph, verbose=verbose)
        eg.evaluate(array_format=format)

    if "-graph" in sys.argv:
        mod.to_graph_image(
            engine="dot",
            output_format="png",
            view_on_render=False,
            level=3,
            filename_root="abc_conditions",
            only_warn_on_fail=
            True,  # Makes sure test of this doesn't fail on Windows on GitHub Actions
        )
Exemplo n.º 9
0
def test_OutputPort_init_kwargs():
    op = OutputPort(id="test_OutputPort", value="test_value")
    assert op.value == "test_value"
Exemplo n.º 10
0
Arquivo: FNrun.py Projeto: kmantel/MDF
def execute(multi=False):

    mdf_model = load_mdf("FN.mdf.yaml")
    mod_graph = mdf_model.graphs[0]

    dt = 0.00005
    duration = 0.1

    if not multi:

        fn_node = mod_graph.nodes[0]
        fn_node.get_parameter("initial_v").value = [-1.0]
        fn_node.get_parameter("initial_w").value = [0.0]
        input = np.array([0])

    else:
        size = 15
        max_amp = 0.5
        input = np.array(
            [max_amp * (-1 + 2 * i / size) for i in range(size + 1)])
        # input = [-0.4,-0.2, 0.,0.2,0.4]
        input_node = Node(id="input_node", parameters={"input_level": input})

        op1 = OutputPort(id="out_port", value="input_level")
        input_node.output_ports.append(op1)
        mod_graph.nodes.append(input_node)

        fn_node = mod_graph.nodes[0]
        fn_node.get_parameter("initial_v").value = np.array([1.0] * len(input))
        fn_node.get_parameter("initial_w").value = np.array([0.0] * len(input))

        print(fn_node)

        e1 = Edge(
            id="input_edge",
            sender=input_node.id,
            sender_port=op1.id,
            receiver="FNpop_0",
            receiver_port="INPUT",
        )

        mod_graph.edges.append(e1)

        mdf_model.to_graph_image(
            engine="dot",
            output_format="png",
            view_on_render=False,
            level=3,
            filename_root="FNmulti",
            only_warn_on_fail=
            True,  # Makes sure test of this doesn't fail on Windows on GitHub Actions
        )

        duration = 0.1

    eg = EvaluableGraph(mod_graph, verbose)
    # duration= 2
    t = 0

    times = []
    vv = {}
    ww = {}

    format = FORMAT_TENSORFLOW if "-tf" in sys.argv else FORMAT_NUMPY

    while t < duration + 0.00005:
        times.append(t)
        print("======   Evaluating at t = %s  ======" % (t))
        if t == 0:
            eg.evaluate(array_format=format)  # replace with initialize?
        else:
            eg.evaluate(array_format=format, time_increment=dt)

        for i in range(
                len(eg.enodes["FNpop_0"].evaluable_parameters["V"].curr_value)
        ):
            if not i in vv:
                vv[i] = []
                ww[i] = []
            v = eg.enodes["FNpop_0"].evaluable_parameters["V"].curr_value[i]
            w = eg.enodes["FNpop_0"].evaluable_parameters["W"].curr_value[i]
            vv[i].append(v)
            ww[i].append(w)
            if i == 0:
                print(f"    Value at {t}: v={v}, w={w}")
        t += dt

    import matplotlib.pyplot as plt

    for vi in vv:
        plt.plot(times, vv[vi], label="V %.3f" % input[vi])
        plt.plot(times, ww[vi], label="W %.3f" % input[vi])
    plt.legend()

    if not multi:
        plt.savefig("MDFFNrun.png", bbox_inches="tight")

    if not "-nogui" in sys.argv:
        plt.show()
Exemplo n.º 11
0
def torchnode_to_mdfnode(
    node: torch.Node,
    graph: torch.Graph,
    consts: Dict[str, Any],
    port_mapper: "PortMapper",
) -> Union[Node, None]:
    """
    Convert a TorchScript node to an MDF node.

    Args:
        node: The node to convert.
        graph: The graph that this node is a member.
        consts: A dict containing any constants in the graph.

    Returns:
        The MDF node for this TorchScript node. prim::Constant nodes are excluded from the MDF graph and are
        instead placed as parameters. In this case, return None.
    """
    op = node.kind()

    # Exclude constants (as nodes) from the MDF graph. We will instead insert them as parameters to the nodes that
    # they project to.
    if op == "prim::Constant":
        return None

    # If we are dealing with a loop node, we need to recursively create a sub-graph for the loop body
    if op == "onnx::Loop":
        sub_mdf_graph = Graph(id=f"LoopSubgraph{make_node_id(node)}")
        block_graph = list(node.blocks())[0]
        translate_graph(
            graph=block_graph,
            mdf_graph=sub_mdf_graph,
            consts=consts,
            port_mapper=port_mapper,
        )
        return sub_mdf_graph

    outputs = [o.unique() for o in node.outputs()]
    inputs = [i.unique() for i in node.inputs()]

    # Get the argument names and parameter names and values for this Node's operation
    if "onnx::" in op:
        arguments, parameters = process_onnx_schema(node, port_mapper)
    else:
        arguments, parameters = process_torch_schema(node, consts, port_mapper)

    mdf_node = Node(id=make_node_id(node))
    for p in parameters:
        mdf_node.parameters.append(Parameter(id=p, value=parameters[p]))

    # Add any output ports
    for o in outputs:
        mdf_node.output_ports.append(
            OutputPort(id=port_mapper.id_to_port(o), value=make_func_id(node)))

    # Add any input ports to the node, exclude inputs from constant nodes, these are parameters now
    for inp_i, inp in enumerate(inputs):
        if inp not in consts:
            ip_name = port_mapper.id_to_port(inp)

            # Try to get the shape and type of the input port
            inp_type = node.inputsAt(inp_i).type()
            try:
                shape = str(inp_type.sizes()) if inp_type.sizes() else "(?)"
            except RuntimeError:
                shape = "(?)"

            mdf_node.input_ports.append(
                InputPort(id=ip_name, shape=shape, type=str(inp_type)))

    # Add Parameter
    if type(arguments) == list:
        arguments = {"arguments": arguments}
    f = Parameter(id=make_func_id(node), function=op, args=arguments)
    mdf_node.parameters.append(f)

    return mdf_node