The convex conjugate (or Fenchel dual) for a single variable function is defined as:
We assume that is convex, differentiable and simple (closed-form solution exist for minimum). The conjugate can then symbolically be calculated using the following Python code:
def calc_conjugate(str, varnames='x'): # set the symbols vars = sp.symbols(varnames) x = vars[0] if isinstance(vars, tuple) else vars y = sp.symbols('y', real=True) # set the function and objective fun = parse_expr(str) obj = x*y - fun # calculate derivative of obj and solve for zero sol = solve(sp.diff(obj, x), x) # substitute solution into objective solfun = sp.simplify(obj.subs(x, sol[0])) # if extra values were passed add to lambda function varnames = [y] + list(vars[1:]) if isinstance(vars, tuple) else y return (sp.sstr(solfun), lambdify(vars, fun, 'numpy'), lambdify(varnames, solfun, 'numpy'))
The full source code is here. The above code was used to calculate and plot the conjugates of several functions, which is given below.
Function | Conjugate | |
Quadratic | ||
Exponential | ||
Log | ||
Log-Exponential | ||
x log(x) |