-module(tastoids). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -define(FILEPATH, "src/tastoids.gleam"). -export([blend/2, retract/1, less/2, both/2, bland/2, squash/1, smashing/2, equal/2, length/1, distance/1]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. ?MODULEDOC( " Tastoids (& their 'Temperate' Algebra)\n" "\n" " It is often said, one can't compare \"apples\" to \"oranges\",\n" " but I daresay.. _perhaps you can?_\n" "\n" " **Let me show you how.**\n" "\n" " On their own, it is hard to figure how one might compare\n" " apples to oranges, let alone deign to approach a calculus\n" " of taste however, with _just enough_ structure, a **Taste**\n" " can become a **Tastoid**, along with a curious and powerful\n" " _Temperate_ Algebra.\n" "\n" " > Not unlike a [_Tropical_ geometry](https://en.wikipedia.org/wiki/Tropical_geometry),\n" " > where the notion of addition and multiplication are replaced by min(a,b) & add(a,b),\n" " > I pose that a _Temperate Algebra_ is one whose typical notions of (+,ร—) are replaced\n" " > with operations that effectively 'average' taste (with commutativity, distributivity\n" " > and reversibility, no less!)\n" "\n" " ### A Taste (t) Field\n" " \n" " \"Tastes\", broadly, are any measurable/comparable sentiment about a thing.\n" " Something with a unique direction and magnitude. _A vector!_\n" " \n" " Consider if you will, then:\n" "\n" " - The set of all Vectors are a field โ„โฟ (aka ๐•).\n" " - You may partition ๐• by some enumerable set of indices (as โ…ˆ <= countable โˆž))\n" " - The '[Algebraic extension](https://en.wikipedia.org/wiki/Algebraic_extension)'\n" " of ๐•/โ…ˆ, is itself a field (with Algebra)\n" "\n" " > In the context of large-language- and embedding-models, this idea of\n" " > mapping _things_ (text or otherwise) into a well-defined set of possible\n" " > indices and probabilities is referred to as an '_embedding_'.\n" "\n" " ### A Taste -> One Tastoid\n" "\n" " We're almost there, I promise. Lets talk about plain numbers for a bit; say\n" " I told you knew the average of some set of values was `42`. You also know\n" " for a fact there was a 13 in there once, somewhere.\n" "\n" " Knowing nothing else, how would you _un_-average 13 from 42?\n" "\n" " _Were there two values that averaged to 42? Three? More?_\n" "\n" " Without the _cardinality_ of the original sampling, its (absolutely) impossible to know.\n" " But with it... say n=13, in which case, we can merely remove 1/13th of 13 (i.e. 1)\n" " from our combined average to find out the average without that 13 was just 41.\n" "\n" " Similarly, on their own Taste vectors _are_ comparable, even averagable in some sense,\n" " but without a cardinality, their operations aren't quite _lined up_ to have solutions\n" " to previously impossible questions become possible and yield seemingly 'free' results.\n" "\n" " Attempting to put some formalism to the above,\n" " \n" " - We can partition a taste-field further, by its cardinality k โˆˆ ๐•‚ (๐•‚ ~ โ„ x โ„โ‚„ ~ โ„‚)\n" " (As well as a 4-cycle of like -> dislike -> unlike -> undislike)\n" " \n" " i.e. someone (or thing) expressing { like ( 1+i ) -> dislike (-1 + i)\n" " ๐•’ taste (valued at weight w), k times -> un-like (-1 + -i) -> un-dislike (1 + -i) } \n" " A Tastoid, can be arrived at by a person/subject, expressing a taste _once_ (tแตข, k=1), \n" " imbedding (sic) that individuals' sentiment in a univesal/possibly infinite set of all\n" " the tastoid's that subject could express ๐•ฅแตคโ†ชแตข โˆˆ ๐•‹แตค\n" "\n" " Then, we may define a handful a tiny, tidy, yet supremely powerful (ฯƒ/sigma-)\n" " _Algebra_ of Taste_\n" "\n" " - [ ] Brief introduction to operators\n" ). -file("src/tastoids.gleam", 98). ?DOC( " Blend (**โฉ**) two tastoids, producing a larger tastoid _congruent_ to\n" " the weighted power mean, aka their average 'taste' (via `squash`).\n" "\n" " See also `retract` - which yields u' which _unblends_ when blended,\n" ). -spec blend(tastoids@tastoid:tastoid(EGQ), tastoids@tastoid:tastoid(EGQ)) -> tastoids@tastoid:tastoid(EGQ). blend(T, U) -> case {T, U} of {tasteless, _} -> U; {_, tasteless} -> T; {{tastoid, T@1, K_t}, {tastoid, U@1, K_u}} -> _pipe = tastoids@taste:add(T@1, U@1), {tastoid, _pipe, gleam@int:add(K_t, K_u)} end. -file("src/tastoids.gleam", 107). ?DOC(" Return the inverse of a taste (over `blend`)\n"). -spec retract(tastoids@tastoid:tastoid(EGU)) -> tastoids@tastoid:tastoid(EGU). retract(Taste) -> case Taste of {tastoid, T, K} -> _pipe = tastoids@taste:negate(T), {tastoid, _pipe, gleam@int:negate(K)}; tasteless -> tasteless end. -file("src/tastoids.gleam", 118). ?DOC( " Unblend a Tastoid (the _divisor_), removing it `from`\n" " another (the _numerator_).\n" "\n" " nb. This works even if the `divisor` tastoid isn't in the `from` Tastoid.\n" ). -spec less(tastoids@tastoid:tastoid(EGX), tastoids@tastoid:tastoid(EGX)) -> tastoids@tastoid:tastoid(EGX). less(Divisor, Numerator) -> _pipe = Divisor, _pipe@1 = retract(_pipe), blend(_pipe@1, Numerator). -file("src/tastoids.gleam", 128). ?DOC( " Return the 'and'-product (**โฉ**), multiplying tastes/cardinalities\n" " between _left_ and _right_; effectively erasing unshared tastes.\n" ). -spec both(tastoids@tastoid:tastoid(EHB), tastoids@tastoid:tastoid(EHB)) -> tastoids@tastoid:tastoid(EHB). both(Left, Right) -> case {Left, Right} of {tasteless, _} -> tasteless; {_, tasteless} -> tasteless; {{tastoid, T1, K1}, {tastoid, T2, K2}} -> T = tastoids@taste:multiply(T1, T2), K = gleam@int:multiply(K1, K2), {tastoid, T, K} end. -file("src/tastoids.gleam", 150). ?DOC( " **Experimental** Return the 'not-and'-product, letting\n" " the maths take the wheel.\n" "\n" " _Avery's guess is this will act like a harsh move away the\n" " interesected indices, conversely strengthening everything else_\n" " \n" " Bland : A, B -> (A โฉ B) - (A โฉ B)\n" ). -spec bland(tastoids@tastoid:tastoid(EHF), tastoids@tastoid:tastoid(EHF)) -> tastoids@tastoid:tastoid(EHF). bland(Left, Right) -> Or = blend(Left, Right), And = both(Left, Right), case {Or, And} of {tasteless, {tastoid, Ands, K}} -> {tastoid, tastoids@taste:negate(Ands), gleam@int:negate(K)}; {_, tasteless} -> Or; {{tastoid, Ors, K_or}, {tastoid, Ands@1, K_and}} -> Xor = tastoids@taste:add(Ors, tastoids@taste:negate(Ands@1)), {tastoid, Xor, gleam@int:subtract(K_or, K_and)} end. -file("src/tastoids.gleam", 168). ?DOC( " Reduce k -> 1, yielding the 'average'/normalized tastoid of all\n" " the tastoids blended/present\n" ). -spec squash(tastoids@tastoid:tastoid(EHJ)) -> tastoids@tastoid:tastoid(EHJ). squash(Tastoid) -> case Tastoid of {tastoid, _, 1} = T -> T; {tastoid, _, 0} -> tasteless; {tastoid, T@1, K} -> Try_divide = gleam@float:divide(1.0, erlang:float(K)), case Try_divide of {ok, One_over_k} -> _pipe = tastoids@taste:scale(T@1, One_over_k), {tastoid, _pipe, 1}; {error, _} -> tasteless end; tasteless -> tasteless end. -file("src/tastoids.gleam", 189). ?DOC( " Blend, squashing, aka 'smash' as it is effectively the smash-product (โจณ),\n" " or t โจณ u (see [Smash Product](https://ncatlab.org/nlab/show/smash+product))\n" ). -spec smashing(tastoids@tastoid:tastoid(EHM), tastoids@tastoid:tastoid(EHM)) -> tastoids@tastoid:tastoid(EHM). smashing(T, U) -> _pipe = blend(T, U), squash(_pipe). -file("src/tastoids.gleam", 194). ?DOC(" Returns `True` iff Tastoids `t` & `u` are congruent (weakly equivalent)\n"). -spec equal(tastoids@tastoid:tastoid(EHQ), tastoids@tastoid:tastoid(EHQ)) -> boolean(). equal(T, U) -> case {T, U} of {tasteless, tasteless} -> true; {_, tasteless} -> false; {tasteless, _} -> false; {{tastoid, T@1, K_t}, {tastoid, U@1, K_u}} when K_t =:= K_u -> T@1 =:= U@1; {T@2, U@2} -> equal(squash(T@2), squash(U@2)) end. -file("src/tastoids.gleam", 209). ?DOC( " Project a tastoid into a _Length-oid_ of sorts, condensing\n" " it into a 1-d tastoid indexed by the set of its indexes,\n" " and a value of its dimensions sum.\n" ). -spec length(tastoids@tastoid:tastoid(EHT)) -> tastoids@tastoid:tastoid(gleam@set:set(EHT)). length(Tastoid) -> case Tastoid of tasteless -> tasteless; {tastoid, T, K} -> _pipe = T, _pipe@1 = tastoids@taste:condense(_pipe), {tastoid, _pipe@1, K} end. -file("src/tastoids.gleam", 220). ?DOC( " Returns a Tastoid's _scalar_ value length, discarding its cardinality\n" "\n" " nb. This doesn't _need_ to be a `length(of: tastoid)` result, and in\n" " fact they yield the same value over `distance(covered_by:)`\n" ). -spec distance(tastoids@tastoid:tastoid(any())) -> float(). distance(Tastoid) -> case Tastoid of tasteless -> +0.0; {tastoid, T, _} -> tastoids@taste:length(T) end.