Files

questions / element / graph / question.html
Edit Download
<pl-question-panel>
    <p>This question was created to show the graph rendering capabilities of the <a href="https://docs.prairielearn.com/elements/pl-graph"><code>pl-graph</code></a> element.</p>
</pl-question-panel>

<pl-card>
    <pl-question-panel>
        <p>Here's a static graph that was created by hand with DOT markup:</p>

<pl-code language="html">
&lt;pl-graph&gt;
digraph G {
  A -&gt; B
  B -&gt; C
}
&lt;/pl-graph&gt;
</pl-code>

    </pl-question-panel>
    <pl-graph>
        digraph G {
        A -&gt; B
        B -&gt; C
        }
    </pl-graph>
</pl-card>

<pl-card>
    <pl-question-panel>
        <p>Here's a graph with randomly-generated edge weights. Because here the graph is specified in the <code>question.html</code>, parameters can be templated using Mustache.</p>

<pl-code language="html">
&lt;pl-graph&gt;
digraph G {
  A -&gt; B [label="&#123;{ params.weight1 }}"]
  B -&gt; C [label="&#123;{ params.weight2 }}"]
}
&lt;/pl-graph&gt;
</pl-code>

    </pl-question-panel>
    <pl-graph>
        digraph G {
        A -&gt; B [label="  {{ params.weight1 }}"]
        B -&gt; C [label="  {{ params.weight2 }}"]
        }
    </pl-graph>
</pl-card>

<pl-card>
    <pl-question-panel>
        <p>Here's a graph created from a randomly-generated adjacency matrix. By default, weights will be displayed when they are not <code>0</code> or <code>1</code>. The matrix and labels can be specified with <code>params-name</code> and <code>params-name-labels</code>, respectively.</p>

<pl-code language="python">
mat = np.random.random((3, 3))
mat = mat / la.norm(mat, 1, axis=0)
data['params']['labels'] = pl.to_json(['A', 'B', 'C'])
data['params']['matrix'] = pl.to_json(mat)
</pl-code>

<pl-code language="html">
&lt;pl-matrix-latex params-name="matrix"&gt;&lt;/pl-matrix-latex&gt;
&lt;pl-graph params-name="matrix" params-name-labels="labels"&gt;&lt;/pl-graph&gt;
</pl-code>

    </pl-question-panel>
    <pl-matrix-latex params-name="matrix"></pl-matrix-latex>
    <pl-graph params-name="matrix" params-name-labels="labels"></pl-graph>
</pl-card>

<pl-card>
    <pl-question-panel>
        <p>To force no weights being displayed, the attribute <code>weights</code> can be set to <code>"false"</code>. Here is the same graph with no edge weights.</p>
    </pl-question-panel>
    <pl-graph params-name="matrix" params-name-labels="labels" weights="false"></pl-graph>
</pl-card>

<pl-card>
    <pl-question-panel>
        <p>To force the graph to be undirected, the attribute <code>directed</code> can be set to <code>"false"</code>. Here is an undirected graph.
            <b>The input matrix must be symmetric in this case.</b>
        </p>
    </pl-question-panel>
    <pl-matrix-latex params-name="symmetric_matrix"></pl-matrix-latex>
    <pl-graph params-name="symmetric_matrix" params-name-labels="labels" directed="false"></pl-graph>
</pl-card>

<pl-card>
    <pl-question-panel>
        <p>The formatting of the weight labels can also be changed with the <code>weights-digits</code> and <code>weights-presentation-type</code> attributes. This example has <code>weights-digits="5"</code>.</p>
    </pl-question-panel>
    <pl-graph params-name="matrix" params-name-labels="labels" weights-digits="5"></pl-graph>
</pl-card>

<pl-card>
    <pl-question-panel>
        <p>Here is another graph with binary <code>0</code> or <code>1</code> weights. These weights will not be displayed unless specified with <code>weights="true"</code>.</p>
    </pl-question-panel>
    <pl-matrix-latex params-name="matrix2"></pl-matrix-latex>
    <pl-graph params-name="matrix2"></pl-graph>
</pl-card>

