I spent some time exploring the parameter space for the example given in 2026-07-09. More specifically, I modified the weights of triangles as follows:
I then did an exhaustive computation of with a step size of . For each set of weights, I solved the flat norm LP and stored the objective value , and whether is integral. In other words, I looked at the following map:
I then plotted this map using a contour plot:

We find the following interesting facts:
- Every fractional solution has a corresponding integral solution with the same objective .
- For each objective value , its corresponding parameter space is divided into two parts: fractional vertices and integral vertices.
My idea is as follows:
- Compute the flat norm LP
- If the solution is fractional, tweak the weights so that we get an equivalent integral solution.
Parameter Space and It’s Tangent Space
This strategy requires us to have a strong understanding of the parameter space. That is, fix and and look at the space . Assume that the LP gave as in our example. For any vertex of the LP , consider . Then our objective is given by
We want to look at the following hypersurface in where :
Notice that the map is smooth and on . Experimentation suggests that is orthogonal to the direction we need to travel, i.e., we need to nudge tangent to :
Gradient projected to space:

Tangent of the gradient:

In our higher dimension, we want to look at the tangent space:
However, there are a ton of options to choose from! In the 2D picture we took
If we want an orthonormal basis for , we could use a Householder reflection and compute the QR decomposition of (viewed as a matrix). Set and . Then the QR decomposition is given by
Then for any ,
i.e., the columns of form a basis for .
Proof. Denote by . Notice that for ,
and
as . Thus,
Orthonormal is left as an exercise.
While we can compute an orthonormal basis for , it is unclear which tangent we should take. However, if we could find the “best” one, then we would have an algorithm to find an integral solution given a fractional.
The Algorithm
Denote the tangent to by . One approach to this is as follows:
- Set by the given parameters.
- Solve the flat norm LP to find , record the objective value .
- At step , do the following:
- If , stop.
- Otherwise, set
- Find such that .
The difficult step is projecting back into . Let . Notice that
implies that
So, we get back to by setting
However, this doesn’t respect the homology constraints. Notice that
Notice that if we set , then
What we need to do, is solve the following LP:
Call this problem and the flat norm . Then our algorithm is as follows:
- Set by the given parameters.
- Solve to find , record the objective value .
- At step , do the following:
- If , stop.
- Otherwise, set
- Find by solving .
- Compute with the original parameters .
However, I don’t know if this will converge in a linear number of steps. We would likely need a good step size to ensure it doesn’t overshoot. It would also be great if we could quickly solve .
Update 7/24/26: I implemented this approach with the exception that I find by solving the flat norm problem with the new weights instead of solving . The algorithm converged to an integral solution. Moreover, the solution was the exact integral solution! For a step size, I used
Initial Solution:
z = 3.00004
x = 0.5*[3,4] + 0.5*[0,1] + 0.5*[1,2] + 0.5*[4,5] + 0.5*[2,3] + -0.5*[0,5]
y = 0.5*[3,4,6] + 1*[0,4,6] + -0.5*[0,3,6] + -0.5*[1,4,6] + -0.5*[0,1,6] + -1*[4,6,7] + 0.5*[1,4,7] + -1*[2,4,7] + -0.5*[1,2,7] + 0.5*[4,5,7] + -0.5*[5,7,8] + -0.5*[2,7,8] + -0.5*[2,3,8] + -0.5*[0,5,8] + -0.5*[0,3,8]
Iteration 1:
grad=(3, 9); step=0.000123457; w=(0.6, 1.46667)
z = 3.00005
x = 1*[6,7] + 1*[7,8] + -1*[6,8]
y = -1*[0,1,4] + -1*[1,2,4] + -1*[2,3,8] + -1*[0,3,8] + -1*[3,6,8]
Converged!
Solution:
z = 3.00004
x = 1*[6,7] + 1*[7,8] + -1*[6,8]
y = -1*[0,1,4] + -1*[1,2,4] + -1*[2,3,8] + -1*[0,3,8] + -1*[3,6,8]
Solution verified by Gurobi (with integer constraints):
ampl: model flatnorm.mod;
ampl: option solver gurobi;
ampl: solve;
Gurobi 13.0.2: optimal solution; objective 3.000045
42 simplex iterations
1 branching node
ampl: display Obj;
Obj = 3.00004
ampl: display xp;
xp [*] :=
0 0 3 0 6 0 9 1 12 0 15 0 18 1 21 0 24 0
1 0 4 0 7 0 10 0 13 0 16 0 19 0 22 0 25 0
2 0 5 0 8 0 11 0 14 0 17 0 20 0 23 0 26 0
;
ampl: display xm;
xm [*] :=
0 0 3 0 6 0 9 0 12 0 15 0 18 0 21 0 24 0
1 0 4 0 7 0 10 0 13 0 16 0 19 0 22 0 25 0
2 0 5 0 8 0 11 0 14 0 17 0 20 0 23 0 26 1
;
ampl: display yp;
yp [*] :=
0 0 3 0 6 0 9 1 12 0 15 0 18 0 21 0 24 0
1 0 4 0 7 0 10 0 13 0 16 0 19 0 22 0 25 0
2 0 5 0 8 0 11 0 14 0 17 0 20 0 23 0 26 0
;
ampl: display ym;
ym [*] :=
0 0 3 0 6 1 9 0 12 0 15 0 18 0 21 0 24 0
1 0 4 0 7 0 10 1 13 0 16 0 19 0 22 0 25 1
2 0 5 0 8 0 11 1 14 0 17 0 20 1 23 1 26 0
;