I'm trying to create a graph that looks like a lattice that keeps extending. Here's the code I have:
graph G {
0 [label=""];
1 [label=""];
2 [label=""];
3 [label=""];
4 [label=""];
5 [label=""];
6 [label=""];
7 [label=""];
8 [label=""];
9 [label="", shape="none"];
10 [label="", shape="none"];
11 [label="", shape="none"];
12 [label="", shape="none"];
13 [label="", shape="none"];
14 [label="", shape="none"];
15 [label="", shape="none"];
16 [label="", shape="none"];
17 [label="", shape="none"];
18 [label="", shape="none"];
19 [label="", shape="none"];
20 [label="", shape="none"];
0 -- 1;
0 -- 2;
0 -- 3;
0 -- 4;
1 -- 5;
2 -- 5;
2 -- 6;
3 -- 6;
3 -- 7;
4 -- 7;
4 -- 8;
1 -- 8;
1 -- 9;
2 -- 10;
3 -- 11;
4 -- 12;
5 -- 13;
6 -- 14;
7 -- 15;
8 -- 16;
5 -- 17;
6 -- 18;
7 -- 19;
8 -- 20;
}
However, this produces output like:
Is there a way to get the edges on the corner nodes rectified so that it looks more regular?
Well I ended up adding a few more invisible vertices and invisible edges, which works. It's not the most elegant solution though.
graph G {
ratio="fill";
margin=0;
0 [label=""];
1 [label=""];
2 [label=""];
3 [label=""];
4 [label=""];
5 [label=""];
6 [label=""];
7 [label=""];
8 [label=""];
9 [label="", shape=none];
10 [label="", shape=none];
11 [label="", shape=none];
12 [label="", shape=none];
13 [label="", shape=none];
14 [label="", shape=none];
15 [label="", shape=none];
16 [label="", shape=none];
17 [label="", shape=none];
18 [label="", shape=none];
19 [label="", shape=none];
20 [label="", shape=none];
0 -- 1;
0 -- 2;
0 -- 3;
0 -- 4;
1 -- 5;
2 -- 5;
2 -- 6;
3 -- 6;
3 -- 7;
4 -- 7;
4 -- 8;
1 -- 8;
1 -- 9;
2 -- 10;
3 -- 11;
4 -- 12;
5 -- 13;
6 -- 14;
7 -- 15;
8 -- 16;
5 -- 17;
6 -- 18;
7 -- 19;
8 -- 20;
11 -- 18 [style=invis];
14 -- 10 [style=invis];
10 -- 17 [style=invis];
13 -- 9 [style=invis];
9 -- 16 [style=invis];
20 -- 12 [style=invis];
12 -- 15 [style=invis];
19 -- 11 [style=invis];
}
Related
I am trying to use Graphviz to produce a tree such as the following:
I have it almost working, as shown below:
My problems are the following:
Subtrees should never overlap, but the PP tree and the (.) tree overlap.
Subtrees should always be fairly regular, so that if there are multiple children, the edges should go to the left and right of the parent. Again, this does not work properly for the PP tree.
I have fixed (1) by using subgraph clusters, however, this introduces a few new issues. Namely, the edges are not straight, and I can't figure out how to hide the borders without leaving tons of empty space.
Is there a better way to force the tree formatting? It feels like it shouldn't be too unusual.
My code is below (generated by Python, sorry for unhelpful names):
graph {
subgraph 0 {
subgraph 1 {
0 [label=ROOT group=0 shape=plain]
subgraph 8 {
1 [label=S group=1 shape=plain]
subgraph 11 {
2 [label=NP group=2 shape=plain]
subgraph 15 {
3 [label=PRP group=3 shape=plain]
4 [label=I shape=plain]
3 -- 4
4 [label=I group=3]
}
2 -- 3
3 [label=PRP group=2]
}
subgraph 24 {
5 [label=VP group=5 shape=plain]
subgraph 28 {
6 [label=VBD group=6 shape=plain]
7 [label=solved shape=plain]
6 -- 7
7 [label=solved group=6]
}
subgraph 41 {
8 [label=NP group=8 shape=plain]
subgraph 45 {
9 [label=DT group=9 shape=plain]
10 [label=the shape=plain]
9 -- 10
10 [label=the group=9]
}
subgraph 63 {
11 [label=NN group=11 shape=plain]
12 [label=problem shape=plain]
11 -- 12
12 [label=problem group=11]
}
8 -- 9
8 -- 11
}
subgraph 77 {
13 [label=PP group=13 shape=plain]
subgraph 81 {
14 [label=IN group=14 shape=plain]
15 [label=on shape=plain]
14 -- 15
15 [label=on group=14]
}
subgraph 89 {
16 [label=NP group=16 shape=plain]
subgraph 93 {
17 [label=DT group=17 shape=plain]
18 [label=the shape=plain]
17 -- 18
18 [label=the group=17]
}
subgraph 102 {
19 [label=NN group=19 shape=plain]
20 [label=bus shape=plain]
19 -- 20
20 [label=bus group=19]
}
16 -- 17
16 -- 19
}
13 -- 14
13 -- 16
}
5 -- 6
5 -- 8
5 -- 13
}
subgraph 114 {
21 [label="." group=21 shape=plain]
22 [label="." shape=plain]
21 -- 22
22 [label="." group=21]
}
1 -- 2
1 -- 5
1 -- 21
}
0 -- 1
1 [label=S group=0]
}
}
ranksep=0.2
}
You are correct, Graphviz has "problems" with trees. That said, here is your graph, with clusters (peripheries=0), splines=false, and margin=2:
graph {
graph [splines=false]
subgraph cluster_0 {
peripheries=0
margin=2
subgraph cluster_1 {
0 [label=ROOT group=0 shape=plain]
subgraph cluster_8 {
1 [label=S group=1 shape=plain]
subgraph cluster_11 {
2 [label=NP group=2 shape=plain]
subgraph cluster_15 {
3 [label=PRP group=3 shape=plain]
4 [label=I shape=plain]
3 -- 4
4 [label=I group=3]
}
2 -- 3
3 [label=PRP group=2]
}
subgraph cluster_24 {
5 [label=VP group=5 shape=plain]
subgraph cluster_28 {
6 [label=VBD group=6 shape=plain]
7 [label=solved shape=plain]
6 -- 7
7 [label=solved group=6]
}
subgraph cluster_41 {
8 [label=NP group=8 shape=plain]
subgraph cluster_45 {
9 [label=DT group=9 shape=plain]
10 [label=the shape=plain]
9 -- 10
10 [label=the group=9]
}
subgraph cluster_63 {
11 [label=NN group=11 shape=plain]
12 [label=problem shape=plain]
11 -- 12
12 [label=problem group=11]
}
8 -- 9
8 -- 11
}
subgraph cluster_77 {
13 [label=PP group=13 shape=plain]
subgraph cluster_81 {
14 [label=IN group=14 shape=plain]
15 [label=on shape=plain]
14 -- 15
15 [label=on group=14]
}
subgraph cluster_89 {
16 [label=NP group=16 shape=plain]
subgraph cluster_93 {
17 [label=DT group=17 shape=plain]
18 [label=the shape=plain]
17 -- 18
18 [label=the group=17]
}
subgraph cluster_102 {
19 [label=NN group=19 shape=plain]
20 [label=bus shape=plain]
19 -- 20
20 [label=bus group=19]
}
16 -- 17
16 -- 19
}
13 -- 14
13 -- 16
}
5 -- 6
5 -- 8
5 -- 13
}
subgraph cluster_114 {
21 [label="." group=21 shape=plain]
22 [label="." shape=plain]
21 -- 22
22 [label="." group=21]
}
1 -- 2
1 -- 5
1 -- 21
}
0 -- 1
1 [label=S group=0]
}
}
ranksep=0.2
}
Giving:
i have this quiz, you should make an output like this, and i search youtube tutorials for "for golang" and it explain that it has 2 style of for in golang,
1
21
11
12
13
14
22
11
12
13
14
23
11
12
13
14
24
11
12
13
14
2
21
11
12
13
14
22
11
12
13
14
23
11
12
13
14
24
11
12
13
14
3
21
11
12
13
14
22
11
12
13
14
23
11
12
13
14
24
11
12
13
14
4
21
11
12
13
14
22
11
12
13
14
23
11
12
13
14
24
11
12
13
14
5
21
11
12
13
14
22
11
12
13
14
23
11
12
13
14
24
11
12
13
14
it should be vertically outputted, not horizontally, so i build 3 variable, i = 1, j = 21, and k = 11, and i use for to automatically increase the value, the 1st style worked, but the 2nd style somehow its different
yt vid : https://www.youtube.com/watch?v=jZ-llP_yKNo on 5:28 min he explain that for has 2 style
1st style :
for i:=1; i <= 5; i++{
fmt.Println(i)
for j:=21; j <= 24; j++ {
println(j)
for k:=11; k<=14; k++ {
fmt.Println(k)
}
}
}
2nd style :
i:=1
j:=21
k:=11
for i <= 5{
fmt.Println(i)
i++
for j <= 24 {
println(j)
j++
for k<=14 {
fmt.Println(k)
k++
}
}
}
It's not about the syntax but about your logic.
In the 1st style with for i := ..., whenever next loop run, you reset the value to the init state, means it always sets j to 21 and k to 11. So there will a many sub loop runs.
In contrast, 2nd style, you init value j and k right before going to loop. So in the second loop of i, j and k are still the same value with 25 and 15 in that order.
There are multiple options to print the output in the golang.
fmt.Println appends a new line in the end.
fmt.Printf prints content as it is.
For more details read the documentation.
for i := 1; i <= 5; i++ {
fmt.Printf("%v ", i)
for j := 21; j <= 24; j++ {
fmt.Printf("%v ", j)
for k := 11; k <= 14; k++ {
fmt.Printf("%v ", k)
}
}
}
Output
1 21 11 12 13 14 22 11 12 13 14 23 11 12 13 14 24 11 12 13 14 2 21 11 12 13 14 22 11 12 13 14 23 11 12 13 14 24 11 12 13 14 3 21 11 12 13 14 22 11 12 13 14 23 11 12 13 14 24 11 12 13 14 4 21 11 12 13 14 22 11 12 13 14 23 11 12 13 14 24 11 12 13 14 5 21 11 12 13 14 22 11 12 13 14 23 11 12 13 14 24 11 12 13 14
To add a new line use the \n escape sequence.
Check the running code link
This question was asked as a puzzle in one Book of Puzzles by RS AGGARWAL, which stated the problem as to build an order N matrix where each i'th row and i'th column combined have all the elements from 1 to 2N-1.
For instance, for N=2
[3,2]
[1,3]
I want to know when is an answer possible for it for which values of N it is possible to make a matrix and how to make it? and write code for it
this has simple solution for square matrices where n is power of 2 so n=1,2,4,8,16,... do not ask me why there surely is some math proof for it ...
The algorithm to create such matrix is easy:
clear matrix (with 0)
loop i through all values i=1,2,3...2n-1
for each i find all locations where i matrix is not yet filled (0) and there is not i present in row and column
fill the position with i and repeat until no such location found.
In C++ something like this:
//---------------------------------------------------------------------------
const int n=8;
int m[n][n];
//---------------------------------------------------------------------------
// compute histogram u[n+n] of values per ith row,col of m[n][n]
void hist_rst(int *u ) { for (int j=0;j<n+n;j++) u[j]=0; }
void hist_row(int *u,int m[n][n],int i) { for (int j=0;j<n;j++) u[m[j][i]]=1; }
void hist_col(int *u,int m[n][n],int i) { for (int j=0;j<n;j++) u[m[i][j]]=1; }
//---------------------------------------------------------------------------
void matrix_init(int m[n][n])
{
int i,x,y,h[n][n+n];
// clear matrix (unused cells)
for (x=0;x<n;x++)
for (y=0;y<n;y++)
m[x][y]=0;
// clear histograms
for (i=0;i<n;i++) hist_rst(h[i]);
// try to fill values 1..2n-1
for (i=1;i<n+n;i++)
{
// find free position
for (x=0;x<n;x++) if (!h[x][i])
for (y=0;y<n;y++) if (!h[y][i])
if (!m[x][y])
{
// set cell
m[x][y]=i;
h[x][i]=1;
h[y][i]=1;
break;
}
}
}
//---------------------------------------------------------------------------
here few outputs:
1
1 3
2 1
1 5 6 7
2 1 7 6
3 4 1 5
4 3 2 1
1 9 10 11 12 13 14 15
2 1 11 10 13 12 15 14
3 4 1 9 14 15 12 13
4 3 2 1 15 14 13 12
5 6 7 8 1 9 10 11
6 5 8 7 2 1 11 10
7 8 5 6 3 4 1 9
8 7 6 5 4 3 2 1
for non power of 2 matrices you could use backtracking but take in mind even 4x4 matrix will have many iterations to check ... so some heuristics would need to be in place to make it possible in finite time... as brute force is (n+n)^(n*n) so for n=4 there are 281474976710656 combinations to check ...
[edit1] genere&test solution for even n
//---------------------------------------------------------------------------
const int n=6;
int m[n][n];
//---------------------------------------------------------------------------
// compute histogram u[n+n] of values per ith row,col of m[n][n]
void hist_rst(int *u ) { for (int j=0;j<n+n;j++) u[j]=0; }
void hist_row(int *u,int m[n][n],int i) { for (int j=0;j<n;j++) u[m[j][i]]=1; }
void hist_col(int *u,int m[n][n],int i) { for (int j=0;j<n;j++) u[m[i][j]]=1; }
//---------------------------------------------------------------------------
void matrix_init2(int m[n][n]) // brute force
{
int x,y,a,ax[(n*n)>>1],ay[(n*n)>>1],an,u[n+n];
// clear matrix (unused cells)
for (x=0;x<n;x++)
for (y=0;y<n;y++)
m[x][y]=0;
// main diagonal 1,1,1,1...
for (x=0;x<n;x++) m[x][x]=1;
// 1st row 1,2,3...n
for (x=1;x<n;x++) m[x][0]=x+1;
// cells for brute force
for (an=0,x=0;x<n;x++)
for (y=0;y<x;y++)
if (!m[x][y])
{
ax[an]=x;
ay[an]=y;
an++;
m[x][y]=2;
}
// brute force attack values 2,3,4,5,...,n-1
for (;;)
{
// increment solution
for (a=0;a<an;a++)
{
x=ax[a];
y=ay[a];
m[x][y]++;
if (m[x][y]<=n) break;
m[x][y]=2;
}
if (a>=an) break; // no solution
// test
for (x=0;x<n;x++)
{
hist_rst(u);
hist_col(u,m,x);
hist_row(u,m,x);
for (y=1;y<=n;y++) if (!u[y]) { y=0; x=n; break; }
}
if (y) break; // solution found
}
// mirror other triangle
for (x=0;x<n;x++)
for (y=0;y<x;y++)
m[y][x]=m[x][y]+n-1;
}
//---------------------------------------------------------------------------
however its slow so do not try to go with n>6 without more optimizations/better heuristics... for now it is using triangle+mirror and diagonal + first row hard-coded heuristics.
maybe somehow exploit the fact that each iterated value will be placed n/2 times could speed this up more but too lazy to implement it ...
Here output for n=6:
[ 52.609 ms]
1 2 3 4 5 6
7 1 6 5 3 4
8 11 1 2 4 5
9 10 7 1 6 3
10 8 9 11 1 2
11 9 10 8 7 1
iterating through 5^10 cases ...
As requested by Spektre, here is the 6x6 matrix.
I an interesting property that may be used as heuristic. We need only to solve a triangular matrix because the other half can be easily deduced. We fill the upper (or lower) half of the matrix by values from 1 to n only. We can then complete the matrix by using the property that a[j][i] = 2n + 1 - a[i][j].
Another property I found is that there is a trivial way to place 1, 2 and N in the matrix. The values 1 are all on the diagonal, the values 2 and N are next to the diagonal at a step 2.
Finally, another thing I found is that matrix with odd N have no solutions. It is because the value in a[i][j] belongs to row and column i and row and column j. We thus need an even number of row and columns to store all values.
Here is the 6x6 matrix I found manually.
1 2 3 4 5 6
11 1 6 5 3 4
10 7 1 2 4 5
9 8 11 1 6 3
8 10 9 7 1 2
7 9 8 10 11 1
As we can see 2 + 11 = 6 + 7 = 3 + 10 = 13 = 2*6+1.
Here is a 4x4 matrix
1 2 3 4
7 1 4 3
6 5 1 2
5 6 7 1
Here again 2 + 7 = 4 + 5 = 3 + 6 = 9 = 2*4+1
It is possible to have other permutations of values >N, but with the 2N+1 property we can trivially deduce one triangular matrix from the other.
EDIT
Here is a solution for power two sized matrix. The matrix of size 2048x2048 is generated in 57ms (without printing).
#include <stdio.h>
int **newMatrix(int n) {
int **m = calloc(n, sizeof(int*));
m[0] = calloc(n*n, sizeof(int));
for (int i = 1; i < n; i++)
m[i] = m[0]+i*n;
return m;
}
void printMatrix(int **m, int n) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++)
printf("%3d ", m[i][j]);
printf("\n");
}
}
void fillPowerTwoMatrix(int **m, int n) {
// return if n is not power two
if (n < 0 || n&(n-1) != 0)
return;
for (int i = 0; i < n; i++)
m[0][i] = i+1;
for (int w = 1; w < n; w *= 2)
for (int k = 0; k < n; k += 2*w)
for (int i = 0; i < w; i++)
for (int j = k; j < k+w; j++) {
m[i+w][j] = m[i][j+w];
m[i+w][j+w] = m[i][j];
}
int k = 2*n+1;
for (int i = 1; i < n; i++)
for (int j = 0; j < i; j++)
m[i][j] = k - m[j][i];
}
int main() {
int n = 16;
int **m = newMatrix(n);
fillPowerTwoMatrix(m, n);
printMatrix(m, n);
return 0;
}
Here is the matrix 16x16. As can be seen there is a symmetry that is exploited to efficiently generate the matrix.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
31 1 4 3 6 5 8 7 10 9 12 11 14 13 16 15
30 29 1 2 7 8 5 6 11 12 9 10 15 16 13 14
29 30 31 1 8 7 6 5 12 11 10 9 16 15 14 13
28 27 26 25 1 2 3 4 13 14 15 16 9 10 11 12
27 28 25 26 31 1 4 3 14 13 16 15 10 9 12 11
26 25 28 27 30 29 1 2 15 16 13 14 11 12 9 10
25 26 27 28 29 30 31 1 16 15 14 13 12 11 10 9
24 23 22 21 20 19 18 17 1 2 3 4 5 6 7 8
23 24 21 22 19 20 17 18 31 1 4 3 6 5 8 7
22 21 24 23 18 17 20 19 30 29 1 2 7 8 5 6
21 22 23 24 17 18 19 20 29 30 31 1 8 7 6 5
20 19 18 17 24 23 22 21 28 27 26 25 1 2 3 4
19 20 17 18 23 24 21 22 27 28 25 26 31 1 4 3
18 17 20 19 22 21 24 23 26 25 28 27 30 29 1 2
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 1
I can't get GraphViz to respect some node positions, even though they have pos attributes with !. E.g.:
digraph Versions {
ranksep=0.05;
node [style=filled, shape=point, fillcolor=black, fixedsize=true, width=0.3, height=0.1, fontname="Helvetica", fontsize=8, fontcolor=white];
edge [arrowhead=none, len=0.1];
2 [pos="0,0!", fillcolor=red];
3 [pos="20,0!", fillcolor=red];
4 [pos="40,0!", fillcolor=red];
5 [pos="60,0!", fillcolor=red];
6 [pos="80,0!", fillcolor=red];
7 [pos="100,0!", fillcolor=red];
8 [pos="120,0!", fillcolor=red];
9 [pos="140,0!", fillcolor=red];
10 [pos="160,0!", fillcolor=red];
11 [pos="180,0!", fillcolor=red];
12 [pos="200,0!", fillcolor=red];
13 [pos="220,0!", fillcolor=red];
2 -> 14;
14 -> 15;
3 -> 16;
16 -> 17;
11 -> 18;
18 -> 19;
6 -> 20;
20 -> 21;
10 -> 22;
22 -> 23;
13 -> 24;
24 -> 25;
9 -> 26;
26 -> 27;
4 -> 28;
28 -> 29;
7 -> 30;
30 -> 31;
5 -> 32;
32 -> 33;
8 -> 34;
34 -> 35;
12 -> 36;
36 -> 37;
15 -> 38;
38 -> 39;
17 -> 40;
40 -> 41;
19 -> 42;
42 -> 43;
// etc.
}
The top most rank should be evenly distributed, but is not. The horizontal spacing between the top most nodes is not the same:
From the documentation of the pos attribute:
In neato and fdp, pos can be used to set the initial position of a node.
Are you using neato or fdp? Because dot does not respect this attribute.
Assuming you're using neato, here's an excerpt from the manual:
-n[1|2] (no-op) If set, neato assumes nodes have already been positioned and all nodes have a pos attribute giving the positions
This means you can render a graph with
neato -n2 -Tpng mygraph.gv -o mygraph.png
and have neato respect the pos attributes (in points) of the nodes.
This also states that all nodes must have a pos attribute.
Since some nodes of your graph do not have a pos attribute, this will lead to an error.
I have this graph:
digraph G {
1 [label="car"];
2 [label="x"];
3 [label="car"];
4 [label="y"];
5 [label="cdr"];
6 [label="cdr"];
7 [label="cons"];
8 [label="x1"];
9 [label="x2"];
10 [label="cons"];
11 [label="y1"];
12 [label="y2"];
13 [label="f"];
14 [label="f"];
15 [label="car"];
16 [label="cdr"];
17 [label="car"];
18 [label="cdr"];
1 -> 2;
3 -> 4;
5 -> 2;
6 -> 4;
7 -> 8;
7 -> 9;
10 -> 11;
10 -> 12;
13 -> 2;
14 -> 4;
15 -> 7;
16 -> 7;
17 -> 10;
18 -> 10;
}
and I want to add these other edges:
1 -> 3 [style="dashed"];
2 -> 7 [style="dashed"];
3 -> 8 [style="dashed"];
4 -> 10 [style="dashed"];
5 -> 6 [style="dashed"];
6 -> 9 [style="dashed"];
7 -> 10 [style="dashed"];
8 -> 11 [style="dashed"];
9 -> 12 [style="dashed"];
13 -> 14 [style="dashed"];
15 -> 8 [style="dashed"];
16 -> 9 [style="dashed"];
17 -> 11 [style="dashed"];
18 -> 12 [style="dashed"];
but without altering the layout.
I tried setting the edge weight to 0, but it doesn't work.
Thanks
You can simply add
edge[constraint=false];
before adding the irrelevant edges.
Without:
With the edges:
(There still seem to be some small changes)