Naming commas and other intervals: a compilation of various sources

User avatar
cmloegcmluin
Site Admin
Posts: 1246
Joined: Tue Feb 11, 2020 3:10 pm
Location: San Francisco, California, USA
Real Name: Douglas Blumeyer
Contact:

Re: Naming commas and other intervals: a compilation of various sources

Post by cmloegcmluin »

Dave Keenan wrote: Sat Jan 02, 2021 11:15 pm
cmloegcmluin wrote: Sat Jan 02, 2021 4:14 am Then what is the reason [for considering log-product complexity rather than product complexity]? Sorry to make you spell it out.
Only the perhaps-too-obvious fact that, in enumerating the commas with the same prime content above 3, between [0⟩ and the comma being named, no matter which order you do it, you are presumably incrementing or decrementing exponents of 2 and 3, and computing cents by taking the dot product of the monzo with 1200×⟨lb(2) lb(3) lb(5) ... ], not multiplying or dividing by factors of 2 and 3. i.e. you will be working entirely in the log domain.
I just borrowed down into the part of the code which compares a candidate comma's size against the size category bounds to make sure it's inside, and it actually doesn't take the log. It's comparing, in each case, a rational monzo (comma candidate) against a sqrt of a rational monzo (size category bound) and it just computes what those numbers are, then checks <=>. Taking the log seems like an unnecessary step to me. Maybe it's more performant. All I can remember was that I was grappling for the longest time getting default precision levels just right everywhere across everything so things worked out reasonably across all these parts of the code, where things which certainly should be considered equal but actually aren't insanely close are, while some other things which certainly should not be considered equal in other contexts but actually are much more insanely close together than the other things are too. And where it landed, it landed.
It's really not very important, since you don't need to actually calculate any complexity measure.
Aye yaye yaye... I'm probably just being obtuse here, but it feels like you're being playfully cryptic sometimes, and I'm not always in the mood to play. Need some more coffee in my system maybe. Why don't I need to actually calculate any complexity measure? Do you mean because of your proposal below to tie-break via a binary exponent assignment scheme? I mean, we're still naming commas by complexity levels, right? And as we discussed earlier in this thread, the main thing we're doing here — (in/de)crementing across powers of 3 and 2 within a 2,3-free class "x" and counting commas in a size category zone between a comma and [0 0 {x}⟩, counting occurrences to assign a complexity tier, qualifies as a complexity metric in terms of the other types of metrics we've discussed recently (phew, almost just said "this year"... first 2021 catch of the year for me!)

It's also log5(7).

I wanted 5n ≈ 7m. Take the base-2 log of both sides.
lb(5)×n ≈ lb(7)×m therefore
n/m ≈ lb(7)/lb(5)
Nice trick! Man, it feels less like a trick, and more like something I should just be able to do naturally;-)... and I probably could at one point, when I first learning logarithms in grade school. A bit disappointed in myself there, so I'll review that one until it sticks. It seems like the kind of bit of information I'm going to want to find again and again. The log5(7) form actually clicks best for me. Thanks for unpacking that.
I love this idea. Yes! Instead of agonizing over some arbitrary tie-breaker regarding their complexity, we flip back to the other aspect they exhibit — size — and implicitly recognize that while the size category bounds established work quite well for commas of musical significance, they fail us at higher levels of complexity, and therefore it's occasionally necessary within a size category to have a greater and lesser for the otherwise same named comma. Brilliant brilliant brilliant.
Not so fast.
<cartoon-villain>Blast!</cartoon-villain>

(yes the caffeine has kicked in now... in a better mood)
I just realised it's possible for there to be more than 2. Repeat what I did with powers of 5 and 7 using powers of 11 and 13. So we have a small 2,3-comma, a small 5,7-comma (no 2's or 3's) and a small 11,13-comma (no 2's, 3's, 5's or 7's). Then we can add and subtract them in various ways to make 4 commas with the same complexity in the same size category. Then we can do the same again with powers of 17 and 19 and get 8 commas, and so on.

Sorry for the bad news. We can either fall back on:  not musically relevant.

