Any hints how to draw branching schema in spirit of attached image is welcomed.
Note that I would like to do it in graphviz for fast editing and future changes.
I made an attempt to imitate the famous git branching strategy from http://nvie.com/posts/a-successful-git-branching-model/ using GraphViz.
This is the original picture:
And this is the result:
The code:
strict digraph g{
rankdir="TB";
nodesep=0.5;
ranksep=0.25;
splines=line;
forcelabels=false;
// general
node [style=filled, color="black",
fontcolor="black", font="Consolas", fontsize="8pt" ];
edge [arrowhead=vee, color="black", penwidth=2];
// branch names
node [fixedsize=false, penwidth=0, fillcolor=none, shape=none, width=0, height=0, margin="0.05"];
subgraph {
rank=sink;
me [label="master", group="master"];
}
subgraph {
rank=sink;
de [label="develop", group="develop"];
}
// tags
node [shape=cds, fixedsize=false, fillcolor="#C6C6C6", penwidth=1, margin="0.11,0.055"]
t1 [label="0.1"]
t2 [label="0.2"]
t3 [label="1.0"]
// graph
node [width=0.2, height=0.2, fixedsize=true, label="", margin="0.11,0.055", shape=circle, penwidth=2, fillcolor="#FF0000"]
// branches
node [group="master", fillcolor="#27E4F9"];
m1;
m2;
m3;
m4;
subgraph {
rank=source;
ms [label="", width=0, height=0, penwidth=0];
}
m1 -> m2 -> m3 -> m4;
ms -> m1 [color="#b0b0b0", style=dashed, arrowhead=none ];
m4 -> me [color="#b0b0b0", style=dashed, arrowhead=none ];
node [group="hotfixes", fillcolor="#FD5965"];
h1;
node [group="release", fillcolor="#52C322"];
r1;
r2;
r3;
r4;
r5;
r1 -> r2 -> r3 -> r4;
node [group="develop", fillcolor="#FFE333"];
d1;
d2;
d3;
d4;
d5;
d6;
d7;
d8;
d9;
d10;
d1 -> d2 -> d3 -> d4 -> d5 -> d6 -> d7 -> d8 -> d9 -> d10;
d10 -> de [color="#b0b0b0", style=dashed, arrowhead=none ];
node [group="feature 1", fillcolor="#FB3DB5"];
fa1;
fa2;
fa3;
fa4;
fa5;
fa6;
subgraph fas1 {
fa1 -> fa2 -> fa3;
}
subgraph fas2 {
fa4 -> fa5 -> fa6;
}
node [group="feature 2", fillcolor="#FB3DB5"];
fb1;
fb2;
fb3;
fb4;
subgraph{ rank=same; fa6; fb4; } // hack
subgraph{ rank=same; fa1; fb1; } // hack
fb1 -> fb2 -> fb3 -> fb4;
// nodes
m1 -> d1;
m1 -> h1;
h1 -> m2;
h1 -> d5;
d3 -> fa1;
fa3 -> d6;
d6 -> r1;
r2 -> d7;
r4 -> d8;
r4 -> m3;
d9 -> r5;
r5 -> m4;
r5 -> d10;
d7 -> fa4;
fa6 -> d9;
d3 -> fb1;
fb4 -> d9;
// tags connections
edge [color="#b0b0b0", style=dotted, len=0.3, arrowhead=none, penwidth=1];
subgraph {
rank="same";
m1 -> t1;
}
subgraph {
rank="same";
m2 -> t2 ;
}
subgraph {
rank="same";
m3 -> t3;
}
}
Hope this helps someone.
This particular diagram was made with inkscape, therefore it will be difficult to match it with graphviz's output.
Here's how you may match some of it with graphviz:
Use a different group attribute for each branch in order to get straight lines for each branch (here's another example of using group, and one using weight)
Define the branches in the right order to have them appear from top to bottom
Use shape, style, width and height have some nodes stand out, and hide others
Use some \n newline cheating to have labels on top of the nodes (you may also try labelloc="t", or using xlabel instead of label)
digraph g{
rankdir="LR";
pad=0.5;
nodesep=0.6;
ranksep=0.5;
forcelabels=true;
node [width=0.12, height=0.12, fixedsize=true,
shape=circle, style=filled, color="#909090",
fontcolor="deepskyblue", font="Arial bold", fontsize="14pt" ];
edge [arrowhead=none, color="#909090", penwidth=3];
node [group="release3"];
s3 [label="release 3\n\n", width=0.03, height=0.03, shape=box];
r30 [label=" R3.0\n\n\n"];
e3 [label="", width=0.03, height=0.03, shape=box];
e3f [label="", width=0.03, height=0.03, shape=circle, color="#b0b0b0"];
s3 -> r30 -> e3;
e3 -> e3f [color="#b0b0b0", style=dashed];
node [group="release2"];
s2 [label="release 2\n\n", width=0.03, height=0.03, shape=box];
b2 [label="", width=0.03, height=0.03, shape=box];
r20 [label=" R2.0\n\n\n"];
e2 [label="", width=0.03, height=0.03, shape=box];
e2f [label="", width=0.03, height=0.03, shape=circle, color="#b0b0b0"];
s2 -> b2 -> r20 -> e2;
e2 -> e2f [color="#b0b0b0", style=dashed];
node [group="release1"];
s1 [label="release 1\n\n", width=0.03, height=0.03, shape=box];
ttest [label=" test\n\n\n"];
b1 [label="", width=0.03, height=0.03, shape=box];
r10 [label=" R1.0\n\n\n"];
r11 [label=" R1.1\n\n\n"];
e1 [label="", width=0.03, height=0.03, shape=box];
e1f [label="", width=0.03, height=0.03, shape=circle, color="#b0b0b0"];
s1 -> ttest -> b1 -> r10 -> r11 -> e1;
e1 -> e1f [color="#b0b0b0", style=dashed];
b1 -> s2;
b2 -> s3;
}
Related
I am trying to learn MATLAB.
How can I convert this cell arraay:
1×4 cell array
{'A'} {'B4'} {'G6'} {'D5'}
to this string:
A -> B4 -> G6 -> D5
You can use strjoin to merge them into one string, with a delimeter ->
c = {'A', 'B4', 'G6', 'D5'};
str = strjoin( c, ' -> ' );
disp( str );
% 'A -> B4 -> G6 -> D5'
I am trying to to formalize Skew Heaps in Lean. I have defined the straightforward tree type:
inductive tree : Type
| leaf : tree
| node : tree -> nat -> tree -> tree
Next, I want to define the fusion operation the following way:
def fusion : arbre × arbre -> arbre
| (t1, leaf) := t1
| (leaf, t2) := t2
| (node g1 x1 d1, node g2 x2 d2) :=
if x1 <= x2
then (node (fusion (d1, node g2 x2 d2)) x1 g1)
else (node (fusion (d2, node g1 x1 d1)) x2 g2)
But, of course, Lean doesn't not accept this function, as it "failed to prove recursive application is decreasing, well founded relation". Apparently, it uses the lexicographical product of the sizes of the trees… and fails, obviously.
How can I tell it to use the sum of the sizes?
The following code works for me. There are docs on how well founded recursion works in lean at
https://github.com/leanprover-community/mathlib/blob/master/docs/extras/well_founded_recursion.md
def fusion : tree × tree -> tree
| (t1, leaf) := t1
| (leaf, t2) := t2
| (node g1 x1 d1, node g2 x2 d2) :=
if x1 <= x2
then (node (fusion (d1, node g2 x2 d2)) x1 g1)
else (node (fusion (d2, node g1 x1 d1)) x2 g2)
using_well_founded
{ rel_tac := λ _ _,
`[exact ⟨_, measure_wf (λ t, tree.sizeof t.1 + tree.sizeof t.2)⟩] }
The idea is that you have to give it a new relation, and a proof that the relation is well founded. This is the tuple ⟨_, measure_wf (λ t, tree.sizeof t.1 + tree.sizeof t.2)⟩ Any function to the natural numbers gives a well founded relation, the proof of this is measure_wf, and the _ is just a placeholder for the relation, since it can be inferred from the type of measure_wf (λ t, tree.sizeof t.1 + tree.sizeof t.2).
Suppose I have two streams of A's and B's.
Stream 1: A1, A2, A3, A4, A5, A6
Stream B: B1, B2, B3, B4
Timeline: B1 > A1 > A2 > B2 > A3 > A4 > B3 > A5
Desired output: [B1 & A1], [A2 & B2], [B2 & A3], [A4 & B3], [B3 & A5], [A6 & B4]
This mirrors a real life process where B's are double sided and stacked together. For example,
---- B1 ----]
|-1
---- A1 ----]
---- A2 ----]
]-2
---- B2 ----|]
]|-3
---- A3 ---- ]
---- A4 ----]
|-4
---- B3 ----]]
|-5
---- A5 ---- ]
---- A6 ----]
|-6
---- B4 ----]
Grouping 1 is characteristic of the initial pair. Grouping 6 is characteristic of the terminal pairing. Groups 2/3 and 4/5 can be repeated.
I'm looking for ideas on how to achieve this with RxJava2.
Thanks, Dan.
EDIT
I made a test case:
import java.util.Objects;
import org.junit.Test;
import io.reactivex.Flowable;
import io.reactivex.functions.BiFunction;
import io.reactivex.processors.FlowableProcessor;
import io.reactivex.processors.ReplayProcessor;
public class BuildControllerTest {
#Test
public void testProductBlanketSequencing() throws Exception {
final String a1="A1", a2="A2", a3="A3", a4="A4", a5="A5", a6="A6";
final String b1="B1", b2="B2", b3="B3", b4="B4";
class AB {
String a;
String b;
public AB(String a, String b) {
this.a = a;
this.b = b;
}
#Override public boolean equals(Object obj) {
if(getClass() != obj.getClass()) return false;
if( ! Objects.equals(a, ((AB)obj).a)) return false;
if( ! Objects.equals(b, ((AB)obj).b)) return false;
return true;
}
}
final FlowableProcessor<String> a = ReplayProcessor.create();
final FlowableProcessor<String> b = ReplayProcessor.create();
b.onNext(b1);
a.onNext(a1);
a.onNext(a2);
b.onNext(b2);
a.onNext(a3);
a.onNext(a4);
b.onNext(b3);
a.onNext(a5);
a.onNext(a6);
b.onNext(b4);
a.onComplete(); b.onComplete();
Flowable.zip(a, b, new BiFunction<String, String, AB>() {
#Override public AB apply(String t1, String t2) throws Exception {
return new AB(t1, t2);
}
})
.test()
.assertResult(
new AB(a1, b1),
new AB(a2, b2),
new AB(a3, b2),
new AB(a4, b3),
new AB(a5, b3),
new AB(a6, b4));
}
}
From your example it is not clear what condition drives pairing.
When we use zip the pair is formed as soon as both sources has next item:
(A1, B1), (A2, B2), (A3, B3), (A4, B4)
If we use combineLatest the pair is formed when there is next item in any source:
(A1, B1), (A2, B1), (A2, B2), (A3, B2), (A4, B2), (A4, B3), (A5, B3), (A6, B3), (A6, B4)
For me it looks like you want to combine sources but take not every pair. You can remove extra pairs depending on business rules.
The extra rule can be time, then take look at sampling.
Flowable.combineLatest(a, b, (t1, t2) -> new AB(t1, t2))
.throttleLast(1, TimeUnit.MICROSECONDS)
it will take latest result from combined pairs every time interval
(A1, B1), (A4, B3), (A5, B3), (A6, B3), (A6, B4)
If extra rules is to have unique values from source A and posible repeats from B then you can use distinct
Flowable.combineLatest(a, b, (t1, t2) -> new AB(t1, t2))
.distinct(ab -> ab.a)
(A1, B1), (A2, B1), (A3, B2), (A4, B2), (A5, B3), (A6, B3)
I have the following problem: R(ABCDEFG) and F ={ AB->CD, C->EF, G->A, G->F, CE ->F}. Clearly, B & G should be part of the key as they are not part of the dependent set. Further, BG+ = ABCDEFG, hence candidate key. Clearly, AB->CD violates BCNF. But when I follow the algorithm, I do not end up in any answer. Probably doing something wrong. Can anyone show me how to apply the algorithm correctly to reach the decomposition?
Thanks in advance.
First, you should calculate a canonical cover of the dependencies. In this case it is:
{ A B → C
A B → D
C → E
C → F
G → A
G → F } >
Since the (unique) candidate key is B G, no functional dependency satisfies the BNCF. Then, starting from any functional dependency X → Y that violates the BCNF, we calculate the closure of X, X+, and replace the original relation R<T,F> with two relations, R1<X+> and R2<T - X+ + X>. So, chosing in this case the dependency A B → C, we replace the original relation with:
R1 < (A B C D E F) ,
{ A B → C
A B → D
C → E
C → F} >
and:
R2 < (A B G) ,
{ G → A } >
Then we check each decomposed relation to see if it satisfies the BCNF, otherwise we apply recursively the algorithm.
In this case, for instance, in R1 the key is A B, so C -> E violates the BCNF, and we replace R1 with:
R3 < (C E F) ,
{ C → E
C → F } >
and:
R4 < (A B C D) ,
{ A B → C
A B → D } >
two relations that satisfy the BCNF.
Finally, since R2 too does not satisfy the BCNF (beacuse the key is B G), we decompose R2 in:
R5 < (A G) ,
{ G → A } >
and:
R6 < (B G) ,
{ } >
that are in BCNF.
So the final decomposition is constituted by the relations: R3, R4, R5, and R6. We can also note that the dependency G → F on the original relation is lost in the decomposition.
I have some data that looks like this:
G1 G2 G3 G4
Pf1 NO B1 NO D1
Pf2 NO NO C1 D1
Pf3 A1 B1 NO D1
Pf4 A1 NO C1 D2
Pf5 A3 B2 C2 D3
Pf6 NO B3 NO D3
My purpose is to check in each column if an element (different from the "NO" cases) is showed twice (like A1 in column 2, for example) and only twice (if it is showed three times or more I don't want it in the output) and, if so, write it as correspondenting to the element of the first column. Of course, I will have more elements of the columns corresponding to an element of the first column. So, the desired output looks like this:
Pf1 B1
Pf2 C1
Pf3 A1 B1
Pf4 A1 C1
Pf5 D3
Pf6 D3
I have a code, that work in the opposite direction. It lists the elements of the first column that correspond to the elements that are showed twice and only twice in the other columns. This code looks like this:
use Data::Dumper;
my %hash;
while (<DATA>) {
next if $.==1;
chomp;
my ($first,#others) = (split /\s+/);
for (#others){
$hash{$_}.=' '.$first;
}
}
print Dumper \%hash;
I need to be pushed in order to adapt it to my new purpose. Any help or suggestion is totally welcome!
my %hash;
my #r;
while (<DATA>) {
next if $.==1;
chomp;
my #t = grep $_ ne "NO", split;
push #r, \#t;
$hash{$_}++ for #t[1 .. $#t];
}
for my $l (#r) {
my $k = shift #$l;
my #t = grep { $hash{$_} ==2 } #$l;
print "$k #t\n";
}
__DATA__
G1 G2 G3 G4
Pf1 NO B1 NO D1
Pf2 NO NO C1 D1
Pf3 A1 B1 NO D1
Pf4 A1 NO C1 D2
Pf5 A3 B2 C2 D3
Pf6 NO B3 NO D3
output
Pf1 B1
Pf2 C1
Pf3 A1 B1
Pf4 A1 C1
Pf5 D3
Pf6 D3