Networkx and graphviz. How to suppress node and edge positions in dot output? - networkx

Take this simple networkx script.
import networkx as nx
g = nx.DiGraph()
g.add_edge("a","b")
g.add_edge("a","c")
g.add_node("D")
dotter = nx.nx_agraph.to_agraph(g)
dotter.layout("dot")
dot = dotter.to_string()
with open("test_w_pos.dot","w") as fo:
fo.write(dot)
The output is:
strict digraph "" {
graph [bb="0,0,162,108"];
node [label="\N"];
a [height=0.5,
pos="63,90",
width=0.75];
b [height=0.5,
pos="27,18",
width=0.75];
a -> b [pos="e,35.634,35.269 54.285,72.571 50.04,64.081 44.846,53.693 40.134,44.267"];
c [height=0.5,
pos="99,18",
width=0.75];
a -> c [pos="e,90.366,35.269 71.715,72.571 75.96,64.081 81.154,53.693 85.866,44.267"];
D [height=0.5,
pos="135,90",
width=0.75];
}
I'd like to not have any of the pos, height and width attributes as they vary from run to run and make it hard to compare to previous runs on complex graphs.
desired output
strict digraph "" {
node [label="\N"];
a;
b;
a -> b;
c;
a -> c;
D;
}
Both dot files give substantially the same output in svg (see below), so I find the positioning unnecessary and in fact I've never seen this information put into dot files previously.
I could not find anything in to_agraph or dotter.to_string, but I did not notice extra arguments are possible in dotter.layout(dot):
agraph.py
def layout(self, prog="neato", 👉args=""👈):
"""Assign positions to nodes in graph.
Yes, with this very simplistic file, I could drop the positioning data afterwards. But in a real graph, there will be a lot of other color and label attributes mixed in with the positions.
image with position attributes:
image without position attributes:

If you are only interested in the dot file you can use the pydot interface of networkx and call write_dot, e.g.
drawing.nx_pydot.write_dot(g, "test.dot")

Try dotter.layout("canon") (https://graphviz.org/docs/outputs/canon/). This will provide a (pretty printed) version of your graph without any positioning.

Related

Reshape of Inducing Variables - GPflow

I have an SGPR model:
import numpy as np
import gpflow
X, Y = np.random.randn(50, 2), np.random.randn(50, 1)
Z1 = np.random.randn(13, 2)
k = gpflow.kernels.SquaredExponential()
m = gpflow.models.SGPR(data=(X, Y), kernel=k, inducing_variable=Z1)
And I would like to assign inducing variable but with different shape, like:
Z2 = np.random.randn(29, 2)
m.inducing_variable.Z.assign(Z2)
But if I do it, I got:
ValueError: Shapes (13, 2) and (29, 2) are incompatible
is there a way to reassign the inducing variables without redefining the model?
Context: Instead of optimizing the model with the inducing variables, I would like to optimize the model without optimizing the inducing variables, manually reassigning the inducing variables at each step of the optimization.
UPDATE: This issue is resolved by https://github.com/GPflow/GPflow/pull/1594, which will become part of the next GPflow patch release (2.1.4).
With that fix, you don't need a custom class. All you need to do is explicitly set the static shape with None along the first dimension:
inducing_variable = gpflow.inducing_variables.InducingPoints(
tf.Variable(
Z1, # initial value
trainable=False, # True does not work - see Note below
shape=(None, Z1.shape[1]), # or even tf.TensorShape(None)
dtype=gpflow.default_float(), # required due to tf's 32bit default
)
)
m = gpflow.models.SGPR(data=(X, Y), kernel=k, inducing_variable=inducing_variable)
Then m.inducing_variable.Z.assign(Z2) should work just fine.
Note that in this case Z cannot be trainable, as the TensorFlow optimizers need to know the shape at construction time and don't support dynamic shapes.
Right now (as of GPflow 2.1.2) there is no built-in way to change the shape of inducing variables for SGPR, though it is in principle possible. You can get what you want with your own inducing variable class though:
class VariableInducingPoints(gpflow.inducing_variables.InducingPoints):
def __init__(self, Z, name=None):
super().__init__(Z, name=name)
# overwrite with Variable with None as first element in shape so
# we can assign arrays with arbitrary length along this dimension:
self.Z = tf.Variable(Z, dtype=gpflow.default_float(),
shape=(None, Z.shape[1])
)
def __len__(self):
return tf.shape(self.Z)[0] # dynamic shape
# instead of the static shape returned by the InducingPoints parent class
and then do
m = gpflow.models.SGPR(
data=(X, Y), kernel=k, inducing_variable=VariableInducingPoints(Z1)
)
instead. Then your m.inducing_variable.Z.assign() should work as you like it.
(For SVGP, the size of the inducing variable and the distribution defined by q_mu and q_sqrt has to match, as well as be known at construction time, so in this case changing the number of inducing variables is less trivial.)

Depth-first search that starts from the right side of the loop

Currently, I have a function that list all the branch from level to level in the leftest side. I want to list all the branch in the rightest side but not sure how to list them.
My code is as follow:
adj=SparseGraph;
next = cell(n,1);
for i = 1:n
next{i} = find(adj(i,:));
end
Thank you for your time,
Original output is
[2,3,4,5,6,7,8]
[9,10]
[9,10,11]
[10,11,12]
[11,12,13]
[12,13,14]
[13,14,15]
[14,15]
Desire output is
[8,7,6,5,4,3,2]
[15,14]
[15,14,13]
[14,13,12]
[13,12,11]
[12,11,10]
[11,10,9]
[10,9]
You could use MATLABs builtin graph class
G = graph(adj);
for k = 1:G.numnodes
disp(G.dfsearch(k));
end

How to convert string to variable name which will be passed into plot function

How I can convert a string to a variable which will be passed into plot function?
Time = [0,1,2,3];
A = sin(Time);
B = cos(Time);
c = 2*sin(Time);
lookup = {"A", "Freq(Hz)"; "B", "Pressure(bar)", "c", "time(ms),....};
for i=1:length(lookup)
plot(Time, lookup(i,1))
ylabel(lookup(i,2))
end
I want to plot Time vs A and Time vs B and Time vs C likewise I have 50 different variables to plot.
So I planned to create the lookup with string and planned to pass as variable to plot function using eval function call.
But in few places I read that using eval is not good option so kindly suggest the alternate method.
This will solve your immediate problem:
Replace
lookup = {"A", "Freq(Hz)"; "B", "Pressure(bar)", "c", "time(ms)", ...};
with
lookup = {A, "Freq(Hz)"; B, "Pressure(bar)", c, "time(ms)", ...};
Cell arrays are heterogeneous containers, each element can be an array of any time, independently from all other types.
With this change, the rest of your code should work as intended. You might want to add a figure command or a print command inside your loop, as each plot will overwrite the previous one. figure creates a new figure window to plot in, you'll have 50 windows (not so nice). print can save the plot to a file, which might be a better approach here. Don't try to combine the 50 data lines into a single plot, it'll be a mess!
On a larger scale, you might want to rethink your strategy with defining 50 different variables. Cell arrays and struct arrays are really good ways to go about this. For example, you can think of
data.A = sin(Time);
data.B = cos(Time);
data.c = 2*sin(Time);
or
data(1).values = sin(Time);
data(1).name = "A";
data(1).units = "Freq(Hz)";
data(2).values = cos(Time);
data(2).name = "B";
data(2).units = "Pressure(bar)";
data(3).values = 2*sin(Time);
data(3).name = "c";
data(3).units = "time(ms)";
Note that, in the first case, you can also index with data.("A"), which brings you pretty close to your original idea, except that you don't have 50 variables in your workspace, but one single data structure that is easier to deal with.
Here is a very detailed list of reasons why eval can be bad to use. That link also shows some alternatives, similar to what I summarized above.

How can I get the Methodlist while iterating?

I want to iterate through all classes and packages in a special path.
After that, I want to get the MethodList.
In the command window I can use following and it’s working fine:
a = ?ClassName;
a.MethodList(X);
Now I separate this into a function:
function s = befehlsreferenz(path)
s = what(path); % list MATLAB files in folder
for idx = 1:numel(s.classes)
c = s.classes(idx);
b = ?c;
b.MethodList(0);
end
end
I get an error:
Too many outputs requested. Most likely cause is missing [] around left hand side that has a comma separated list
expansion. Error in (line 7) b.MethodList(0);
While debugging I can see:
c: 1x1 cell = ‘Chapter’
b: empty 0x0 meta.class
Why is b empty? How can I get the methodlist?
1 Edit:
Here is an example class, also not working with it.
classdef TestClass
%TESTCLASS Summary of this class goes here
% Detailed explanation goes here
properties
end
methods
function [c] = hallo(a)
c = 1;
end
end
end
When struggling with operators in Matlab, it's typically the best choice to use the underlying function instead, which is meta.class.fromname(c)
Relevant documentation: http://de.mathworks.com/help/matlab/ref/metaclass.html
Further it seems s.classes(idx); is a cell, use cell indexing: s.classes{idx} ;

matlab How to use a textstring as input parameter in functions

I would like to use a dataset filename "AUDUSD" in several functions. It would be easier for me, just to change the filename "AUDUSD" to a more general name like "FX" and then using the abbreviation "FX" in other_matlab functions, e.g. double(). But matlab does not know the name "FX" (that should be assigned to the dataset "AUDUSD") in the code below... Any suggestions?
CODE:
FX = 'AUDUSD';
load(FX); %OKAY !!! FX works as input to open file AUDUSD!
Svars = {'S_bid','S_offer'};
Fvars = {'F_bid','F_offer'};
vS = double(FX,Svars); % FX does NOT work as input for the file AUDUSD
There is no double() function that accepts multiple cell arrays as arguments (this is what happens when you call double(FX,Svars)).
If you call double(FX), then each character in FX is interpreted for its ASCII value and then cast to double. So you get [ 65.0 85.0 68.0 85.0 83.0 68.0 ]. This is the behavior for the double() function if you provide a vector: each individual value in the vector is cast to double.
You'd have to provide more details on what you're trying to accomplish to give any more suggestions.
I have a different example, maybe you will better understand my point. The key work I would like to process is as follows:
I have got a folder with "dataset" files. I would like to loop through this folder, entering in any datasetfile, extracting the 2nd and 3rd column of each dataset file, and constructing only ONE new datasetfile with all 2nd and 3rd columns of the datasetfiles.
One problem is that the size of the datasetfiles are not the same, so I tried to translate a datasetfile into a double-matrix and then consolidate all double matrices into ONE double matrx.
Here my code:
folder_string = 'Diss_Data/Raw';
FolderContent = dir(folder_string);
No_ds = numel(FolderContent);
for i = 1:No_ds
if isdir(FolderContent(i).name)==0
file_string = FolderContent(i).name;
file_path = strcat(folder_string,'/',file_string)
dataset_filename = file_string(1:6);
load(file_path); %loads the suggested datasetfile; OKAY
M = double(dataset_filename);% returns an ASCII code number; WRONG; should transfer the datasetfile into a matrix M
vS = M(:,2:3);
%... to be continued
end
end