Artificial General Intelligence (AGI): Concepts, Mathematics and Python Code

AGI

Artificial General Intelligence (AGI): Concepts, Mathematics and Python Code

Artificial General Intelligence (AGI) is a hypothetical form of AI that can learn, reason and solve problems across any intellectual task a human can do, without being rebuilt for each new task. In this post we explain what AGI is, walk through the mathematics behind it, and implement each idea in short, runnable Python.

In one line: Narrow AI is excellent at one thing. AGI is competent at many things, transfers knowledge between them, and adapts to situations it has never seen.

1. What is AGI?

TypeCapabilityExample
Narrow AI (ANI)One task or a small set of tasksSpam filter, chess engine, image classifier
AGIHuman-level performance across most cognitive tasks, with transfer learningNot yet achieved (research goal)
Super-intelligence (ASI)Far beyond the best humans in virtually every domainTheoretical

Key properties of an AGI system

  • Generalization: performs well on tasks not seen during training.
  • Transfer learning: uses knowledge from one domain to learn another faster.
  • Reasoning and planning: chains logical steps and looks ahead.
  • Continual learning: keeps learning without forgetting old skills.
  • Autonomy: sets sub-goals and acts in an environment.

2. Mathematical Foundations of AGI

No single equation defines AGI, but several mathematical frameworks capture its parts: probability (belief), information theory (learning), optimisation (training), and decision theory / reinforcement learning (acting).

2.1 Bayesian Inference: Learning from Evidence

An intelligent agent must update beliefs when it sees data. For hypothesis \(h\) and data \(D\):

