repetition relabeling

37 views
Skip to first unread message

Christian Helbling

unread,
Feb 9, 2021, 5:06:25 PM2/9/21
to juggling-interchange-format
Hi

As promised my thoughts about repetition and symmetries.
Be prepared, its gonna be long :)

And thanks a lot for your code, Lukas!
Looking forward to look into it.


First of all, I think repetition should be a feature rather than the default.
The reason for that is, that a complete show routine (or a part of it) could
already be written in jif using only jugglers, limbs and throws as properties.
A default repetition of that - i.e. jumping from the last catch time to time 0 -
seems unnatural to me as all the props from the end time would need to teleport
back instantly to where they started.

To enable repetition, we have to provide at least the period as a parameter.
Without any relabeling mechanism, this period can get really big and a lot of
throws need to be provided until all the limbs, props and jugglers are in their
starting configuration again. This can be seen by the current passist code
generating 36 throws from the 4-handed 975.
This is not handy for a lot of applications.
We want to have the natural period which is the siteswap/prechac length, the length
of a manipulation sequence until juggler relabeling, etc.

I suggest the following format for specifying repetition:
"repetition": {
"period": .. ,
"limbPermutation": [..],
"propPermutation": [..],

"jugglerPermutation": [..], # disputed :)

# .. more repetition features like rotation and translation of juggler positions
}
If a repetition is specified, only the period is mandatory (I think it cannot be guessed).
The rest should have sensible defaults (to be discussed).
Permutations are given as an array.
for example, [2, 0, 1] is short for
0 becomes 2
1 becomes 0
2 becomes 1


Let's look at a simple example: (6x,4)*

Without props the verbose version is this:
"period": 4,
"throws": [
{ "time": 0, "duration": 6, "from": 0, "to": 1, "label": "6x" },
{ "time": 0, "duration": 4, "from": 1, "to": 1, "label": "4" },
{ "time": 2, "duration": 6, "from": 1, "to": 0, "label": "6x" },
{ "time": 2, "duration": 4, "from": 0, "to": 0, "label": "4" }
]

Specifying that left and right should be swapped at every repetition we arrive at:
"throws": [
{ "time": 0, "duration": 6, "from": 0, "to": 1, "label": "6x" },
{ "time": 0, "duration": 4, "from": 1, "to": 1, "label": "4" },
],
"repetition": {
"period": 2,
"limbPermutation": [ 1, 0], # swapping left/right
}


If we take props into account, the verbose version is even longer:
"period": 12,
"throws": [
{ "time": 0, "duration": 6, "from": 0, "to": 1, "label": "6x", "prop": 0 },
{ "time": 0, "duration": 4, "from": 1, "to": 1, "label": "4", "prop": 1 },
{ "time": 2, "duration": 6, "from": 1, "to": 0, "label": "6x", "prop": 2 },
{ "time": 2, "duration": 4, "from": 0, "to": 0, "label": "4", "prop": 3 },

{ "time": 4, "duration": 6, "from": 0, "to": 1, "label": "6x", "prop": 4 },
{ "time": 4, "duration": 4, "from": 1, "to": 1, "label": "4", "prop": 1 },
{ "time": 6, "duration": 6, "from": 1, "to": 0, "label": "6x", "prop": 0 },
{ "time": 6, "duration": 4, "from": 0, "to": 0, "label": "4", "prop": 3 },

{ "time": 8, "duration": 6, "from": 0, "to": 1, "label": "6x", "prop": 2 },
{ "time": 8, "duration": 4, "from": 1, "to": 1, "label": "4", "prop": 1 },
{ "time": 10, "duration": 6, "from": 1, "to": 0, "label": "6x", "prop": 4 },
{ "time": 10, "duration": 4, "from": 0, "to": 0, "label": "4", "prop": 3 },
],

For a period of 2 we get the following prop transitions:
0 => 2
1 => 3
2 => 4
3 => 1
4 => 0
which can be compactly stored as the permutation [ 2, 3, 4, 1, 0 ], giving us:

"throws": [
{ "time": 0, "duration": 6, "from": 0, "to": 1, "label": "6x", "prop": 0 },
{ "time": 0, "duration": 4, "from": 1, "to": 1, "label": "4", "prop": 1 },
],
"repetition": {
"period": 2,
"limbPermutation": [ 1, 0], # exchanging left/right
"propPermutation": [ 2, 3, 4, 1, 0 ]
}



A quick note on props:

Many applications like causal diagram editors or jif generators won't care about
props and prop permutations at all. They should not need to specify them.
Luckily, they can be filled in by code.
If we include a few rules how this prop-filling code should behave, we can
probably arrive at deterministic prop ids.
"What reasons do we have to specifiy props in jif at all then?", you ask.
Well, if we have a lot of multiplexes, the prop-filling code might not
do what we want to express.


Another example, 4-handed 975 aka holy grail:

