예제 #1
0
def render_proof_stack(proof_stack, node_events, node_actions):
    """
    Render a proof.ProofGoalStack object
    """
    g = CyElements()

    # add nodes
    for goal in proof_stack.stack:
        classes = ['proof_goal']
        short_info = "At ARG node {}".format(goal.node.id)
        if refuted_goal(goal):
            classes += ['refuted']
            short_info += ' (refuted)'
        long_info = [short_info, str(goal.formula)]
        g.add_node(
            obj=goal,
            label=str(goal.id),
            classes=classes,
            short_info=short_info,
            long_info=long_info,
            events=node_events,
            actions=node_actions(goal),
            locked=True,
        )

    # add edges
    for goal in proof_stack.stack:
        if goal.parent is not None:
            g.add_edge(
                'parent',
                goal,
                goal.parent,
                label='',
                classes=['proof_edge'],
                short_info='',
                long_info='',
                events=[],
                actions=[],
            )

    return g
예제 #2
0
def render_concept_graph(widget):
    """
    Render the result of concept_alpha to an annotated graph.

    The graph is represented using Python objects compatible with
    Cytoscape's JSON format.

    TODO: maybe this should be a method of ConceptSessionWidget
    """
    concept_session = widget.concept_session
    a = dict(concept_session.abstract_value)
    domain = concept_session.domain

    # treat custom_edge_info and custom_node_label
    custom = set()
    for tag in a.keys():
        if tag[0].startswith('custom_'):
            not_custom_tag = (tag[0][len('custom_'):],) + tag[1:]
            a[not_custom_tag] = a[tag]
            custom.add(tag[2:])

    # get information from the abstract value
    nodes = set()
    node_labels = set()
    edges = set()
    for tag in a:
        if tag[0] == 'node_info':
            nodes.add(tag[2])
        elif tag[0] == 'edge_info':
            nodes.add(tag[3])
            nodes.add(tag[4])
            edges.add(tag[2:])
        elif tag[0] == 'node_label':
            nodes.add(tag[2])
            node_labels.add(tag[3])
    nodes = sorted(nodes)
    node_labels = sorted(node_labels)
    edges = sorted(edges)

    g = CyElements()

    # add nodes
    non_existing_nodes = set()
    for node in nodes:
        if a[('node_info', 'none', node)]:
            non_existing_nodes.add(node)
            classes = ['non_existing']
            class_disp = 'non existing'
        elif a[('node_info', 'at_least_one', node)] and a[('node_info', 'at_most_one', node)]:
            classes = ['exactly_one']
            class_disp = 'exactly one'
        elif a[('node_info', 'at_least_one', node)]:
            classes = ['at_least_one']
            class_disp = 'at least one'
        elif a[('node_info', 'at_most_one', node)]:
            classes = ['at_most_one']
            class_disp = 'at most one'
        else:
            classes = ['node_unknown']
            class_disp = 'maybe non existing, maybe more than one'

        possible_splits = []
        label_lines = []
        for label_name in node_labels:
            if ('node_label', 'node_necessarily', node, label_name) not in a:
                # label not present, probably not well sorted, skip
                continue
            possible_splits.append(label_name)
            if a[('node_label', 'node_necessarily', node, label_name)]:
                k = 'node_necessarily'
            elif a[('node_label', 'node_necessarily_not', node, label_name)]:
                k = 'node_necessarily_not'
            else:
                k = 'node_maybe'
            if (widget.node_label_display_checkboxes[label_name][k].value is False and
                (node, label_name) not in custom):
                # don't add invisible labels
                continue
            if label_name.startswith('='):
                disp = _label_prefix_equality[k] + label_name[1:]
            else:
                disp = _label_prefix[k] + label_name
            label_lines.append(disp)

        actions = ([
            ('remove', widget.remove_concept),
            ('suppose empty', widget.suppose_empty),
            ('materialize', widget.materialize_node),
        ] + [
            ('split by {}'.format(x), widget.split, x)
            for x in possible_splits
        ] + [
            ('add {}'.format(name),
             widget.add_projection, name, concept)
            for name, concept in
            concept_session.get_projections(node)
        ])

        disp = node
        if '+' in disp or '-' in disp:
            # for concepts that are the result of splits, display just the sort
            disp = str(domain.concepts[node].sorts[0])
        label = '\n'.join([disp] + label_lines)
        info = '\n'.join(
            [
                node,
                str(domain.concepts[node]),
                class_disp,
            ] +
            label_lines
        )
        # cluster by sort in concrete models
        if '!' in node:
            cluster = node.split('!')[0].lower()
        else:
            cluster = None

        if hasattr(widget, 'apply_structure_renaming'):
            label = widget.apply_structure_renaming(label)
            info = widget.apply_structure_renaming(info)
            actions = [
                (widget.apply_structure_renaming(action[0]), ) + tuple(action[1:])
                for action in actions
            ]

        shape = get_shape(node)

        g.add_node(
            obj=node,
            label=label,
            classes=classes,
            short_info=info,
            long_info=info,
            events=[],
            actions=actions,
            locked=True,
            cluster=cluster,
            shape=shape,
        )

    # add edges
    hidden_by_transitive = get_transitive_reduction(widget, a, edges)
    for edge, source, target in edges:
        x = (edge, source, target)

        if (x in hidden_by_transitive and x not in custom):
            # don't draw edges hidden by transitive reduction
            continue

        if (source in non_existing_nodes or
            target in non_existing_nodes):
            # don't draw edges to non-existing nodes
            continue

        classes = []
        if a[('edge_info', 'none_to_none') + x]:
            classes.append('none_to_none')
        elif a[('edge_info', 'all_to_all') + x]:
            classes.append('all_to_all')
        else:
            classes.append('edge_unknown')

        if (widget.edge_display_checkboxes[edge][classes[0]].value is False and
            x not in custom):
            # don't add invisible edges
            continue

        if not a[('edge_info', 'none_to_none') + x]:
            classes += [
                c for c in [
                    'total',
                    'functional',
                    'surjective',
                    'injective',
                ] if a.get(('edge_info', c) + x)
            ]

        # TODO: custom edge labels
        labels = ['{}({}, {}):'.format(edge, source, target)]
        labels += [
            c.replace('_', ' ') for c in [
                'none_to_none',
                'all_to_all',
                'total',
                'functional',
                'surjective',
                'injective',
            ] if a.get(('edge_info', c) + x)
        ]

        if hasattr(widget, 'apply_structure_renaming'):
            labels[0] = widget.apply_structure_renaming(labels[0])

        g.add_edge(
            edge,
            source,
            target,
            label=edge,
            classes=classes,
            short_info='\n'.join(labels),
            long_info=[str(domain.concepts[edge])] + labels[1:],
            events=[],
            actions=[
                ('remove', widget.remove_concept),
                ('materialize +', widget.materialize_edge, True),
                ('materialize -', widget.materialize_edge, False),
            ],
        )

    return g
