Current section
Files
Jump to
Current section
Files
src/tastoids.erl
-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(EHP), tastoids@tastoid:tastoid(EHP)) -> tastoids@tastoid:tastoid(EHP).
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(EHT)) -> tastoids@tastoid:tastoid(EHT).
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(EHW), tastoids@tastoid:tastoid(EHW)) -> tastoids@tastoid:tastoid(EHW).
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(EIA), tastoids@tastoid:tastoid(EIA)) -> tastoids@tastoid:tastoid(EIA).
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(EIE), tastoids@tastoid:tastoid(EIE)) -> tastoids@tastoid:tastoid(EIE).
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(EII)) -> tastoids@tastoid:tastoid(EII).
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(EIL), tastoids@tastoid:tastoid(EIL)) -> tastoids@tastoid:tastoid(EIL).
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(EIP), tastoids@tastoid:tastoid(EIP)) -> 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(EIS)) -> tastoids@tastoid:tastoid(gleam@set:set(EIS)).
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.