<pl-card>
    <pl-question-panel>
        <p>Here is a graph with negative weights. These weights will not be displayed unless specified with
            <code>negative-weights="true"</code>.
            In the input matrix, to hide an edge, simply set the corresponding entry to <code>None</code>.
        </p>
    </pl-question-panel>
    <pl-python-variable params-name="matrix3"></pl-python-variable>
    <pl-graph params-name="matrix3" params-name-labels="labels" negative-weights="true"></pl-graph>
</pl-card>

<pl-card>
    <pl-question-panel>
        <p> The <code>pl-graph</code> element has the ability to be extended on a course level to create graphs based on custom inputs. This course extension located in <code>elementExtensions/pl-graph/edge-inc-matrix</code> adds the capability of rendering edge-incidence matrices as graphs. </p>
        <pl-matrix-latex params-name="edge-inc-mat"></pl-matrix-latex>
        <pl-graph params-name="edge-inc-mat" params-type="edge-inc-matrix"></pl-graph>
        <p> For more information on how to create extensions, check the <a href="https://docs.prairielearn.com/elementExtensions">extension documentation</a> and <a href="https://docs.prairielearn.com/elements/pl-graph">graph element documentation</a>. </p>
    </pl-question-panel>
</pl-card>

<pl-card>
    <pl-question-panel>
        <p>Here's a graph created from a randomly-generated networkx graph.
            To specify the use of a networkx graph, set <code>params-type="networkx"</code>.
            The graph can be specified with <code>params-name</code>.
            To make it accessible to screen readers, set <code>aria-label</code> to a description of the graph; since a static label can't describe a randomly-generated graph, that description is generated in <code>server.py</code> from the graph data.
        </p>

<pl-code language="python">
random_graph = nx.gnm_random_graph(5, 6)

for in_node, out_node, edge_data in random_graph.edges(data=True):
    edge_data['label'] = random.choice(string.ascii_lowercase)

data['params']['random-graph'] = pl.to_json(random_graph)

edges = ", ".join(
    f"{in_node} to {out_node} (labeled {edge_data['label']})"
    for in_node, out_node, edge_data in random_graph.edges(data=True)
)
data['params']['random_graph_alt'] = (
    f"Undirected graph with {random_graph.number_of_nodes()} nodes "
    f"and {random_graph.number_of_edges()} edges: {edges}."
)
</pl-code>
<pl-code language="html">
&lt;pl-graph params-type="networkx" params-name="random-graph" aria-label="&#123;{ params.random_graph_alt }}"&gt;&lt;/pl-graph&gt;
</pl-code>
    </pl-question-panel>
    <pl-graph params-type="networkx" params-name="random-graph" aria-label="{{ params.random_graph_alt }}"></pl-graph>
</pl-card>

<pl-card>
    <pl-question-panel>
        <p>Rendering directed graphs and multigraphs is supported natively with networkx.
            Here, we also set <code>rankdir="LR"</code> in the constructor for the graph.
        </p>
    </pl-question-panel>
    <pl-graph params-type="networkx" params-name="multigraph"></pl-graph>
</pl-card>

<pl-card>
    <pl-question-panel>
        <p>The color of each node or edge in a networkx graph can be set by assigning the <code>'color'</code> attribute in the
            associated data dictionary for each object. In the example below, we've set the color of each edge to <code>'blue'</code>
            and used different colors for nodes in different layers.
        </p>
    </pl-question-panel>
    <pl-graph params-type="networkx" params-name="color-graph"></pl-graph>
</pl-card>

<pl-card>
    <pl-question-panel>
        <p>The <code>source-file-name</code> attribute allows loading graph content from an external file. This is particularly useful for graphs with complex DOT syntax, such as record-based nodes that use angle brackets <code>&lt;&gt;</code>, which can cause issues when embedded directly in HTML.</p>

<pl-code language="html">
&lt;pl-graph source-file-name="record-graph.dot"&gt;&lt;/pl-graph&gt;
</pl-code>

        <p>The file <code>record-graph.dot</code> contains:</p>

<pl-code language="graphviz" source-file-name="record-graph.dot"></pl-code>

    </pl-question-panel>
    <pl-graph source-file-name="record-graph.dot"></pl-graph>
</pl-card>