verbose version:
"period": 36,
"throws": [
{ "time": 0, "duration": 9, "from": 0, "to": 1, "label": "9", "prop": 0 },
{ "time": 1, "duration": 7, "from": 1, "to": 0, "label": "7", "prop": 1 },
{ "time": 2, "duration": 5, "from": 2, "to": 3, "label": "5", "prop": 2 },
{ "time": 3, "duration": 9, "from": 3, "to": 0, "label": "9", "prop": 3 },
{ "time": 4, "duration": 7, "from": 0, "to": 3, "label": "7", "prop": 4 },
{ "time": 5, "duration": 5, "from": 1, "to": 2, "label": "5", "prop": 5 },
{ "time": 6, "duration": 9, "from": 2, "to": 3, "label": "9", "prop": 6 },
{ "time": 7, "duration": 7, "from": 3, "to": 2, "label": "7", "prop": 2 },
{ "time": 8, "duration": 5, "from": 0, "to": 1, "label": "5", "prop": 1 },
{ "time": 9, "duration": 9, "from": 1, "to": 2, "label": "9", "prop": 0 },
{ "time": 10, "duration": 7, "from": 2, "to": 1, "label": "7", "prop": 5 },
{ "time": 11, "duration": 5, "from": 3, "to": 0, "label": "5", "prop": 4 },
{ "time": 12, "duration": 9, "from": 0, "to": 1, "label": "9", "prop": 3 },
{ "time": 13, "duration": 7, "from": 1, "to": 0, "label": "7", "prop": 1 },
{ "time": 14, "duration": 5, "from": 2, "to": 3, "label": "5", "prop": 2 },
{ "time": 15, "duration": 9, "from": 3, "to": 0, "label": "9", "prop": 6 },
{ "time": 16, "duration": 7, "from": 0, "to": 3, "label": "7", "prop": 4 },
{ "time": 17, "duration": 5, "from": 1, "to": 2, "label": "5", "prop": 5 },
{ "time": 18, "duration": 9, "from": 2, "to": 3, "label": "9", "prop": 0 },
{ "time": 19, "duration": 7, "from": 3, "to": 2, "label": "7", "prop": 2 },
{ "time": 20, "duration": 5, "from": 0, "to": 1, "label": "5", "prop": 1 },
{ "time": 21, "duration": 9, "from": 1, "to": 2, "label": "9", "prop": 3 },
{ "time": 22, "duration": 7, "from": 2, "to": 1, "label": "7", "prop": 5 },
{ "time": 23, "duration": 5, "from": 3, "to": 0, "label": "5", "prop": 4 },
{ "time": 24, "duration": 9, "from": 0, "to": 1, "label": "9", "prop": 6 },
{ "time": 25, "duration": 7, "from": 1, "to": 0, "label": "7", "prop": 1 },
{ "time": 26, "duration": 5, "from": 2, "to": 3, "label": "5", "prop": 2 },
{ "time": 27, "duration": 9, "from": 3, "to": 0, "label": "9", "prop": 0 },
{ "time": 28, "duration": 7, "from": 0, "to": 3, "label": "7", "prop": 4 },
{ "time": 29, "duration": 5, "from": 1, "to": 2, "label": "5", "prop": 5 },
{ "time": 30, "duration": 9, "from": 2, "to": 3, "label": "9", "prop": 3 },
{ "time": 31, "duration": 7, "from": 3, "to": 2, "label": "7", "prop": 2 },
{ "time": 32, "duration": 5, "from": 0, "to": 1, "label": "5", "prop": 1 },
{ "time": 33, "duration": 9, "from": 1, "to": 2, "label": "9", "prop": 6 },
{ "time": 34, "duration": 7, "from": 2, "to": 1, "label": "7", "prop": 5 },
{ "time": 35, "duration": 5, "from": 3, "to": 0, "label": "5", "prop": 4 }
]

the limbs shift through by one: 0 => 3 => 2 => 1 => 0

for the props, it helps to look at the orbits:
900 (3 props) (0->3->6->0)
075 (4 props) (1->4->2->5->1)

thus we arrive at the following compact jif:

"throws": [
{ "time": 0, "duration": 9, "from": 0, "to": 1, "label": "9", "prop": 0 },
{ "time": 1, "duration": 7, "from": 1, "to": 0, "label": "7", "prop": 1 },
{ "time": 2, "duration": 5, "from": 2, "to": 3, "label": "5", "prop": 2 }
],
"repetition": {
"period": 3,
"limbPermutation": [ 3, 0, 1, 2 ],
"propPermutation": [ 3, 4, 5, 6, 2, 1, 0 ]
}


Last one - swinging door:
"jugglers": [
{ "name": "A" },
{ "name": "B" }
],
"limbs": [
{ "juggler": 0, "type": "right hand" },
{ "juggler": 0, "type": "left hand" },
{ "juggler": 1, "type": "right hand" },
{ "juggler": 1, "type": "left hand" }
],
"throws": [
{ "time": 0, "duration": 4, "from": 0, "to": 3, "label": "4p straigt A->B", "prop": 0 },
{ "time": 0, "duration": 4, "from": 2, "to": 1, "label": "4p straigt B->A", "prop": 1 },
{ "time": 0, "duration": 4, "from": 1, "to": 0, "label": "4x A", "prop": 2 },
{ "time": 0, "duration": 4, "from": 3, "to": 2, "label": "4x B", "prop": 3 }
],
"repetition": {
"period": 2,
"limbPermutation": [ 1, 0, 3, 2 ], # exchanging left/right
"propPermutation": [ 4, 5, 6, 7, 3, 2, 0, 1 ]
}


We still need to check, if this approach works for the rest of our use-cases.


Manipulation patterns are quite interesting here.

jugglerPermutation seem quite natural for that.
This is the "becomes" property in lukas's examples, and also the lines like
A => B => C => M on manipulation workshop sheets.

