How to specify the vertice order and the edge order when obtaining the incidence matrix of a digraph in sage? - sage

We can obtain the incidence matrix of a digraph using the method incidence_matrix(oriented=None, sparse=True, vertices=None) in SageMath.
Each row is a vertex, and each column is an edge. The vertices are ordered as obtained by the method vertices(), except when parameter vertices is given, and the edges as obtained by the method edge_iterator().
My question is how to specify the vertice order and the edge order?
For example, g is a weighted digraph with 10 edges:
edges = [('s', 'x', 3), ('s', 'y', 5),
('x', 'y', 2), ('x', 'z', 6),
('y', 'x', 1), ('y', 'z', 4), ('y', 't', 6),
('z', 't', 2),
('t', 's', 3), ('t', 'z', 7)]
g = DiGraph(edges)
I want to arrange the incidence matrix such that the vertices (from top to down) are ordered as s, x, y, z, t and the edges are ordered (from left to right) as those in edges (i.e., listing the edges in the alphabetic order s, x, y, z, t).

A quick look at the code (which you can obtain by doing g.edge_iterator??) for edge_iterator() suggests
The iterator returned is over the edges incident with any vertex
given in the parameter "vertices".
if oriented:
for e, (i, j) in enumerate(self.edge_iterator(labels=False)):
if i != j:
m[verts[i],e] = -1
m[verts[j],e] = +1
else:
for e, (i, j) in enumerate(self.edge_iterator(labels=False)):
m[verts[i],e] += 1
m[verts[j],e] += 1
tells me that probably one would have to hack the code for this a bit to change the order.
This seems like a reasonable request to have this customizable, so I've opened Sage Trac ticket 27513 for this.

Related

Find the longest path down a mountain with different stations

I a got a list of tuples, each tuple representing a station on a mountain. Each station has a certain distance to another station and we can only visit stations which are below us (so we basically cannot travel the mountain upwards). The tuples look like this:
t_1 = (1, 2, 5)
t_2 = (1, 3, 4)
t_3 = (2, 3 , 10)
t_4 = (2, 4, 1)
The first element of each tuple is the station and the second element indicates there exists path to that station with a distance of 5. So we can get from station 1 to 2 with a distance of 5 or we can get from station 1 to station 3 with a distance of 4. Ultimately, we are looking for the longest distance possible, which would be 15 (We visit station 2 first, then station 3). My idea was to use DFS for this with the following code:
def dfs(graph, node, dist, res):
cur, nxt, d = node
dist += d
if len(graph[nxt]) == 0:
res[0] = max(res[0], dist)
else:
for neighbor in graph[nxt]:
dfs(graph, neighbor, dist, res)
res = [0]
for start_nodes in graph[1]:
dfs(graph, start_nodes, 0, res)
The idea is, that I check if the current node "cur" has a neighbor "nxt" and visit this neighbor in an adj. list looking like this:
graph = [[(1,2,5),(1,3,4)],[(2,3,10),(2,4,1)],[]]
if there is no neighbor, we check if we have a new max distance. I am certainly missing something, so I would appreciate if anyone finds any errors and/or flaws!

R- Custom Keras Layer With Weight Constraints

I'm trying to write a custom Keras layer with trainable weights in R which:
Takes an input vector x and returns the value exp(A * X*A) where $A$ is diagonal and trainable..
Where exp is the matrix exponential map.
Notice that it's very important that you understand where your batch size is, and that a layer CANNOT have weights with sizes based on the batch size (unless you define your inputs with batch_shape or batch_input_shape instead of shape -- this will force you to use a fixed batch size in the model). Since the batch size is usually for "individual" and "independent" samples, it's not healthy to use the batch size in operations and mixing samples!
That said, I am assuming that X here has shape (batch, dim, dim), and that A will have shape (dim, dim) consequently.
For this, you build a custom layer such as here: https://tensorflow.rstudio.com/guide/keras/custom_layers/
Where build will have kernel (A) with shape (1, dim, 1) --
build = function(input_shape) {
self$kernel <- self$add_weight(
name = 'kernel',
shape = list(1,input_shape[[2]], 1),
initializer = initializer_random_normal(), #you may choose different initializers
trainable = TRUE
)
},
And call will use a mathematical trick to simulate the diagonal.
Notice that if A is diagonal, the result of A x X x A will be B*X (elementwise), where B is:
#supposing A has the elements [a, b, c, ...] in the diagonals,
B is:
[ [aa, ab, ac, ...],
[ab, bb, bc, ...],
[ac, bc, cc, ...],
...
]
Because of this, we will not use diagonals, but a broadcasting trick with elementwise multiplication:
call = function(x, mask = NULL) {
kernelTransposed <- tf$reshape(self$kernel, shape(1L, 1L, -1L)) #(1, 1, dim)
B <- self$kernel * kernelTransposed #(1, dim, dim)
tf$math$exp(x * B)
},
The output shape goes unchanged:
compute_output_shape = function(input_shape) {
input_shape
}

