Re:Advice on naming and structuring scholarLY commands

2018-06-18 Thread Flaming Hakama by Elaine
> I understand your concern with using "Mark" as the basis of the name,
> since while this \editorialMark will often (or always?) include a mark that
> appears on the page, it also contains musical alternatives, so it is not
> merely a type of Mark.
>
>
> Not *alternatives*, basically an individual segment of music.
>

I guess I didn't fully understand the variations aspect of this.

What are the circumstances when you would want to have a variation?

I assumed they would be treated as alternatives (each edition might include
the original, or a variation).  But maybe, variations are included in
addition to the original, like in footnotes, or and appendix?




>
> So, here is a basic question that I think has import to this discussion:
> Can the musical segments addressed by \editorialMark be nested and/or
> overlapping?
>
>
> Technically (as music-functions) they can be nested but not overlapping.
> Conceptually it should be possible to have overlapping findings, but I
> don't plan to try supporting this. I think users would have to work around
> with adjacent segments.
>

I guess that this concern of mine was motivated by the (mis-)conception
that the variations were alternatives.  Which is to say, if the musical
segments were not disjoint, then the resolution of alternatives would get
tricky, as different \editorialMark segments might have conflicting
alternatives.




>
> If yes, they can be nested and/or overlapping, then each \editorialMark
> could map to a single annotation/comment/remark.  In which case, the
> concept of \editorialMark as describing the specific mark makes sense, and
> the musical segment is simply the entity on which the \editorialMark
> operates.
>
> If this is the case, possibly better names might be \editorialRemark or
> \annotation.
>
>
> We already have these, in the existing scholarLY annotations
> \criticalRemark, \musicalIssue etc. These "point" to a specific element
> (through a \tweak or \once \override) and "attach" an annotation to this.
> In the sense of "I want to say something about this score element", not
> "this 'is' something".
>


I guess the distinction I was teasing out was whether the \editorialMark
referred to one editorial concept, versus a container for several.  Sounds
like it is for a single concept.

As such, it doesn't seem like there is a point in making a distinction
between whether the "score element" is actually applies to a single
note--an accidental, dynamic or articulation--versus when the "score
element" spans a bunch of notes--like a slur or dynamic spanners, or
ottava, etc.



>
> However, if the musical segments addressed by \editorialMark-s must be
> distinct from one another, then we might have several marks/topics/comments
> in a single musical segment.  In that case, maybe the command should be
> named after the identification of this musical segment?
>
>
> Basically this is what I would like to achieve. I want to encode the
> information that
>
>- this beam "is" an addition by the editor
>- these four notes "are" illegible
>- this measure "is" a gap because of damage
>
> This would call for a bunch of commands like \editorialAddition,
> \illegible, \gap etc.
>
> However, this would "pollute" the namespace with numerous names, many of
> whom being pretty generic (gap, add, del, corr etc.), which is why I am
> looking for a generic "wrapper" command that is specified by its first
> argument.
>
>
That sounds like the right concept--a function that requires a first
argument describing the type of entity.



>
> Based on some of the earlier posts, it seems like one of the outcomes of
> this command is to attach unique IDs to the start and end of this musical
> segment.  If this is true, then maybe the command should be named with
> regard to the fact that its main job is to identify and tag this musical
> segment, to which the editorial remarks and the alternatives will apply.
>
> If that is the case, maybe the command should be named something like
> \identifyEditorialSegment or \editorialTag.
>
>
> Maybe (probably) I'll drop the idea of tagging both the beginning and end
> of the segment, but I think this description is going into the right
> direction ...
>

In any case, my concern about this is not relevant since these segments are
not alternatives.

And semantically, the \editorialMark is more about the remark than the
specifics of what it attaches to.




>
> I don't really like these initial suggestions for this second conception
> of the command, but I'd like to get clarity on what the essential
> requirements are for any such usage.  (Do you need to have alternatives?
> Do you need to have editorial marks?)
>
>
> There need not be alternatives. The command in question encodes *one*
> finding, which may include a single musical element or a (sequential) music
> expression. If the editor wants to encode alternatives (for example the
> original vs. the corrected text) there is (going to be) an additional
> command that 

Re: Ties across voices

2018-06-18 Thread David Kastrup
"Phil Holmes"  writes:

> - Original Message - 
> From: "Carl Sorensen" 
> To: "Simon Albrecht" ; "Shachar Shemesh"
> ; 
> Sent: Monday, June 18, 2018 4:52 PM
> Subject: Re: Ties across voices
>
>
>>
>>
>> On 6/17/18, 12:14 PM, "Simon Albrecht"  wrote:
>>
>>On 16.06.2018 20:41, Shachar Shemesh wrote:
>>> The Tie won't tie between the voices and the chord past the voices.
>>
>>It seems to work if you move the Tie_engraver from Voice to Staff
>> level:
>>
>>I moved Tie_performer along, since you were talking about the
>> importance
>>of accurate MIDI for your use case. I don’t use MIDI (or hardly
>> ever) so
>>I can’t test reasonably, but it should work, I imagine.
>>
>> This looks like the right answer, and one that maybe ought to be
>> documented in a docs snippet.  Lots of people use the LSR trick of
>> hidden notes, when a more straightforward approach is to move the
>> Tie_engraver.
>>
>> I wonder if having the Tie_engraver be in the Staff ought to be the
>> default?  Can anyone see negatives to having it be in the Staff?
>
> If it means ties will tie equal pitch notes in, say, voiceOne with
> others in voiceTwo, both on the same stave, it seems like an excellent
> change.

tieWaitForNote would work worse in several situations.  So would other
things like a choir unison note held over a bar.

-- 
David Kastrup

___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


Re: Ties across voices

2018-06-18 Thread Phil Holmes
- Original Message - 
From: "Carl Sorensen" 
To: "Simon Albrecht" ; "Shachar Shemesh" 
; 

Sent: Monday, June 18, 2018 4:52 PM
Subject: Re: Ties across voices





On 6/17/18, 12:14 PM, "Simon Albrecht"  wrote:

   On 16.06.2018 20:41, Shachar Shemesh wrote:
   > The Tie won't tie between the voices and the chord past the voices.

   It seems to work if you move the Tie_engraver from Voice to Staff 
level:


   I moved Tie_performer along, since you were talking about the 
importance
   of accurate MIDI for your use case. I don’t use MIDI (or hardly ever) 
so

   I can’t test reasonably, but it should work, I imagine.

This looks like the right answer, and one that maybe ought to be 
documented in a docs snippet.  Lots of people use the LSR trick of hidden 
notes, when a more straightforward approach is to move the Tie_engraver.