As already stated on this list, limbPermutation is powerful enough
to fix the from/to of the throws.
Having both at the same time sure looks messy somehow.
In what order are they applied?
Why whould we need them both?
A simple reason to have an additional limbPermutation
in a manipulation pattern cold be an additional right/left swap,
in which case the order of applying the permutations wouldnt' matter.
But there could be valid reasons for more complicated limbPermutations.


Lets see what else an explicit or implicit jugglerPermutation would do exactly.
If we have:
"jugglers": [
{ "name": "Alice", "label": "A" },
{ "name": "Bob", "label": "B" }
{ "name": "Charlie", "label": "C" }
{ "name": "Mallory", "label": "M" }
],
"limbs": [
{ "juggler": 0, "type": "right hand" },
{ "juggler": 0, "type": "left hand" },
{ "juggler": 1, "type": "right hand" },
{ "juggler": 1, "type": "left hand" }
{ "juggler": 2, "type": "right hand" },
{ "juggler": 2, "type": "left hand" },
{ "juggler": 3, "type": "right hand" },
{ "juggler": 3, "type": "left hand" }
],
"repetition": {
"period": 6,
"jugglerPermutation": [ 1, 2, 3, 0 ], # A => B => C => M, explicity specified or implicit through limbPermutation
}

At time 6 Alice will stay Alice but gets the label B.

Her position will not jump somewhere else, but her movement
instructions for the second round change to B's instructions.
( it is not yet discussed how to represent movement instructions yet,
I can imagine something like
"movements": [
{"time": .., "duration": .., "juggler": .., ..movement instructions},
..
]
but I have not given much thought about that yet,
please discuss this in another thread :)
)

Alice inherits Bobs throws and catches, which can technicaly be done
by either permuting limbs (from/to of any throw point to a different limb)
or by permuting the jugglers (juggler of any limb points to a different juggler).

If we would go by the second option, right after time 6 we would get this:
"jugglers": [
{ "name": "Mallory", "label": "A" }
{ "name": "Alice", "label": "B" },
{ "name": "Bob", "label": "C" }
{ "name": "Charlie", "label": "M" }
],
with limbs staying the same.
So the jugglers array is permuted, except for the labels that stay at the same place.
This is a bit weird (but neccessary) and not covered directly if we would only have limbPermutation.

If there is an additional limbPermutation,
the limbs array is permuted as well.

for example,
"limbPermutation": [ 1, 0, 3, 2, 5, 4 ],
would yield:

"limbs": [
{ "juggler": 0, "type": "left hand" },
{ "juggler": 0, "type": "right hand" },
{ "juggler": 1, "type": "left hand" }
{ "juggler": 1, "type": "right hand" },
{ "juggler": 2, "type": "left hand" },
{ "juggler": 2, "type": "right hand" },
{ "juggler": 3, "type": "left hand" }
{ "juggler": 3, "type": "right hand" },
],

This way limbPermutation could live alongside jugglerPermutation, with a clearly defined
behavior but we would usually only need one of them.


But what about throws across repetition bounaries?
If we look at the first throw of the holy grail example,
{ "time": 0, "duration": 9, "from": 0, "to": 1, "label": "9", "prop": 0 },
we see that we evaluated the to-limb at time 0, that is at the throw time.

Let's say we use the same rule (evaulating at throw time) for going from limb to juggler.
Depending if by juggler we mean the juggler by name or the juggler by label,
we have Aiden's or Ed's notation.
I forgot which one is which, and I'm not sure which one we should prefer. Lukas?

In either case, an animator would have to schedule a throw of the involved prop
and be able to calculate the landing destination in advance.


@Co:
Thanks for the idea of different periods. I'll have to think about that.

Cheers
Christian

JaCo Stuifbergen

unread,
Feb 10, 2021, 5:02:47 PM2/10/21
to juggling-interchange-format
Christian,

I enjoyed your text.
One long text is often better than several short messages.

On Tue, 9 Feb 2021 at 23:06, Christian Helbling <he...@helch.ch> wrote:
First of all, I think repetition should be a feature rather than the default.
 I agree. Check!

To enable repetition, we have to provide at least the period as a parameter.
I suggest the following format for specifying repetition:
 "repetition": {
     "period":              .. ,
     "limbPermutation":    [..],
     "propPermutation":    [..],

         "jugglerPermutation": [..], # disputed :)

     # .. more repetition features like rotation and translation of juggler positions
 }
Repetition like rotation and translation? certainly!
For example, a scrambled V is rotated by almost 180 degrees after 3 passes.

I think that propPermutation can be derived from the pattern, even for multiplexes. I will return to this subject later in this message.

If a repetition is specified, only the period is mandatory (I think it cannot be guessed).
The default value for a period could be the number of throws.
For a solo siteswap, this would work.
It would also work for the social site-swaps in Passist.org
Permutations are given as an array. 
For a period of 2 we get the following prop transitions:
 0 => 2
 1 => 3
 2 => 4
 3 => 1
 4 => 0
which can be compactly stored as the permutation [ 2, 3, 4, 1, 0 ], giving us:

 "throws": [
     { "time": 0,  "duration": 6, "from": 0, "to": 1, "label": "6x", "prop": 0 },
     { "time": 0,  "duration": 4, "from": 1, "to": 1, "label": "4",  "prop": 1 },
 ],
 "repetition": {
     "period": 2,
     "limbPermutation": [ 1, 0],               # exchanging left/right
     "propPermutation": [ 2, 3, 4, 1, 0 ]
 }