Create Static Directed Graph in Julia

How can I create a Static Directed Graph from an array of tuples in Julia without having to create a Simple Directed Graph first. An example edge list I have is [(1,2),(2,3),(3,4)]. The documentation of StaticGraphs.jl is limited.
There's a way to do this but it requires you to have the edges and their reverses already sorted into two vectors. Assume you have a directed path graph 1 -> 2 -> 3 -> 4:
fwd = [(1, 2), (2, 3), (3, 4)] # these are your forward edges, sorted
rev = [(2, 1), (3, 2), (4, 3)] # these are the reverse of the forward edges, sorted
# also, sort(reverse.(fwd)) will do this easily.
g = StaticDiGraph(4, fwd, rev) # number of vertices is the first argument
testing:
julia> h = StaticDiGraph(path_digraph(4))
{4, 3} directed simple static {UInt8, UInt8} graph
julia> g == h
true

Bokeh: grid of plots and aspect ratio

I trying to make a grid a image and line plots, but the first image plot is stretched horizontally, apparently because of the width taken by the y-axis labels of the line plot on the second row.
Is there any way to prevent this?
# create an array of RGBA data
N = 20
img = np.empty((N, N), dtype=np.uint32)
view = img.view(dtype=np.uint8).reshape((N, N, 4))
for i in range(N):
for j in range(N):
view[i, j, 0] = int(255 * i / N)
view[i, j, 1] = 158
view[i, j, 2] = int(255 * j / N)
view[i, j, 3] = 255
#output_file("grid.html", )
p = figure(plot_width=200, plot_height=200, x_range=(0, 10), y_range=(0, 10))
p.image_rgba(image=[img], x=[0], y=[0], dw=[10], dh=[10])
p2 = figure(plot_width=200, plot_height=200, x_range=(0, 10), y_range=(0, 10))
p2.image_rgba(image=[img], x=[0], y=[0], dw=[10], dh=[10])
p3 = figure(plot_width=400, plot_height=200)
p3.line([1, 2, 3, 4, 5], np.array([6, 7, 2, 4, 5])*10000, line_width=2)
p3.xaxis.axis_label = f'Wavelength'
p3.yaxis.axis_label = f'Flux'
l = gridplot([
[p, p2],
[p3]
], sizing_mode='fixed')
show(l)
As of Bokeh 1.0.2 there is not a direct way to control the inner frame dimensions. There is an ongoing WIP Pull Request to add this capability, and others, that will land in a 1.1 release.
In the mean time, you can:
control the overall canvas width/height with plot_width and plot_height
control the minimum padding around the inner from with min_border, min_border_left, etc.
control the extent of axis ticks by controlling their rotation, formatting, or location
So, if you control the ticks (and account for any colorbar size, etc), and set appropriate min_border values that will not be exceeded, you can effectively exert control over the frame dimensions indirectly. I note that this is far from ideal, and look forward to the layout PR arriving.

Create logical ordered queue list from percentage value

This is math task. I need to create an order list (or queue list) from x values - everyone is percent and sum of all of them is 100. I want logical order of these values. Let see this:
a = 50,
b = 25,
c = 15,
d = 10
The greatest common divisor of these numbers is 5, so the queue should has length 100/5 = 20. And the result should look like this (or very similar):
a, b, a, b, a, c, a, b, a, d, a, c, a, b, a, c, a, b, a, d
I'm looking for formula how to this order. Thanks in advance.
I take it that you'd like to distribute each letter as uniformly as possible throughout the array or string. The preliminary step of finding the greatest common divisor and dividing the numbers 50,25,15,10 by it is straightforward. Once this is done, you get the number of times each letter must appear. Then the algorithm can be: beginning with the empty string, add the "most underrepresented" letter, repeat. I define "most underrepresented" as the one with the maximal difference of (desired proportion) - (actual proportion so far).
Here is this algorithm implemented in Python.
count = {'a': 10, 'b': 5, 'c': 3, 'd': 2}
length = sum(count.values())
str = ''
while len(str) < length:
deficit = {}
for char in count:
deficit[char] = count[char]/length - (str.count(char)/len(str) if str else 0)
str += max(deficit, key=deficit.get)
print(str)
The output is abcadabacabadabacaba. Split by letter to show the distribution:
a..a.a.a.a.a.a.a.a.a
.b....b...b...b...b.
..c.....c.......c...
....d.......d.......

Resources