I wonder if having the Tie_engraver be in the Staff ought to be the 
default?  Can anyone see negatives to having it be in the Staff?


Thanks,

Carl



If it means ties will tie equal pitch notes in, say, voiceOne with others in 
voiceTwo, both on the same stave, it seems like an excellent change.


--
Phil Holmes 



___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


Re: Ties across voices

2018-06-18 Thread Carl Sorensen


On 6/17/18, 12:14 PM, "Simon Albrecht"  wrote:

On 16.06.2018 20:41, Shachar Shemesh wrote:
> The Tie won't tie between the voices and the chord past the voices.

It seems to work if you move the Tie_engraver from Voice to Staff level:

I moved Tie_performer along, since you were talking about the importance 
of accurate MIDI for your use case. I don’t use MIDI (or hardly ever) so 
I can’t test reasonably, but it should work, I imagine.

This looks like the right answer, and one that maybe ought to be documented in 
a docs snippet.  Lots of people use the LSR trick of hidden notes, when a more 
straightforward approach is to move the Tie_engraver.

I wonder if having the Tie_engraver be in the Staff ought to be the default?  
Can anyone see negatives to having it be in the Staff?

Thanks,

Carl


___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


Re: Does \balloonText only work inside chords?

2018-06-18 Thread Urs Liska




Am 18.06.2018 um 14:17 schrieb David Kastrup:

Urs Liska  writes:


