I want to minimize:
|0.2126 * R1 + 0.7152 * G1 + 0.0722 * B1 - 7(0.2126 * R2 + 0.7152 * G2 + 0.0722 * B2) - (7-1) * 0.05|
subject to the constraint:
0.2126 * R1 + 0.7152 * G1 + 0.0722 * B1 - (0.2126 * R2 + 0.7152 * G2 + 0.0722 * B2) >= 0
This is my code so far
ratio = 7;
objective_coefficients = [ 0.2126, 0.7152, 0.0722, ratio * -0.2126, ratio * -0.7152, ratio * -0.0722, (1 - ratio) * 0.05]';
constraint_coefficients = [ 0.2126, 0.7152, 0.0722, -0.2126, -0.7152, -0.0722];
constraint_right_hand_side_values = [0]';
variable_lower_bounds = [0, 0, 0, 0, 0, 0, 1]';
variable_upper_bounds = [1, 1, 1, 1, 1, 1, 1];
constriant_types = "L";
variable_types = "CCCCCCC";
sense = 1;
parameters.messsage_level = 1;
parameters.iterations_limit = 100;
[xmin, fmin, status, extra] = glpk(objective_coefficients,
constraint_coefficients,
constraint_right_hand_side_values,
variable_lower_bounds,
variable_upper_bounds,
constriant_types,
variable_types,
sense,
parameters);
The result xmin are all 1s.
In practical terms, demonstrating with a similar-smelling scipy.optimize.linprog
, you need an objective auxiliary variable that's minimized with coefficient 1, having 0 for all other objective coefficients. Add constraint rows so that the objective auxiliary is greater than both the absolute argument and the absolute negative argument; this leaves you with
import numpy as np
from scipy.optimize import linprog
ratio = 7
objective_coefficients = np.array([0, 0, 0, 0, 0, 0, 1])
constraint_coefficients = np.array([
[-0.2126, -0.7152, -0.0722, 0.2126, 0.7152, 0.0722, 0], # -ax <= 0
[ 0.2126, 0.7152, 0.0722, -ratio*0.2126, -ratio *0.7152, -ratio*0.0722, -1], # bx + c <= obj : bx - obj <= -c
[-0.2126, -0.7152, -0.0722, ratio*0.2126, ratio *0.7152, ratio*0.0722, -1], # -bx - c <= obj : -bx - obj <= c
])
constraint_right_hand_side_values = np.array([
0,
ratio*0.05 + 0.36,
-ratio*0.05 - 0.36,
])
variable_lower_bounds = [0, 0, 0, 0, 0, 0, 0]
variable_upper_bounds = [1, 1, 1, 1, 1, 1, np.inf]
result = linprog(
c=objective_coefficients,
bounds=np.array((variable_lower_bounds, variable_upper_bounds)).T,
A_ub=constraint_coefficients,
b_ub=constraint_right_hand_side_values,
)
R1, G1, B1, R2, G2, B2, obj = result.x
print(result)
print()
print('Confirmation:')
print(0.2126*R1 + 0.7152*G1 + 0.0722 - (0.2126*R2 + 0.7152*G2 + 0.0722*B2), '>= 0')
obj_lhs = result.x[:-1] @ [
0.2126, 0.7152, 0.0722, ratio*-0.2126, ratio*-0.7152, ratio*-0.0722
] - (ratio*0.05 + 0.36)
print(f'|{obj_lhs}| <= {obj}')
print()
message: Optimization terminated successfully. (HiGHS Status 7: Optimal)
success: True
status: 0
fun: 0.0
x: [ 0.000e+00 8.918e-01 1.000e+00 0.000e+00 0.000e+00
0.000e+00 0.000e+00]
nit: 1
lower: residual: [ 0.000e+00 8.918e-01 1.000e+00 0.000e+00
0.000e+00 0.000e+00 0.000e+00]
marginals: [ 0.000e+00 0.000e+00 0.000e+00 0.000e+00
0.000e+00 0.000e+00 1.000e+00]
upper: residual: [ 1.000e+00 1.082e-01 0.000e+00 1.000e+00
1.000e+00 1.000e+00 inf]
marginals: [ 0.000e+00 0.000e+00 0.000e+00 0.000e+00
0.000e+00 0.000e+00 0.000e+00]
eqlin: residual: []
marginals: []
ineqlin: residual: [ 7.100e-01 0.000e+00 0.000e+00]
marginals: [-0.000e+00 -0.000e+00 -0.000e+00]
mip_node_count: 0
mip_dual_bound: 0.0
mip_gap: 0.0
Confirmation:
0.71 >= 0
|0.0| <= 0.0
In other words, it's quite possible for your objective to be "perfect" (equal to 0), which means that (using your new definition of the objective function) you can simplify the problem to
import numpy as np
from scipy.optimize import linprog
ratio = 7
coeffs = np.outer([-1, 1], [0.2126, 0.7152, 0.0722])
result = linprog(
c=np.zeros(6),
bounds=np.array((np.zeros(6), np.ones(6))).T,
A_ub= coeffs.reshape((1, -1)), b_ub=[0],
A_eq=(([1], [ratio])*coeffs).reshape((1, -1)), b_eq=[(1 - ratio)*0.05])
R1, G1, B1, R2, G2, B2 = result.x
print(result)
print()
print('Confirmation:')
print(0.2126*R1 + 0.7152*G1 + 0.0722*B1 - (0.2126*R2 + 0.7152*G2 + 0.0722*B2), '>= 0')
obj_lhs = result.x @ [
0.2126, 0.7152, 0.0722, ratio*-0.2126, ratio*-0.7152, ratio*-0.0722,
] - (ratio - 1)*0.05
print(obj_lhs, '== 0')
message: Optimization terminated successfully. (HiGHS Status 7: Optimal)
success: True
status: 0
fun: 0.0
x: [ 1.000e+00 2.125e-02 1.000e+00 0.000e+00 0.000e+00
0.000e+00]
nit: 0
lower: residual: [ 1.000e+00 2.125e-02 1.000e+00 0.000e+00
0.000e+00 0.000e+00]
marginals: [ 0.000e+00 0.000e+00 0.000e+00 0.000e+00
0.000e+00 0.000e+00]
upper: residual: [ 0.000e+00 9.787e-01 0.000e+00 1.000e+00
1.000e+00 1.000e+00]
marginals: [ 0.000e+00 0.000e+00 0.000e+00 0.000e+00
0.000e+00 0.000e+00]
eqlin: residual: [ 0.000e+00]
marginals: [-0.000e+00]
ineqlin: residual: [ 3.000e-01]
marginals: [-0.000e+00]
mip_node_count: 0
mip_dual_bound: 0.0
mip_gap: 0.0
Confirmation:
0.30000000000000004 >= 0
0.0 == 0