Let’s define the **absolute ratio** for positive numbers:

When x is smaller than 1 return 1 / x, otherwise return x. Here are a few example values:

x | abs_ratio(x) |
---|---|

0.5 | 2 |

2 | 2 |

0.2 | 5 |

5 | 5 |

And a graph:

Another spelling for the same operator would take 2 positive numbers and give their absolute ratio:

And a graph:

## Use case examples

- Music and audio – an octave of a frequency F is 2F. More generally a harmony of a frequency F is N*F where N is a natural number. To decide if one frequency is a harmony of another we just need to get their absolute ratio and see if it’s whole. E.g. if abs_ratio(F1, F2) == 2 they’re octaves. If abs_ratio(F1, F2) is whole – they’re harmonies.
- Computer vision – to match shapes that have similar dimensions e.g. their width is only 10% larger or smaller. We don’t care which is the bigger or smaller, we just want to know if 0.91 < W1 / W2 < 1.1 which may be easier to pronounce as abs_ratio(W1, W2) < 1.1
- Real life – when we see 2 comparable objects we’re more likely to say one is “three times the other” vs “one third the other”. Either way in our brains both statements mean the same concept. We think in absolute ratios.
- General case – When you want to know if X is K times bigger than Y or vice versa and you don’t care which is the bigger one.

## Interesting Properties

- abs_ratio(Y / X) == abs_ratio(X / Y)
- log(abs_ratio(X)) = abs(log(X))
- log(abs_ratio(Y / X)) = abs(log(Y / X)) = abs(log(Y) – log(X))
- You can see from the above that absolute ratio is somewhat of an absolute value for log-space.

## What’s next for absolute ratio

- I’d love to hear more use cases and relevant contexts.
- What would be the written symbol or notation?
- How can we get this operator famous enough to be of use to mainstream minds?
- About negative numbers and zero – right now that’s undefined as I don’t see a use case for that domain.
- For some code and graphs in python checkout https://github.com/ubershmekel/abs_ratio

EDIT – I’m growing to like the binary form of the operator more so from now on let’s call it like this in python:

def abs_ratio(a, b): return a / b if a > b else b / a

Consider a “fingerprint” made of a binary list of features. Bit 0 is 1 iff feature 0 is present in the object of interest. If the objects are too hard to compare directly, then it’s sometimes reasonable to use fingerprint comparisons as a proxy for the comparison. One such comparison is the Tanimoto simarity, which is the number of bits in the bitwise intersection divided by the number of bits in the bitwise union. (If the fingerprints are 011 and 101 then the intersection is 001 and the union is 111 so the Tanimoto is 1/3.)

Suppose you have a object whose fingerprint has N bits set, and you want to search for all other objects whose fingerprints have at least 0.90 Tanimoto similarity to the original fingerprint. Then simple math shows that the other fingerprints must have between N*0.9 and N/0.9 bits.

Written your way, abs_ratio(N, search_N) <= 1/0.9 . This shows some difficulties with the notation: It uses a value greater than 1.0 when the problem domain uses numbers between 0.0 and 1.0, and the broken out form: N*0.9 <= search_N <= N/0.9 is easily understood while a special notation is not.

Interesting example, thanks for that. I don’t understand what happens when zero is compared to zero in Tanimoto Similarity, also, zero compared to anything else is of distance zero.

The presented definition for absolute ratio doesn’t work well with zero as it wouldn’t work with the property: abs_ratio(Y, X) == abs_ratio(X, Y), should abs_ratio(0, X) be inf, 0 or NaN?

So I don’t think abs_ratio plays with Tanimoto Similarity at all.

Tanimoto(0, 0) is undefined. Most software either defines it arbitrarily as 0.0 or 1.0, depending on the context. I once described it in allusion to Poe, Tanimoto(“raven”, “writing desk”) is undefined.

The abs_ratio() doesn’t come in computing the Tanimoto. It comes during the search. Suppose the query fingerprint has N bits set, and I’m searching for a set of target fingerprints to find those with a similarity of at least 0.9.

I can sometimes reject targets just by knowing the number of bits it has in the fingerprint. A target has M bits set in it, so if M<=N then the maximum possible Tanimoto is M/N. This is because the Tanimoto is the intersection/union, and since M=N then the maximum possible Tanimoto is N/M, using the same logic.

It takes time to compute the number of bits in the intersection of two fingerprints. Excluding obvious rejects (precomputing the value of M for each fingerprint) means much faster performance.

So the abs_ratio(N, M)>1/0.9 comes in the calculation of which fingerprints can be excluded from doing a Tanimoto calculation, and not in doing the Tanimoto calculation itself.

The comment system ate some of my text. Perhaps because of the less than/greater than signs?

Starting from “This is because the Tanimoto is the intersection/union,…”

This is because the Tanimoto is the intersection/union. The maximum intersection of a fingerprint with M bits and a fingerprint with N bits is min(N, M), so M for this case. The number of bits in the union must range between N and N+M so to maximize intersection/union is to maximize M/union, is to minimize union, which gives M. Hence, when M .le. N then the maximum possible Tanimoto is M/N.

Now consider when M .ge. N. In that case, the intersection is at most N and the ratio is maximized when N+M is minimized, which means selecting M, so the maximum possible Tanimoto is N/M, using the same logic.

Hi there! Someone in my Facebook group shared this site with us

so I came to check it out. I’m definitely enjoying the information. I’m bookmarking and will be tweeting this to my followers!

Terrific blog and wonderful design.