I'm using AMPL & Gurobi for a continuous quadratic problem with mostly linear constraints, but also some ratio-type constraints: xy=z.
Gurobi doesn't directly support those constraints, so I have a work-around:
- Supply a rough estimate of the solution values
- Use this rough estimate to create a linear constraint that approximates the ratio constraint in the neighbourhood of the rough estimate (Taylor series method)
- Solve, using the linear constraint
- Use the solutions to update the rough estimates
- Repeat until solutions converge
Small code example:
prices.mod:
var volume; # the quantity sold for some commodity
var value; #the value sold for that commodity
var price; #the price of this commodity
param volume_first_estimate := 10; # our initial estimate for volume
param price_first_estimate := 150;
param value_first_estimate := 1000;
# note that these values are not consistent; we wish to adjust them so that the
# final values are consistent.
# The following constraint is what I want:
# subject to ExactPriceConstraint: value = price * volume;
# but since price and volume are both var, this would be quadratic. Instead:
param volume_best_estimate;
param price_best_estimate;
param value_best_estimate;
# Our working best estimate for each of these items
subject to LinearisedPriceConstraint: value = price*volume_best_estimate + price_best_estimate*volume - price_best_estimate*volume_best_estimate;
minimize OF: (price-price_first_estimate)^2+(value-value_first_estimate)^2+(volume-volume_first_estimate)^2;
prices.run:
reset;
option solver gurobi_ampl;
model prices.mod;
let price_best_estimate=price_first_estimate;
let volume_best_estimate=volume_first_estimate;
let value_best_estimate=value_first_estimate;
printf "\nPrice %s, volume %s, value %s: ratio PVo/Va = %s", price_best_estimate, volume_best_estimate, value_best_estimate, price_best_estimate*volume_best_estimate/value_best_estimate;
for {i in 1..10}{
solve;
let price_best_estimate := price;
let value_best_estimate := value; # don't actually end up using this, except
let volume_best_estimate := volume;
printf "\nIteration %s: Price %s, volume %s, value %s: ratio PVo/Va = %s",
i, price, volume, value,
price*volume/value;
}
For this small example, the method works as expected. After five iterations, price*volume = value to six significant figures, which is more than good enough for my purposes.
However, when I try to use this method as part of a larger system with many other variables, constraints, and terms in the objective function, I often get "suboptimal" and/or "numeric error" messages from the solver. Often the first couple of iterations go OK, with these messages only displaying at later iterations; despite the messages, the solver still returns a solution that appears reasonable.
The fact that it happens mostly in later iterations leads me to suspect that the error is associated with the case where the optimal solution is very close to the previous best estimate. Note that in this constraint:
value = price*volume_best_estimate +
price_best_estimate*volume - price_best_estimate*volume_best_estimate;
if volume = volume_best_estimate and price = price_best_estimate then the RHS becomes: price*volume + price*volume - price*volume i.e. all three terms are equal, except for the sign.
I'm aware that subtracting two numbers that are almost equal can result in drastic loss of precision, and I suspect something of this sort might be going on.
As far as I can tell, Gurobi is still producing a good solution to the problem given, but I don't like ignoring warning messages. Any thoughts on what's happening here, and how it might be resolved?
Thanks in advance - Geoffrey