This notation is beautiful.
A quick note on props:

Many applications like causal diagram editors or jif generators won't care about
props and prop permutations at all. They should not need to specify them.
Luckily, they can be filled in by code.
If we include a few rules how this prop-filling code should behave, we can
probably arrive at deterministic prop ids.
"What reasons do we have to specifiy props in jif at all then?", you ask.
Well, if we have a lot of multiplexes, the prop-filling code might not
do what we want to express.
I think that, in multiplexes, we should make a distinction between [45] and [54].
The definition might be that in [45], the ball that was first caught, will be thrown as 4, and a ball that was later caught, will be thrown as 5.
Prop-filling will then be unambigous, except in the case of a multiplex catche! (2 or more catches at the same count)
To treat multiplex catches, a solution could be:
- to add a parameter to a limb, to specify the multiplex position
or
- treat multiplexes as catches/throws to additional limbs, that happen to be at the same place as another limb.

My intuition is that if we can describe multiplexes, prop-filling can be done automatically.
And we should design a way to describe multiplexes anyway... :-)

On the other hand, for animators, it is probably convenient if the propPermutation doesn't have to be calculated.

Another example, 4-handed 975 aka holy grail:
 the limbs shift through by one: 0 => 3 => 2 => 1 => 0


 for the props, it helps to look at the orbits:
        900 (3 props) (0->3->6->0)
        075 (4 props) (1->4->2->5->1)

 thus we arrive at the following compact jif:

  "throws": [
    { "time": 0, "duration": 9, "from": 0, "to": 1, "label": "9", "prop": 0 },
    { "time": 1, "duration": 7, "from": 1, "to": 0, "label": "7", "prop": 1 },
    { "time": 2, "duration": 5, "from": 2, "to": 3, "label": "5", "prop": 2 }
  ],
  "repetition": {
    "period": 3,
    "limbPermutation": [ 3, 0, 1, 2 ],
    "propPermutation": [ 3, 4, 5, 6, 2, 1, 0 ]
  }
I suppose that you use the definition of the limbs in passist.org:
 "limbs": [
     {      "juggler": 0,       "type": "right hand"     },
    {       "juggler": 1,       "type": "right hand"     },
    {       "juggler": 0,       "type": "left hand"     },
    {       "juggler": 1,       "type": "left hand"     }
]
For swinging door, you use a different definition.
When we add jugglerPermutations, we should adopt a consistent order.
Last one - swinging door:
 "jugglers": [
     { "name": "A" },
     { "name": "B" }
 ],
 "limbs": [
     { "juggler": 0, "type": "right hand" },
     { "juggler": 0, "type": "left hand" },
     { "juggler": 1, "type": "right hand" },
     { "juggler": 1, "type": "left hand" }
   ],
 "throws": [
     { "time": 0,  "duration": 4, "from": 0, "to": 3, "label": "4p straigt A->B", "prop": 0 },
     { "time": 0,  "duration": 4, "from": 2, "to": 1, "label": "4p straigt B->A", "prop": 1 },
     { "time": 0,  "duration": 4, "from": 1, "to": 0, "label": "4x A",            "prop": 2 },
     { "time": 0,  "duration": 4, "from": 3, "to": 2, "label": "4x B",            "prop": 3 }
 ],
 "repetition": {
     "period": 2,
     "limbPermutation": [ 1, 0, 3, 2 ],               # exchanging left/right
     "propPermutation": [ 4, 5, 6, 7, 3, 2, 0, 1 ]
 }
 
Manipulation patterns are quite interesting here.


jugglerPermutation seem quite natural for that.
This is the "becomes" property in lukas's examples, and also the lines like
A => B => C => M on manipulation workshop sheets.

  "repetition": {
     "period": 6,
     "jugglerPermutation": [ 1, 2, 3, 0 ],   # A => B => C => M, explicity specified or implicit through limbPermutation
 }

At time 6 Alice will stay Alice but gets the label B.

Her position will not jump somewhere else, but her movement
instructions for the second round change to B's instructions.
Alice inherits Bobs throws and catches, which can technicaly be done

by either permuting limbs (from/to of any throw point to a different limb)
or by permuting the jugglers (juggler of any limb points to a different juggler).
Physically, her position will not jump.
But I think that for animations, it will be better to prescribe that she does also inherit the positions of Bob.
If we prescribe the rotation/translation of positions after each cycle, the animator will not make her jump.
If we would go by the second option, right after time 6 we would get this:
 "jugglers": [
     { "name": "Mallory", "label": "A" }
     { "name": "Alice",   "label": "B" },
     { "name": "Bob",     "label": "C" }
     { "name": "Charlie", "label": "M" }
 ],
  So the jugglers array is permuted, except for the labels that stay at the same place.
I prefer to connect labels to the names, but I could imagine an attribute "function".
After permutation, this becomes:
"jugglers": [
     { "name": "Mallory", "label": "M" , "function":"feeder", "functionLabel":"M"},
    { "name": "Alice",   "label": "A"  , "function":"left feedee", "functionLabel":"M"},
     { "name": "Bob",     "label": "B" , "function":"right feedee", "functionLabel":"M"},
     { "name": "Charlie", "label": "C" , "function":"Manipulator", "functionLabel":"M"}
 ],
 This is a bit weird (but neccessary) and not covered directly if we would only have limbPermutation.