Or we come up with some way of sorting them based on the signs of all the primes. e.g. Treat the signs as a binary number where a minus is a 1 and a plus is a 0, and the sign of the 2-exponent is the least significant bit.
I think this is a good solution. So you take all the tied commas and get them into their super form. Then work your way from the highest prime down, and the first one you hit a negative sign for is the most complex, the second one you hit a negative sign for is the next most complex, and so on.
We had to be clever, to do a lot with so little.
I've seen videos about the corners video game developers and composers would cut to squeeze their work into the extremely limited space available. To be battling through such constraints while still innovating design on such a young artform absolutely blows my mind.
Now, the world needs so many programmers we can't require them to all have IQs of 125 or more, because that's only 5% of the population (although you probably do).
I do, yeah (and little doubt that you do too). But it's way more important to keep a growth mindset, I think. Focus on the things you can learn and accomplish, not rest on intelligence stats. I'm grateful that my upbringing and education imparted that really helpful bit of insight. I've seen bad stuff happen to really bright folks who didn't pick up on that one simple guiding thought.
And we have computing power to squander. About a million times the computing power on our desks now, compared to what I had back then. So who cares if the searching of a list of 3000 words is so inefficient it is doing a thousand times more operations than it really needs to. An efficiency of 0.1%. It causes me pain to think of it. But it's far more important that the programmer can write it quickly and test it easily and still understand how it works a few weeks later.
So the onus nowadays is on the programming language creator who can create a language which humans can read naturally but which manages to compile down performantly.

User avatar
Dave Keenan
Site Admin
Posts: 1574
Joined: Tue Sep 01, 2015 2:59 pm
Location: Brisbane, Queensland, Australia
Contact:

Re: Naming commas and other intervals: a compilation of various sources

Post by Dave Keenan »

cmloegcmluin wrote: Sun Jan 03, 2021 2:36 am I just borrowed down into the part of the code which compares a candidate comma's size against the size category bounds to make sure it's inside, and it actually doesn't take the log. It's comparing, in each case, a rational monzo (comma candidate) against a sqrt of a rational monzo (size category bound) and it just computes what those numbers are, then checks <=>. Taking the log seems like an unnecessary step to me. Maybe it's more performant. All I can remember was that I was grappling for the longest time getting default precision levels just right everywhere across everything so things worked out reasonably across all these parts of the code, where things which certainly should be considered equal but actually aren't insanely close are, while some other things which certainly should not be considered equal in other contexts but actually are much more insanely close together than the other things are too. And where it landed, it landed.
I'm almost sorry I said anything about this. It seems to be another case of programmer generation difference. I assumed you'd do what to me seems the obvious efficient thing. But it doesn't matter if you didn't, so long as it works in a reasonable time, by human standards, and of course, so long as it works correctly. But I'm a little worried about the latter, when it comes to the double-float representation used in JavaScript. We know it can't represent consecutive integers beyond 2^53, although it can represent them approximately up to 2^1024.

You say "taking the log seems like an unnecessary step", and it certainly would be. But you don't need to take any logs. When you have monzos, you're already in log space. I understand from what you wrote above, that you're exponentiating and multiplying, to go back to linear (frequency ratio) space, to compare the size of the comma against the category boundary. Is that correct?

If so, then I say it is you who is doing unnecessary exponentiation, not me who would do unnecessary logs. What I would do (and was assuming you were doing) involves only multiplication by constants and summing (a dot-product of a monzo with a constant mapping), and doesn't risk overflowing the number representation.

