Mathematical Programming

February 22, 2026

We can use conventional mathematical functions as a programming language. This section was inspired by a YouTube video covering Willian's Formula (a function that calculates the nn-th prime), as well as another video covering the basics of mathematical programming. Most mathematical programming is not practical, but it's interesting to see how programs can be designed using pure mathematical syntax. In mathematical programming, design choices are made to control the flow of data, which reminds me of digital circuits and gating in neural network architectures. Simple perceptron networks that attempt to simulate logical operators require mathematical expressions.

Useful Identities and Functions

  1. Sign function:
sgn(x)=xx,x0\operatorname{sgn}(x) = \frac{|x|}{x}, \quad x \neq 0
  1. Differentiable Sign Function (Approximation). We approximate the non-differentiable sign function using a sigmoid:
sgn(x)2σ(kx)1,where σ(x)=11+ex.\operatorname{sgn}(x) \approx 2\sigma(kx) - 1, \quad \text{where } \sigma(x) = \frac{1}{1 + e^{-x}}.

As kk \to \infty, this approximation converges pointwise to sgn(x)\operatorname{sgn}(x).

  1. Maximum of two numbers:
max(a,b)=a+b2+ab2\max(a,b) = \frac{a+b}{2} + \frac{|a-b|}{2}
  1. Minimum of two numbers:
min(a,b)=a+b2ab2\min(a,b) = \frac{a+b}{2} - \frac{|a-b|}{2}
  1. Integer indicator function (returns 11 if nn is an integer, 00 otherwise):
1Z(n)=cos2(πn)\mathbf{1}_{\mathbb{Z}}(n) = \left\lfloor \cos^2(\pi n) \right\rfloor
  1. Logical operations (assume ff and gg are functions that return 11 if true and 00 if false):

Negation (NOT):

¬f=1f\lnot f = 1 - f

Logical OR:

fg=sgn(f+g)f \lor g = \operatorname{sgn}(f+g)

Logical AND:

fg=fgf \land g = f \cdot g

Logical XOR:

fg=fgf \oplus g = |f-g|
  1. DeMorgan's Law:
1sgn ⁣(j=1n1j)=j=1n(11j)1-\operatorname{sgn}\!\left(\sum_{j=1}^{n}\mathbf{1}_{j}\right) = \prod_{j=1}^{n}(1-\mathbf{1}_{j})

Converting Conditional Functions into Mathematical Expressions

Consider a function defined piecewise by a condition:

f(x)={a,x>10,b,5x<10,c,x<5.f(x) = \begin{cases} a, & x > 10, \\ b, & 5 \le x < 10, \\ c, & x < 5. \end{cases}

We can express this as a single-line mathematical expression using indicator functions:

f(x)=a1{x>10}+b1{5x<10}+c1{x<5}.f(x) = a \, \mathbf{1}_{\{x>10\}} + b \, \mathbf{1}_{\{5 \le x < 10\}} + c \, \mathbf{1}_{\{x < 5\}}.

This works because the conditions in a piecewise function are mutually exclusive (or "one-hot"): exactly one condition is satisfied at a time. For example, xx cannot simultaneously satisfy both x>10x > 10 and 5x<105 \le x < 10. The indicator function 1{}\mathbf{1}_{\{\cdot\}} equals 1 when the condition is true and 0 otherwise, allowing us to sum all terms while only the active condition contributes to the function's value.

In practice, you will need to construct your own indicator functions using a concoction of conventional mathematical functions. The following exercises will ask you to construct basic indicator functions e.g. equality, less than, etc.

Exercises

I recommend using Desmos to construct your functions, which makes it easier to check your work. Also, the solution to these exercises look complicated not because they are complicated, but because math can be a horrible programming language!

  1. Write a mathematical function that checks equality between two numbers (returns 11 if true, 00 otherwise).

  2. Write mathematical functions for strict and non-strict inequalities (<< and \leq), returning 11 if true and 00 otherwise.

  3. Write functions that compute the maximum and minimum of two numbers aa and bb.

  4. Write a function that calculates the number of factors of a given integer nn.

  5. Write a function that computes nmodkn \bmod k without using the modulus operator.

  6. Write a function that counts the number of 11s in the binary representation of an integer nn.

  7. Write a function that rounds an integer nn down to the nearest power of 2.

  8. Write a function that computes the XOR of two integers aa and bb.

  9. Write a function that computes the number of ways the integers 1, 2, 5 can sum to integer nn (inspired by LeetCode: Coin Change II).

Solutions

  1. Equality check (returns 11 if a=ba=b, 00 otherwise):
feq(a,b)=1(sgn(ab))2f_{\mathrm{eq}}(a,b) = 1 - \left( \operatorname{sgn}(a-b) \right)^2
  1. Strict less-than (returns 11 if a<ba < b, 00 otherwise):
fslt(a,b)=sgn(ba)+12(1feq(a,b))f_{\mathrm{slt}}(a,b) = \frac{\operatorname{sgn}(b-a)+1}{2} \cdot \left(1 - f_{\mathrm{eq}}(a,b)\right)
  1. Less-than-or-equal-to (returns 11 if aba \le b, 00 otherwise):
fleq(a,b)=sgn(ba)+12+12feq(a,b)f_{\mathrm{leq}}(a,b) = \frac{\operatorname{sgn}(b-a)+1}{2} + \frac{1}{2} f_{\mathrm{eq}}(a,b)
  1. Maximum of two numbers:
max(a,b)=asgn(ab)+12+bsgn(ba)+12(1feq(a,b))\max(a,b) = a \cdot \left\lceil \frac{\operatorname{sgn}(a-b)+1}{2} \right\rceil + b \cdot \left\lceil \frac{\operatorname{sgn}(b-a)+1}{2} \right\rceil \cdot \left(1 - f_{\mathrm{eq}}(a,b)\right)
  1. Minimum of two numbers:
min(a,b)=asgn(ba)+12+bsgn(ab)+12(1feq(a,b))\min(a,b) = a \cdot \left\lceil \frac{\operatorname{sgn}(b-a)+1}{2} \right\rceil + b \cdot \left\lceil \frac{\operatorname{sgn}(a-b)+1}{2} \right\rceil \cdot \left(1 - f_{\mathrm{eq}}(a,b)\right)
  1. Number of factors of nn:
j=1ncos2 ⁣(πnj)\sum_{j=1}^{n} \left\lfloor \cos^2\!\left( \pi \cdot \frac{n}{j} \right) \right\rfloor
  1. nmodkn \bmod k without using mod:
nknkn - k \cdot \left\lfloor \frac{n}{k} \right\rfloor
  1. Number of ones in the binary representation of nn:
j=1log2n+1(1feq ⁣(0,  mod(n,2j)mod(n,2j1)))\sum_{j=1}^{\lfloor \log_2 n \rfloor + 1} \left( 1 - f_{\mathrm{eq}} \!\left( 0,\; \operatorname{mod}(n,2^j) - \operatorname{mod}(n,2^{j-1}) \right) \right)
  1. Round integer down to nearest power of 2:

Let c=log2(n)+1c = \lfloor \log_2(n) \rfloor + 1. Then:

j=1c2cj(1sgn(l=1j1feq(1, mod(n2cl,2))))\sum_{j=1}^{c} 2^{c-j} \cdot \Biggl( 1 - \operatorname{sgn} \Biggl( \sum_{l=1}^{j-1} f_{\mathrm{eq}} \Bigl( 1, \ \operatorname{mod} \Bigl( \Bigl\lfloor \frac{n}{2^{c-l}} \Bigr\rfloor, 2 \Bigr) \Bigr) \Biggr) \Biggr)

The expression above works using bit manipulation, but a simpler expression is:

2log2(n)2^{\lfloor \log_2(n) \rfloor}
  1. XOR function on two integers aa and bb:
c1=log2(a)+1,c2=log2(b)+1,fXOR(a,b)=j=0min(c1,c2)12jmod ⁣(a2j,2)mod ⁣(b2j,2)+j=min(c1,c2)max(c1,c2)12j[fslt(a,b)feq ⁣(1,mod ⁣(b2j,2))+fslt(b,a)feq ⁣(1,mod ⁣(a2j,2))]\begin{align*} c_{1} &= \lfloor \log_{2}(a) \rfloor + 1, \\ c_{2} &= \lfloor \log_{2}(b) \rfloor + 1, \\ f_{XOR}(a,b) &= \sum_{j=0}^{\min(c_{1},c_{2})-1} 2^{j} \left| \operatorname{mod}\!\left(\left\lfloor \frac{a}{2^{j}} \right\rfloor, 2\right) - \operatorname{mod}\!\left(\left\lfloor \frac{b}{2^{j}} \right\rfloor, 2\right) \right| \\ &\quad + \sum_{j=\min(c_{1},c_{2})}^{\max(c_{1},c_{2})-1} 2^{j} \left[ f_{slt}(a,b) \cdot f_{eq}\!\left(1, \operatorname{mod}\!\left(\left\lfloor \frac{b}{2^{j}} \right\rfloor, 2\right)\right) + f_{slt}(b,a) \cdot f_{eq}\!\left(1, \operatorname{mod}\!\left(\left\lfloor \frac{a}{2^{j}} \right\rfloor, 2\right)\right) \right] \end{align*}
  1. Coin Change II:
i=0nj=0nk=0njfeq ⁣(j+k,ni)feq ⁣(0,mod ⁣(j,2))feq ⁣(0,mod ⁣(k,5))\sum_{i=0}^{n} \sum_{j=0}^{n} \sum_{k=0}^{n-j} f_{\mathrm{eq}}\!\left(j+k,\,n-i\right) \, f_{\mathrm{eq}}\!\left(0,\,\operatorname{mod}\!\left(j,2\right)\right) \, f_{\mathrm{eq}}\!\left(0,\,\operatorname{mod}\!\left(k,5\right)\right)

Limitations of Mathematical Programming

One annoying problem in mathematical programming is that math does not have a concept of mutable variable in the sense that as we pass a value through a function, we do not have a variable that updates through computation. As a result, our programs were verbose and hard to understand to the reader.

On the other hand, programming offers mutable variables. Consider the following program:

foo = 0
for i in range(100):
    foo = foo + 1

In this example, the variable foo is a mutable variable, since its value changes as the program is executed. In addition, we are able to reference the new value after assignment from a previous iteration. This would have been extremely useful in the solutions (for example, the question that asks to round an integer down to the nearest power of 2), since the condition used in the solution repeatedly checks if the first jj bits contain a 1, when an array can reduce this check into a lookup.