The MathWorks has an interesting demo on how the shape of a circus tent can be modeled as the solution of a quadratic program in MATLAB. In this post, we’ll show how to solve this same problem in R using the quadprog package and also provide the technical details not covered in the Mathwork’s example. In particular, we’ll explain how an energy function is associated to this problem and how descretizing this energy function gives rise to a sparse quadratic program.

Quadratic programming is a powerful and versatile technique that has found applications in a diverse range of fields. Perhaps its most famous application is in portfolio allocation theory, though it also is very well known as the computational foundation of SVM. A quadratic program is a constrained optimization problem where the objective function is a quadratic form (multidimensional generalization of a quadratic function). The constraints in a standard quadratic program are a mix of linear equality and inequality constraints. This example provides both an intuitive introduction to quadratic programming in R and a great test case for benchmarking optimization algorithms.

### Problem Description

We imagine draping a piece of fabric over an ensemble of 5 tent poles, placed symmetrically over a 36 by 36 grid. The four outer poles are all the same size. The center pole is somewhat larger and taller. In R, it’s easy to build this ensemble by exploiting symmetry:

1 2 3 4 5 6 7 |
# Build the pole grid using basic symmetries. q2 = matrix(0,18,18) q2[8:9,8:9] = .3 q2[17:18,17:18] = 1/2 q1 <- q2[,18:1] top <- cbind(q2,q1) z <- rbind(top,top[18:1,]) |

Let’s plot the pole ensemble and the piece of fabric:

1 2 3 4 5 6 7 8 |
# Plot library(rgl) x <- (1:36)/36 y <- (1:36)/36 open3d() rgl.surface(x,y, z, color='blue',alpha=.75, smooth=TRUE) rgl.surface(x,y, matrix(1/2,36,36), color='red', front='lines', back='lines') rgl.bg(color="white") |

The task is to model the height of the piece of fabric over the grid point .

### Defining an Energy Function

We now need to specify an energy function which defines what should happen when you drape the fabric over the pole ensemble. The idea is that once the fabric is placed, it eventually settles to some minimal energy state. Let be any function that gives heights of the fabric over any grid point . Suppose we come up with a way to measure the energy of any fabric distribution . We call this measurement . A minimal energy state is a particular fabric distribution that makes our measurement as small as possible.

The question of how to measure the energy is one for physicists and engineers. Without specifying the mechanical laws governing the process by which the fabric “settles”, we shouldn’t expect to be able to provide realistic solutions to this model. Nevertheless, let’s consider the famous energy measurement:

where and are the length of the vertical and horizontal sides of the grid and is the gradient operator.

This measurement is called the Dirichlet energy of and, roughly, it captures the total amount of variation in .

We would like to find a numerical approximation to the fabric distribution that makes the energy as small as possible and also fits on top of our tent peg ensemble. Let’s take for granted that such an optimal fabric distribution exists and that this function has no tears or creases (continuous differentiability). We can then use integration by parts to rewrite the Dirichlet energy as:

The second integral in the last expression is a surface integral around the rectangular boundary of our grid. If we assume that at the edge of the grid then this term vanishes and we’re left with the energy expression:

### Discretizing the Energy Function

Now, let’s show how to use the previous formula to get a numerical approximation to the function that minimizes the energy . To do this, we choose a uniform discretization of our grid. Let and be the spacing between grid points in the and directions. We can then approximate the Laplacian using finite difference formulas:

Now we discretize the energy function :

In our discrete problem we are trying to find the values of at each of our grid points. In the current formulation, these points are arranged as an matrix but it turns out to be much more convenient to reorganize these points into a single long vector of components. We’ll do this by stacking the columns of the grid matrix into a single column so that the grid point will map to component . In R, we can stack the columns of the matrix M in this way by

1 2 3 4 |
nr <- nrow(z) nc <- ncol(z) N <- nr*nc bvec <- matrix(z,N,1,byrow=FALSE) |

We write to denote the -th entry of the solution vector in this new indexing system. Then the energy approximation becomes:

Now, we observe that the approximation of involves only five components of the vector. In fact:

Using this observation, we write the energy approximation as