You are right.
This way limbPermutation could live alongside jugglerPermutation, with a clearly defined
behavior but we would usually only need one of them.
I agree. I think that is sufficient to specify that we apply jugglerPermutation first, limbPermutation second.
Just a standard to cover weird situations.


But what about throws across repetition bounaries?
If we look at the first throw of the holy grail example,
 { "time": 0, "duration": 9, "from": 0, "to": 1, "label": "9", "prop": 0 },
we see that we evaluated the to-limb at time 0, that is at the throw time.

Let's say we use the same rule (evaulating at throw time) for going from limb to juggler.
Depending if by juggler we mean the juggler by name or the juggler by label,
Does "by label" mean "by function" ?  (just asking to be sure)
we have Aiden's or Ed's notation.
I forgot which one is which, and I'm not sure which one we should prefer. Lukas?
I am glad we have Lukas!

Good night!
Cheers
Christian

--
You received this message because you are subscribed to the Google Groups "juggling-interchange-format" group.
To unsubscribe from this group and stop receiving emails from it, send an email to juggling-interchang...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/juggling-interchange-format/e26d2e3a-1628-5704-934c-6a81371549a1%40helch.ch.

Graham Haslehurst

unread,
Feb 10, 2021, 10:17:15 PM2/10/21
to juggling-interchange-format
All

I think I might have missed something. What happens with prop inheritance with regards to position inheritance? Do you rename the props at position handover or do they remain with the juggler and deal with them as if they have instantly moved? 

Thanks

Graham

JaCo Stuifbergen

