maril
maril

Reputation: 49

L0 and Inf Norms plotting with Contour, Contourf

I am trying to plot different norms with contourf and contour. I have succeeded with all norms except zero-norm and inf-norm. What is the right way to draw similar graphs for 0-norm and inf-norm?

Here is my code:

`p_values = [0., 0.04, 0.5, 1, 1.5, 2, 7, np.inf]
xx, yy = np.meshgrid(np.linspace(-3, 3, num=101), np.linspace(-3, 3, num=101))
fig, axes = plt.subplots(ncols=(len(p_values) + 1)// 2,
                     nrows=2, figsize=(14, 7))
for p, ax in zip(p_values, axes.flat):
    if p != 0:
        zz = ((np.abs((xx))**p) + (np.abs((yy))**p))**(1./p)
    else:
        zz = np.full_like(xx, np.sum(xx !=0)) 
    ax.contourf(xx, yy, zz, 30, cmap='bwr')
    ax.contour(xx,yy,zz, [1], colors='red', linewidths = 2) 
    proxy = [plt.Rectangle((0,0),1,1, facecolor='red')]
plt.show()`

My code and graphs

Upvotes: 1

Views: 3222

Answers (2)

Pavel Tikhomirov
Pavel Tikhomirov

Reputation: 1

Pretty similar answer, with the usage of numpy.linalg.norm and beautiful latex legend:

p_values = [0., 0.04, 0.5, 1, 1.5, 2, 7, np.inf]
xx, yy = np.meshgrid(np.linspace(-3, 3, num=101),
                     np.linspace(-3, 3, num=101))

fig, axes = plt.subplots(ncols=(len(p_values) + 1)// 2,
                         nrows=2, figsize=(16, 7))

for p, ax in zip(p_values, axes.flat):
    h = np.linalg.norm([xx, yy], ord=p, axis=0)
    ax.contourf(xx, yy, h, 20, cmap='coolwarm')
    ax.contour(xx, yy, h, [1], colors='#fd02d5')
    ax.legend([mlines.Line2D([], [], color="#fd02d5")], [f"$x: \|x\|_{{{p}}}=1$",])
plt.show()

output.png

Upvotes: 0

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339580

First, let me mention that numpy provides numpy.linalg.norm which could simplify things, when calculating norms. In the remainder I will stick to the attempt from the question to calculate the norm manually though.

L∞ norm

The L∞ norm would be the suppremum of the two arrays. This can easily be calculated using numpy.maximum.

zz = np.maximum(np.abs(xx),np.abs(yy))

L0 "norm"

The L0 "norm" would be defined as the number of non-zero elements. For the 2D case it can hence take the values 0 (both zero), 1 (one zero), or 2 (both non-zero). Depicting this function as a contour plot is not really succefull because the function essentially deviates from 2 only along two lines in the plot. Using an imshow plot would show it though.

zz = (xx != 0).astype(int) + (yy != 0).astype(int)
ax.imshow(zz, cmap='bwr', aspect="auto")

enter image description here

Complete example.

In total the plot could then look like

import matplotlib.pyplot as plt
import numpy as np

p_values = [0., 0.04, 0.5, 1, 1.5, 2, 7, np.inf]
xx, yy = np.meshgrid(np.linspace(-3, 3, num=101), np.linspace(-3, 3, num=101))
fig, axes = plt.subplots(ncols=(len(p_values) + 1)// 2,
                     nrows=2, figsize=(14, 7))
for p, ax in zip(p_values, axes.flat):
    if p == 0:
        zz = (xx != 0).astype(int) + (yy != 0).astype(int)
        ax.imshow(zz, cmap='bwr', extent=(xx.min(),xx.max(),yy.min(),yy.max()), aspect="auto")
    else:
        if np.isinf(p):
            zz = np.maximum(np.abs(xx),np.abs(yy))
        else:
            zz = ((np.abs((xx))**p) + (np.abs((yy))**p))**(1./p)
        ax.contourf(xx, yy, zz, 30, cmap='bwr')
        ax.contour(xx,yy,zz, [1], colors='red', linewidths = 2) 

plt.show()

enter image description here

Upvotes: 3

Related Questions