Quote by Leslie Lamport:
Coding is to programming like typing is to writing
My generalization: IMHO, developers often start coding (i.e. typing) way too early.
I am a full-time consultant and provide services related to the design, implementation and deployment of mathematical programming, optimization and data-science applications. I also teach courses and workshops. Usually I cannot blog about projects I am doing, but there are many technical notes I'd like to share. Not in the least so I have an easy way to search and find them again myself. You can reach me at erwin@amsterdamoptimization.com.
Quote by Leslie Lamport:
Coding is to programming like typing is to writing
My generalization: IMHO, developers often start coding (i.e. typing) way too early.
I needed to find a ranking of a large data set. Using Python, it makes sense to look at the numpy library for this.
Numpy has the function argsort, which returns index positions [1]. One would think these are exactly the ranks we are after. Unfortunately, this is not the case.
>>> import numpy as np >>> a = [3.0, 1.0, 5.0, 2.0] >>> indx = np.argsort(a) >>> indx array([1, 3, 0, 2], dtype=int64)
On sudoku.com[1] there is now an "evil" difficulty level. I found these very difficult to solve by hand (I usually give up).
cfm = quicksum( max(quicksum(cf[i][t] * q[i] - L[t] for i in range(I)), 0) for t in range(T) / quicksum(L[t] for t in range(T)) <= 0.015
The GAMS documentation mentions f.nr=1 (standard notation) and f.nr=2 (scientific notation) for formatting numeric items using the PUT statement. There are however a few more. Here we print values using different formats:
f.nr=1 f.nr=2 f.nr=3 f.nr=4 1.20 1.20E+00 1.2000000000 1.2 1.23 1.23E+00 1.2345000000 1.2345 123450000.00 1.23E+08 123450000.00 123450000 0.00 1.20E-07 0.0000001200 1.2E-7 0.00 1.23E-07 0.0000001235 1.2345E-7
|
set |
It is always a good idea to revisit existing GAMS code and see if we can improve it. Here is an example of an actual model.
The problem is that we want to set up a mapping set between two sets based on the first two characters. If they are the same, the pair should be added to the mapping. The old code looked like:
|
sets |
To verify this indeed generates the correct result for set rs, we look at the output:
---- 27 PARAMETER value AP CB LA APN0501 APN0502 APN0504 CBL0704 CBM0404 LAM0404 1 6580.000 6766.000 7665.000 2 6580.000 6580.000 6580.000 6766.000 6766.000 7665.000 + LAM0406 2 7665.000 ---- 28 SET rs mapping regions<->subregions APN0501 APN0502 APN0504 CBL0704 CBM0404 LAM0404 LAM0406 AP YES YES YES CB YES YES LA YES YES
|
* new
code: |
---- 22 SET rs mapping regions<->subregions
APN0501 APN0502 APN0504 CBL0704 CBM0404 LAM0404 LAM0406
AP YES YES YES
CB YES YES
LA YES YES
In [1], an excellent tutorial is presented about the process of making maps. It is a little bit dated, so here I develop some Windows-based scripts that make it possible to follow these tutorials. The goal is two-fold:
The output format of these scripts is svg. SVG files are plain text, represent vectors (instead of bitmaps), and can be read directly by a standard web browser.
The first thing to do is to install node.js if you don't have this available already. Using [2] this process is quite straightforward. Our first batch file will follow the steps in [1].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | ::--------------------------------------------------------------------------- :: :: Mike Bostock :: Command-Line Cartography, Part 1 :: A tour of d3-geo’s new command-line interface. :: :: https://medium.com/@mbostock/command-line-cartography-part-1-897aa8f8ca2c :: :: Needs node.js. Install from: https://nodejs.org/en/download/ :: :: we translate UNIX command line to Windows CMD ::--------------------------------------------------------------------------- :: download shape file from Census Bureau (region 06 = California) :: :: curl 'http://www2.census.gov/geo/tiger/GENZ2014/shp/cb_2014_06_tract_500k.zip' -o cb_2014_06_tract_500k.zip :: use https instead, curl is part of windows curl -O https://www2.census.gov/geo/tiger/GENZ2014/shp/cb_2014_06_tract_500k.zip :: unzip -o cb_2014_06_tract_500k.zip :: use tar instead (part of windows) tar -xf cb_2014_06_tract_500k.zip :: install node.js package :: and extract geojson call npm install -g shapefile call shp2json cb_2014_06_tract_500k.shp -o ca.json :: perform projection call npm install -g d3-geo-projection call geoproject "d3.geoConicEqualArea().parallels([34, 40.5]).rotate([120, 0]).fitSize([960, 960], d)" < ca.json > ca-albers.json :: create svg call geo2svg -w 960 -h 960 < ca-albers.json > ca-albers.svg :: launch browser start ca-albers.svg |
Notes:
The result should be the following vector image displayed in your browser:
mdl.addConstrs((t[i,k] * X[i,j,k] - te1[i] <= 5) >> (z1[i,k] == 1) for i,j,k in arcos if i != 0 and i != 23)(t and X and variables). This is not accepted, and the following error message is issued:
AttributeError: 'gurobipy.QuadExpr' object has no attribute 'getVar'
Indicator constraints have the form:binary variable == 0 ==> linear constraintorbinary variable == 1 ==> linear constraintYour constraint does not have this form. You need to reformulate it to fit this format, or use a different (big-M) formulation.
Well-formed and meaningful error messages are very important. The user is already confused, otherwise (s)he would formulate a correct constraint. Adding confusing error messages to this confusion is not a good idea. A good error message could have prevented this post. We can think of error messages as the UI (User Interface) when it really matters: when the user needs help. Developers should pay much more attention to this.
A question for another day is of course: why are only linear constraints supported?