unread,
Feb 11, 2021, 3:24:10 AM2/11/21
to juggling-interchange-format
I must correct myself:
I suppose that you use the definition of the limbs in passist.org:
 "limbs": [
     {      "juggler": 0,       "type": "right hand"     },
    {       "juggler": 1,       "type": "right hand"     },
    {       "juggler": 0,       "type": "left hand"     },
    {       "juggler": 1,       "type": "left hand"     }
]
For swinging door, you use a different definition.
When we add jugglerPermutations, we should adopt a consistent order.
Last one - swinging door:
 "jugglers": [
     { "name": "A" },
     { "name": "B" }
 ],
 "limbs": [
     { "juggler": 0, "type": "right hand" },
     { "juggler": 0, "type": "left hand" },
     { "juggler": 1, "type": "right hand" },
     { "juggler": 1, "type": "left hand" }
It is not necessary to define a standard for the order of the limbs.
Each limb contains a reference to its juggler, so if  jugglerPermutations is known, limbPermutations can be derived from it.

Co Stuifbergen
=========================
in...@jacos.nl
www.jacos.nl
+31 6 13 02 44 69 (mobile)

Kloosterwei 102
2361 XN  Warmond
the Netherlands
=========================


JaCo Stuifbergen

unread,
Feb 11, 2021, 3:45:52 AM2/11/21
to juggling-interchange-format
Graham, that is a good question!

I think that the answer is related to how we define "to" in a throw:
does it refer to the actual limb (Lukas's preference) or is a label that can be permuted?

I need to think more.

Co Stuifbergen
=========================
in...@jacos.nl
www.jacos.nl
+31 6 13 02 44 69 (mobile)

Kloosterwei 102
2361 XN  Warmond
the Netherlands
=========================


JaCo Stuifbergen

unread,
Feb 11, 2021, 4:30:10 PM2/11/21
to juggling-interchange-format
I just noticed that, essentially, passist.org already answers Grahams question (and my anxiety).
I will take 5344 for 3 persons as an example. (I chose this pattern because all the catches are in the next cycle)
"limbs": [
    { "juggler": 0, "type": "right hand" },
    { "juggler": 1, "type": "right hand" },
    { "juggler": 2, "type": "right hand" },

    { "juggler": 0, "type": "left hand" },
    { "juggler": 1, "type": "left hand" },
    { "juggler": 2, "type": "left hand" }
  ],
"throws": [
    { "time": 0, "duration": 5, "from": 0, "to": 5, "label": "5", "prop": 0 },
    { "time": 1, "duration": 3, "from": 1, "to": 4, "label": "3", "prop": 1 },
    { "time": 2, "duration": 4, "from": 2, "to": 0, "label": "4", "prop": 2 },
    { "time": 3, "duration": 4, "from": 3, "to": 1, "label": "4", "prop": 3 },

Like passist, I will use the convention that, in the first cycle, "from" and "to" refer directly to the limbs.
so:
  { "time": 1, "duration": 3, "from": 1, "to": 4, "label": "3", "prop": 1 } means:
# from    Bob's right hand  to Bob's left hand

For every hand that hasn't caught anything yet, we must add a prop number. So the prop numbering is simply 0-1-2-3
We also know that 53 is a site-swap, so we must exchange 2 objects.
Passist doesn't yet describe the permutations, but it would look something like:
"repetition": {
     "period": 4,
     "limbPermutation": [4,5,0,1,2,3]              # shift by the period
     "propPermutation": [1,0,2,3]                   # exchange the first 2 props
 }

When we apply these permutations directly on the pattern, we obtain:
"throws": [
    { "time": 4, "duration": 5, "from": 4, "to": 3, "label": "5", "prop": 1 },
    { "time": 5, "duration": 3, "from": 5, "to": 2, "label": "3", "prop": 0 },
    { "time": 6, "duration": 4, "from": 0, "to": 4, "label": "4", "prop": 2 },
    { "time": 7, "duration": 4, "from": 1, "to": 5, "label": "4", "prop": 3 } ]

So we may define propPermutation as "the permutations that must be applied on the pattern, in combination with limbPermutation, to indicate the correct prop labels for throws in the next cycle"

note 1
if I add
"jugglers": [
    { "name": "Alice",   "label": "A"  , "function":"start with a high pass", "functionLabel":"H"},
     { "name": "Bob",     "label": "B" , "function":"throw a self", "functionLabel":"S"},
     { "name": "Charlie", "label": "C" , "function":"throw a low pass", "functionLabel":"L"}
 ],
limbPermutation may also be obtained by
"jugglerPermutation": [1,2,0] # Alice gives her role to Bob.
"limbPermutation":[3,4,2,0,1,5] # 

because
"jugglerPermutation": [1,2,0] #  This is the same as "limbPermutation":[1,2,0,4,5,3]
 first [1,2,0,4,5,3], then [3,4,2,0,1,5] yields [4,5,0,1,2,3]   

note 2
If I make the pattern 9344, not all props will have landed in the next cycle.
So we must fill in another prop in the next cycle. I copied this from Christian's website:
    { "time": 4, "duration": 9, "from": 4, "to": 1, "label": "9", "prop": 1 },
    { "time": 5, "duration": 3, "from": 5, "to": 2, "label": "3", "prop": 4 }, # new prop
    { "time": 6, "duration": 4, "from": 0, "to": 4, "label": "4", "prop": 2 },
    { "time": 7, "duration": 4, "from": 1, "to": 5, "label": "4", "prop": 3 },
This can be obtained by the addition of a prop in propPermutation:
"repetition": {
     "period": 4,
     "limbPermutation": [4,5,0,1,2,3]              # shift by the period
     "propPermutation": [1,4,2,3,0]                   # prop 0 is still in the air in the next cycle.
 }

Co Stuifbergen
=========================
in...@jacos.nl
www.jacos.nl
+31 6 13 02 44 69 (mobile)

Kloosterwei 102
2361 XN  Warmond
the Netherlands
=========================

JaCo Stuifbergen

unread,
Feb 14, 2021, 1:48:38 PM2/14/21
to juggling-interchange-format
note 3
The following example is the same pattern, but I have given the props different labels. propPermutation has been adapted as a consequence.
    { "time": 0, "duration": 9, "from": 4, "to": 1, "label": "9", "prop": 1 },
    { "time": 1, "duration": 3, "from": 5, "to": 2, "label": "3", "prop": 0 },
    { "time": 2, "duration": 4, "from": 0, "to": 4, "label": "4", "prop": 2 },
    { "time": 3, "duration": 4, "from": 1, "to": 5, "label": "4", "prop": 3 },
"repetition": {
     "period": 4,
     "limbPermutation": [4,5,0,1,2,3]              # shift by the period
     "propPermutation": [0,4,2,3,1]                   # prop 0 is still in the air in the next cycle.
 }

I wonder if JIF should set a standard (or recommendation) for the order of the props.
I don't expect problems for animators etcetera.
It might perhaps be useful for software that compares or sorts patterns.

Christian Helbling

unread,
Feb 18, 2021, 1:39:03 PM2/18/21
to juggling-inte...@googlegroups.com
Hi

> If we would go by the second option, right after time 6 we would get this:
> "jugglers": [
> { "name": "Mallory", "label": "A" }
> { "name": "Alice", "label": "B" },
> { "name": "Bob", "label": "C" }
> { "name": "Charlie", "label": "M" }
> ],
> with limbs staying the same.
> So the jugglers array is permuted, except for the labels that stay at the same place.
> This is a bit weird (but neccessary) and not covered directly if we would only have limbPermutation.


I've worked out a cleaner solution to the weirdness that jugglers
roles/labels/functions (A/B/C/M/..) stay in-place while the rest permutes.
I chose to call them "roles" for now. Naming can of course still be
discussed later if the model turns out to be useful.

The roles are extracted away from the jugglers array. Their only purpose
is to label jugglers with their current role. Movements do not refer to roles
but rather directly to juggler ids.

I wrote movements with words on purpose as not to provoke any movement
discussions yet. The important thing there is to notice that movement
instructions are not absolute but rather relative (to the juggler in this
example, we could also choose some coordinate system that changes place
and rotation along with the pattern).


The following is an example of a three person runaround in two/four count.

a: Alice A: left feedee
b: Bob B: right feedee
c: Charlie C: feeder

time 0 1 2 4 | 6 7 8 10
-----------------------------+-------------------------------
a a a b a b | a b b b b
jugglers / b / \ | / a / \
c b c c c | c c a c a c
-----------------------------+-------------------------------
A A A B A B | B C C C C
roles / B / \ | / B / \
C B C C C | A A B A B A


"jugglers": [
{ "name": "Alice" },
{ "name": "Bob" }
{ "name": "Charlie" }
],
"roles": [
{ "label": "A", "juggler": 0 },
{ "label": "B", "juggler": 1 },
{ "label": "C", "juggler": 2 },
],
"limbs": [
{ "juggler": 0, "type": "right hand" },
{ "juggler": 0, "type": "left hand" },
{ "juggler": 1, "type": "right hand" },
{ "juggler": 1, "type": "left hand" }
{ "juggler": 2, "type": "right hand" },
{ "juggler": 2, "type": "left hand" },
],
"movements": [
{ "time": 0, "duration": 3, "juggler": 0, [step to the right] },
{ "time": 0, "duration": 3, "juggler": 1, [walk in front, turn 180 degrees] },
{ "time": 0, "duration": 3, "juggler": 2, [step to the right] },
],
"throws": [
{ "time": 0, "duration": 3, "from": 0, "to": 5, "label": "3p A -> C" },
{ "time": 0, "duration": 3, "from": 2, "to": 3, "label": "3 B" },
{ "time": 0, "duration": 3, "from": 4, "to": 1, "label": "3p C -> A" },

{ "time": 1, "duration": 3, "from": 1, "to": 0, "label": "3 A" },
{ "time": 1, "duration": 3, "from": 3, "to": 2, "label": "3 B" },
{ "time": 1, "duration": 3, "from": 5, "to": 4, "label": "3 C" },

{ "time": 2, "duration": 3, "from": 0, "to": 1, "label": "3 A" },
{ "time": 2, "duration": 3, "from": 2, "to": 5, "label": "3p B -> C" },
{ "time": 2, "duration": 3, "from": 4, "to": 3, "label": "3p C -> B" },

{ "time": 3, "duration": 3, "from": 1, "to": 0, "label": "3 A" },
{ "time": 3, "duration": 3, "from": 3, "to": 2, "label": "3 B" },
{ "time": 3, "duration": 3, "from": 5, "to": 4, "label": "3 C" },

{ "time": 4, "duration": 3, "from": 0, "to": 5, "label": "3p A -> C" },
{ "time": 4, "duration": 3, "from": 2, "to": 3, "label": "3 B" },
{ "time": 4, "duration": 3, "from": 4, "to": 1, "label": "3p C -> A" },

{ "time": 5, "duration": 3, "from": 1, "to": 0, "label": "3 A" },
{ "time": 5, "duration": 3, "from": 3, "to": 2, "label": "3 B" },
{ "time": 5, "duration": 3, "from": 5, "to": 4, "label": "3 C" },
],
"repetition": {
"period": 6,
"jugglerPermutation": [ 1, 2, 0 ], # A => B => C => A
}


In the second period (after 6 beats) the jugglers are permuted:

"jugglers": [
{ "name": "Charlie" }, # A
{ "name": "Alice" }, # B
{ "name": "Bob" } # C
],

Now, Alice has role B, Bob role C, and Charlie role A.
Notice that movement instructions always stay with the same role.
We didn't need to do some weird permutation of only part of the keys in the jugglers array.



This juggler rearrangement looks simple but has some issues:
1) It applies only to one specific period. If I jump back and forth in time between periods,
I'd have to rearrange the jugglers all the time which can be confusing.
@Graham: Is the same issue but with propPermutation the reason for your confusion?

2) I may want to use the jugglers ids for a reference into a array of 3d-objects
of an animation scene for example. Alice should always have the same 3d-object no matter
her current role.


Instead of permuting the jugglers array, we can permute all the juggler references like this
to achieve the same:

"jugglers": [
{ "name": "Alice" },
{ "name": "Bob" }
{ "name": "Charlie" }
],
"roles": [
{ "label": "A", "juggler": 2 },
{ "label": "B", "juggler": 0 },
{ "label": "C", "juggler": 1 },
],
"limbs": [
{ "juggler": 2, "type": "right hand" },
{ "juggler": 2, "type": "left hand" },
{ "juggler": 0, "type": "right hand" },
{ "juggler": 0, "type": "left hand" }
{ "juggler": 1, "type": "right hand" },
{ "juggler": 1, "type": "left hand" },
],
"movements": [
[ ..same movements for time 0.. ]

{ "time": 6, "duration": 3, "juggler": 2, [step to the right] },
{ "time": 6, "duration": 3, "juggler": 0, [walk in front, turn 180 degrees] },
{ "time": 6, "duration": 3, "juggler": 1, [step to the right] },
],
"throws": [
[ ..same throws for time 0-5.. ]

{ "time": 6, "duration": 3, "from": 0, "to": 5, "label": "3p A -> C" },
{ "time": 6, "duration": 3, "from": 2, "to": 3, "label": "3 B" },
{ "time": 6, "duration": 3, "from": 4, "to": 1, "label": "3p C -> A" },

[..]

],

This solves issue 2).
Issue 1) is solved for movements and throws.
We can solve it for limbs as well, if jugglerPermutation implies a limbPermutation
and we apply the same trick there as well, rewriting limb references in the
throws from/to values.

