Packages

Tastoids are a uniform abstraction of 'taste' and Algebra thereof.

Current section

Files

Jump to
tastoids src tastoids.gleam
Raw

src/tastoids.gleam

//// Tastoids (& their 'Temperate' Algebra)
////
//// It is often said, one can't compare "apples" to "oranges",
//// but I daresay.. _perhaps you can?_
////
//// **Let me show you how.**
////
//// On their own, it is hard to figure how one might compare apples to oranges,
//// let alone deign to approach a calculus of taste however, with _just enough_
//// structure , a **Taste** can become a **Tastoid**, along with a curious and powerful
//// _Temperate_ Algebra.
////
//// > Not unlike a [_Tropical_ geometry](https://en.wikipedia.org/wiki/Tropical_geometry),
//// > where the notion of addition and multiplication are replaced by min(a,b) & add(a,b),
//// > I pose that a _Temperate Algebra_ is one whose typical notions of (+,×) are replaced
//// > with operations that effectively 'average' taste (with commutativity, distributivity
//// > and reversibility, no less!)
////
//// ### A Taste (t) Field
//// "Tastes", broadly, are any measurable/comparable sentiment about a thing. Something
//// with a unique direction and magnitude. _A vector!_
////
//// Consider if you will, then:
////
//// - The set of all Vectors are a field ℝⁿ (aka 𝕍).
//// - You may partition 𝕍 by some enumerable set of indices (as ⅈ <= countable ∞))
//// - The '[Algebraic extension](https://en.wikipedia.org/wiki/Algebraic_extension)'
//// of 𝕍/ⅈ, is itself a field (with Algebra)
////
//// > In the context of large-language- and embedding-models, this idea of mapping _things_
//// > (text or otherwise) into a well-defined set of possible indices and probabilities is
//// > referred to as an '_embedding_'.
////
//// ### A Taste -> One Tastoid
////
//// We're almost there, I promise. Lets talk about plain numbers for a bit; say I told you
//// knew the average of some set of values was 42. You also know for a fact there was a 13
//// in there once, somewhere.
////
//// Knowing nothing else, how would you _un_-average 13 from 42?
////
//// _Were there two values that averaged to 42? Three? More?_
////
//// Without the _cardinality_ of the original sampling, its (absolutely) impossible to know.
//// But with it... say n=13, in which case, we can merely remove 1/13th of 13 (i.e. 1)
//// from our combined average to find out the average without that 13 was just 41.
////
//// Similarly, on their own Taste vectors _are_ comparable, even averagable in some sense,
//// but without a cardinality, their operations aren't quite _lined up_ to have solutions
//// to previously impossible questions become possible and yield seemingly 'free' results.
////
//// Attempting to put some formalism to the above,
////
//// - We can partition a taste-field further, by its cardinality k ∈ 𝕂 (𝕂 ~ ℝ x ℝ₄ ~ ℂ)
//// (As well as a 4-cycle of like -> dislike -> unlike -> undislike)
////
//// i.e. someone (or thing) expressing { like ( 1+i ) -> dislike (-1 + i)
//// 𝕒 taste (valued at weight w), k times -> un-like (-1 + -i) -> un-dislike (1 + -i) }
//// A Tastoid, can be arrived at by a person/subject, expressing a taste _once_ (tᵢ, k=1),
//// imbedding (sic) that individuals' sentiment in a univesal/possibly infinite set of all
//// the tastoid's that subject could express 𝕥ᵤ↪ᵢ ∈ 𝕋ᵤ
////
//// Then, we may define a handful a tiny, tidy, yet supremely powerful (σ/sigma-)
//// _Algebra_ of Taste_
////
//// - [ ] Brief introduction to operators
//
// ### Operations
//
// - [ ] Tidy this up with all the more recent changes; probably into a more formal
// 'proof'ing ground
//
// (A thorough reckoning of its axioms will take time, learning, and discourse with others;
// suffice to say I mean a formal category-theory 'Algebra' with several handy properties,
// notably invertible, self-integrating distillation of an 'average' taste!)
//
// - add(t¹, u¹) -> (t + u)¹ ('regular' properties of scalar vector addition)
// - scale(tⁿ, k) -> tⁿᵏ ('regular' properties of scalar vector multiplication)
// - blend(t¹, u¹)) -> (t + u)² ('tensor' product; associative, distributive, commutative, invertable)
// (equiv. to) ~> (½t + ½u)¹
// - squash(tᵏ, p) -> ||t||ₚ ( for p =0, yields the unipotent norm--i.e. every sparse tᵢ -> 1
// p==1, yields the normal tastoid (weighted power mean)
// p!=0, yields the p-norm of t with k=p )
import gleam/float
import gleam/int
import tastoids/taste.{add, negate, scale}
import tastoids/tastoid.{type Tastoid, Tasteless, Tastoid}
/// Blend the two tastoids, producing a larger tastoid congruent to
/// the weighted power mean, aka their average (via `squash`)
///
/// See also `retract` - which yields u' which _unblends_ when blended,
pub fn blend(t: Tastoid(index), with u: Tastoid(index)) {
case t, u {
Tasteless, _ -> u
_, Tasteless -> t
Tastoid(t, k_t), Tastoid(u, k_u) -> add(t, u) |> Tastoid(int.add(k_t, k_u))
}
}
/// Return the inverse of a taste (over `blend`)
pub fn retract(taste: Tastoid(index)) -> Tastoid(index) {
case taste {
Tastoid(t, k) -> negate(t) |> Tastoid(int.negate(k))
Tasteless -> Tasteless
}
}
/// Reduce k -> 1, yielding the 'average'/normalized tastoid of all
/// the tastoids blended/present
pub fn squash(tastoid: Tastoid(index)) {
case tastoid {
// Squashing a k=1 tastoid is the base case, so it returns unchanged.
Tastoid(_, 1) as t -> t
// A 0-strength taste squashes towards the emptiest taste (Null)
Tastoid(_, 0) -> Tasteless
// When k is non-zero, return the de-weighted norm of t (scale by 1 over k)
Tastoid(t, k) -> {
// A special coefficient that grounds t into k=1 when applied via scalar multiplication
let try_divide = float.divide(1.0, int.to_float(k))
case try_divide {
Ok(one_over_k) -> scale(t, by: one_over_k) |> Tastoid(1)
Error(_) -> Tasteless
}
}
Tasteless -> Tasteless
}
}
/// Combine two tastoids _hard_, blending them and returing their squashed mean.
pub fn smash(t: Tastoid(index), with u: Tastoid(index)) -> Tastoid(index) {
blend(t, u) |> squash
}
/// Returns `True` iff Tastoids `t` & `u` are congruent (weakly equivalent)
pub fn equal(t: Tastoid(index), u: Tastoid(index)) -> Bool {
case t, u {
Tasteless, Tasteless -> True
_, Tasteless -> False
Tasteless, _ -> False
Tastoid(t, k_t), Tastoid(u, k_u) if k_t == k_u -> {
t == u
}
t, u -> equal(squash(t), squash(u))
}
}