Semigroup

Aggregation, data combining

Publish at:
 ____  _____ __  __ ___ ____ ____   ___  _   _ ____  ____
/ ___|| ____|  \/  |_ _/ ___|  _ \ / _ \| | | |  _ \/ ___|
\___ \|  _| | |\/| || | |  _| |_) | | | | | | | |_) \___ \
 ___) | |___| |  | || | |_| |  _ <| |_| | |_| |  __/ ___) |
|____/|_____|_|  |_|___\____|_| \_\\___/ \___/|_|   |____/

Previous chapters were demanding. Understanding context mapping and parallel computations within a context can be challenging. This time we turn to a more fundamental concept that is still simple to understand: semigroups[1]. I am not sure there is anything simpler that is also as useful in practice.

Algebraic Data Structures #

So far, we have met functors and applicative functors. Putting the programming mindset aside, we can think of them as sets equipped with operations. From this point of view, they are very similar, except that an applicative functor is also a functor. Expanding the idea of a set with operations, where those operations are closed and their results remain inside the same set, opens a wider, more abstract point of view[2] on the tools we are building.

Algebraic structure[3] or algebraic system consists of a nonempty set A (called the underlying set, carrier set or domain), a collection of operations on A (typically binary operations such as addition and multiplication), and a finite set of identities (known as axioms) that these operations must satisfy.*

This perfectly correlates with what we've been dealing with so far about objects and morphisms and laws of their application. So algebraic structures are sets with one or more operations that obey specific laws.

When a new problem involves the same laws as such an algebraic structure, all the results that have been proved using only the laws of the structure can be directly applied to the new problem.

Remember functor country mapping example? That was about studying the problem in one country using a different country. Now, it's about the same country and building new bridges using laws for previous ones, so to speak.

Semigroup #

A semigroup is one of the simplest structures in computer science. At its core, a semigroup is simply a set equipped with an associative binary operation.

  • binary - involves two elements of the set (x, y)
  • associative - recall that the operation is associative if the order of grouping does not matter.

Important note: Commutativity is not mandatory.

What makes semigroups particularly powerful is their composability. When you can combine two things of the same type to get another thing of the same type, and when this combination is associative, you unlock powerful patterns for building scalable, parallelizable systems.

Formal definition #

A semigroup is an algebraic structure consisting of:

  1. A set S (the underlying set or carrier)
  2. A binary operation ∘ : S × S -> S (closed under the operation)
  3. Associativity law: For all a, b, c ∈ S, the following must hold: (a ∘ b) ∘ c = a ∘ (b ∘ c)

Examples #

Triangle Semigroup Example #

Let's revisit our geometric example, but this time describe the semigroup in terms of centroids[4].

The Set and Operation #

To obtain a centroid-based semigroup, we restrict attention to one fixed triangle shape and all of its translations. Fix a reference triangle T_0 whose centroid is at the origin, and let S = {T_c | c ∈ R^2} be the set of all translated copies of T_0, where T_c is the unique translated copy whose centroid is c.

This works because, for a fixed triangle shape, the centroid uniquely determines the translation.

Define the operation by adding centroids:

T_c ∘ T_d = T_{c + d}

If c = (x1, y1) and d = (x2, y2), then:

c + d = (x1 + x2, y1 + y2)

Verification of Semigroup Laws #

  1. Closure

If c, d ∈ R^2, then c + d ∈ R^2, so T_{c + d} is again an element of S.

  1. Associativity

For any c, d, e ∈ R^2:

(T_c ∘ T_d) ∘ T_e = T_{(c + d) + e} = T_{c + (d + e)} = T_c ∘ (T_d ∘ T_e)

This holds because vector addition in R^2 is associative.

CSV Transform example #

Our practical example can benefit from semigroups as well. Let's take the initial one as a base.

With semigroups we can use things like:

  • 👥 Person Combination: Merges person records by combining names and aggregating ages
  • Age Summation: Uses addition semigroup to total all ages
  • 📋 Name Collection: Concatenates arrays of names
  • 🗂️ Dataset Merging: Combines multiple CSV datasets
  • 📊 Statistics Aggregation: Accumulates counts, sums, and collections in parallel