I assume you have a function that takes a monzo and gives cents. All you need to do in there is multiply each monzo term by the correct constant, and sum all those products. The correct constant multiplier for the prime-p term is lb(p)*1200, but you don't code it in such a way that it is computing those lb(p) at runtime (perhaps those are the unnecessary logs you thought I was proposing). They should be computed at compile time. But maybe that's not even possible with Javascript. Maybe you have to compute them outside the source code and put them into the source code as number literals with 17 significant digits. If so, that's what I'd do.
Aye yaye yaye... I'm probably just being obtuse here, but it feels like you're being playfully cryptic sometimes, and I'm not always in the mood to play. Need some more coffee in my system maybe. Why don't I need to actually calculate any complexity measure? Do you mean because of your proposal below to tie-break via a binary exponent assignment scheme? I mean, we're still naming commas by complexity levels, right? And as we discussed earlier in this thread, the main thing we're doing here — (in/de)crementing across powers of 3 and 2 within a 2,3-free class "x" and counting commas in a size category zone between a comma and [0 0 {x}⟩, counting occurrences to assign a complexity tier, qualifies as a complexity metric in terms of the other types of metrics we've discussed recently (phew, almost just said "this year"... first 2021 catch of the year for me!)
Honestly, not trying to be cryptic. But apparently I'm making unwarranted assumptions about how you've implemented this enumeration of commas. Or unwarranted assumptions about how you view it. If you have an algorithm that provably generates successive commas in order of their complexity, then why do you ever need to calculate a number for that complexity?

If you happen to do so, because you're reusing a function where you calculate a complexity number for other reasons, that's fine. And if so, why would you calculate product complexity (as opposed to log product complexity)? This has the same issue of unnecessary exponentiation, and with the commas we're talking about here, we're getting close to overflowing double-floats on product complexity. I'd stick to log product complexity, at least internally. Only convert it to product complexity (rounding to the nearest integer) if the human asks.

But hey. Don't let me tell you how to do your job.
Or we come up with some way of sorting them based on the signs of all the primes. e.g. Treat the signs as a binary number where a minus is a 1 and a plus is a 0, and the sign of the 2-exponent is the least significant bit.
I think this is a good solution. So you take all the tied commas and get them into their super form.
Agreed so far.
Then work your way from the highest prime down, and the first one you hit a negative sign for is the most complex, the second one you hit a negative sign for is the next most complex, and so on.
No. You have to effectively make a monzo of the signs for each comma, i.e. with only zeros and ones in it. Then calculate
2^0 × 2's_sign + 2^1 × 3's_sign + 2^2 × 5's_sign + 2^3 × 7's-sign ... and compare these "sign-pattern numbers" to arbitrarily sort these commas into a complexity order (when they really have the same product complexity).
So the onus nowadays is on the programming language creator who can create a language which humans can read naturally but which manages to compile down performantly.
I'm not too sure about this word "performantly". But no, it doesn't need to run efficiently at all.

User avatar
cmloegcmluin
Site Admin
Posts: 1246
Joined: Tue Feb 11, 2020 3:10 pm
Location: San Francisco, California, USA
Real Name: Douglas Blumeyer
Contact:

Re: Naming commas and other intervals: a compilation of various sources

Post by cmloegcmluin »

Dave Keenan wrote: Sun Jan 03, 2021 8:16 am I assume you have a function that takes a monzo and gives cents. All you need to do in there is multiply each monzo term by the correct constant, and sum all those products. The correct constant multiplier for the prime-p term is lb(p)*1200, but you don't code it in such a way that it is computing those lb(p) at runtime (perhaps those are the unnecessary logs you thought I was proposing). They should be computed at compile time. But maybe that's not even possible with Javascript. Maybe you have to compute them outside the source code and put them into the source code as number literals with 17 significant digits. If so, that's what I'd do.
Oh... I did have it that way at one point, actually! Up to a certain prime limit anyway. Unfortunately it was too long ago for me to remember why it ceased sufficing. I think it was when we were looking for ways to speed up computations so the LFC for finding our unpopularity metric could run in days instead of weeks.
Honestly, not trying to be cryptic. But apparently I'm making unwarranted assumptions about how you've implemented this enumeration of commas. Or unwarranted assumptions about how you view it. If you have an algorithm that provably generates successive commas in order of their complexity, then why do you ever need to calculate a number for that complexity?
Well, I haven't implemented a tie-breaker yet, but I was thinking that if I used some sort of complexity measure as a tie-breaker, then I'd have to get a couple numbers that were complexity results for two commas and then compare those two result numbers.

Like, I just don't know how to reconcile your statement "you don't need to calculate a complexity measure" with the fact that below you're continuing to try to explain exactly how I should calculate a particular complexity measure slash tie-breaker measure. I mean I need to calculate something, right? Anyway...

Certainly there's a bit of miscommunication going on here, and maybe this is the kind of thing that wouldn't happen over a video call, but it appears we both have sufficient grasp of the ultimate goal, and this particularly point is a couple layers of meta-meta-discussion, maybe we just move on.
Or we come up with some way of sorting them based on the signs of all the primes. e.g. Treat the signs as a binary number where a minus is a 1 and a plus is a 0, and the sign of the 2-exponent is the least significant bit.
I think this is a good solution. So you take all the tied commas and get them into their super form.
Agreed so far.
Then work your way from the highest prime down, and the first one you hit a negative sign for is the most complex, the second one you hit a negative sign for is the next most complex, and so on.
No. You have to effectively make a monzo of the signs for each comma, i.e. with only zeros and ones in it. Then calculate
2^0 × 2's_sign + 2^1 × 3's_sign + 2^2 × 5's_sign + 2^3 × 7's-sign ... and compare these "sign-pattern numbers" to arbitrarily sort these commas into a complexity order (when they really have the same product complexity).
Oh okay, I see. ...I think,

So maybe we should just do some examples?

You're saying

[84 -53 52 -43⟩ → 0101 → 0 + 2 + 0 + 8 = 10
[-84 53 52 -43⟩ → 1001 → 1 + 0 + 0 + 8 = 9

therefore, [-84 53 52 -43⟩ is the 552/743C and [84 -53 52 -43⟩ is the c552/743C.

And

[-19 12 133 -110⟩ → 1001 → 1 + 0 + 0 + 8 = 9
[-19 12 -133 110⟩ → 1010 → 1 +0 + 4 + 0 = 5

So [19 -12 133 -110⟩ is the 5133/7110C and [-19 12 133 -110⟩ is the c5133/7110C. (The former I kept super while computing its complexity but then flipped to be sub to minimize the difference between their names).

I believe the interpretation of this process I gave would be equivalent, because the way binary numbers work (or decimal, or hexadecimal, for that matter) is that even if you max out the digits in all the less significant positions, you still can't exceed a unit in the next position. In other words, if I was deciding which between [84 -53 52 -43⟩ and [-84 53 52 -43⟩ was more complex, if I was working my way down from the most significant digit, the first position where I didn't get a tie would tell me my answer, i.e. there's no need for me to check whether those 84's are positive or negative, because we would have already seen in the difference of the signs of the 53's that we had our answer.

I see now that the way I explained my process in my previous post was not particularly rigorous, but this is what I meant by what I said.

Maybe I still haven't understood your intentions correctly though.
So the onus nowadays is on the programming language creator who can create a language which humans can read naturally but which manages to compile down performantly.
I'm not too sure about this word "performantly". But no, it doesn't need to run efficiently at all.
That is what I meant, yes. That's a commonplace usage of "performant" in my intersection of geographic region and industry.

But I do see that your point was that even after compiling, it doesn't have to be performant. Got it. I mean, sometimes it does still have to. But maybe you'd argue that anyone who still needs to have their code run fast just knows how to write it to run fast themselves. That may be the case.

User avatar
Dave Keenan
Site Admin
Posts: 1574
Joined: Tue Sep 01, 2015 2:59 pm
Location: Brisbane, Queensland, Australia
Contact:

Re: Naming commas and other intervals: a compilation of various sources

Post by Dave Keenan »

cmloegcmluin wrote: Sun Jan 03, 2021 8:59 amOh... I did have it that way at one point, actually! Up to a certain prime limit anyway. Unfortunately it was too long ago for me to remember why it ceased sufficing. I think it was when we were looking for ways to speed up computations so the LFC for finding our unpopularity metric could run in days instead of weeks.
I'm guessing you had it recomputing the log of every prime every time you called it.
Well, I haven't implemented a tie-breaker yet, but I was thinking that if I used some sort of complexity measure as a tie-breaker, then I'd have to get a couple numbers that were complexity results for two commas and then compare those two result numbers.

Like, I just don't know how to reconcile your statement "you don't need to calculate a complexity measure" with the fact that below you're continuing to try to explain exactly how I should calculate a particular complexity measure slash tie-breaker measure. I mean I need to calculate something, right? Anyway...

Certainly there's a bit of miscommunication going on here, and maybe this is the kind of thing that wouldn't happen over a video call, but it appears we both have sufficient grasp of the ultimate goal, and this particularly point is a couple layers of meta-meta-discussion, maybe we just move on.
Yes, miscommunication. Yes, we should just move on. But I can't help defending myself as follows:

Don't cross the streams. (Ghostbusters reference). The sub-thread regarding those statements of mine that you found contentious (preferring to think in terms of log product complexity rather than product complexity, and it not really mattering because you don't need to calculate either of them), were made at a time when we thought we could get away without a tie-breaker, or at least when the tie-breaker was not itself any kind of complexity measure.

But in a parallel sub-thread, we've worked up to a new tie-breaker (the sign vector interpreted as a binary integer) that you see as a kind of complexity. It's not valid to criticise my earlier statements on the basis that they are incorrect when applied in this new realm. Hence my "Don't cross the streams". :)

But, even if that was a valid form of argument, I note that I do not consider this new tie-breaker, which I have called the "sign-pattern number", to be a complexity measure in itself, since it's completely arbitrary whether we code negatives as 1 and positives as 0, or vice versa. And it's arbitrary whether we read it as an integer (higher primes have higher-weighted signs) or as a binary fraction (higher primes have lower-weighted signs). So, in so far as my earlier statements only related to the question of whether we needed to calculate the product complexity or log product complexity of the commas in order to enumerate them, I think my statement still stands.
No. You have to effectively make a monzo of the signs for each comma, i.e. with only zeros and ones in it. Then calculate
2^0 × 2's_sign + 2^1 × 3's_sign + 2^2 × 5's_sign + 2^3 × 7's-sign ... and compare these "sign-pattern numbers" to arbitrarily sort these commas into a complexity order (when they really have the same product complexity).
Oh okay, I see. ...I think,

So maybe we should just do some examples?

You're saying

[84 -53 52 -43⟩ → 0101 → 0 + 2 + 0 + 8 = 10
[-84 53 52 -43⟩ → 1001 → 1 + 0 + 0 + 8 = 9

therefore, [-84 53 52 -43⟩ is the 552/743C and [84 -53 52 -43⟩ is the c552/743C.

And

[-19 12 133 -110⟩ → 1001 → 1 + 0 + 0 + 8 = 9
[-19 12 -133 110⟩ → 1010 → 1 +0 + 4 + 0 = 5

So [19 -12 133 -110⟩ is the 5133/7110C and [-19 12 133 -110⟩ is the c5133/7110C. (The former I kept super while computing its complexity but then flipped to be sub to minimize the difference between their names).
Agreed.
I believe the interpretation of this process I gave would be equivalent, because the way binary numbers work (or decimal, or hexadecimal, for that matter) is that even if you max out the digits in all the less significant positions, you still can't exceed a unit in the next position.
Sure. But what you wrote was:
Then work your way from the highest prime down, and the first one you hit a negative sign for is the most complex, the second one you hit a negative sign for is the next most complex, and so on.
Looking at your first example.
[84 -53 52 -43⟩ → 0101 → 0 + 2 + 0 + 8 = 10
[-84 53 52 -43⟩ → 1001 → 1 + 0 + 0 + 8 = 9

You hit a negative sign at the same time in both of them. So clearly that's not enough to rank them. In the most general case, you have to look at all the bits. Simpler to just calculate the integer and compare those.
In other words, if I was deciding which between [84 -53 52 -43⟩ and [-84 53 52 -43⟩ was more complex, if I was working my way down from the most significant digit, the first position where I didn't get a tie would tell me my answer, i.e. there's no need for me to check whether those 84's are positive or negative, because we would have already seen in the difference of the signs of the 53's that we had our answer.
That's not equivalent to what you wrote above. And yes, that would work fine if you were only comparing two of them. But I showed that you can have more than 2.
I see now that the way I explained my process in my previous post was not particularly rigorous, but this is what I meant by what I said.
Cool.
Maybe I still haven't understood your intentions correctly though.
You seem to have understood my suggestion perfectly, based on your examples.
I'm not too sure about this word "performantly". But no, it doesn't need to run efficiently at all.
That is what I meant, yes. That's a commonplace usage of "performant" in my intersection of geographic region and industry.
I see definitions that include the idea of "performant" meaning "good enough", e.g. so humans don't notice a lag. In 1980 the fastest possible program might have run 2 times faster than the one that was just good enough. Now, the fastest possible program might run 2 thousand (or 2 million) times faster than the one that is just good enough (and the fastest one won't be written in Javascript and it won't be doing integer math using floating-point numbers).

User avatar
cmloegcmluin
Site Admin
Posts: 1246
Joined: Tue Feb 11, 2020 3:10 pm
Location: San Francisco, California, USA
Real Name: Douglas Blumeyer
Contact:

Re: Naming commas and other intervals: a compilation of various sources

Post by cmloegcmluin »

Dave Keenan wrote: Sun Jan 03, 2021 1:43 pm I'm guessing you had it recomputing the log of every prime every time you called it.
No, they were hardcoded. Not even computed up front, just checked in as source code.
That's not equivalent to what you wrote above.
Agreed. I did a bad job of confirming my understanding the first time around. I should have taken the time to articulate it in an accurate, unambiguous, and complete way. I think I'm just trying and failing to do too many things at once, as I often do.

Post Reply