Archive for August, 2010

Vim syntax highlighting for cmake’s CMakeLists.txt files

Tuesday, August 31st, 2010

I use the following at the end of my .vimrc file to force vim to highlight cmake’s CMakeLists.txt files like any other cmake file:


au BufNewFile,BufRead CMakeLists.txt set filetype=cmake

Looks much better than whatever it was trying to do before, which for me was nothing.

Universal File Dialog, a first step

Tuesday, August 31st, 2010

I’m switching from Qt to straight Glut with AntTweakBar for my next project. I’m happy about getting rid of Qt. For my small prototyping projects it was too heavy (hard to get a target working on computers that don’t have Qt installed) and too much work to add simple ui for tweaking parameters and flipping flags. AntTweakBar doesn’t yet solve the deployable problem (I’m trying to figure that out too) but is miles better for prototyping. The only thing I miss from Qt is the native File Save/File Open Dialogs. Since Glut is fairly universal I have taken a stab at writing a small header that could be the start of a universal file dialog “library”. I’d only want this library to depend on standard includes and it only needs to implement get_file_save_path and get_file_open_path.

Here’s what I put in FileDialog.h:


#include <stdio.h>
#define FILE_DIALOG_MAX_BUFFER 1024

// Sets buffer to a path to an existing file 
// buffer[0]=0 on cancel
//
// Usage:
//   char buffer[FILE_DIALOG_MAX_BUFFER];
//   get_open_file_path(buffer);
void get_open_file_path(char buffer[]){
#ifdef __APPLE__
  // For apple use applescript hack
  FILE * output = popen(
    "osascript -e \""
    "   tell application \\\"System Events\\\"\n"
    "           activate\n"
    "           set existing_file to choose file\n"
    "   end tell\n"
    "   set existing_file_path to (POSIX path of (existing_file))\n"
    "\" 2>/dev/null | tr -d '\n' ","r");
  while ( fgets(buffer, FILE_DIALOG_MAX_BUFFER, output) != NULL ){
  }
#else
  // For every other machine type 
  printf("Please enter a file path: ");
  gets(buffer);
#endif
}

// Sets buffer to a path to a new/existing file 
// buffer[0]=0 on cancel
//
// Usage:
//   char buffer[FILE_DIALOG_MAX_BUFFER];
//   get_save_file_path(buffer);
void get_save_file_path(char buffer[]){
#ifdef __APPLE__
  // For apple use applescript hack
  // There is currently a bug in Applescript that strips extensions off
  // of chosen existing files in the "choose file name" dialog
  // I'm assuming that will be fixed soon :-)
  FILE * output = popen(
    "osascript -e \""
    "   tell application \\\"System Events\\\"\n"
    "           activate\n"
    "           set existing_file to choose file name\n"
    "   end tell\n"
    "   set existing_file_path to (POSIX path of (existing_file))\n"
    "\" 2>/dev/null | tr -d '\n' ","r");
  while ( fgets(buffer, FILE_DIALOG_MAX_BUFFER, output) != NULL ){
  }
#else
  // For every other machine type 
  printf("Please enter a file path: ");
  gets(buffer);
#endif
}

And here’s a sample program that calls both functions. Save it in test.c:


#include "FileDialog.h"
#include <stdio.h>

int main(void){
  char buffer[FILE_DIALOG_MAX_BUFFER];

  get_open_file_path(buffer);
  if(buffer[0] == 0)
    printf("Cancelled\n");
  else
    printf("Open file path: %s\n",buffer);

  get_save_file_path(buffer);
  if(buffer[0] == 0)
    printf("Cancelled\n");
  else
    printf("Save file path: %s\n",buffer);

  return 0;
};

Compile and run on a Mac with:


gcc -o test test.c;
./test

Update: I've been looking into a way to do the above for Mac using Carbon or Cocoa but it seems impossible to do correctly without starting up an entire new app...