Of course, choosing between the two versions of applying the permutation
is an implementation detail of the application. The resulting modified
jif with additional throws and movement insctrutions will typically only be
used as internal state and won't be exported as jif again.

What do you think about that approach?


And by the way, for declaring the permutations, I think the inverse of what I wrote
in the examples is probably more handy.
[ 2, 0, 1 ] instead of [ 1, 2, 0 ] in this example.

Cheers
Christian

JaCo Stuifbergen

unread,
Feb 19, 2021, 1:18:26 PM2/19/21
to juggling-interchange-format
note 4
In many cases, the permutation of the limbs is essentially a permutation of the jugglers, perhaps followed by an exchange of Left and Right, for some (or for all) jugglers.

For example, this is the case for:
- a regular 4-count between 2 jugglers (no permutation at all)
- a waltz (3-count) (change L/R)
- the scrambled V variations
- every social siteswap (an example is below)

Of course, those cases can be described with just a limbPermutation.
In that case, the jugglerPermutation can be derived from the limbPermutationWithoutJugglerPermutation.

I can imagine situations that don't have a limbPermutation but not a jugglerPermutation.
For example, if 2 jugglers decide to alternate
p s s s
with
s p p p

example of permutations in a social siteswap
In the example of 5344 for 3 jugglers:
"limbs": [
    { "juggler": 0, "type": "right hand" },
    { "juggler": 1, "type": "right hand" },
    { "juggler": 2, "type": "right hand" },
    { "juggler": 0, "type": "left hand" },
    { "juggler": 1, "type": "left hand" },
    { "juggler": 2, "type": "left hand" }
  ],
