As part of a larger simulation program (the context of which I'm happy to share, but which is not relevant to the question), I have run across the following problem and am looking for a good algorithm.
The problem: You are given a floating-point array f of length n (with elements f_1, ..., f_n) specifying a point in n-dimensional space. It can fairly be assumed that the sum of f is 0.0 (subject to floating point precision).
The sought: Find the integer array i of length n (with elements i_1, ..., i_n), specifying a grid point in n-dimensional space, such that the sum of i is exactly 0 and d(f,i), a suitable measure of distance between f and i, is minimized.
As for the suitable measure, I think the best one would be the one that minimizes the relative error (i.e., sum over j of (i_j/f_j-1)^2), but minimizing ordinary euclidean distance (i.e., sum over j of (i_j-f_j)^2) might work too.
The best algorithm which readily occurs to me is to guess a suitable point on the i grid (with sum 0) and then repeatedly switching to the neighboring grid points (with sum 0) with the minimal distance until all neighbors have a larger distance. Given the concavity of the distance function, this should converge on the solution.
But that algorithm seems clunky. Can anyone do better?
There is a related discussion at How to round floats to integers while preserving their sum? but it does not reach the optimality point I'm looking for.
ADDENDUM ON CONTEXT: In case it is of interest (and also because I thought it was kind of cool), let me specify the context in which the problem arose.
The problem occurs as part of a trading simulation (which is part of a yet larger simulation). At each location, agents offer to trade a number of commodities. As each location and commodity is handled separately, we can focus on one location and commodity and deal with them seriatim.
Each agent j has an amount of currency c_j and a quantity of the commodity q_j, which are and have to remain integral. Each agent also specifies a real-valued, continuous, non-negative, non-monotonically decreasing demand function d_j(p) which essentially represents how many units of the commodity the agent would like to own at any given price.
Trades are executed in the following steps.
- For each agent j calculate a budget-constrained demand function b_j(p) = min (d_j(p), q_j + c_j/p)
- Define total quantity q_tot (sum over j of q_j) and total budget-constrained demand function b_tot(p) (sum over j of b_j(p).
- Find the equilibrium price p_eq for which b_tot(p_eq) = q_tot, using Newton's method. If there is no equilibrium price, return.
- Define the traded quantity for each agent f_j as b_j(p_eq)-q_j (which is positive for net purchases and negative for net sales).
- Agents for which f_j is very small (e.g., less than 1/10) are removed from the calculation
- Each q_j should be adjusted to q_j+f_j and each c_j to c_j-p_eq*f_j
- It as this point that the problem arises. f_j and p_eq are floating point, but the q_j and c_j need to remain integral. To avoid creating or destroying currency or commodities, the arrays f_j and (-p_eq*f_j) need to be consistently rounded to integrals