Animating a circle of lights - math

I am trying to create some basic animations for a set of RGB LEDs. Normal linear animations are simple enough using loops and counters to vary the light colour.
What I have is a ring of 24 LEDs and want to be able to apply animations to them so that the effect, say a simple colour wipe, occurs from top to bottom, or side to side (basically any given direction).
I have not made any progress worth sharing, other than storing an array of each "row" of LEDs:
0 => 0
1 => 1, 23
2 => 2, 22
3 => 3, 21
and so on
This is a crude solution, and I am hoping there are better ways using cos/tan perhaps.
My question is how to address each LED in sequence when performing an animation from top to bottom (or starting at any n degrees).

Trigonometry is relevant if you want to go from a single number (an angle) to a pair of numbers (coordinates of a point on a circle). Your LED addresses seem to be single numbers in the range 0 to 23. They essentially are angles (one every 360/24 = 15 degrees, so you don't need an angle to coordinate conversion.
What you do need is a way to model rotational symmetry, but that is simply modular arithmetic (working mod 24). To give some idea, here is a Python script which could be used to "wipe" from any of the 24 points:
def wipe_from(i):
leds = [[i]]
for j in range(1,12):
leds.append([(i+j) % 24, (i-j) % 24])
leds.append([(i+12)%24])
return leds
For example, wipe_from(0) corresponds to what you already have, and wipe_from(5) is:
[[5], [6, 4], [7, 3], [8, 2], [9, 1], [10, 0], [11, 23], [12, 22], [13, 21], [14, 20], [15, 19], [16, 18], [17]]

Related

How update intersection when an angle.Value() change

I have a construction that starts with a point and a segment. Later I have an intersection. The correct output of the intersection depend if the 3.rd parameter i is 0 or 1. The point and the line are not part of create('intersection'....
If 0 or 1 depends where the point is relative to the line. Is it above or left the line it is 1 otherwise 0.
So I thougt I create an angle between the the point and the segment and decide if the angle is less pi. Statically this works, but how do I update the intersection, if I move the point or the segment?
Best regards basil
At the moment (i.e. v1.5.0) dynamic values for the intersection number are not supported.
But this is a very good suggestion. We included it into the source, it will be available in 1.5.1. Here is an example how to use it:
var ci = board.create('circle', [[0, 0], 3]);
var li = board.create('line', [[-3, -3], [4, 1]]);
var sl = board.create('slider', [[1,4], [2,4], [0, 0, 1]],
{snapWidth: 1, name:'i', digits:0});
var is = board.create('intersection', [ci, li, () => sl.Value()]);

How to determine if Quadrilateral is convex or not by given points

Is there any way to determine whether quadrilateral is convex or not? (meaning each of its angles are less than 180 degree) by using points. For example A(0,0) B(2,0) C(2,2) D(-1,3). How can we determine that all of the angles in ABCD quadrilateral are less than 180 degrees.
I believe this link answers your question, for any polygon.
In summary, given a list of points [[0, 0], [2, 0], [2, 2], [-1, 3]], check if the direction of the cross product of any two adjacent sides are the same (if so, the polygon is convex).

Creating subgraphs with overlapping vertices

I've been looking for packages using which I could create subgraphs with overlapping vertices.
From what I understand in Networkx and metis one could partition a graph into two or multi-parts. But I couldn't find how to partition into subgraphs with overlapping nodes.
Suggestions on libraries that support partitioning with overlapping vertices will be really helpful.
EDIT: I tried the angel algorithm in CDLIB to partition the original graph into subgraphs with 4 overlapping nodes.
import networkx as nx
from cdlib import algorithms
if __name__ == '__main__':
g = nx.karate_club_graph()
coms = algorithms.angel(g, threshold=4, min_community_size=10)
print(coms.method_name)
print(coms.method_parameters) # Clustering parameters)
print(coms.communities)
print(coms.overlap)
print(coms.node_coverage)
Output:
ANGEL
{'threshold': 4, 'min_community_size': 10}
[[14, 15, 18, 20, 22, 23, 27, 29, 30, 31, 32, 8], [1, 12, 13, 17, 19, 2, 21, 3, 7, 8], [14, 15, 18, 2, 20, 22, 30, 31, 33, 8]]
True
0.6470588235294118
From the communities returned, I understand 1 and 3 have an overlap of 4 nodes but 2 and 3 or 1 and 3 don't have an overlap size of 4 nodes.
It is not clear to me how the overlap threshold (4 overlaps) has to be specified
here algorithms. angel(g, threshold=4, min_community_size=10). I tried setting threshold=4 here to define an overlap size of 4 nodes. However, from the documentation available for angel
:param threshold: merging threshold in [0,1].
I am not sure how to translate the 4 overlaps to the value that has to be set between the bounds [0, 1]. Suggestions will be really helpful.
You can check out CDLIB:
They have a great amount of community finding algorithms applicable to networkX, including some overlapping communities algorithms.
On a side note:
The return type of the functions is called Node Clustering which might be a little confusing at first so here are the methods applicable to it, usually you simply want to convert to a Python dictionary.
Specifically about the angel algorithm in CDLIB:
According to ANGEL: efficient, and effective, node-centric community discovery in static and dynamic networks, the threshold is not the overlapping threshold, but used as follows:
If the ratio is greater than (or equal to) a given threshold, the merge is applied and the node label updated.
Basically, this value determines whether to further merge the nodes into bigger communities, and is not equivalent to the number of overlapping nodes.
Also, don't mistake "labels" with "node's labels" (as in nx.relabel_nodes(G, labels)). The "labels" referred are actually correlated with the Label Propagation Algorithm which is used by ANGEL.
As for the effects of varying this threshold:
[...] Increasing the threshold, we obtain a higher number of communities since lower quality merges cannot take place.
[based on the comment by #J. M. Arnold]
From ANGEL's github repository you can see that when threshold >= 1 only the min_comsize value is used:
self.threshold = threshold
if self.threshold < 1:
self.min_community_size = max([3, min_comsize, int(1. / (1 - self.threshold))])
else:
self.min_community_size = min_comsize

How to make a diagonal tensor and why doesn't Tensorflow linalg.tensor_diag do that?

What I would consider a diagonal tensor is a tensor t of shape (d1, ..., dr) which is all zero except when the components are equal.
So t[i,j,k,l] = 0 unless i == j == k == l.
A function to create such a tensor should take in a shape (d1, ..., dr) and a vector [a1, ..., ak] of length min(d1, ..., dr), placing these values along the diagonal.
I would like to do this in Tensorflow, and the most relevant function I could find was tf.linalg.tensor_diag, but it doesn't do what I want. For instance, the diagonal input is a tensor, and the output tensor always has twice the rank, and so it can never output tensors of odd rank.
The documentation says "Given a diagonal, this operation returns a tensor with the diagonal and everything else padded with zeros", but I don't know how to square that with its actual behavior.
My question is two parts:
What is the best way in TF to do create what I am calling a diagonal tensor. Is there another name for this?
Why does linalg.tensor_diag work like this? What is the intended use?
Here is an example output:
>>> tf.linalg.tensor_diag([1,2],[3,4]])
<tf.Tensor: shape=(2, 2, 2, 2), dtype=int32, numpy=
array([[[[1, 0],
[0, 0]],
[[0, 2],
[0, 0]]],
[[[0, 0],
[3, 0]],
[[0, 0],
[0, 4]]]], dtype=int32)>```
So this is a little tricky to think about but I'll try to explain the thinking.
If you do tf.linalg.tensor_diag([1,2,3,4]) this is intuitively gives a matrix with that diagonal:
[[1, 0, 0, 0],
[0, 2, 0, 0],
[0, 0, 3, 0],
[0, 0, 0, 4]]
Notice you went from rank 1 to rank 2 doing this, the rank doubled. So to "diagonalize" it's going to end up doubling the rank.
Now your question, tf.linalg.tensor_diag([[1,2],[3,4]]) What you're passing in is a matrix so rank 2
[[1, 2],
[3, 4]]
But now, how should this be diagonalized? So it's rank 2 and following the pattern means we'll end up with something of rank 4. In the previous example diagonalize sort of "pulled up" the vector into the higher rank. And each step of "pulling up" took a single value from the diagonal and put it there.
So this matrix will also be "pulled up" and each step of the way leaving a value. So it's going to make 4 squares of [[0,0],[0,0]] and drop the value in each one. This would give us
[[1,0],
[0,0]]
[[0,2],
[0,0]]
[[0,0],
[3,0]]
[[0,0],
[0,4]]
Lastly things will be "grouped" if they were originally (like [1,2] idk how better to say this) so that gives the final result of
[
[
[[1,0],
[0,0]] ,
[[0,2],
[0,0]]
],
[
[[0,0],
[3,0]] ,
[[0,0],
[0,4]]
]
]
Which indeed gives us a rank 4 result 👍
Note: You may want to look into the other diag function for more of you're trying to do

Mathematica piecewise function bad plot rendering

I wanted to plot a user-defined Piecewise function (pagoda function) in Mathematica 10.2.
It seems straightforward to me unfortunately the easy command leads to a bad result.
My first approach was:
f[x_] := Piecewise[{{0, x <= -1}, {-Abs[x] + 1, -1 < x < 1}, {0,
x >= 1}}]
Plot3D[ 5*f[x]*f[y], {x, -1.5, 1.5}, {y, -1.5, 1.5}]
I also tried to set MaxRecursion which lead to more terrible results in a few cases (e.g. 2,3).
Can anybody tell me how to plot this function in a smooth nice way?
Thanks,
Felix
As far as I can remember, making visible gaps was introduced as a feature. Before that, piecewise or discontinuous functions were plotted like this:
Plot[Piecewise[{{x, x <= 1}, {3, x > 1}}], {x, 0, 3}, Exclusions -> None]
That behavior gives the wrong impression. I would have to check when this was default or if I'm completely off here. Anyway, as already noted in the comments, you can use the Exclusions option to get connected graphs.
You don't need to increase PlotPoints because Mathematica will (hopefully always) recognize the boundaries of the pieces as places where it needs to recursively increase points. Therefore, the MaxRecursion option is far more important to give a smooth plot. This example was rendered with only 10 points, but a recursion value of 5:
Therefore, your function renders extremely well even with 10 plot-points when the recursion is high enough. Look how many subdivisions you get on the cracks
Plot3D[5*f[x]*f[y], {x, -1.5, 1.5}, {y, -1.5, 1.5}, PlotRange -> All,
Exclusions -> None, PlotPoints -> 10, MaxRecursion -> 6, Mesh -> All]
Finally, note that the gaps are not restricted to Piecewise functions. As you can verify yourself, UnitStep will also show gaps. You can try it with your example by using an undocumented function to turn everything to UnitStep:
Simplify`PWToUnitStep[5*f[x]*f[y]]
(*
5 (1 - Abs[x]) (1 - Abs[y]) (1 - UnitStep[-1 - x]) (1 -
UnitStep[-1 + x]) (1 - UnitStep[-1 - y]) (1 - UnitStep[-1 + y])
*)
With all due respect to #halirutan, by itself MaxRecursion set to 6 was not enough in the following plot to adjust the peak values of a piecewise function to be a monotonic increasing sequence:
This improved, when, in addition, I set PlotPoints to 240, as follows.
However, that does not completely solve all the display problems. For example, note in the plots above, that the initial value y = 0, is not correctly plotted as a blue vertical line despite use of Exclusions->None. Moreover, the grid lines, which are Dotted, do not display as dots, but as dashes which run off below the x-axis. All of these problems can be solved, probably more efficiently, by generating the points or dots as list data and using ListPlot or, as in this case ListLogPlot and using Joined->True when appropriate. That is low level solution, but is needed in more complicated plots to obtain a plot with shorter run time and more accessible control over the display features.

Resources