"jugglers": [
    { "name": "Alice",   "label": "A"  , "function":"start with a high pass", "functionLabel":"H"},
     { "name": "Bob",     "label": "B" , "function":"throw a self", "functionLabel":"S"},
     { "name": "Charlie", "label": "C" , "function":"throw a low pass", "functionLabel":"L"}
 ],
limbPermutation may also be obtained by
"jugglerPermutation": [1,2,0] # Alice gives her role to Bob.
"limbPermutation":[3,4,2,0,1,5] #  B will continue with left (3<-->0),
     # ...C will continue with left (4<-->1)
     # ...and A will continue with right (2 and 5 stay at their place)





Co Stuifbergen
=========================
in...@jacos.nl
www.jacos.nl
+31 6 13 02 44 69 (mobile)

Kloosterwei 102
2361 XN  Warmond
the Netherlands
=========================



JaCo Stuifbergen

unread,
Feb 19, 2021, 2:49:05 PM2/19/21
to juggling-interchange-format
About the definition of the permutations, in reply to:
And by the way, for declaring the permutations, I think the inverse of what I wrote
in the examples is probably more handy.
 [ 2, 0, 1 ] instead of [ 1, 2, 0 ] in this example.

if we have
"limbs": [
    { "juggler": 0, "type": "right hand" },
    { "juggler": 0, "type": "left hand"  },
    { "juggler": 1, "type": "right hand" },
    { "juggler": 1, "type": "left hand"  }
    { "juggler": 2, "type": "right hand" },
    { "juggler": 2, "type": "left hand"  },
 ],
I like that
 "limbPermutation": [ 2,3,4,5,0,1],              
means "after 1 period, juggler 1 takes the role of juggler 0"

Because it means that if we have
 "throws": [
     { "time": 0,  "duration": 6, "from":3, "to": 1, "label": "6x", "prop": 5 },
    ................. ],
"to" and "from" contain the indexes that we need to find the new values.
(from: p[3], to: p[5])

Of course, if we want to go back in time, the procedure is more complicated.

JaCo Stuifbergen

unread,
Feb 19, 2021, 2:49:15 PM2/19/21
to juggling-interchange-format
(a short note: In a previous message, I used the word "function" and I meant the same as "role")

Christian,

It took a moment, but I think that I understand your purpose.

For example, when we have
 "jugglers": [
     { "name": "Leo"  , "hair":"blonde", "role":"feeder" },
     { "name": "Mary"    , "hair":"brown", "role":"left feedee" },
     { "name": "Neil" , "hair":"gray", "role":"right feedee" },
 ],
the roles may change after a permutation, but not the hair colors (and not the name, either).
So it makes sense to define
 "roles": [
    { "label": "A", "task": "feeder", "juggler": 0 },
    { "label": "B", "task": "left feedee", "juggler": 1 },
    { "label": "C", "task": "right feedee", "juggler": 2 },
 ],

Concering the implementation of the permutations:

To me, it seems easiest if the "jugglers" array is never changed.
And the same holds for the "limbs" array.

I think that the labeling of jugglers and roles can have a use:
  • - for labeling jugglers by role in stead of name
  • - for describing displacements of jugglers
    Whether positions should be described for jugglers or for roles still has to be discussed.
Such descriptions will not be required for every pattern in every program.
So "roles" and the jugglerPermutation should in my opinion be optional.
(By the way, I prefer that positions also refer to jugglers, not to roles)

If jugglerPermutation is optional, limbPermutation should be independent of jugglerPermutation.

Co Stuifbergen
=========================
in...@jacos.nl
www.jacos.nl
+31 6 13 02 44 69 (mobile)

Kloosterwei 102
2361 XN  Warmond
the Netherlands
=========================
--
You received this message because you are subscribed to a topic in the Google Groups "juggling-interchange-format" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/juggling-interchange-format/_joONqzVNqQ/unsubscribe.
To unsubscribe from this group and all its topics, send an email to juggling-interchang...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/juggling-interchange-format/19b06925-d7f1-69e4-86fd-a896b3f147bc%40helch.ch.

JaCo Stuifbergen

unread,
Feb 20, 2021, 5:28:42 AM2/20/21
to juggling-interchange-format
Tiny correction:

Op vr 19 feb. 2021 19:16 schreef JaCo Stuifbergen <j.c.stu...@gmail.com>:
note 4

I can imagine situations that do have a limbPermutation but not a jugglerPermutation.
Reply all
Reply to author
Forward
0 new messages