예제 #3
0
def render_rg(rg, node_events, node_actions):
    """
    Render an ivy_arg.AnalysisGraph object

    node_actions is a function that maps nodes to action lists
    """
    g = CyElements()

    # add nodes for states
    for s in rg.states:
        if s.is_bottom():
            classes = ['bottom_state']
        else:
            classes = ['state']
        events = node_events
        actions = node_actions(s)
        g.add_node(
            obj=s,
            label=str(s.id),
            classes=classes,
            #short_info=str(s),
            #long_info=str(s),
            short_info=str(s.id),
            long_info=[str(x) for x in s.clauses.to_open_formula()],
            events=events,
            actions=actions,
            locked=True,
        )

    # add edges for transitions
    for source, op, label, target in rg.transitions:
        if label == 'join':
            classes = ['transition_join']
            label = 'join'
            info = 'join'
        else:
            classes = ['transition_action']
            label = label if label != str(op) else ''
            info = str(op)
        g.add_edge(
            op,
            source,
            target,
            label=label,
            classes=classes,
            short_info=info,
            long_info=info,
            events=[],
            actions=[],
        )

    # add edges for covering
    for covered, by in rg.covering:
        g.add_edge(
            'cover',
            covered,
            by,
            label='',
            classes=['cover'],
            short_info='',
            long_info='',
            events=[],
            actions=[],
        )

    return g