Visualizing semigroups #

Understanding semigroups becomes much clearer with visual representations. Let's explore how semigroup operations work through diagrams and illustrations.

1. The fundamental semigroup operation takes two elements and
produces a third element of the same type

Semigroup Operation: S × S → S

   a ∈ S      b ∈ S
     │          │
     └────┬─────┘
          │
          ∘ (binary operation)
          │
          ▼
        c ∈ S

Where: c = a ∘ b

The key property of semigroups is associativity.
The order of grouping doesn't matter:

Associativity: (a ∘ b) ∘ c = a ∘ (b ∘ c)

Left-associative grouping:          Right-associative grouping:
      (a ∘ b) ∘ c                         a ∘ (b ∘ c)

        a   b   c                           a   b   c
        │   │   │                           │   │   │
        └─┬─┘   │                           │   └─┬─┘
          │     │                           │     │
          ∘     │              =            │     ∘
          │     │                           │     │
          └──┬──┘                           └──┬──┘
             │                                 │
             ∘                                 ∘
             │                                 │
             ▼                                 ▼
           result                            result

Both paths produce the same result!

2. Triangle example

Triangles with centroids `c`, `d`, and `c + d`

```txt
        T_c     +      T_d       =       T_(c + d)

         /\            /\                    /\
        /| \          /| \                  /| \
       / •--\        / •--\                / •--\
      /__|___\      /__|___\              /__|___\

    centroid = c    centroid = d         centroid = c + d

The centroid is shown at the intersection of the medians; the triangle shape stays the same, only the centroid position changes.

Parallel Processing #

We mentioned parallel computations before, but have not examined them closely. Associativity is what makes semigroups so useful here. Because regrouping does not change the result, we can split a reduction into independent chunks, process those chunks separately, and combine the partial results later. The following examples compute parallel sums and illustrate a few techniques commonly used in parallel computing:

  1. Divide and Conquer: Breaking large datasets into smaller chunks that can be processed independently.
  2. Tree Reduction: Combining results in a tree-like fashion to minimize synchronization points.
  3. Load Distribution: Spreading work across available CPU cores or worker threads.
  4. Safe Parallelization: Maintaining correctness regardless of how the work is partitioned.

The key insight is that (a + b) + c = a + (b + c). We can safely split sum computations across multiple threads or workers and combine the partial results in any grouping, making parallel processing both safe and efficient.

We can visualize parallel computations as well.

Sequential Processing:

  a -> (∘) -> temp1 -> (∘) -> temp2 -> (∘) -> result
  b ->       -> c ->         -> d ->

Reduction depth: O(n)

Parallel Processing (Divide & Conquer):

                    Level 1 (Parallel)
   a ──┐                              ┌── c
       |--> (∘) --> temp1             │
   b ──┘                              |--> (∘) --> temp2
                                      │
                                  d ──┘

                    Level 2 (Combine)
            temp1 ──┐
                    |--> (∘) --> final_result
            temp2 ──┘

Reduction depth: O(log n) with enough workers

Conclusion #

Semigroups are among the most fundamental and practical algebraic structures. Their simplicity, requiring only an associative binary operation, belies their power and versatility in real-world applications.

Semigroups are useful for:

🔧 Simplicity Minimal requirements: just a set with an associative operation Easy to understand and implement across different programming languages Natural abstraction that models many common operations (concatenation, addition, multiplication, merging)

⚡ Parallel Processing Associativity enables safe parallelization without coordination overhead Support for divide-and-conquer algorithms Scalability across multiple CPU cores and distributed systems MapReduce-style computations

🧩 Composability and Modularity Combine small, simple operations into larger transformations Build larger systems from smaller, testable components

Source code #

Reference implementation (opens in a new tab)

References

  1. Semigroup (opens in a new tab) · Back
  2. Magma (opens in a new tab) · Back
  3. Algebraic structure (opens in a new tab) · Back
  4. Centroid (opens in a new tab) · Back