$$P(h \mid D) = \frac{P(D \mid h)\,P(h)} {\sum_{h'}P(D \mid h')\,P(h')}$$
import numpy as np

# Three hypotheses about a coin's probability of heads
hypotheses = np.array([0.2, 0.5, 0.8])
posterior = np.ones(3) / 3            # uniform prior
data = [1, 1, 0, 1, 1, 1, 0, 1]       # 1 = heads, 0 = tails

for x in data:
    likelihood = hypotheses if x == 1 else 1 - hypotheses
    posterior = posterior * likelihood
    posterior = posterior / posterior.sum()   # normalise (Bayes rule)

for h, p in zip(hypotheses, posterior):
    print(f"P(theta={h} | data) = {p:.4f}")

2.2 Information Theory: Entropy and KL Divergence

Entropy measures uncertainty; KL divergence measures how far a model \(Q\) is from reality \(P\). Learning means minimising this gap.

$$H(P) = -\sum_x P(x)\log_2 P(x), \qquad D_{KL}(P \,\|\, Q) = \sum_x P(x)\log\frac{P(x)}{Q(x)}$$
import numpy as np

def entropy(p):
    p = np.asarray(p, dtype=float)
    p = p[p > 0]
    return -np.sum(p * np.log2(p))

def kl(p, q):
    p, q = np.asarray(p, float), np.asarray(q, float)
    mask = p > 0
    return np.sum(p[mask] * np.log2(p[mask] / q[mask]))

P = [0.5, 0.3, 0.2]      # true world
Q = [0.4, 0.4, 0.2]      # agent's model
print("H(P)        =", round(entropy(P), 4), "bits")
print("KL(P || Q)  =", round(kl(P, Q), 4), "bits")

2.3 Universal Intelligence (Legg and Hutter)

Legg and Hutter proposed a formal definition: intelligence is an agent's ability to achieve goals in a wide range of environments. For agent \(\pi\):

$$\Upsilon(\pi) = \sum_{\mu \in E} 2^{-K(\mu)}\, V_{\mu}^{\pi}$$

Here \(E\) is the set of computable environments, \(K(\mu)\) is the Kolmogorov complexity of environment \(\mu\) (simpler worlds get more weight, an Occam's razor), and \(V_\mu^\pi\) is the expected total reward of \(\pi\) in \(\mu\). Kolmogorov complexity is uncomputable, so below we use a toy version with a handful of two-armed bandit environments and approximate complexity by a rank.

import numpy as np
rng = np.random.default_rng(42)

# Toy environment set: two-armed bandits (p_arm0, p_arm1). K = pseudo-complexity (bits)
envs = [((0.9, 0.1), 1), ((0.2, 0.8), 2), ((0.6, 0.4), 3), ((0.5, 0.7), 4), ((0.3, 0.35), 5)]
weights = np.array([2.0 ** -k for _, k in envs])
weights = weights / weights.sum()            # normalise so Upsilon is in [0, 1]

def random_agent(counts, wins, t):
    return rng.integers(2)

def greedy_agent(counts, wins, t):
    if 0 in counts:
        return int(np.argmin(counts))
    return int(np.argmax(wins / counts))

def ucb_agent(counts, wins, t):
    if 0 in counts:
        return int(np.argmin(counts))
    return int(np.argmax(wins / counts + np.sqrt(2 * np.log(t + 1) / counts)))

def value(agent, probs, horizon=300, runs=40):
    total = 0.0
    for _ in range(runs):
        counts, wins, ret = np.zeros(2), np.zeros(2), 0.0
        for t in range(horizon):
            a = agent(counts, wins, t)
            r = float(rng.random() < probs[a])
            counts[a] += 1; wins[a] += r; ret += r
        total += ret / horizon               # average reward per step in [0, 1]
    return total / runs

for name, agent in [("random", random_agent), ("greedy", greedy_agent), ("UCB1", ucb_agent)]:
    V = np.array([value(agent, p) for p, _ in envs])
    print(f"{name:7s} Upsilon = {np.dot(weights, V):.3f}")

2.4 Reinforcement Learning: Acting to Maximise Reward

An agent interacts with the world as a Markov Decision Process \((S, A, P, R, \gamma)\). It seeks a policy \(\pi\) maximising expected discounted return:

$$G_t = \sum_{k=0}^{\infty} \gamma^{k} R_{t+k+1}, \qquad V^{\pi}(s) = \mathbb{E}_{\pi}[G_t \mid S_t = s]$$

The optimal action-value function satisfies the Bellman optimality equation:

$$Q^{*}(s,a) = \mathbb{E}\left[ R + \gamma \max_{a'} Q^{*}(s',a') \right]$$

Q-learning learns it with the update:

$$Q(s,a) \leftarrow Q(s,a) + \alpha\left[r + \gamma \max_{a'} Q(s',a') - Q(s,a)\right]$$
import numpy as np
rng = np.random.default_rng(0)

N, goal = 4, (3, 3)
moves = [(-1, 0), (1, 0), (0, -1), (0, 1)]          # up, down, left, right
arrows = ["^", "v", "<", ">"]
Q = np.zeros((N, N, 4))
alpha, gamma, eps = 0.1, 0.95, 0.2

for episode in range(2000):
    s = (0, 0)
    for step in range(100):
        a = int(rng.integers(4)) if eps > rng.random() else int(np.argmax(Q[s]))
        s2 = (min(max(s[0] + moves[a][0], 0), N - 1),
              min(max(s[1] + moves[a][1], 0), N - 1))
        r = 1.0 if s2 == goal else -0.01
        target = r + (0.0 if s2 == goal else gamma * np.max(Q[s2]))
        Q[s][a] += alpha * (target - Q[s][a])        # Q-learning update
        s = s2
        if s == goal:
            break

print("Learned policy (G = goal):")
for i in range(N):
    print(" ".join("G" if (i, j) == goal else arrows[int(np.argmax(Q[i, j]))] for j in range(N)))

2.5 AIXI: The Theoretical Model of AGI

Marcus Hutter's AIXI combines Solomonoff induction with sequential decision theory. At time \(k\), with horizon \(m\), it chooses:

$$a_k = \arg\max_{a_k}\sum_{o_k r_k}\cdots\max_{a_m}\sum_{o_m r_m}\big[r_k+\cdots+r_m\big]\sum_{q:\,U(q,a_{1:m})=o_1r_1\cdots o_mr_m}2^{-\ell(q)}$$

where \(U\) is a universal Turing machine, \(q\) is a program (a hypothesis about the world) and \(\ell(q)\) its length in bits. AIXI is provably optimal in a strong sense but incomputable, so practical AGI research approximates it.

2.6 Neural Networks: Learning by Gradient Descent

Modern AI approximates functions with layered networks. A layer computes \(\mathbf{h} = \sigma(W\mathbf{x} + \mathbf{b})\) and the weights are trained by minimising a loss \(\mathcal{L}\):

$$\theta \leftarrow \theta - \eta\,\nabla_{\theta}\mathcal{L}(\theta), \qquad \sigma(z)=\frac{1}{1+e^{-z}}$$
import numpy as np
rng = np.random.default_rng(1)

# XOR: a problem a single linear neuron cannot solve
X = np.array([[0,0],[0,1],[1,0],[1,1]], float)
y = np.array([[0],[1],[1],[0]], float)

sigmoid = lambda z: 1 / (1 + np.exp(-z))
W1, b1 = rng.normal(size=(2, 4)), np.zeros((1, 4))
W2, b2 = rng.normal(size=(4, 1)), np.zeros((1, 1))
lr = 1.0

for epoch in range(6000):
    h = sigmoid(X @ W1 + b1)                  # forward pass
    out = sigmoid(h @ W2 + b2)
    d_out = (out - y) * out * (1 - out)       # backpropagation (MSE loss)
    d_h = (d_out @ W2.T) * h * (1 - h)
    W2 -= lr * h.T @ d_out;  b2 -= lr * d_out.sum(0, keepdims=True)
    W1 -= lr * X.T @ d_h;    b1 -= lr * d_h.sum(0, keepdims=True)

print("Predictions:", np.round(out.ravel(), 3))
print("Loss:", round(float(np.mean((out - y) ** 2)), 5))

2.7 Attention: The Core of Modern Language Models

Transformers let every token look at every other token. For queries \(Q\), keys \(K\), values \(V\) and key dimension \(d_k\):

$$\text{Attention}(Q,K,V)=\text{softmax}\!\left(\frac{QK^{\top}}{\sqrt{d_k}}\right)V$$
import numpy as np
rng = np.random.default_rng(3)

def softmax(z):
    z = z - z.max(axis=-1, keepdims=True)
    e = np.exp(z)
    return e / e.sum(axis=-1, keepdims=True)

def attention(Q, K, V):
    d_k = K.shape[-1]
    scores = Q @ K.T / np.sqrt(d_k)
    weights = softmax(scores)
    return weights @ V, weights

tokens, d = 4, 8
Q, K, V = (rng.normal(size=(tokens, d)) for _ in range(3))
out, w = attention(Q, K, V)
print("Attention weights (rows sum to 1):")
print(np.round(w, 3))
print("Output shape:", out.shape)

2.8 Scaling Laws: Why Bigger Models Get Smarter

Empirically, model loss follows a power law in parameter count \(N\) (and similarly in data and compute):

$$L(N) = \left(\frac{N_c}{N}\right)^{\alpha_N} \;\;\Longrightarrow\;\; \log L = \alpha_N \log N_c - \alpha_N \log N$$

This is a straight line in log-log space, so we can estimate \(\alpha_N\) with linear regression.

import numpy as np
rng = np.random.default_rng(7)

alpha_true, Nc = 0.076, 8.8e13
N = np.logspace(6, 11, 12)                                  # 1M to 100B parameters
L = (Nc / N) ** alpha_true * np.exp(rng.normal(0, 0.01, N.size))   # noisy observed loss

slope, intercept = np.polyfit(np.log(N), np.log(L), 1)
print("Estimated alpha_N =", round(-slope, 4), "(true:", alpha_true, ")")

for n in [1e12, 1e13]:
    print(f"Predicted loss at N={n:.0e}: {np.exp(intercept + slope*np.log(n)):.3f}")

3. Putting It Together: The AGI Loop

  1. Perceive: turn raw input into a representation (neural networks, attention).
  2. Believe: maintain a probabilistic model of the world (Bayes, \(D_{KL}\) minimisation).
  3. Plan: search over futures to maximise expected return (Bellman equation, AIXI-style).
  4. Act and learn: execute, observe reward, update parameters (gradient descent, Q-learning).
  5. Generalize: reuse knowledge across tasks, the \(\Upsilon(\pi)\) idea.

4. Open Challenges

  • Generalization beyond training data: current models still fail on genuinely novel problems.
  • Continual learning: avoiding catastrophic forgetting.
  • Reasoning and grounding: robust causal and common-sense understanding.
  • Compute and energy: scaling laws are expensive to follow.
  • Alignment and safety: ensuring goals match human values.
  • No agreed definition or test: researchers disagree on what counts as AGI.

5. Conclusion

AGI remains a research goal, not a finished product. Its mathematics, from Bayesian inference and information theory to reinforcement learning, universal intelligence and scaling laws, gives us a rigorous language to reason about it. The Python snippets above are deliberately small, so you can copy them, change the numbers, and build intuition for how general intelligence might one day emerge.

Tip: run each code block in Google Colab or any Python 3 environment with NumPy installed.

Post a Comment

0 Comments