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

조회 수: 22 (최근 30일)
jf
jf 2024년 8월 13일
댓글: jf 2024년 8월 13일
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');

채택된 답변

Steven Lord
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'})
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
Christine Tobler
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');
jf
jf 2024년 8월 13일
Very nice, indeed. Thank you

댓글을 달려면 로그인하십시오.

추가 답변 (0개)

카테고리

Help CenterFile Exchange에서 2-D and 3-D Plots에 대해 자세히 알아보기

제품


릴리스

R2022b

Community Treasure Hunt

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

Start Hunting!

Translated by