Create and plot an oriented graph of a circuit from a netlist
조회 수: 22 (최근 30일)
이전 댓글 표시
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');
댓글 수: 0
채택된 답변
Steven Lord
2024년 8월 13일
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'})
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
G.Edges.Label = edgeTable.Label;
G.Edges % Show the edges table after
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'})
G2 = digraph(edgeTable);
G2.Edges
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
Christine Tobler
2024년 8월 13일
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');
추가 답변 (0개)
참고 항목
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!