How to code adjacency lists in a dodecahedron graph? - graph

It has:
20 vertices
30 edges
G{20,30}
How can you generate the adjacency lists for each vertex 1,2,...20?
V1 is linked with 2 and 3
v2 is linked with 1 and 4
v3 is linked with 1 and 5 ??
Is there like a formula? This is for a game project, don't know if I missed a math class or something? What should I study to understand the solution?

Manually constructed:
int adjs[] = { 1, 4, 7, 0, 2, 9, 1, 3, 11, 2, 4, 13, 0, 3, 5, 4, 6, 14, 5, 7, 16, 0, 6, 8, 7, 9, 17, 1, 8, 10, 9, 11, 18, 2, 10, 12, 11, 13, 19, 3, 12, 14, 5, 13, 15, 14, 16, 19, 6, 15, 17, 8, 16, 18, 10, 17, 19, 12, 15, 18 };
for (int i = 0, int j = 0; i < 20; i++, j = i * 3) {
caves[i] = Cave(i);
for (int c = j; c < j + 3; c++) {
caves[i].adjsListy.addAdj(adjs[c]);
}
I found help in the solution here: https://rosettacode.org/wiki/Hunt_The_Wumpus/C%2B%2B

I think the link list is usually manually constructed.
However you can take a look at the special case of a 2:1 pyritohedron in https://en.wikipedia.org/wiki/Dodecahedron to get an understanding of how to go from a cube to a dodecahedron. (Also take a look at the animated gif in the section "Cartesian Coordinates")
What this tells us is that a dodecahedron can be constructed by inserting new vertices bisecting each of the cubes 12 edges. Then insert new edges connecting these new vertices such that they bisect each face of the 6 faces of the cube in alternating directions.
I think this understanding can be helpful, either for constructing an algorithm, or just to help you construct a manual link list.
This of-course only takes care of the vertex-links, to find the coordinates of each vertex, see e.g. How to generate/calculate vertices of dodecahedron?

Related

Calculate log probability, darts game R

I am having trouble with the following problem, I have done some research but I still cannot come up with any solution to this problem.
Darts Player shoots 30 times every night for a period of 42 days.
Create a function which takes the probability p of shooting the target and calculates the log of probability that the player has done the following shoots of the target for each of the 42 days:
shots = c(
8, 5, 12, 11, 12, 8, 6, 7, 11, 7, 11, 13, 15,
12, 17, 12, 9, 15, 8, 11, 11, 13, 10, 8, 12, 12, 11,
13, 12, 14, 9, 11, 13, 10, 10, 12, 13, 10, 15, 12, 15, 12
)
I am new to probability and this type of programming in R, so any help and approach to solving this problem would be appreciated. Thank you in advance!
The probability of getting 8 shots or less given a hit probability of 0.5 can be found with:
pbinom(8, 30, 0.5)
But to find the probability of exactly 8 shots, we need to subtract the probability of getting 7 shots or less:
pbinom(8, 30, 0.5) - pbinom(8 - 1, 30, 0.5)
Since pbinom is vectorized, we can get the independent probabilities of getting all the shots with:
pbinom(shots, 30, 0.5) - pbinom(shots - 1, 30, 0.5)
But this gives us a vector of 42 probabilities. To get the probability of getting exactly this string of shots, we need to multiply all these probabilities together:
prod(pbinom(shots, 30, 0.5) - pbinom(shots - 1, 30, 0.5))
#> [1] 2.921801e-62
And the log of this value is what we're looking for:
log(prod(pbinom(shots, 30, 0.5) - pbinom(shots - 1, 30, 0.5)))
#> [1] -141.6881
Note though that we might run into problems with floating point numbers being unable to handle very small numbers, so it is safer to take the sum of the logs rather than the log of the product, which is otherwise mathematically equivalent.
sum(log(pbinom(shots, 30, 0.5) - pbinom(shots - 1, 30, 0.5)))
#> [1] -141.6881
Now all we need to do is wrap this in a function which allows us to specify a number other than 0.5 for probability:
f <- function(p) {
shots = c(
8, 5, 12, 11, 12, 8, 6, 7, 11, 7, 11, 13, 15,
12, 17, 12, 9, 15, 8, 11, 11, 13, 10, 8, 12, 12, 11,
13, 12, 14, 9, 11, 13, 10, 10, 12, 13, 10, 15, 12, 15, 12
)
sum(log(pbinom(shots, 30, p) - pbinom(shots - 1, 30, p)))
}
The reason you are being asked this question is probably as an introduction to likelihood. We can see the likelihood curve of the p parameter by plotting the log probability of getting exactly shots given a particular value of p
probs <- seq(0.01, 0.99, 0.01)
plot(probs, sapply(probs, f))
We can find the value of p with the greatest likelihood by using optimize:
optimize(f, c(0.01, 0.99), maximum = TRUE)$maximum
#> [1] 0.3714248
So we can infer that the player had approximately 37.14% chance of hitting the target each time.
We can confirm this is right by simply calculating the percentage of throws the dart player made, which should give us the same value:
mean(shots/30)
#> [1] 0.3714286

how to create non-perfect binary tree with diagrammeR?

I use diagrammeR library in R to create and render binary trees. I find it very simple to use and it creates high quality renders. However creating a tree that is not fully (perfect) generates messy renders.
Here is what I get when my tree has 16 leaves (h = 4):
Fully binary tree
To be clear, every node label is the row name of nodes data.frame which indicates the sequence of nodes passed to the graph:
nodes$label = rownames(nodes)
And here is what I get if I add one node [32] from node [31] - either manually or by add_node() and add_edge() functions:
Non-perfect binary tree
As you can see, everything goes messy. I would like to have node [32] directly under node [31] with edge of straight vertical line. Is it even possible with this library? I can't figure out the proper order of nodes in nodes data.frame.
Here is how my full code looks like:
library(DiagrammeR)
from = c(1, 1, 2, 2, 3, 3, 4, 4, 7, 7, 10, 10, 11, 11, 14, 14, 17, 17, 18, 18, 19, 19, 22, 22, 25, 25, 26, 26, 29, 29)
to = c(2, 17, 3, 10, 4, 7, 5, 6, 8, 9, 11, 14, 12, 13, 15, 16, 18, 25, 19, 22, 20, 21, 23, 24, 26, 29, 27, 28, 30, 31)
h=4
n = 2^(h+1)-1
edges = data.frame(from, to)
nodes = data.frame(id = 1:n, label=1:n, shape='circle')
g1 = create_graph(nodes, edges)
render_graph(g1, layout='tree', title='g1')
# add node [32] and edge [31-32]
edges2 = rbind(edges, c(31, 32))
nodes2 = nodes
nodes2[32, 1:2] = 32
nodes2[32, 3] = 'circle'
g2 = create_graph(nodes2, edges2)
render_graph(g2, layout='tree', title='g2')

Quade test in R

I would like to perform a Quade test with more than one covariate in R. I know the command quade.test and I have seen the example below:
## Conover (1999, p. 375f):
## Numbers of five brands of a new hand lotion sold in seven stores
## during one week.
y <- matrix(c( 5, 4, 7, 10, 12,
1, 3, 1, 0, 2,
16, 12, 22, 22, 35,
5, 4, 3, 5, 4,
10, 9, 7, 13, 10,
19, 18, 28, 37, 58,
10, 7, 6, 8, 7),
nrow = 7, byrow = TRUE,
dimnames =
list(Store = as.character(1:7),
Brand = LETTERS[1:5]))
y
quade.test(y)
My question is as follows: how could I introduce more than one covariate? In this example the covariate is the Store variable.

changing the spacing between vertices in iGraph in R

Suppose I want to make a plot with the following data:
pairs <- c(1, 2, 2, 3, 2, 4, 2, 5, 2, 6, 2, 7, 2, 8, 2, 9, 2, 10, 2, 11, 4,
14, 4, 15, 6, 13, 6, 19, 6, 28, 6, 36, 7, 16, 7, 23, 7, 26, 7, 33,
7, 39, 7, 43, 8, 35, 8, 40, 9, 21, 9, 22, 9, 25, 9, 27, 9, 33, 9,
38, 10, 12, 10, 18, 10, 20, 10, 32, 10, 34, 10, 37, 10, 44, 10, 45,
10, 46, 11, 17, 11, 24, 11, 29, 11, 30, 11, 31, 11, 33, 11, 41, 11,
42, 11, 47, 14, 50, 14, 52, 14, 54, 14, 55, 14, 56, 14, 57, 14, 58,
14, 59, 14, 60, 14, 61, 15, 48, 15, 49, 15, 51, 15, 53, 15, 62, 15,
63)
g <- graph( pairs )
plot( g,layout = layout.reingold.tilford )
I get a plot like the one below:
As you can see the spaces between some of the vertices are so small that these vertices overlap.
1. I wonder if there is a way to change the spacing between vertices.
2. In addition, is the spacing between vertices arbitrary? For example, Vertices 3, 4, and 5 are very close to each other, but 5 and 6 are far apart.
EDIT:
For my 2nd question, I guess the spacing is dependent on the number of nodes below. E.g., 10 and 11 are farther from each other than 8 and 9 are because there are more children below 10 and 11 than there are below 8 and 9.
I bet there is a better solution but I cannot find it. Here my approach. Since seems that a general parameter for width is missing you have to adjust manually parameters in order to obtain the desired output.
My approach is primarily to resize some elements of the plot in order to make them of the right size, adjust margins in order to optimize the space as much as possible. The most important parameter here is the asp parameter that controls the aspect ratio of the plot (since in this case the plot I guess is better long than tall an aspect ratio of even less than 0.5 is right). Other tricks are to diminish the size of vertex and fonts. Here is the code:
plot( g, layout = layout.reingold.tilford,
edge.width = 1,
edge.arrow.width = 0.3,
vertex.size = 5,
edge.arrow.size = 0.5,
vertex.size2 = 3,
vertex.label.cex = 1,
asp = 0.35,
margin = -0.1)
That produces this plot:
another approach would be to set graphical devices to PDF (or JPEG etc.) and then set the rescale to FALSE. With Rstudio viewer this cut off a huge piece of the data but with other graphic devices it might (not guarantee) work well.
Anyway for every doubt about how to use these parameters (that are very tricky sometimes) type help(igraph.plotting)
For the second part of the question I am not sure but looking inside the function I cannot figure out a precise answer but I guess that the space between elements on the same level is calculated on the child elements they have, say 3,4,5 have to be closer because they have child and sub-child and then they require more space.

Using texture for triangle mesh without having to read/write an image file

This is a followup on a previous question (see Coloring individual triangles in a triangle mesh on javafx) which I believe is another topic on its own.
Is there a way (with javafx) that I can get away from having to actually write to disk (or external device) an image file to use a texture?
In other words: can I use a specific texture without having to use Image?
Since my color map will change on runtime I don't want to have to write to disk every time I run it. Also, this might be a security issue (writing to disk) for someone using my app.(with javafx)
As #Jens-Peter-Haack suggest, with Snapshot you can create any image you want, and then apply this image as the diffusion map. For that, you need to create some nodes, fill them with the colors you require, group them in some container and then take the snapshot.
There's a straight-in approach, where you can build an image with a pattern of colors using PixelWriter.
Let's say you want 256 colors, this method will return an image of 256 pixels, where each pixel has one of these colors. For simplicity I've added two simple ways of building a palette.
public static Image colorPallete(int numColors){
int width=(int)Math.sqrt(numColors);
int height=numColors/width;
WritableImage img = new WritableImage(width, height);
PixelWriter pw = img.getPixelWriter();
AtomicInteger count = new AtomicInteger();
IntStream.range(0, height).boxed()
.forEach(y->IntStream.range(0, width).boxed()
.forEach(x->pw.setColor(x, y, getColor(count.getAndIncrement(),numColors))));
// save for testing purposes
try {
ImageIO.write(SwingFXUtils.fromFXImage(img, null), "jpg", new File("palette.jpg"));
} catch (IOException ex) { }
return img;
}
private Color getColor(int iColor, int numColors){
// nice palette of colors
java.awt.Color c = java.awt.Color.getHSBColor((float) iColor / (float) numColors, 1.0f, 1.0f);
return Color.rgb(c.getRed(), c.getGreen(), c.getBlue());
// raw palette
//return Color.rgb((iColor >> 16) & 0xFF, (iColor >> 8) & 0xFF, iColor & 0xFF);
}
Once you have the image object, you can set the diffuse map:
IcosahedronMesh mesh = new IcosahedronMesh();
PhongMaterial mat = new PhongMaterial();
mat.setDiffuseMap(colorPallete(256));
mesh.setMaterial(mat);
But you still have to provide the proper mapping to the new texture.
For this you need to map the vertices of the mesh to a pixel in the image.
First, we need a way to map colors with texture coordinates on the mesh. This method will return a pair of coordinates for a given color index:
public static float[] getTextureLocation(int iPoint, int numColors){
int width=(int)Math.sqrt(numColors);
int height=numColors/width;
int y = iPoint/width;
int x = iPoint-width*y;
return new float[]{(((float)x)/((float)width)),(((float)y)/((float)height))};
}
Finally, we add these textures to m.getTextCoords() and to the faces m.getFaces(), as shown here.
If we assign a color to every vertex in our icosahedron we pick a color from all the palette (scaling up or down according the number of colors and vertices), and then set every face with t0=p0, t1=p1, t2=p2:
IntStream.range(0,numVertices).boxed()
.forEach(i->m.getTexCoords()
.addAll(getTextureLocation(i*numColors/numVertices,numColors)));
m.getFaces().addAll(
1, 1, 11, 11, 7, 7,
1, 1, 7, 7, 6, 6,
1, 1, 6, 6, 10, 10,
1, 1, 10, 10, 3, 3,
1, 1, 3, 3, 11, 11,
4, 4, 8, 8, 0, 0,
5, 5, 4, 4, 0, 0,
9, 9, 5, 5, 0, 0,
2, 2, 9, 9, 0, 0,
8, 8, 2, 2, 0, 0,
11, 11, 9, 9, 7, 7,
7, 7, 2, 2, 6, 6,
6, 6, 8, 8, 10, 10,
10, 10, 4, 4, 3, 3,
3, 3, 5, 5, 11, 11,
4, 4, 10, 10, 8, 8,
5, 5, 3, 3, 4, 4,
9, 9, 11, 11, 5, 5,
2, 2, 7, 7, 9, 9,
8, 8, 6, 6, 2, 2
);
This will give us something like this:
EDIT
Playing around with the textures coordinates, instead of mapping node with color, you can add some function and easily create a contour plot, like this:
You might create the texture to be used for fill etc. in your code by using any graphic object and convert that into an image in memory, not touching disk.
The example below will create a texture using a green spline.
Pane testImage2(Pane pane) {
Pane inner = new Pane();
inner.prefWidthProperty().bind(pane.widthProperty());
inner.prefHeightProperty().bind(pane.heightProperty());
pane.getChildren().add(inner);
SVGPath texture = new SVGPath();
texture.setStroke(Color.GREEN);
texture.setStrokeWidth(2.5);
texture.setFill(Color.TRANSPARENT);
texture.setContent("M 10 10 C 40 10 10 70 70 20");
SnapshotParameters params = new SnapshotParameters();
params.setViewport(new Rectangle2D(-5, -5, 70, 50));
Image image = texture.snapshot(params, null);
Paint paint = new ImagePattern(image, 5,5, 20, 20, false);
inner.setBackground(new Background(new BackgroundFill(paint, new CornerRadii(0), new Insets(inset))));
return pane;
}

Resources