Update: I've noticed many annoying quirks about the above applescript. There's no way to specify only showing certain file extensions (just UTI types but that's not always what you want). It's quite slow to pop up. But most annoying was that focus was not returned to my GLUT app. Here's the hack I place in my app to use applescript to return the focus to my app. Seems to work great:


// you call to FileDialog.h
get_open_file_path(...)
#ifdef __APPLE__
  // Hack to put focus back on app
  FILE * output = popen(                            
    "osascript -e \""
    "   tell application \\\"NameOfYourApp\\\"\n"           
    "           activate\n"
    "   end tell\"\n"                               
    ,"r");                                          
#endif

Of course, replace NameOfYourApp with the name of your app. If you're unsure what this name is, try using the name that appears above your app's icon on the dock when you hover over it.

Compiling, installing and using AntTweakBar on Mac OS X

Monday, August 30th, 2010

Seeing Bruno Levy‘s demos at SIGGRAPH 2010 convinced me that I want to start using the painlessly easy prototyping GUI library, AntTweakBar. The premise of AntTweakBar is great. Prototyping should be easy and a researcher shouldn’t spend any time on UI that just flips flags and changes input parameter values. With AntTweakBar UI is added with a single line of code for any variable you want to expose. Moreover AntTweakBar figures out which type of UI element should show up: switches for bools, RGB/HSV value manipulators for colors, spinners for numbers. And it’s all Glut and OpenGL (and DirectX I guess), which for most is exactly what they’re already using.

Compiling and installing AntTweakBar as a dynamically linked library on a mac is a bit tricky though. Here’s what I did:

Dowload the source from the AntTweakBar site.

Go to the source directory:


cd AntTweakBar/src

I had to make some changes to the Makefile.osx. Edit the lines to look like this


CXXCFG          = -O3 -arch i386 -arch x86_64
LFLAGS          = -arch i386 -arch x86_64
OUT_DIR         = /usr/local/lib

BASE            = /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks


I want to compile AntTweakBar universally (32-bit and 64-bit) for a 10.6 machine so I need those -arch options. You can leave those out if you just want the default setting.

Copy Makefile.osx over the exisiting Makefile:


cp Makefile.osx Makefile

Then build with


sudo make

This will put the dylib in the right place so you don't have to mess with DYLD_LIBRARY_PATH each time you link to AntTweakBar

Since I've installed libAntTweakBar.dylib all the way at the /usr/local/ level, I'll also put the header file there:


sudo cp ../include/AntTweakBar.h /usr/local/include

Now, hop over to the examples directory:


cd ../examples

Now you should be able to universally compile a simple example with the following:


gcc -O3 -arch i386 -arch x86_64 -Wall -fno-strict-aliasing -D_MACOSX TwSimpleGLUT.c -lAntTweakBar -lpthread -lm -framework OpenGL -framework GLUT -o TwSimpleGLUT

And run it with:


./TwSimpleGLUT

And you should get something like this:
anttweakbar simple example screen capture

Update:
Mac ports does have a port for AntTweakBar, but it's always such a nightmare dealing with the 32-bit/64-bit problem with mac ports so I have done the above. With macports you can just issue:


sudo port install anttweakbar

And you should be able to compile and run the example in the same manner.

head on table

Thursday, August 26th, 2010

head on table

http://alecjacobson.com/art/digital/
http://alecjacobson.com/art/

Compiling L-BFGS-B on Mac OS X and mixing with c++

Tuesday, August 17th, 2010

A new optimization problem required a black box solver that could impose constant bounds on the variables. We opted to use an implementation of L-BFGS-B which does exactly that.
I’m working on a Mac OS X, 10.6, machine and our code base is in c++. So I needed to compile the L-BFGS-B code, which is in fortran and be able to call it from cpp files.

Compiling L-BFGS-B

Note: the following solution requires that you have a proper f2c installed. I used these steps to compile a universal (32-bit and 64-bit) f2c.

Download the source.
You’ll notice there are four *.f files:
routines.f contains the solver
driver*.f contain examples showing you how to set up the parameters to the solver

The Makefile included in the source will try to compile all four files into *.o object files then make executables out of each example. When I try:


make

it seems that while the object files for each *.f file get created, my f77 doesn’t understand how to make the executables. I get errors like this:


f77 -O driver3.o routines.o -o x.lbfgsb3
invalid parameter driver3.o
Undefined symbols:
  "_MAIN__", referenced from:
      _main in libf2c.a(main.o)
ld: symbol(s) not found
collect2: ld returned 1 exit status

This would be OK because I don’t really care about the example executables. But in order to figure out how to call subroutines from routines.o from C/C++, I’ll need to know that they work in the first place. Moreover, f77 was creating x86_64 object files and my code base is i386 (though I’m trying my hardest to build the dependencies as universals).

After digging around in the F77 script I first found where I could tell the compiler to make universal binaries. I do that by setting the CFLAGS environment variable. So as a replacement for the faulty Makefile, I’ve composed this script which should do the same thing but make everything universal for the mac:

Save this in the same directory as the *.f files as make_all.sh:


#!/bin/bash

# save old CFLAGS value
OLD_CFLAGS=$CFLAGS;

# set CFLAGS used by F77 to contain gcc parameters necessary to produce
# universal object files
export CFLAGS="$CFLAGS -arch i386 -arch x86_64";

# compile the algorithm as a universal object file
f77 -O -c -o routines.o routines.f

# compile each of the examples as universal executables
for i in 1 2 3
do
  # translate driver*.f to driver*.c
  f2c driver$i.f
  # compile driver*.c to universal binary driver*.o
  cc $CFLAGS -c -o driver$i.o driver$i.c
  # link driver*.o and routines.o into unversal binary executable x.lbfgsb*
  cc $CFLAGS driver$i.o routines.o -lf2c -lm -o x.lbfgsb$i
  # remove driver*.c
  rm driver$i.c
done

# restore old CFLAGS value
export CFLAGS='$OLD_CFLAGS';

Call it by issuing:


bash make_all.sh

You can test that everything went ok by executing ./x.lbfgsb1, ./x.lbfgsb2, ./x.lbfgsb3.

Mixing with C++

Now that we have a universal routines.o, we would like to be able to call the algorithm subroutines from a c++ program.

I could use f2c to “translate driver1.f” into c++, but all it does is translate it into c and put it in an extern "C" block. Instead I used f2c to translate driver1.f into c code, then methodically human-translated that into a (more) human-readable cpp program.

Below is my human readable version of driver1.f. Save it in a file called driver1.cpp:


/* driver1.f -- translated by f2c (version 20090411).
   You must link the resulting object file with libf2c:
	on Microsoft Windows system, link with libf2c.lib;
	on Linux or Unix systems, link with .../path/to/libf2c.a -lm
	or, if you install libf2c.a in a standard place, with -lf2c -lm
	-- in that order, at the end of the command line, as in
		cc *.o -lf2c -lm
	Source for libf2c is in /netlib/f2c/libf2c.zip, e.g.,

		http://www.netlib.org/f2c/libf2c.zip
*/

// Compile this with
// !c++ routines.o -lf2c -lm -o driver1cpp driver1.cpp

#include "f2c.h"
#include "stdio.h"

/*                             DRIVER 1 */
/*     -------------------------------------------------------------- */
/*                SIMPLE DRIVER FOR L-BFGS-B (version 2.1) */
/*     -------------------------------------------------------------- */

/*        L-BFGS-B is a code for solving large nonlinear optimization */
/*             problems with simple bounds on the variables. */

/*        The code can also be used for unconstrained problems and is */
/*        as efficient for these problems as the earlier limited memory */
/*                          code L-BFGS. */

/*        This is the simplest driver in the package. It uses all the */
/*                    default settings of the code. */


/*     References: */

/*        [1] R. H. Byrd, P. Lu, J. Nocedal and C. Zhu, ``A limited */
/*        memory algorithm for bound constrained optimization'', */
/*        SIAM J. Scientific Computing 16 (1995), no. 5, pp. 1190--1208. */

/*        [2] C. Zhu, R.H. Byrd, P. Lu, J. Nocedal, ``L-BFGS-B: FORTRAN */
/*        Subroutines for Large Scale Bound Constrained Optimization'' */
/*        Tech. Report, NAM-11, EECS Department, Northwestern University, */
/*        1994. */


/*          (Postscript files of these papers are available via anonymous */
/*           ftp to eecs.nwu.edu in the directory pub/lbfgs/lbfgs_bcm.) */

/*                              *  *  * */

/*        NEOS, November 1994. (Latest revision June 1996.) */
/*        Optimization Technology Center. */
/*        Argonne National Laboratory and Northwestern University. */
/*        Written by */
/*                           Ciyou Zhu */
/*        in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. */

/*     NOTE: The user should adapt the subroutine 'timer' if 'etime' is */
/*           not available on the system.  An example for system */
/*           AIX Version 3.2 is available at the end of this driver. */

    // These are fortran wrappers and must be in C
    extern "C" {
      int setulb_(integer *, integer *, doublereal *, 
	    doublereal *, doublereal *, integer *, doublereal *, doublereal *,
	     doublereal *, doublereal *, doublereal *, integer *, char *, 
	    integer *, char *, logical *, integer *, doublereal *, ftnlen, 
	    ftnlen);

      /* Builtin functions */
      integer s_wsfe(cilist *), e_wsfe(void);
      /* Subroutine */ int s_copy(char *, char *, ftnlen, ftnlen);
      integer s_cmp(char *, char *, ftnlen, ftnlen);
      /* Subroutine */ int s_stop(char *, ftnlen);
    }

/*     ************** */
/* Main program */ 
int main(void)
{
    /* Local variables */
    doublereal f, g[1024];
    doublereal l[1024];
    integer m, n;
    doublereal u[1024], x[1024], t1, t2, wa[42584];
    integer nbd[1024], iwa[3072];
    char task[60];
    doublereal factr;
    char csave[60];
    doublereal dsave[29];
    integer isave[44];
    logical lsave[4];
    doublereal pgtol;
    integer iprint;


/*     This simple driver demonstrates how to call the L-BFGS-B code to */
/*       solve a sample problem (the extended Rosenbrock function */
/*       subject to bounds on the variables). The dimension n of this */
/*       problem is variable. */
/*        nmax is the dimension of the largest problem to be solved. */
/*        mmax is the maximum number of limited memory corrections. */
/*     Declare the variables needed by the code. */
/*       A description of all these variables is given at the end of */
/*       the driver. */
/*     Declare a few additional variables for this sample problem. */
/*     We wish to have output at every iteration. */
    iprint = 1;
/*     We specify the tolerances in the stopping criteria. */
    factr = 1e7;
    pgtol = 1e-5;
/*     We specify the dimension n of the sample problem and the number */
/*        m of limited memory corrections stored.  (n and m should not */
/*        exceed the limits nmax and mmax respectively.) */
    n = 25;
    m = 5;
/*     We now provide nbd which defines the bounds on the variables: */
/*                    l   specifies the lower bounds, */
/*                    u   specifies the upper bounds. */
/*     First set bounds on the odd-numbered variables. */
    for(int i = 0; i < n; i+=2){
	nbd[i] = 2;
	l[i] = 1.;
	u[i] = 100.;
    }
/*     Next set bounds on the even-numbered variables. */
    for(int i = 1; i < n; i+=2){
	nbd[i] = 2;
	l[i] = -100.;
	u[i] = 100.;
    }
/*     We now define the starting point. */
    for(int i = 1; i < n; i++){
	x[i] = 3.;
    }

    printf("     Solving sample problem.\n");
    printf("f = 0.0 at the optimal solution.)\n");
/*     We start the iteration by initializing task. */

    s_copy(task, "START", (ftnlen)60, (ftnlen)5);
/*        ------- the beginning of the loop ---------- */
    while(true){
/*       This is the call to the L-BFGS-B code. */
      setulb_(&n, &m, x, l, u, nbd, &f, g, &factr, &pgtol, wa, iwa, task, &
              iprint, csave, lsave, isave, dsave, (ftnlen)60, (ftnlen)60);

      if (s_cmp(task, "FG", (ftnlen)2, (ftnlen)2) == 0) {
/*          the minimization routine has returned to request the */
/*          function f and gradient g values at the current x. */

/*          Compute function value f for the sample problem. */
          f = .25*(x[0]-1.)*(x[0]-1.);
          for(int i = 1;i<n;i++){
              f += (x[i] - x[i-1]*x[i-1])*(x[i] - x[i-1]*x[i-1]);
          }
          f *= 4.;

/*          Compute gradient g for the sample problem. */
          t1 = x[1] - x[0]*x[0];
          g[0] = (x[0] - 1.) * 2. - x[0] * 16. * t1;
          for(int i = 1;i<n-1;i++){
              t2 = t1;
              t1=x[i+1]-x[i]*x[i];
              g[i] = 8.0*t2-16.*x[i]*t1;
          }
          g[n - 1] = t1 * 8.;
/*        go back to the minimization routine. */
      }else if (s_cmp(task, "NEW_X", (ftnlen)5, (ftnlen)5) == 0) {
/*        the minimization routine has returned with a new iterate, */
/*        and we have opted to continue the iteration. */
      }else{
        // anything other than "FG" or "NEW_X" means termination
/*         If task is neither FG nor NEW_X we terminate execution. */
        break;
      }
    }
    return 0;
}

Note: You’ll get runtime errors if you find/replace all of the “integer” keywords with “int”. I guess these are defined by f2c.h. All I know is, leave them alone.

Compile this with:


c++ -arch x86_64 -arch i386 routines.o -lf2c -lm -o driver1cpp driver1.cpp

And you should be able to execute your cpp program with


./driver1cpp

Compiling L-BFGS-B nonlinear optimizer for mac os x

Monday, August 16th, 2010

Just running:


make

on the fortran source code of L-BFGS-B gave me linker errors on my mac OS X 10.6 machine:


invalid parameter driver1.o
Undefined symbols:
  "_s_wsle", referenced from:
      _subsm_ in routines.o
    ....

I fixed this by installing g77, following these instructions.

Then changed the value of F77 in the makefile of L-BFGS-B:


#FC = f77
FC = g77

Then running


make

produced i386 executables and object files.

Note: I’m not sure what you would need to change to produce x86_64 files, luckily for me I wanted i386 all along.

Update: So the examples that g77 creates above work fine. But when I tried to call the fortran subroutines from c or cpp code I got weird errors. To solve this I switched gears and opted to use f2c/f77 and universal binaries, this so far is working much better.

Block matrices in LaTeX, part two

Thursday, August 12th, 2010

Yesterday I made a first attempt at drawing box-like, block matrices in LaTeX. I achieved this with pure LaTeX. Today I’ve been able to produce much cool looking results using the vector graphics package tikz. The documentation for this package is not great, but there are a few tutorials and plenty of examples out there. With it I was able to define some new commands that I can call in LaTeX document to make beautiful colored block matrices. First include the necessary packages:


\usepackage{tikz}
\usepackage{ifthen}

Then add these new command definitions. In there are commands to make framed and unframed blocks and a command to make a diagonal (banded) matrix. There is also mumbo-jumbo macros that reduce the clutter for creating block matrix equations. Also a quick version of left and right parentheses. The unfortunate thing about switching to tikz is that for the matrices in an equation to be aligned across their tops you need to encapsulate them in the vertically aligned box command I provide, which then only really works inside a tabular environment.


% master block matrix, should use wrappers instead of calling this
% directly
% This should be called within the tikzpicture environment
% \blockmatrix
%  {width}
%  {height}
%  {text}
%  {block_line_color} (can be none --> no line)
%  {block_fill_color} (can be none --> empty fill)
%  {is_diagonal} (true --> true, otherwise --> false)
%  {diagonal_line_color} (ignored if not diagonal) (can be none --> no line)
%  {diagonal_fill_color} (ignored if not diagonal) (can be noneo --> empty fill)
%  {diagonal_offset} (half diagonal width in tikz units)
% Note: colors here are not rgb, they are defined colors
\newcommand{\blockmatrix}[9]{
  \draw[draw=#4,fill=#5] (0,0) rectangle( #1,#2);
  \ifthenelse{\equal{#6}{true}}
  {
    \draw[draw=#7,fill=#8] (0,#2) -- (#9,#2) -- ( #1,#9) -- ( #1,0) -- ( #1 - #9,0) -- (0,#2 -#9) -- cycle;
  }
  {}
  \draw ( #1/2, #2/2) node { #3};
}

% Quick implementation of a tikz right parenthesis
% \rightparen{width}
\newcommand{\rightparen}[1]{
  \begin{tikzpicture} 
    \draw (0,#1/2) arc (0:30:#1);
    \draw (0,#1/2) arc (0:-30:#1);
  \end{tikzpicture}%this comment is necessary
}

% Quick implementation of a tikz left parenthesis
% \leftparen{width}
\newcommand{\leftparen}[1]{
  \begin{tikzpicture} 
    \draw (0,#1/2) arc (180:150:#1);
    \draw (0,#1/2) arc (180:210:#1);
  \end{tikzpicture}%this comment is necessary
}

% Unframed block matrix, "m" prefix to match fbox, mbox
% \blockmatrix[r,g,b]{width}{height}{text}
\newcommand{\mblockmatrix}[4][none]{
  \begin{tikzpicture} 
  \ifthenelse{\equal{#1}{none}}
  {
    \blockmatrix{#2}{#3}{#4}{none}{none}{false}{none}{none}{0.0}
  }
  {
    \definecolor{fillcolor}{rgb}{#1}
    \blockmatrix{#2}{#3}{#4}{none}{fillcolor}{false}{none}{none}{0.0}
  }
  \end{tikzpicture}%this comment is necessary
}

% Framed block matrix
% \fblockmatrix[r,g,b]{width}{height}{text}
\newcommand{\fblockmatrix}[4][none]{
  \begin{tikzpicture} 
  \ifthenelse{\equal{#1}{none}}
  {
    \blockmatrix{#2}{#3}{#4}{black}{none}{false}{none}{none}{0.0}
  }
  {
    \definecolor{fillcolor}{rgb}{#1}
    \blockmatrix{#2}{#3}{#4}{black}{fillcolor}{false}{none}{none}{0.0}
  }
  \end{tikzpicture}%this comment is necessary
}

% Diagonal block matrix
% \dblockmatrix[r,g,b]{width}{height}{text}
\newcommand{\dblockmatrix}[4][none]{
  \begin{tikzpicture} 
  \ifthenelse{\equal{#1}{none}}
  {
    \blockmatrix{#2}{#3}{#4}{black}{none}{true}{black}{none}{0.35cm}
  }
  {
    \definecolor{fillcolor}{rgb}{#1}
    \blockmatrix{#2}{#3}{#4}{black}{none}{true}{black}{fillcolor}{0.35cm}
  }
  \end{tikzpicture}%this comment is necessary
}


% Diagonal block matrix, but exposes diagonal offset
% \diagonalblockmatrix[r,g,b]{width}{height}{text}
\newcommand{\diagonalblockmatrix}[5][none]{
  \begin{tikzpicture} 

  \ifthenelse{\equal{#1}{none}}
  {
    \blockmatrix{#2}{#3}{#4}{black}{none}{true}{black}{none}{#5}
  }
  {
    \definecolor{fillcolor}{rgb}{#1}
    \blockmatrix{#2}{#3}{#4}{black}{none}{true}{black}{fillcolor}{#5}
  }

  \end{tikzpicture}%necessary comment
}

\newcommand{\valignbox}[1]{
  \vtop{\null\hbox{#1}}% necessary comment
}

% a hack so that I don't have to worry about the number of columns or
% spaces between columns in the tabular environment
\newenvironment{blockmatrixtabular}
{% necessary comment
  \begin{tabular}{
  @{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l
  @{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l
  @{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l
  @{}
  }
}
{
  \end{tabular}%necessary comment
}

Then here’s the code for a document showing a bunch of uses:


\documentclass[letterpaper,11pt]{article}

\usepackage{tikz}
\usepackage{ifthen}

% master block matrix, should use wrappers instead of calling this
% directly
% This should be called within the tikzpicture environment
% \blockmatrix
%  {width}
%  {height}
%  {text}
%  {block_line_color} (can be none --> no line)
%  {block_fill_color} (can be none --> empty fill)
%  {is_diagonal} (true --> true, otherwise --> false)
%  {diagonal_line_color} (ignored if not diagonal) (can be none --> no line)
%  {diagonal_fill_color} (ignored if not diagonal) (can be noneo --> empty fill)
%  {diagonal_offset} (half diagonal width in tikz units)
% Note: colors here are not rgb, they are defined colors
\newcommand{\blockmatrix}[9]{
  \draw[draw=#4,fill=#5] (0,0) rectangle( #1,#2);
  \ifthenelse{\equal{#6}{true}}
  {
    \draw[draw=#7,fill=#8] (0,#2) -- (#9,#2) -- ( #1,#9) -- ( #1,0) -- ( #1 - #9,0) -- (0,#2 -#9) -- cycle;
  }
  {}
  \draw ( #1/2, #2/2) node { #3};
}

% Quick implementation of a tikz right parenthesis
% \rightparen{width}
\newcommand{\rightparen}[1]{
  \begin{tikzpicture} 
    \draw (0,#1/2) arc (0:30:#1);
    \draw (0,#1/2) arc (0:-30:#1);
  \end{tikzpicture}%this comment is necessary
}

% Quick implementation of a tikz left parenthesis
% \leftparen{width}
\newcommand{\leftparen}[1]{
  \begin{tikzpicture} 
    \draw (0,#1/2) arc (180:150:#1);
    \draw (0,#1/2) arc (180:210:#1);
  \end{tikzpicture}%this comment is necessary
}

% Unframed block matrix, "m" prefix to match fbox, mbox
% \blockmatrix[r,g,b]{width}{height}{text}
\newcommand{\mblockmatrix}[4][none]{
  \begin{tikzpicture} 
  \ifthenelse{\equal{#1}{none}}
  {
    \blockmatrix{#2}{#3}{#4}{none}{none}{false}{none}{none}{0.0}
  }
  {
    \definecolor{fillcolor}{rgb}{#1}
    \blockmatrix{#2}{#3}{#4}{none}{fillcolor}{false}{none}{none}{0.0}
  }
  \end{tikzpicture}%this comment is necessary
}

% Framed block matrix
% \fblockmatrix[r,g,b]{width}{height}{text}
\newcommand{\fblockmatrix}[4][none]{
  \begin{tikzpicture} 
  \ifthenelse{\equal{#1}{none}}
  {
    \blockmatrix{#2}{#3}{#4}{black}{none}{false}{none}{none}{0.0}
  }
  {
    \definecolor{fillcolor}{rgb}{#1}
    \blockmatrix{#2}{#3}{#4}{black}{fillcolor}{false}{none}{none}{0.0}
  }
  \end{tikzpicture}%this comment is necessary
}

% Diagonal block matrix
% \dblockmatrix[r,g,b]{width}{height}{text}
\newcommand{\dblockmatrix}[4][none]{
  \begin{tikzpicture} 
  \ifthenelse{\equal{#1}{none}}
  {
    \blockmatrix{#2}{#3}{#4}{black}{none}{true}{black}{none}{0.35cm}
  }
  {
    \definecolor{fillcolor}{rgb}{#1}
    \blockmatrix{#2}{#3}{#4}{black}{none}{true}{black}{fillcolor}{0.35cm}
  }
  \end{tikzpicture}%this comment is necessary
}


% Diagonal block matrix, but exposes diagonal offset
% \diagonalblockmatrix[r,g,b]{width}{height}{text}
\newcommand{\diagonalblockmatrix}[5][none]{
  \begin{tikzpicture} 

  \ifthenelse{\equal{#1}{none}}
  {
    \blockmatrix{#2}{#3}{#4}{black}{none}{true}{black}{none}{#5}
  }
  {
    \definecolor{fillcolor}{rgb}{#1}
    \blockmatrix{#2}{#3}{#4}{black}{none}{true}{black}{fillcolor}{#5}
  }

  \end{tikzpicture}%necessary comment
}

\newcommand{\valignbox}[1]{
  \vtop{\null\hbox{#1}}% necessary comment
}

% a hack so that I don't have to worry about the number of columns or
% spaces between columns in the tabular environment
\newenvironment{blockmatrixtabular}
{% necessary comment
  \begin{tabular}{
  @{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l
  @{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l
  @{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l@{}l
  @{}
  }
}
{
  \end{tabular}%necessary comment
}

\begin{document}

Linear system for solving a biharmonic PDE with boundary
condtions:


\begin{blockmatrixtabular}
\valignbox{\fblockmatrix       [0.8,1.0,0.8]{0.8in}{0.6in}{$L$}}&
\valignbox{\diagonalblockmatrix[1.0,0.8,0.8]{0.8in}{0.8in}{$M^{-1}$}{0.25in}}&
\valignbox{\fblockmatrix       [0.8,1.0,0.8]{0.6in}{0.8in}{$L$}}&
\valignbox{\fblockmatrix                    {0.15in}{0.6in}{$x$}}&
\valignbox{\mblockmatrix                    {0.15in}{0.6in}{$=$}}&
\valignbox{\fblockmatrix       [0.8,1.0,0.8]{0.8in}{0.6in}{$L$}}&
\valignbox{\diagonalblockmatrix[1.0,0.8,0.8]{0.8in}{0.8in}{$M^{-1}$}{0.25in}}&
\valignbox{\fblockmatrix       [0.8,1.0,0.8]{0.25in}{0.8in}{$L$}}&
\valignbox{\fblockmatrix       [0.8,0.8,1.0]{0.15in}{0.25in}{$b$}}\\
\end{blockmatrixtabular}\\

\begin{tabular}{cc}
Simple linear system:&
Linear system with known values susbstituted:\\
\begin{blockmatrixtabular}
\valignbox{\fblockmatrix       [0.8,1.0,0.8]{0.8in}{0.8in}{$A$}}&
\valignbox{\fblockmatrix                    {0.15in}{0.8in}{$x$}}&
\valignbox{\mblockmatrix                    {0.15in}{0.8in}{$=$}}&
\valignbox{\fblockmatrix       [0.8,0.8,1.0]{0.15in}{0.8in}{$b$}}\\
\end{blockmatrixtabular}&

\begin{blockmatrixtabular}
  \valignbox{
  \begin{blockmatrixtabular}
  \fblockmatrix     [0.8,1.0,0.8]{0.8in}{0.37in}{$A$}\\
  \fblockmatrix     [1.0,0.8,0.8]{0.8in}{0.37in}{$I$}%nc
  \end{blockmatrixtabular}}&
\valignbox{\fblockmatrix{0.15in}{0.8in}{$x$}}&
\valignbox{\mblockmatrix{0.15in}{0.8in}{$=$}}&
  \valignbox{%necessary comment
  \begin{blockmatrixtabular}
  \fblockmatrix     [0.8,1.0,0.8]{0.15in}{0.37in}{$b$}\\
  \fblockmatrix     [1.0,0.8,0.8]{0.15in}{0.37in}{$\hat{x}$}%nc
  \end{blockmatrixtabular}%necessary comment
  }
\end{blockmatrixtabular}\\
\end{tabular}

Linear system addition expanded in system matrix:

\begin{blockmatrixtabular}
\valignbox{\leftparen{0.8in}}&
  \valignbox{
  \begin{blockmatrixtabular}
  \fblockmatrix     [0.8,1.0,0.8]{0.8in}{0.37in}{$A$}\\
  \fblockmatrix     [0.8,0.8,1.0]{0.8in}{0.37in}{$0$}%nc
  \end{blockmatrixtabular}}&
\valignbox{\mblockmatrix{0.15in}{0.8in}{$+$}}&
  \valignbox{
  \begin{blockmatrixtabular}
  \fblockmatrix     [0.8,0.8,1.0]{0.8in}{0.37in}{$0$}\\
  \fblockmatrix     [1.0,0.8,0.8]{0.8in}{0.37in}{$I$}%nc
  \end{blockmatrixtabular}}&
\valignbox{\rightparen{0.8in}}&
\valignbox{\fblockmatrix{0.15in}{0.8in}{$x$}}&
\valignbox{\mblockmatrix{0.15in}{0.8in}{$=$}}&
  \valignbox{%necessary comment
  \begin{blockmatrixtabular}
  \fblockmatrix     [0.8,1.0,0.8]{0.15in}{0.37in}{$b$}\\
  \fblockmatrix     [1.0,0.8,0.8]{0.15in}{0.37in}{$\hat{x}$}%nc
  \end{blockmatrixtabular}%necessary comment
  }
\end{blockmatrixtabular}\\

Linear system with least squares conditions tacked on to the
bottom: 

\begin{blockmatrixtabular}
  \valignbox{%necessary comment
  \begin{blockmatrixtabular}
  \fblockmatrix     [0.8,1.0,0.8]{0.8in}{0.8in}{$A$}\\
  \fblockmatrix     [1.0,0.8,0.8]{0.8in}{0.4in}{$G$}%necessary comment
  \end{blockmatrixtabular}%necessary comment
  }&
\valignbox{\fblockmatrix{0.15in}{0.8in}{$x$}}&
\valignbox{\mblockmatrix{0.15in}{0.8in}{$=$}}&%
  \valignbox{%necessary comment
  \begin{blockmatrixtabular}
  \fblockmatrix       [0.8,0.8,1.0]{0.15in}{0.8in}{$b$}\\
  \fblockmatrix       [1.0,0.8,0.8]{0.15in}{0.4in}{$0$}%nc
  \end{blockmatrixtabular}%necessary comment
  }
\end{blockmatrixtabular}\\


Least squares system with a weights applied to the original
matrix:

\begin{blockmatrixtabular}
\valignbox{\diagonalblockmatrix[0.8,1.0,0.8]{0.8in}{0.8in}{$W_A$}{0.25in}}&
  \valignbox{%necessary comment
  \begin{blockmatrixtabular}
  \fblockmatrix     [0.8,1.0,0.8]{0.8in}{0.8in}{$A$}\\
  \fblockmatrix     [1.0,0.8,0.8]{0.8in}{0.4in}{$G$}%nc
  \end{blockmatrixtabular}%necessary comment
  }&%
\valignbox{\fblockmatrix{0.15in}{0.8in}{$x$}}&
\valignbox{\mblockmatrix{0.15in}{0.8in}{$=$}}&
  \valignbox{%necessary comment
  \begin{blockmatrixtabular}
  \fblockmatrix       [0.8,0.8,1.0]{0.15in}{0.8in}{$b$}\\
  \fblockmatrix       [1.0,0.8,0.8]{0.15in}{0.4in}{$0$}%nc
  \end{blockmatrixtabular}%necessary comment
  }
\end{blockmatrixtabular}\\


\end{document}

Which produces this:
latex tikz block matrics

In conclusion, the disadvantages of the tikz approach is that (1) the command definitions are longer, (2) the code for each block matrix is much more verbose, (3) alignment is not trivial, and (4) it requires an external package. The advantages over the pure LaTeX approach is that (1) alignment is easier, (2) parentheses fit nicely into the vector graphics of the blocks, (3) colors are drop dead easy, (4) diagonal matrices are implemented, and (5) whitespace between rows and columns and above and below symbols is easier to manage.

For now, I’m convinced that the tikz way produces better look matrices. Though I imagine myself keeping the pure LaTeX version as a simple back up.

Block matrices in LaTeX, part one

Wednesday, August 11th, 2010

When I’m writing out complicated linear systems by hand I usually draw the system as block matrices. And when I say block matrices, I mean that I really draw the boxes around each part of the matrix with matching row and column dimensions. So when I draw a single matrix it is just a single box. And when I draw a partitioned (block) matrix I draw a stack of these boxes (I realize “block matrix” technically refers to these partitioned matrices and not drawing them as blocks). This helps me see the matrix multiplication in my head and keep track of whether the system is determined, underdetermined, or over determined. Here’s an example of my hand drawn block matrices in action:
hand drawn block matrices

I looked around and found that most packages print block matrices like this, with at most vertical or horizontal lines (not boxes) sectioning off entries in an array:
array style latex block matrices

So I fiddled around with LaTeX box commands and came up with a first attempt to create the sort of boxed, block matrices that I use in my notes. Here’re the commands that I define:


\newcommand{\blockmatrix}[3]{%These end of the line comments are neccessary
\begin{minipage}[t][#2][c]{#1}%
\center%
#3%
\end{minipage}%
}%
\newcommand{\fblockmatrix}[3]{%
\fbox{%
\begin{minipage}[t][#2][c]{#1}%
\center%
#3%
\end{minipage}%
}%
}

Note: The end of line comments are necessary to prevent fbox from adding spurious spacing.

And here’s a document using the commands:


\documentclass[letterpaper,11pt]{article}

\newcommand{\blockmatrix}[3]{%These end of the line comments are neccessary
\begin{minipage}[t][#2][c]{#1}%
\center%
#3%
\end{minipage}%
}%
\newcommand{\fblockmatrix}[3]{%
\fbox{%
\begin{minipage}[t][#2][c]{#1}%
\center%
#3%
\end{minipage}%
}%
}

\begin{document}

\fblockmatrix{0.5in}{0.5in}{A} \fblockmatrix{0.1in}{0.5in}{x}
\blockmatrix{0.1in}{0.5in}{=} \fblockmatrix{0.1in}{0.5in}{b}
\\
\\

\fblockmatrix{0.5in}{0.3in}{A} \fblockmatrix{0.1in}{0.5in}{x}
\blockmatrix{0.1in}{0.5in}{=} \fblockmatrix{0.1in}{0.3in}{b}
\\
\\

\fblockmatrix{0.5in}{0.3in}{L}
\fblockmatrix{0.5in}{0.5in}{M}
\fblockmatrix{0.3in}{0.5in}{L}
\fblockmatrix{0.1in}{0.3in}{x}
\blockmatrix{0.25in}{0.3in}{=}
\fblockmatrix{0.1in}{0.3in}{b}
\\
\\

\fblockmatrix{0.6in}{0.4in}{L}
\fblockmatrix{0.6in}{0.6in}{M}
\fblockmatrix{0.4in}{0.6in}{L}
\fblockmatrix{0.1in}{0.4in}{x}
\blockmatrix{0.1in}{0.3in}{=}
\fblockmatrix{0.6in}{0.4in}{L}
\fblockmatrix{0.6in}{0.6in}{M}
\fblockmatrix{0.2in}{0.6in}{L}
\fblockmatrix{0.1in}{0.2in}{b}
\\
\\

\fblockmatrix{0.525in}{0.375in}{$L$}
\fblockmatrix{0.525in}{0.525in}{$M$}
\fblockmatrix{0.375in}{0.525in}{$L$}
\fblockmatrix{0.1in}{0.375in}{$x$}
\blockmatrix{0.1in}{0.275in} {$=$}
\fblockmatrix{0.525in}{0.375in}{$L$}
\fblockmatrix{0.525in}{0.525in}{$M$}
\blockmatrix{0.1in}{0.375in}{\Huge{ $($}}
\fblockmatrix{0.175in}{0.525in}{$L$}
\fblockmatrix{0.1in}{0.175in}{$b$}
\blockmatrix{0.1in}{0.4in}{$+$}
\fblockmatrix{0.1in}{0.525in}{$b_n$}
\blockmatrix{0.1in}{0.375in}{\Huge{ $)$}}
\\
\\

\begin{tabular}{llll}
\fblockmatrix{0.5in}{0.5in}{A}&
\fblockmatrix{0.1in}{0.5in}{x}&
\blockmatrix{0.1in}{0.5in}{=}&
\fblockmatrix{0.1in}{0.5in}{b}
\\
\fblockmatrix{0.5in}{0.25in}{G} & & &
\fblockmatrix{0.1in}{0.25in}{0}
\\
\end{tabular}
\\\\

\end{document}

Which produces this:
latex fbox style block matrics

Admittedly there’s a lot left to do. The parenthesis behavior is annoying and it’s not terribly easy to stack them.

hair

Sunday, August 8th, 2010

hair

http://alecjacobson.com/art/digital/
http://alecjacobson.com/art/

Content-aware content

Saturday, August 7th, 2010

content-aware content

http://alecjacobson.com/art/digital/
http://alecjacobson.com/art/