...

 ...
  243: 13  [ly:book-process # #< Output_def> #< Output_def> "unknown"]
In unknown file:
?: 14* [# #]
?: 15* [# # #]
?: 16* [# # # #]

ERROR: In procedure symbol->string:
ERROR: Wrong type argument in position 1 (expecting symbol): ()
Exited with return code 1.

Any idea what is wrong here?

The engravers do things differently.  You have to adapt more than just
the Scheme code.


And would it be useful to turn my function in a proposal?

Not independently of the C++ code I should think.


OK, I see. That basically rules out that I'll be looking into it.




It does seem to work like footnotes, and while the chord issue isn't
sorted out I think this is at a completely different location and
independent of such a change.

I have not looked at the details for years but this sounds optimistic.
I think that some more C++ and Scheme work is required, and then loads
of convert-ly and documentation rewrite work.  It does help that the
documentation currently is terrible, so it's comparatively easy to raise
the bar from where it is.



OK. So that means the current state is that \ballonText can only be 
applied to noteheads within chords. \balloonGrobText can not be made to 
work as post-event but has to be placed before the to-be-annotated music.


So I think I'll at least know enough to create a workaround ...

___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


Re: Binary Search Tree in Scheme

2018-06-18 Thread Urs Liska




Am 18.06.2018 um 13:25 schrieb David Kastrup:

Urs Liska  writes:


Oh my, it's less than a year that I learned and successfully completed
programming assignments on all of these - and already it's so far away
...
Of course I was aware that I'd actually need some regular practice to
keep these things fresh and get to a more thorough understanding that
helps me keep them in mind for longer.

University courses are no substitute for learning by having things hit
you in your face.  Nor are they supposed to be.  What they can (and
hopefully will) do is make it comparatively natural and achievable to
_analyse_ what hit you and have the tools and proven chops for designing
countermeasures.


Exactly. Having attended these (online) courses I'm now in the position 
to at least know what we're talking about. I know the basics of 
algorithms, why the right choice not only decides between good and bad 
but often between god, bad and totally impossible (i.e. having a 
computer calculates for a few seconds vs. a few thousand years), and I 
basically know what you mean with AVL and black-red trees (Jan-Peter) or 
heap-based priority queues (you) and I'd be able to quickly look up and 
recap the details.



Even better is having things hit others in the face
and administer advice from the peanut galleries.  That helps
considerably against "task blindness" where you are so stuck on making
your solution work that you lose sight of its impact on the overall
scheme of things.


Probably it would have been good if I had made good on my intention to
reimplement my Python solutions in Scheme. Would probably also have
produced some tools ready for use ...

Sometimes it's more motivational to learn on the things that count and
do the finger exercises at a point of time where they are only
moderately annoying rather than a hard challenge.


My motivation would have been to add these to my "Scheme book" - but 
obviously that wasn't pressing enough ;-)


Best
Urs






___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


Re: Does \balloonText only work inside chords?

2018-06-18 Thread David Kastrup
Urs Liska  writes:

> Am 18.06.2018 um 11:56 schrieb Urs Liska:
>> <... snip discussion of documentation...>
>>
>> 2) Additionally, it seems that \balloonText only works within
>> chords, which seems sort-of strange to me
>>
>> Modified from an example in NR 1.7.2:
>>
>> \version "2.19.80"
>>
>> \new Voice \with {
>>\consists "Balloon_engraver"
>> }
>> \relative {
>>   \displayMusic { > } >}
>>   \displayMusic { c' -\balloonText #'(-2 . -2) \markup { "I'm a note head" }}
>> }
>>
>
> After David's comment I wrote a music-function modeled after \footnote:
>
> myBalloon =
> #(define-music-function (offset text mus)
>(number-pair? markup? ly:music?)
>(let ((ann (make-music
>'AnnotateOutputEvent
>'X-offset (car offset)
>'Y-offset (cdr offset)
>'text (markup #:line (#:simple text)
>  (ly:music-set-property! mus 'articulations (list ann))
>  mus))
>
> This allows the following expressions:
>
>  % annotate the c'' *after* \myBalloon
> c' -\myBalloon #'(2 . -2) "Hey" -!   % this properly annotates the 
> articulation
>
> but (as said in my initial post) it is not possible to annotate single
> notes outside of chords:
>
> \myBalloon #'(2 . -2) "Hey" c'
> % like the "official" c' -\balloonText #'(-2 . -2) \markup { "Hey" }
>
> errors out with:
>
> /home/uliska/software/lilypond/releases/2.19.80/usr/share/lilypond/current/scm/lily.scmBacktrace:
> In unknown file:
>?:  0* [lilypond-main ("/home/uliska/Schreibtisch/unknown.ly")]
> In 
> /home/uliska/software/lilypond/releases/2.19.80/usr/share/lilypond/current/scm/lily.scm:
> 1025:  1* (let* ((failed #)) (if (ly:get-option #) (begin #)) ...)
> 1025:  2* [lilypond-all ("/home/uliska/Schreibtisch/unknown.ly")]
> 1038:  3  (let* ((failed #) (separate-logs #) (ping-log #) ...) (gc) ...)
> 1050:  4* [for-each # 
> ("/home/uliska/Schreibtisch/unknown.ly")]
> In unknown file:
>?:  5* [# "/home/uliska/Schreibtisch/unknown.ly"]
> In 
> /home/uliska/software/lilypond/releases/2.19.80/usr/share/lilypond/current/scm/lily.scm:
> 1052:  6* (let* (# # #) (if separate-logs #) (if ping-log #) ...)
> 1063:  7* [lilypond-file # 
> "/home/uliska/Schreibtisch/unknown.ly"]
> 1098:  8  [catch ly-file-failed # # args)>]
> In unknown file:
>?:  9* [#]
> In 
> /home/uliska/software/lilypond/releases/2.19.80/usr/share/lilypond/current/scm/lily.scm:
> 1099: 10* [ly:parse-file "/home/uliska/Schreibtisch/unknown.ly"]
> In 
> /home/uliska/software/lilypond/releases/2.19.80/usr/share/lilypond/current/ly/init.ly:
>   56: 11* (let* ((book-handler #)) (cond (# #) (# #)))
>   59: 12  (cond (# #) (# #))
> In 
> /home/uliska/software/lilypond/releases/2.19.80/usr/share/lilypond/current/scm/lily-library.scm:
> ...
>  243: 13  [ly:book-process # #< Output_def> #< Output_def> "unknown"]
> In unknown file:
>?: 14* [# #]
>?: 15* [# # #]
>?: 16* [# # # #]
>
> ERROR: In procedure symbol->string:
> ERROR: Wrong type argument in position 1 (expecting symbol): ()
> Exited with return code 1.
>
> Any idea what is wrong here?

The engravers do things differently.  You have to adapt more than just
the Scheme code.

> And would it be useful to turn my function in a proposal?

Not independently of the C++ code I should think.

> It does seem to work like footnotes, and while the chord issue isn't
> sorted out I think this is at a completely different location and
> independent of such a change.

I have not looked at the details for years but this sounds optimistic.
I think that some more C++ and Scheme work is required, and then loads
of convert-ly and documentation rewrite work.  It does help that the
documentation currently is terrible, so it's comparatively easy to raise
the bar from where it is.

-- 
David Kastrup

___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


Re: Does \balloonText only work inside chords?

2018-06-18 Thread Urs Liska




Am 18.06.2018 um 11:56 schrieb Urs Liska:

<... snip discussion of documentation...>

2) Additionally, it seems that \balloonText only works within chords, 
which seems sort-of strange to me


Modified from an example in NR 1.7.2:

\version "2.19.80"

\new Voice \with {
   \consists "Balloon_engraver"
}
\relative {
  \displayMusic { }
  \displayMusic { c' -\balloonText #'(-2 . -2) \markup { "I'm a note head" }}
}



After David's comment I wrote a music-function modeled after \footnote:

myBalloon =
#(define-music-function (offset text mus)
   (number-pair? markup? ly:music?)
   (let ((ann (make-music
   'AnnotateOutputEvent
   'X-offset (car offset)
   'Y-offset (cdr offset)
   'text (markup #:line (#:simple text)
 (ly:music-set-property! mus 'articulations (list ann))
 mus))

This allows the following expressions:

 % annotate the c'' *after* \myBalloon
c' -\myBalloon #'(2 . -2) "Hey" -!   % this properly annotates the 
articulation

but (as said in my initial post) it is not possible to annotate single 
notes outside of chords:


\myBalloon #'(2 . -2) "Hey" c'
% like the "official" c' -\balloonText #'(-2 . -2) \markup { "Hey" }

errors out with:

/home/uliska/software/lilypond/releases/2.19.80/usr/share/lilypond/current/scm/lily.scmBacktrace:
In unknown file:
   ?:  0* [lilypond-main ("/home/uliska/Schreibtisch/unknown.ly")]
In 
/home/uliska/software/lilypond/releases/2.19.80/usr/share/lilypond/current/scm/lily.scm:
1025:  1* (let* ((failed #)) (if (ly:get-option #) (begin #)) ...)
1025:  2* [lilypond-all ("/home/uliska/Schreibtisch/unknown.ly")]
1038:  3  (let* ((failed #) (separate-logs #) (ping-log #) ...) (gc) ...)
1050:  4* [for-each # 
("/home/uliska/Schreibtisch/unknown.ly")]
In unknown file:
   ?:  5* [# "/home/uliska/Schreibtisch/unknown.ly"]
In 
/home/uliska/software/lilypond/releases/2.19.80/usr/share/lilypond/current/scm/lily.scm:
1052:  6* (let* (# # #) (if separate-logs #) (if ping-log #) ...)
1063:  7* [lilypond-file # 
"/home/uliska/Schreibtisch/unknown.ly"]
1098:  8  [catch ly-file-failed # #]
In unknown file:
   ?:  9* [#]
In 
/home/uliska/software/lilypond/releases/2.19.80/usr/share/lilypond/current/scm/lily.scm:
1099: 10* [ly:parse-file "/home/uliska/Schreibtisch/unknown.ly"]
In 
/home/uliska/software/lilypond/releases/2.19.80/usr/share/lilypond/current/ly/init.ly:
  56: 11* (let* ((book-handler #)) (cond (# #) (# #)))
  59: 12  (cond (# #) (# #))
In 
/home/uliska/software/lilypond/releases/2.19.80/usr/share/lilypond/current/scm/lily-library.scm:
...
 243: 13  [ly:book-process # #< Output_def> #< Output_def> "unknown"]
In unknown file:
   ?: 14* [# #]
   ?: 15* [# # #]
   ?: 16* [# # # #]

ERROR: In procedure symbol->string:
ERROR: Wrong type argument in position 1 (expecting symbol): ()
Exited with return code 1.

Any idea what is wrong here?
And would it be useful to turn my function in a proposal? It does seem 
to work like footnotes, and while the chord issue isn't sorted out I 
think this is at a completely different location and independent of such 
a change.


Urs

___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


Re: Does \balloonText only work inside chords?

2018-06-18 Thread Urs Liska



Am 18.06.2018 um 12:31 schrieb David Kastrup:

David Kastrup  writes:


Urs Liska  writes:


According to NR 1.7.2 \balloonText is "used like \tweak, typically
within chords, to attach text to an individual note." I have two
questions to this:

The documentation is ridiculous.  I don't remember the details but
basically footnotes were previously done similar and reimplemented with
more sane user interface and documentation.  Balloons should likely be
done likewise.

Until they aren't,

Uh, you know what I mean.


ignore the documentation texts and rather go for examples that might
be present in doc examples or regtests.


OK, that also means documentation patches aren't really what is needed 
before the implementation has been fixed. I have tried doing something, 
but I'll leave that for another sub-thread, as it doesn't actually 
address the other part of my question.


Urs


___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


Re: Binary Search Tree in Scheme

2018-06-18 Thread David Kastrup
Urs Liska  writes:

> Oh my, it's less than a year that I learned and successfully completed
> programming assignments on all of these - and already it's so far away
> ...
> Of course I was aware that I'd actually need some regular practice to
> keep these things fresh and get to a more thorough understanding that
> helps me keep them in mind for longer.

University courses are no substitute for learning by having things hit
you in your face.  Nor are they supposed to be.  What they can (and
hopefully will) do is make it comparatively natural and achievable to
_analyse_ what hit you and have the tools and proven chops for designing
countermeasures.  Even better is having things hit others in the face
and administer advice from the peanut galleries.  That helps
considerably against "task blindness" where you are so stuck on making
your solution work that you lose sight of its impact on the overall
scheme of things.

> Probably it would have been good if I had made good on my intention to
> reimplement my Python solutions in Scheme. Would probably also have
> produced some tools ready for use ...

Sometimes it's more motivational to learn on the things that count and
do the finger exercises at a point of time where they are only
moderately annoying rather than a hard challenge.

-- 
David Kastrup

___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


Re: Binary Search Tree in Scheme

2018-06-18 Thread Urs Liska




Am 18.06.2018 um 11:41 schrieb Jan-Peter Voigt:

Am 18.06.2018 um 11:16 schrieb Urs Liska:



Am 18.06.2018 um 10:57 schrieb Jan-Peter Voigt:

Hi Urs,

there are self balancing trees like AVL or Red-Black, but I'd say 
implementation cost is quite for this purpose to sort n<1000 
elements. I might be wrong, but I'd prefer the sort method.


OK, this is why I ask.
(I assume with "implementation" cost you mean the additional time 
needed for insertion/balancing, not the time *I* need for the 
implementation?)
Yes I mean insertion cost, but I also mean weight of the code. You 
have a complex structure to maintain.


The EE uses a tree that sorts by measure on the first level, by 
moment on second and then by the edition-id-path. So there is a tree 
structure, but on each level the child-list for each node is sorted 
by the guile method sort, when it is displayed in order. To access 
the elements it uses a hashtable.
In your case annotations should be at least partially sorted. The 
question is, where/when do you need the sorted list?


When exporting annotations.

So this is a one time sorting task. Or twice, if you have two views.

While typesetting music, you need to insert access the elements by a 
path moment/context or the like.


Yes. When an acknowledged grob has an annotation attached it will be 
prepended to the list or inserted into the tree.
The list will be sorted for one view. I assume `reverse` a quite cheap 
function.


To export a summary the order might be given by a path 
piece/movement/measure/moment/context.


So do I get this right: you're suggestion that I *do* use a tree 
structure, but not a BST but one where the hierarchy matches the 
musical one > This means that assuming my current movement has 1000 
measures, and an
average of five annotations per measure I wouldn't have one list of 
5000 annotations but one of 1000 (to sort) and 1000 of five each.
And when I have 1000 measures where only 37 include 1-2 annotations 
I'd have that list of 37 measures with sublists of 1-2 each.?
Yes. The tree-structure is for creating different views and for 
directory lookup. If all annotations are fetched by an engraver it 
might be OK to first collect them in one large list. And if you drop 
them into a tree with the scheme of the desired view you don't need to 
sort the list, but just the tree. If you already know the scheme of 
the view while fetching the annotation events you can of course insert 
the annotations immediatly in the tree. That insertion might be hidden 
behind a method of an insert-collect-object. That way you can 
interchange the implementation without touching the engraver ... and 
perhaps I didn't study the ScholarLY code and that is already the case 
;-)


No, it's not :-(




To give a different view on the data I'd build another tree with the 
desired scheme like type/mvmt/measure. If you have the primary tre 
in insertion order you would have to visit some nodes more than 
twice so a copy should be cheaper. (That is not a proof but an 
assumption!)


You mean: walk over the initial tree and insert each element into a 
new tree with its own hierarchical structure matching the desired 
output hierarchy?

Yes



I'll take all this into account when reviewing the package. Based on my 
recent experience with the original breaks and the edition-engraver I'll 
have to review the behaviour with multiple scores and bookparts anyway.


Best
Urs

___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


Re: Binary Search Tree in Scheme

2018-06-18 Thread Urs Liska

Hi David,


Am 18.06.2018 um 12:25 schrieb David Kastrup:

Urs Liska  writes:


Hi all,

as you know I'm currently reviewing the scholarLY package, not only
for new features but also for its coding - which blatantly shows how
it was initially done directly from within my learning curve ;-)

One thing I'd like to change is the storage/handling of
annotations. The current implementation does the following:

  * an engraver creates an annotation (an alist) and appends it to a
global "annotations" variable (OK, simple improvement: don't append
but cons to the beginning)

That improvement is definitely something you should do.  Reduces
complexity from O(n^2) to O(n).


Yes, I know that by now, and I was surprised to be confronted with my 
old code ;-)





  * in a later stage sort this "annotations" list and export the
annotations.

This looks very inefficient,

Why?  Batch sorting once is in general more efficient than keeping data
sorted during input.  It's O(n log n).  Which means that the time spent
here will become insignificant compared to the time your "appends
it to a global annotations variable" takes once you are talking about
larger amounts of data.


OK.



You know the joke about the drunk crawling on the ground under a street
lamp looking for his keys?  Someone helps him but no success, so he
finally asks "are you sure that you lost your keys here?"  "No, down
there."  "Why are we looking here?"  "Well, there is better light here
and it's not as dirty."


Yes, I knew that one.



Except that you are looking for your performance where it's dark and
dirty when you likely lost it under the street lamp.


Very good description !




and I think it should be much better to store the annotations in a
binary search tree and have them sorted upon insertion already. (Or am
I misunderstanding this? One thing I'm unaware of is how efficient
Guile's "stable-sort" works on a simple (linked) list).

Guile's stable sort is a merge sort.  There is nothing better on linked
lists.  There is actually almost nothing in terms of total comparison
operations regardless of data structure.  If your access pattern needs
the sorted data only once, it will be totally useless to try anything
else.  It's pretty much guaranteed to end up more expensive in execution
time, let alone in programming and maintenance effort.


OK, I'll take that as sound advice.



Even for the task of intermittently requesting (and removing) the
smallest element so far (a special case of access pattern mixing writes
and reads), there are special data structures called "priority queues"
that are cheaper than trees with guaranteed O(n log n) worst case
behavior without balancing complications because they don't need to
maintain complete order.  Typically implemented using "heaps".


Oh my, it's less than a year that I learned and successfully completed 
programming assignments on all of these - and already it's so far away ...
Of course I was aware that I'd actually need some regular practice to 
keep these things fresh and get to a more thorough understanding that 
helps me keep them in mind for longer. Probably it would have been good 
if I had made good on my intention to reimplement my Python solutions in 
Scheme. Would probably also have produced some tools ready for use ...


Best
Urs



___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


Re: Does \balloonText only work inside chords?

2018-06-18 Thread David Kastrup
David Kastrup  writes:

> Urs Liska  writes:
>
>> According to NR 1.7.2 \balloonText is "used like \tweak, typically
>> within chords, to attach text to an individual note." I have two
>> questions to this:
>
> The documentation is ridiculous.  I don't remember the details but
> basically footnotes were previously done similar and reimplemented with
> more sane user interface and documentation.  Balloons should likely be
> done likewise.
>
> Until they aren't,

Uh, you know what I mean.

> ignore the documentation texts and rather go for examples that might
> be present in doc examples or regtests.

-- 
David Kastrup

___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


Re: Does \balloonText only work inside chords?

2018-06-18 Thread David Kastrup
Urs Liska  writes:

> According to NR 1.7.2 \balloonText is "used like \tweak, typically
> within chords, to attach text to an individual note." I have two
> questions to this:

The documentation is ridiculous.  I don't remember the details but
basically footnotes were previously done similar and reimplemented with
more sane user interface and documentation.  Balloons should likely be
done likewise.

Until they aren't, ignore the documentation texts and rather go for
examples that might be present in doc examples or regtests.

-- 
David Kastrup

___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


Re: Binary Search Tree in Scheme

2018-06-18 Thread David Kastrup
Urs Liska  writes:

> Hi all,
>
> as you know I'm currently reviewing the scholarLY package, not only
> for new features but also for its coding - which blatantly shows how
> it was initially done directly from within my learning curve ;-)
>
> One thing I'd like to change is the storage/handling of
> annotations. The current implementation does the following:
>
>  * an engraver creates an annotation (an alist) and appends it to a
>global "annotations" variable (OK, simple improvement: don't append
>but cons to the beginning)

That improvement is definitely something you should do.  Reduces
complexity from O(n^2) to O(n).

>  * in a later stage sort this "annotations" list and export the
>annotations.
>
> This looks very inefficient,

Why?  Batch sorting once is in general more efficient than keeping data
sorted during input.  It's O(n log n).  Which means that the time spent
here will become insignificant compared to the time your "appends
it to a global annotations variable" takes once you are talking about
larger amounts of data.

You know the joke about the drunk crawling on the ground under a street
lamp looking for his keys?  Someone helps him but no success, so he
finally asks "are you sure that you lost your keys here?"  "No, down
there."  "Why are we looking here?"  "Well, there is better light here
and it's not as dirty."

Except that you are looking for your performance where it's dark and
dirty when you likely lost it under the street lamp.

> and I think it should be much better to store the annotations in a
> binary search tree and have them sorted upon insertion already. (Or am
> I misunderstanding this? One thing I'm unaware of is how efficient
> Guile's "stable-sort" works on a simple (linked) list).

Guile's stable sort is a merge sort.  There is nothing better on linked
lists.  There is actually almost nothing in terms of total comparison
operations regardless of data structure.  If your access pattern needs
the sorted data only once, it will be totally useless to try anything
else.  It's pretty much guaranteed to end up more expensive in execution
time, let alone in programming and maintenance effort.

Even for the task of intermittently requesting (and removing) the
smallest element so far (a special case of access pattern mixing writes
and reads), there are special data structures called "priority queues"
that are cheaper than trees with guaranteed O(n log n) worst case
behavior without balancing complications because they don't need to
maintain complete order.  Typically implemented using "heaps".

-- 
David Kastrup

___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


Does \balloonText only work inside chords?

2018-06-18 Thread Urs Liska
According to NR 1.7.2 \balloonText is "used like \tweak, typically 
within chords, to attach text to an individual note." I have two 
questions to this:


1) If it were used like \tweak it would affect the element *following 
after* the command, isn't it? But in


2.

(from the NR) the balloon text is applied to the g', not the c''. So 
wouldn't it be more correct to say that it works "like an 
articulation"?  also it's an event-function. Additionally, if I'm not 
mistaken this adds an entry to the 'articulations list, so it wouldn't 
be possible to add a balloon to, say, a staccato, isn't it, only a 
rhythmic-event?


2) Additionally, it seems that \balloonText only works within chords, 
which seems sort-of strange to me


Modified from an example in NR 1.7.2:

\version "2.19.80"

\new Voice \with {
  \consists "Balloon_engraver"
}
\relative {
 \displayMusic { }
 \displayMusic { c' -\balloonText #'(-2 . -2) \markup { "I'm a note head" }}
}

This prints

(make-music
  'SequentialMusic
  'elements
  (list (make-music
  'EventChord
  'elements
  (list (make-music
  'NoteEvent
  'duration
  (ly:make-duration 2)
  'articulations
  (list (make-music
  'AnnotateOutputEvent
  'text
  (markup #:line (#:simple "I'm a note head"))
  'Y-offset
  -2
  'X-offset
  -2))
  'pitch
  (ly:make-pitch 0 0))

(make-music
  'SequentialMusic
  'elements
  (list (make-music
  'NoteEvent
  'articulations
  (list (make-music
  'AnnotateOutputEvent
  'text
  (markup #:line (#:simple "I'm a note head"))
  'Y-offset
  -2
  'X-offset
  -2))
  'duration
  (ly:make-duration 2)
  'pitch
  (ly:make-pitch 0 0

which looks fine to me, but it fails with the following error:

ERROR: In procedure symbol->string:
ERROR: Wrong type argument in position 1 (expecting symbol): ()
Exited with return code 1.

Am I misunderstanding anything here? What I ultimately want to achieve is:

 * There's a music function that takes a ly:music? argument
 * single out either the argument or its first element (if sequential)
 * "tweak" the music (i.e. the element following the function in the
   input) and add a balloon text.

I see how I could take the music and create/add-to the articulations 
property. But I'm not sure how to do that when the music is not a chord, 
or even a \tweak-able element: In


{ c' -\myBalloon d' e' }

the balloon should be attached to the d', and in

{ c' -\myBalloon -! d' }

I would want the balloon to be attached to the -! articulation while in

{  }

it should be attached to the middle g', not the upper c''.

Any explanation or advice? Thanks Urs

___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


Re: Binary Search Tree in Scheme

2018-06-18 Thread Jan-Peter Voigt

Am 18.06.2018 um 11:16 schrieb Urs Liska:



Am 18.06.2018 um 10:57 schrieb Jan-Peter Voigt:

Hi Urs,

there are self balancing trees like AVL or Red-Black, but I'd say 
implementation cost is quite for this purpose to sort n<1000 elements. 
I might be wrong, but I'd prefer the sort method.


OK, this is why I ask.
(I assume with "implementation" cost you mean the additional time needed 
for insertion/balancing, not the time *I* need for the implementation?)
Yes I mean insertion cost, but I also mean weight of the code. You have 
a complex structure to maintain.


The EE uses a tree that sorts by measure on the first level, by moment 
on second and then by the edition-id-path. So there is a tree 
structure, but on each level the child-list for each node is sorted by 
the guile method sort, when it is displayed in order. To access the 
elements it uses a hashtable.
In your case annotations should be at least partially sorted. The 
question is, where/when do you need the sorted list?


When exporting annotations.

So this is a one time sorting task. Or twice, if you have two views.

While typesetting music, you need to insert access the elements by a 
path moment/context or the like.


Yes. When an acknowledged grob has an annotation attached it will be 
prepended to the list or inserted into the tree.
The list will be sorted for one view. I assume `reverse` a quite cheap 
function.


To export a summary the order might be given by a path 
piece/movement/measure/moment/context.


So do I get this right: you're suggestion that I *do* use a tree 
structure, but not a BST but one where the hierarchy matches the musical 
one > This means that assuming my current movement has 1000 measures, and an
average of five annotations per measure I wouldn't have one list of 5000 
annotations but one of 1000 (to sort) and 1000 of five each.
And when I have 1000 measures where only 37 include 1-2 annotations I'd 
have that list of 37 measures with sublists of 1-2 each.?
Yes. The tree-structure is for creating different views and for 
directory lookup. If all annotations are fetched by an engraver it might 
be OK to first collect them in one large list. And if you drop them into 
a tree with the scheme of the desired view you don't need to sort the 
list, but just the tree. If you already know the scheme of the view 
while fetching the annotation events you can of course insert the 
annotations immediatly in the tree. That insertion might be hidden 
behind a method of an insert-collect-object. That way you can 
interchange the implementation without touching the engraver ... and 
perhaps I didn't study the ScholarLY code and that is already the case ;-)



To give a different view on the data I'd build another tree with the 
desired scheme like type/mvmt/measure. If you have the primary tre in 
insertion order you would have to visit some nodes more than twice so 
a copy should be cheaper. (That is not a proof but an assumption!)


You mean: walk over the initial tree and insert each element into a new 
tree with its own hierarchical structure matching the desired output 
hierarchy?

Yes



___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


Re: Binary Search Tree in Scheme

2018-06-18 Thread Urs Liska



Am 18.06.2018 um 10:57 schrieb Jan-Peter Voigt:

Hi Urs,

there are self balancing trees like AVL or Red-Black, but I'd say 
implementation cost is quite for this purpose to sort n<1000 elements. 
I might be wrong, but I'd prefer the sort method.


OK, this is why I ask.
(I assume with "implementation" cost you mean the additional time needed 
for insertion/balancing, not the time *I* need for the implementation?)


The EE uses a tree that sorts by measure on the first level, by moment 
on second and then by the edition-id-path. So there is a tree 
structure, but on each level the child-list for each node is sorted by 
the guile method sort, when it is displayed in order. To access the 
elements it uses a hashtable.
In your case annotations should be at least partially sorted. The 
question is, where/when do you need the sorted list?


When exporting annotations.

While typesetting music, you need to insert access the elements by a 
path moment/context or the like.


Yes. When an acknowledged grob has an annotation attached it will be 
prepended to the list or inserted into the tree.


To export a summary the order might be given by a path 
piece/movement/measure/moment/context.


So do I get this right: you're suggestion that I *do* use a tree 
structure, but not a BST but one where the hierarchy matches the musical 
one?
This means that assuming my current movement has 1000 measures, and an 
average of five annotations per measure I wouldn't have one list of 5000 
annotations but one of 1000 (to sort) and 1000 of five each.
And when I have 1000 measures where only 37 include 1-2 annotations I'd 
have that list of 37 measures with sublists of 1-2 each.?


To give a different view on the data I'd build another tree with the 
desired scheme like type/mvmt/measure. If you have the primary tre in 
insertion order you would have to visit some nodes more than twice so 
a copy should be cheaper. (That is not a proof but an assumption!)


You mean: walk over the initial tree and insert each element into a new 
tree with its own hierarchical structure matching the desired output 
hierarchy?


Thanks
Urs



HTH
Jan-Peter


Am 18.06.2018 um 10:18 schrieb Urs Liska:

Hi all,

as you know I'm currently reviewing the scholarLY package, not only 
for new features but also for its coding - which blatantly shows how 
it was initially done directly from within my learning curve ;-)


One thing I'd like to change is the storage/handling of annotations. 
The current implementation does the following:


  * an engraver creates an annotation (an alist) and appends it to a
    global "annotations" variable (OK, simple improvement: don't append
    but cons to the beginning)
  * in a later stage sort this "annotations" list and export the
    annotations.

This looks very inefficient, and I think it should be much better to 
store the annotations in a binary search tree and have them sorted 
upon insertion already. (Or am I misunderstanding this? One thing I'm 
unaware of is how efficient Guile's "stable-sort" works on a simple 
(linked) list).


On https://gist.github.com/tushar-sharma/c476003598c03373e52c I found 
a clean and simple implementation of a BST which looks like I can 
very easily make if work in LilyPond (I can't test because I'm not at 
my PC at the moment, but I'm talking about the general algorithms 
anyway).


This should let me insert the annotations in sorted order (replacing 
the <, >, and = with appropriate functions to sort annotations 
according to the configured requests), and it's not hard to add a 
function to walk the tree from left to right.


However - and now the question starts - if I'm not mistaken the 
annotations encountered by the engraver will be somewhat (or 
completely?) sorted by musical moment, which will be the requested 
sort order most of the time but not always. And if elements that are 
inserted in that BST are already sorted the tree will be totally 
unbalanced, and the insertion time is as bad (or worse) as simply 
appending to a list.


So if annotations would always be sorted by moment I would probably 
go back to the simple linked list, but they may be sorted differently 
and also by multiple keys (e.g. first by part, then by annotation 
type and only then by moment).


I could make a switch and choose the storage data structure based on 
the requested sorting (moment => list, everything else => BST), or I 
could use a BST that realigns itself after each insertion.


I would be glad about any opinions/recommendations:

  * Is it worth the effort looking into this (often there will be only a
    couple of dozens of annotations per score, but three-digit numbers
    shouldn't be unusual, and I have already encountered scores with
    four-digit numbers of annotations)?
  * Is my idea of a self-balancing BST the right direction?
  * If so, which type of BST would be good to investigate (both in terms
    of performance and implementation complexity)?

Thanks
Urs




Re: Binary Search Tree in Scheme

2018-06-18 Thread Jan-Peter Voigt

Hi Urs,

there are self balancing trees like AVL or Red-Black, but I'd say 
implementation cost is quite for this purpose to sort n<1000 elements. I 
might be wrong, but I'd prefer the sort method.
The EE uses a tree that sorts by measure on the first level, by moment 
on second and then by the edition-id-path. So there is a tree structure, 
but on each level the child-list for each node is sorted by the guile 
method sort, when it is displayed in order. To access the elements it 
uses a hashtable.
In your case annotations should be at least partially sorted. The 
question is, where/when do you need the sorted list? While typesetting 
music, you need to insert access the elements by a path moment/context 
or the like. To export a summary the order might be given by a path 
piece/movement/measure/moment/context.
To give a different view on the data I'd build another tree with the 
desired scheme like type/mvmt/measure. If you have the primary tre in 
insertion order you would have to visit some nodes more than twice so a 
copy should be cheaper. (That is not a proof but an assumption!)


HTH
Jan-Peter


Am 18.06.2018 um 10:18 schrieb Urs Liska:

Hi all,

as you know I'm currently reviewing the scholarLY package, not only for 
new features but also for its coding - which blatantly shows how it was 
initially done directly from within my learning curve ;-)


One thing I'd like to change is the storage/handling of annotations. The 
current implementation does the following:


  * an engraver creates an annotation (an alist) and appends it to a
global "annotations" variable (OK, simple improvement: don't append
but cons to the beginning)
  * in a later stage sort this "annotations" list and export the
annotations.

This looks very inefficient, and I think it should be much better to 
store the annotations in a binary search tree and have them sorted upon 
insertion already. (Or am I misunderstanding this? One thing I'm unaware 
of is how efficient Guile's "stable-sort" works on a simple (linked) list).


On https://gist.github.com/tushar-sharma/c476003598c03373e52c I found a 
clean and simple implementation of a BST which looks like I can very 
easily make if work in LilyPond (I can't test because I'm not at my PC 
at the moment, but I'm talking about the general algorithms anyway).


This should let me insert the annotations in sorted order (replacing the 
<, >, and = with appropriate functions to sort annotations according to 
the configured requests), and it's not hard to add a function to walk 
the tree from left to right.


However - and now the question starts - if I'm not mistaken the 
annotations encountered by the engraver will be somewhat (or 
completely?) sorted by musical moment, which will be the requested sort 
order most of the time but not always. And if elements that are inserted 
in that BST are already sorted the tree will be totally unbalanced, and 
the insertion time is as bad (or worse) as simply appending to a list.


So if annotations would always be sorted by moment I would probably go 
back to the simple linked list, but they may be sorted differently and 
also by multiple keys (e.g. first by part, then by annotation type and 
only then by moment).


I could make a switch and choose the storage data structure based on the 
requested sorting (moment => list, everything else => BST), or I could 
use a BST that realigns itself after each insertion.


I would be glad about any opinions/recommendations:

  * Is it worth the effort looking into this (often there will be only a
couple of dozens of annotations per score, but three-digit numbers
shouldn't be unusual, and I have already encountered scores with
four-digit numbers of annotations)?
  * Is my idea of a self-balancing BST the right direction?
  * If so, which type of BST would be good to investigate (both in terms
of performance and implementation complexity)?

Thanks
Urs



___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user




___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


Re: Advice on naming and structuring scholarLY commands

2018-06-18 Thread Urs Liska

Hi Elaine,

I was off my PC over the weekend, so I'll only now reply to your post.


Am 16.06.2018 um 03:21 schrieb Flaming Hakama by Elaine:


-- Forwarded message -
From: Urs Liska mailto:li...@openlilylib.org>>
Date: Fri, 15 Jun 2018 09:28:05 +0200
Subject: Re: Advice on naming and structuring scholarLY command

Hi Elaine,


Am 15.06.2018 um 02:21 schrieb Flaming Hakama by Elaine:


Actually I think  \edmark and \edMarkup (or something along
these lines) might be the best compromise between the
generality of the command, expressiveness and practicality.

Urs


My $0.02 is that you should spell out \editorialMark.

\edMark is not expressive enough.

We're not in an 8.3 epoch, there is no cost to a few extra
letters to say what you really mean.


OK, good point.
But (also in light of your other post on this thread) it "mark"
really what it is?
I think I'd really be fine with \editorialXXX, but while we're at
it we should really pick the right term, isn't it?

From my (limited) understanding of English a mark is not what
we're encoding here. A mark would be a single item that describes
or that points to something.
What we have *is* a descriptive element, but it is not that our
command inserts an "item that describes something" but our command
itself describes something that is actually included in it. We
encode some music, e.g. { s2 } and describe it as being a "gap"
with the attribute of its reason being damage by ink spill, for
example. Or we can say that in { c8 [ d e f ] } the Beam "is" an
editor's addition.

Would it be correct to say that we "mark up" some music? From
Merriam-Webster's definition this is totally alien
(https://www.merriam-webster.com/dictionary/markup
), but isn't
this exactly the meaning of "markup language"?

If that's correct I think that \editorialMarkup would be fine.

What do you think?

Urs



Thanks for your interest in my opinion on this topic.

I understand your concern with using "Mark" as the basis of the name, 
since while this \editorialMark will often (or always?) include a mark 
that appears on the page, it also contains musical alternatives, so it 
is not merely a type of Mark.


Not *alternatives*, basically an individual segment of music.




It seems that, in order to use \editorialMark, you need to identify a 
segment of music, which is then addressed with annotations and 
alternatives.


So, here is a basic question that I think has import to this 
discussion:  Can the musical segments addressed by \editorialMark be 
nested and/or overlapping?


Technically (as music-functions) they can be nested but not overlapping.
Conceptually it should be possible to have overlapping findings, but I 
don't plan to try supporting this. I think users would have to work 
around with adjacent segments.





If yes, they can be nested and/or overlapping, then each 
\editorialMark could map to a single annotation/comment/remark.  In 
which case, the concept of \editorialMark as describing the specific 
mark makes sense, and the musical segment is simply the entity on 
which the \editorialMark operates.


If this is the case, possibly better names might be \editorialRemark 
or \annotation.


We already have these, in the existing scholarLY annotations 
\criticalRemark, \musicalIssue etc. These "point" to a specific element 
(through a \tweak or \once \override) and "attach" an annotation to 
this. In the sense of "I want to say something about this score 
element", not "this 'is' something".






However, if the musical segments addressed by \editorialMark-s must be 
distinct from one another, then we might have several 
marks/topics/comments in a single musical segment.  In that case, 
maybe the command should be named after the identification of this 
musical segment?


Basically this is what I would like to achieve. I want to encode the 
information that


 * this beam "is" an addition by the editor
 * these four notes "are" illegible
 * this measure "is" a gap because of damage

This would call for a bunch of commands like \editorialAddition, 
\illegible, \gap etc.


However, this would "pollute" the namespace with numerous names, many of 
whom being pretty generic (gap, add, del, corr etc.), which is why I am 
looking for a generic "wrapper" command that is specified by its first 
argument.




Based on some of the earlier posts, it seems like one of the outcomes 
of this command is to attach unique IDs to the start and end of this 
musical segment.  If this is true, then maybe the command should be 
named with regard to the fact that its main job is to identify and tag 
this musical segment, to which the editorial remarks and the 
alternatives will apply.


If that is the case, maybe the command should be named something like 

Binary Search Tree in Scheme

2018-06-18 Thread Urs Liska

Hi all,

as you know I'm currently reviewing the scholarLY package, not only for 
new features but also for its coding - which blatantly shows how it was 
initially done directly from within my learning curve ;-)


One thing I'd like to change is the storage/handling of annotations. The 
current implementation does the following:


 * an engraver creates an annotation (an alist) and appends it to a
   global "annotations" variable (OK, simple improvement: don't append
   but cons to the beginning)
 * in a later stage sort this "annotations" list and export the
   annotations.

This looks very inefficient, and I think it should be much better to 
store the annotations in a binary search tree and have them sorted upon 
insertion already. (Or am I misunderstanding this? One thing I'm unaware 
of is how efficient Guile's "stable-sort" works on a simple (linked) list).


On https://gist.github.com/tushar-sharma/c476003598c03373e52c I found a 
clean and simple implementation of a BST which looks like I can very 
easily make if work in LilyPond (I can't test because I'm not at my PC 
at the moment, but I'm talking about the general algorithms anyway).


This should let me insert the annotations in sorted order (replacing the 
<, >, and = with appropriate functions to sort annotations according to 
the configured requests), and it's not hard to add a function to walk 
the tree from left to right.


However - and now the question starts - if I'm not mistaken the 
annotations encountered by the engraver will be somewhat (or 
completely?) sorted by musical moment, which will be the requested sort 
order most of the time but not always. And if elements that are inserted 
in that BST are already sorted the tree will be totally unbalanced, and 
the insertion time is as bad (or worse) as simply appending to a list.


So if annotations would always be sorted by moment I would probably go 
back to the simple linked list, but they may be sorted differently and 
also by multiple keys (e.g. first by part, then by annotation type and 
only then by moment).


I could make a switch and choose the storage data structure based on the 
requested sorting (moment => list, everything else => BST), or I could 
use a BST that realigns itself after each insertion.


I would be glad about any opinions/recommendations:

 * Is it worth the effort looking into this (often there will be only a
   couple of dozens of annotations per score, but three-digit numbers
   shouldn't be unusual, and I have already encountered scores with
   four-digit numbers of annotations)?
 * Is my idea of a self-balancing BST the right direction?
 * If so, which type of BST would be good to investigate (both in terms
   of performance and implementation complexity)?

Thanks
Urs

___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


Binary Search Tree in Scheme

2018-06-18 Thread Urs Liska

Hi all,

as you know I'm currently reviewing the scholarLY package, not only for 
new features but also for its coding - which blatantly shows how it was 
initially done directly from within my learning curve ;-)


One thing I'd like to change is the storage/handling of annotations. The 
current implementation does the following:


 * an engraver creates an annotation (an alist) and appends it to a
   global "annotations" variable (OK, simple improvement: don't append
   but cons to the beginning)
 * in a later stage sort this "annotations" list and export the
   annotations.

This looks very inefficient, and I think it should be much better to 
store the annotations in a binary search tree and have them sorted upon 
insertion already. (Or am I misunderstanding this? One thing I'm unaware 
of is how efficient Guile's "stable-sort" works on a simple (linked) list).


On https://gist.github.com/tushar-sharma/c476003598c03373e52c I found a 
clean and simple implementation of a BST which looks like I can very 
easily make if work in LilyPond (I can't test because I'm not at my PC 
at the moment, but I'm talking about the general algorithms anyway).


This should let me insert the annotations in sorted order (replacing the 
<, >, and = with appropriate functions to sort annotations according to 
the configured requests), and it's not hard to add a function to walk 
the tree from left to right.


However - and now the question starts - if I'm not mistaken the 
annotations encountered by the engraver will be somewhat (or 
completely?) sorted by musical moment, which will be the requested sort 
order most of the time but not always. And if elements that are inserted 
in that BST are already sorted the tree will be totally unbalanced, and 
the insertion time is as bad (or worse) as simply appending to a list.


So if annotations would always be sorted by moment I would probably go 
back to the simple linked list, but they may be sorted differently and 
also by multiple keys (e.g. first by part, then by annotation type and 
only then by moment).


I could make a switch and choose the storage data structure based on the 
requested sorting (moment => list, everything else => BST), or I could 
use a BST that realigns itself after each insertion.


I would be glad about any opinions/recommendations:

 * Is it worth the effort looking into this (often there will be only a
   couple of dozens of annotations per score, but three-digit numbers
   shouldn't be unusual, and I have already encountered scores with
   four-digit numbers of annotations)?
 * Is my idea of a self-balancing BST the right direction?
 * If so, which type of BST would be good to investigate (both in terms
   of performance and implementation complexity)?

Thanks
Urs

___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user