where is a special matrix called the discrete Laplacian. The discrete Laplacian is a famous sparse matrix which has five non-zero bands (one for each component that contributes to a typical value). It is a numerical approximation to the Laplace operator and has many remarkable properties. We can use Kronecker products to easily build the 2D discrete Laplacian on a rectangular grid in R:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# 2D Discrete Laplacian on an lx by ly rectangular grid with # nx grid lines in the x direction and ny grid lines in the y direction. Laplacian2D <- function(lx,ly, nx,ny){ hx <- lx/(nx-1) hy <- ly/(ny-1) tr_x <- c(2,-1,rep(0,nx-2)) tr_y <- c(2,-1,rep(0,ny-2)) Tx <- toeplitz(tr_x)/(hx^2) Ty <- toeplitz(tr_y)/(hy^2) Ix <- diag(nx) Iy <- diag(ny) L <- kronecker(Tx,Iy) + kronecker(Ix,Ty) return(L) } |

### Solving the Quadratic Program

To recap, our goal was to find a numerical approximation to the function which minimizes and which fits on our tent peg ensemble. Our work in the previous section showed that we can find such an approximation by solving the following optimization problem:

where is the vector whose component give the heights of the ground and tent pole ensemble at the (vectorized) grid point . This is a quadratic programming problem, and a very tractable one since an important property of the matrix is that it is symmetric positive definite.

Note that the Mathworks example uses a slightly more general quadratic form

where is a constant vector whose components are all equal to . Though the energy function is not explained in their example, it is likely that this linear term is meant to capture some material effects that aren’t accounted for by the simple Dirichlet energy measure. We’ll also include this term in our solution below to make use of a slightly more interesting quadratic form.

We’ll solve our quadratic program with R’s quadprog library. The solution algorithm implemented in R’s quadprog is somewhat different from that available in MATLAB. One important note about R’s quadprog library is that it does not take advantage of the sparsity of the system matrix nor of the sparsity of the constraints . Since an matrix requires an matrix , the dense matrix representation of can quickly become impractical. For the grid of this problem, however, quadprog works wonderfully:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# Solve the QP: library(quadprog) Ny <- nrow(z) Nx <- ncol(z) N <- Nx*Ny hx <- 1/(Nx-1) hy <- 1/(Ny-1) # System matrices # Note: quadprog's quadratic form is -d^T x + 1/2 x^T D x with t(A)%*%x>= b theta <- 1 # coefficient for linear term Dmat <- hx*hy*Laplacian2D(1,1,36,36) dvec <- -theta*(hx*hy)*rep(1,N) Amat <- t(diag(N)) bvec <- matrix(z,N,1,byrow=FALSE) # lower bound # call the solver sol <- solve.QP(Dmat, dvec, Amat, bvec) # extract and reshape the solution tent <- matrix(sol$solution,nrow(z),ncol(z), byrow=FALSE) |

Now we plot the solution:

1 2 3 4 5 6 7 |
#plot open3d() x <- (1:Nx)/Nx y <- (1:Ny)/Ny rgl.surface(x, y , z, color='blue',alpha=.75, smooth=TRUE) rgl.surface(x, y , tent, color='red', front='lines', back='lines') rgl.bg(color="white") |

Congratulations. Could you please add to your code the initialization of the 'theta' parameter.

Thanks! I fixed that.

Hi, can you pĺease suggest me a book where equation

E[u]=−12∫ly0∫lx0u(x,y)Δu(x,y)dxdy.

is derived?

Thanks,

Diego

HI, I did my research,

It happens that the energy function of a circus tent is:

E[u] = -frac{1}{2} iint_Omega T u(x,y) nabla^2 u(x,y) dd x dd y – mgiint_Omega u(x,y) dd A

here u is the vertical deflection of the tent Omega,

T is a constant that is related to the tension in the fabric, an is related to the elastic properties of the fabric

m is the mass per unit area of the fabric

g is the acceletation of the gravity

the second integral is related to the vector c in the quadratic minimization problem

Cheers,

Diego

Thanks Diego! This is great info. I looked everywhere for a source that explained the MATHWORK's energy function (the one with the 'c' in it). Did you figure this out on your own or did you locate a reference? If so, would love to know what your source is.

Best,

Ryan