Create and plot an oriented graph of a circuit from a netlist

22 views (last 30 days)
Hello,
it should be a ridiculously trivial task, but I have to admit I've been stuck on it for a few months. Sadly, I'm not very good at Python either, so I'm coming here.
Assume that I have some circuit like the one below:
I want to read and parse a netlist such that I create a digraph object, which can later be used for testing subgraphs being a spanning tree and alike graph theoretic features. Prsing a netlist posses no difficulty, but it looks like the digraph function does not care about the order in my input cells and when I plot the graph, it is labeled wrongly.
I have spent weeks on it with no result. Can you see a easy solution how to turn it into a graph object and plot it accordingly?
Code below produces obvisouly wrong plot, for instance resistors, while the topoogy seems to be idnetified correctly. Edges/Nodes are mislabeled.
clear
close all
clc
netlist = {
'R1 N001 0 R';
'R2 N002 N001 R';
'R3 0 N002 R';
'C1 N002 N001 C';
'C2 N001 0 C';
'C3 N002 0 C';
'L1 N002 N001 L';
'L2 0 N001 L';
'L3 0 N002 L'
};
elements = {};
sourceNodes = {};
targetNodes = {};
labels = {};
for i = 1:length(netlist)
parts = strsplit(netlist{i});
elements{end+1} = parts{1};
sourceNodes{end+1} = parts{2};
targetNodes{end+1} = parts{3};
labels{end+1} = [parts{4} ' - ' parts{1}];
end
edgeTable = table(sourceNodes', targetNodes', labels', 'VariableNames', {'EndNodes', 'EndNodes2', 'Label'});
G = digraph(edgeTable.EndNodes, edgeTable.EndNodes2);
G.Edges.Label = edgeTable.Label;
h = plot(G, 'EdgeLabel', G.Edges.Label, 'NodeLabel', G.Nodes.Name, 'Layout', 'force');

Accepted Answer

Steven Lord
Steven Lord on 13 Aug 2024
Note that your list of sourceNodes and targetNodes only includes three unique entries: 0 (which I assume is ground), N001, and N002 (the two nodes on either side of L1, correct?)
netlist = {
'R1 N001 0 R';
'R2 N002 N001 R';
'R3 0 N002 R';
'C1 N002 N001 C';
'C2 N001 0 C';
'C3 N002 0 C';
'L1 N002 N001 L';
'L2 0 N001 L';
'L3 0 N002 L'
};
elements = {};
sourceNodes = {};
targetNodes = {};
labels = {};
for i = 1:length(netlist)
parts = strsplit(netlist{i});
elements{end+1} = parts{1};
sourceNodes{end+1} = parts{2};
targetNodes{end+1} = parts{3};
labels{end+1} = [parts{4} ' - ' parts{1}];
end
None of your resistors, capacitors, or loads (I assume that's what L1 through L3 are?) are nodes. Shouldn't they be? Or should the intermediate nodes between those components be nodes as well?
Continuing on with your code:
edgeTable = table(sourceNodes', targetNodes', labels', 'VariableNames', {'EndNodes', 'EndNodes2', 'Label'})
edgeTable = 9x3 table
EndNodes EndNodes2 Label ________ _________ __________ {'N001'} {'0' } {'R - R1'} {'N002'} {'N001'} {'R - R2'} {'0' } {'N002'} {'R - R3'} {'N002'} {'N001'} {'C - C1'} {'N001'} {'0' } {'C - C2'} {'N002'} {'0' } {'C - C3'} {'N002'} {'N001'} {'L - L1'} {'0' } {'N001'} {'L - L2'} {'0' } {'N002'} {'L - L3'}
G = digraph(edgeTable.EndNodes, edgeTable.EndNodes2);
The next line of your code is problematic. I've added one additional line before it so I can show you why it's problematic.
G.Edges % Show the edges table before
ans = 9x1 table
EndNodes ____________________ {'N001'} {'0' } {'N001'} {'0' } {'0' } {'N001'} {'0' } {'N002'} {'0' } {'N002'} {'N002'} {'N001'} {'N002'} {'N001'} {'N002'} {'N001'} {'N002'} {'0' }
G.Edges.Label = edgeTable.Label;
G.Edges % Show the edges table after
ans = 9x2 table
EndNodes Label ____________________ __________ {'N001'} {'0' } {'R - R1'} {'N001'} {'0' } {'R - R2'} {'0' } {'N001'} {'R - R3'} {'0' } {'N002'} {'C - C1'} {'0' } {'N002'} {'C - C2'} {'N002'} {'N001'} {'C - C3'} {'N002'} {'N001'} {'L - L1'} {'N002'} {'N001'} {'L - L2'} {'N002'} {'0' } {'L - L3'}
The second row in the G.Edges table before doesn't match the second row in edgeTable. You assume that the rows in the G.Edges table are in the same order as they appear in edgeTable. That is not necessarily the case; digraph reserves the right to reorder the Edges table.
Instead of disassembling edgeTable and adding the labels afterwards, why not build edgeTable in such a way that it's a valid value for the EdgeTable input of the digraph function? Then even if digraph needs to reorder the rows of the edges table, the Label variable is reordered so it remain synchronized with the EndNodes variable.
edgeTable = table([sourceNodes', targetNodes'], labels', 'VariableNames', {'EndNodes', 'Label'})
edgeTable = 9x2 table
EndNodes Label ____________________ __________ {'N001'} {'0' } {'R - R1'} {'N002'} {'N001'} {'R - R2'} {'0' } {'N002'} {'R - R3'} {'N002'} {'N001'} {'C - C1'} {'N001'} {'0' } {'C - C2'} {'N002'} {'0' } {'C - C3'} {'N002'} {'N001'} {'L - L1'} {'0' } {'N001'} {'L - L2'} {'0' } {'N002'} {'L - L3'}
G2 = digraph(edgeTable);
G2.Edges
ans = 9x2 table
EndNodes Label ____________________ __________ {'N001'} {'0' } {'R - R1'} {'N001'} {'0' } {'C - C2'} {'0' } {'N001'} {'L - L2'} {'0' } {'N002'} {'R - R3'} {'0' } {'N002'} {'L - L3'} {'N002'} {'N001'} {'R - R2'} {'N002'} {'N001'} {'C - C1'} {'N002'} {'N001'} {'L - L1'} {'N002'} {'0' } {'C - C3'}
If we plot G2 it still doesn't look like your original plot, but the labels are correct.
plot(G2, 'EdgeLabel', G2.Edges.Label)
If you pictured that 0 as being much wider (the ground is not actually a single point), this actually does topologically match the original picture you showed.
Making each of the components an individual node, splitting the 0 ground node into one node for each component, using the layout function (to display it as a 'layered' graph), and/or explicitly specifying the 'XData' and 'YData' coordinates in the plot call would probably make it look closer to your original picture.
  2 Comments
Christine Tobler
Christine Tobler on 13 Aug 2024
Good catch, Steve! Yes, the Edges table is sorted, so the labels will not match the new sorted order.
Another syntax you could use here (only the last lines are modified):
netlist = {
'R1 N001 0 R';
'R2 N002 N001 R';
'R3 0 N002 R';
'C1 N002 N001 C';
'C2 N001 0 C';
'C3 N002 0 C';
'L1 N002 N001 L';
'L2 0 N001 L';
'L3 0 N002 L'
};
elements = {};
sourceNodes = {};
targetNodes = {};
labels = {};
for i = 1:length(netlist)
parts = strsplit(netlist{i});
elements{end+1} = parts{1};
sourceNodes{end+1} = parts{2};
targetNodes{end+1} = parts{3};
labels{end+1} = [parts{4} ' - ' parts{1}];
end
%% Modified code starting here:
Label = labels';
G = digraph(sourceNodes, targetNodes, table(Label));
h = plot(G, 'EdgeLabel', G.Edges.Label, 'NodeLabel', G.Nodes.Name, 'Layout', 'force');

Sign in to comment.

More Answers (0)

Categories

Find more on 2-D and 3-D Plots in Help Center and File Exchange

Products


Release

R2022b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!