Debugging Error: RuntimeError: Unexpected end of file while reading AMPL output

I’m working on a simple optimization problem for selecting bids from advertising campaigns on available ad spaces, subject to several constraints:
(1) only one bid per ad space can be selected,
(2) campaigns are subject to a maximum total spend budget, and
(3) there is a price minimum for each available ad space for each campaign.

Here’s the code I created and ran in Google Colab:

import amplpy
from amplpy import AMPL, ampl_notebook

ampl = ampl_notebook(
    modules=["coin", "highs", "cbc"],  # modules to install
    license_uuid="LICENSE UUID",  # license to use
)  # instantiate AMPL object and register magics

ampl = AMPL()

ampl.eval(r"""
# Define sets
set ADSPACES;  # Unsold Advertisement inventory
set CAMPAIGNS; # Advertising campaigns, bidding on inventory space

# Define parameters
param BidAmount {CAMPAIGNS, ADSPACES} >= 0;  # Amount bid by each CAMPAIGN on each ADSPACE
param PriceFloor {CAMPAIGNS, ADSPACES} >= 0; # Price floors, per CAMPAIGN per ADSPACE
param Budget {CAMPAIGNS} >= 0;               # Maximum budget for each campaign

# Define decision variables
var BidDecision {CAMPAIGNS, ADSPACES} binary;

# Define objective function
maximize TotalRevenue:
  sum {c in CAMPAIGNS, i in ADSPACES} BidAmount[c, i] * BidDecision[c, i];

# Define constraints
subject to OnlyOneWinnerPerAdSpace {i in ADSPACES}:
  sum {c in CAMPAIGNS} BidDecision[c, i] = 1;

subject to PriceFloorConstraint {c in CAMPAIGNS, i in ADSPACES}:
  BidAmount[c, i] * BidDecision[c, i] >= PriceFloor[c, i];

subject to CampaignBudgetConstraint {c in CAMPAIGNS}:
  sum {i in ADSPACES} BidAmount[c, i] * BidDecision[c, i] <= Budget[c];

# Data
data;

set ADSPACES := A1_1, A1_3, A1_6, A2_2, A2_6, A2_7, A3_4, B1_1, B1_3, B1_6, B2_2, B2_6, B2_7, B3_4;
set CAMPAIGNS := CampaignX, CampaignY, CampaignZ;

param BidAmount:
    A1_1 A1_3 A1_6 A2_2 A2_6 A2_7 A3_4 B1_1 B1_3 B1_6 B2_2 B2_6 B2_7 B3_4 :=
CampaignX 3600 2700 3240 2400 3090 3090 3900 2100 2850 2760 3150 3030 3030 3300
CampaignY 3250 3300 3150 3500 3050 3050 3000 3100 3150 3050 2900 2900 2900 3200
CampaignZ 0    0    0    0    0    0    0    0    0    0    0    0    0    0;

param PriceFloor:
    A1_1 A1_3 A1_6 A2_2 A2_6 A2_7 A3_4 B1_1 B1_3 B1_6 B2_2 B2_6 B2_7 B3_4 :=
CampaignX 3000 3000 3000 3000 3000 3000 3000 3000 3000 3000 3000 3000 3000 3000
CampaignY 3000 3000 3000 3000 3000 3000 3000 3000 3000 3000 3000 3000 3000 3000
CampaignZ 3000 3000 3000 3000 3000 3000 3000 3000 3000 3000 3000 3000 3000 3000;

param Budget := CampaignX 30000, CampaignY 30000, CampaignZ 30000;
""")
ampl.solve(solver="cbc") #highs, cplec, cbc, bonmin, base

print(f"{ampl.getVariables()}")

# Print output
print(ampl.getVariable("BidDecision").get_values())

When I run this code, I get the following error message:

RuntimeError: Unexpected end of file while reading AMPL output.
Usually this is caused by the termination of the underlying AMPL interpreter.

The problem seems to be linked to the PriceFloor constraints. I believe this is because the code will execute properly if I edit the problem and program to specify the price floor generically for each ad space instead of per ad space and per campaign. Reference the code below for this example.


ampl.eval(r"""
# Define sets
set ADSPACES;          # Unsold Advertisement inventory
set CAMPAIGNS;         # Advertising campaigns, bidding on inventory space

# Define parameters
param BidAmount {CAMPAIGNS, ADSPACES} >= 0;    # Amount bid by each CAMPAIGN on each ADSPACE
param PriceFloor {i in ADSPACES} >= 0;         # Price floors, should be extended to be per campaign    
param Budget {CAMPAIGNS} >= 0;                 # Maximum budget for each campaign

# Define decision variables
var BidDecision {CAMPAIGNS, ADSPACES} binary;

# Define objective function
maximize TotalRevenue:
  sum {c in CAMPAIGNS, i in ADSPACES} BidAmount[c, i] * BidDecision[c, i];

# Define constraints
subject to OnlyOneWinnerPerAdSpace {i in ADSPACES}:
  sum {c in CAMPAIGNS} BidDecision[c, i] = 1;

subject to PriceFloorConstraint {i in ADSPACES}:
  sum {c in CAMPAIGNS} BidAmount[c, i] * BidDecision[c, i] >= PriceFloor[i];

subject to CampaignBudgetConstraint {c in CAMPAIGNS}:
  sum {i in ADSPACES} BidAmount[c, i] * BidDecision[c, i] <= Budget[c];

# Data
data;

set ADSPACES := A1_1, A1_3, A1_6, A2_2, A2_6, A2_7, A3_4, B1_1, B1_3, B1_6, B2_2, B2_6, B2_7, B3_4;
set CAMPAIGNS := CampaignX, CampaignY, CampaignZ;

param BidAmount:
  A1_1 A1_3 A1_6 A2_2 A2_6 A2_7 A3_4 B1_1 B1_3 B1_6 B2_2 B2_6 B2_7 B3_4 :=
CampaignX  3600 2700 3240 2400 3090 3090 3900 2100 2850 2760 3150 3030 3030 3300
CampaignY  3250 3300 3150 3500 3050 3050 3000 3100 3150 3050 2900 2900 2900 3200
CampaignZ    0    0    0    0    0    0    0    0    0    0    0    0    0    0;

param PriceFloor :=
  A1_1 3000
  A1_3 3000
  A1_6 3000
  A2_2 3000
  A2_6 3000
  A2_7 3000
  A3_4 3000
  B1_1 3000
  B1_3 3000
  B1_6 3000
  B2_2 3000
  B2_6 3000
  B2_7 3000
  B3_4 3000;

param Budget := CampaignX 30000, CampaignY 30000, CampaignZ 30000;
""")

Please help me understand why the code is giving the error.

1 Like

Hi @Sonny,

Thank you for reporting this issue. This reveled a bug in the presolver that was introduced in a recent update and we are currently working on a fix. Meanwhile you can just disabled it with ampl.option["presolve"] = 0.

The issue originates from PriceFloorConstraint which results in many infeasible constraints:

ampl.eval("solexpand PriceFloorConstraint;")
subject to PriceFloorConstraint['CampaignX','A1_1']:
	3600*BidDecision['CampaignX','A1_1'] >= 3000;

subject to PriceFloorConstraint['CampaignX','A1_3']:
	2700*BidDecision['CampaignX','A1_3'] >= 3000;

subject to PriceFloorConstraint['CampaignX','A1_6']:
	3240*BidDecision['CampaignX','A1_6'] >= 3000;

subject to PriceFloorConstraint['CampaignX','A2_2']:
	2400*BidDecision['CampaignX','A2_2'] >= 3000;

subject to PriceFloorConstraint['CampaignX','A2_6']:
	3090*BidDecision['CampaignX','A2_6'] >= 3000;

subject to PriceFloorConstraint['CampaignX','A2_7']:
	3090*BidDecision['CampaignX','A2_7'] >= 3000;

subject to PriceFloorConstraint['CampaignX','A3_4']:
	3900*BidDecision['CampaignX','A3_4'] >= 3000;

subject to PriceFloorConstraint['CampaignX','B1_1']:
	2100*BidDecision['CampaignX','B1_1'] >= 3000;

subject to PriceFloorConstraint['CampaignX','B1_3']:
	2850*BidDecision['CampaignX','B1_3'] >= 3000;

subject to PriceFloorConstraint['CampaignX','B1_6']:
	2760*BidDecision['CampaignX','B1_6'] >= 3000;

subject to PriceFloorConstraint['CampaignX','B2_2']:
	3150*BidDecision['CampaignX','B2_2'] >= 3000;

subject to PriceFloorConstraint['CampaignX','B2_6']:
	3030*BidDecision['CampaignX','B2_6'] >= 3000;

subject to PriceFloorConstraint['CampaignX','B2_7']:
	3030*BidDecision['CampaignX','B2_7'] >= 3000;

subject to PriceFloorConstraint['CampaignX','B3_4']:
	3300*BidDecision['CampaignX','B3_4'] >= 3000;

subject to PriceFloorConstraint['CampaignY','A1_1']:
	3250*BidDecision['CampaignY','A1_1'] >= 3000;

subject to PriceFloorConstraint['CampaignY','A1_3']:
	3300*BidDecision['CampaignY','A1_3'] >= 3000;

subject to PriceFloorConstraint['CampaignY','A1_6']:
	3150*BidDecision['CampaignY','A1_6'] >= 3000;

subject to PriceFloorConstraint['CampaignY','A2_2']:
	3500*BidDecision['CampaignY','A2_2'] >= 3000;

subject to PriceFloorConstraint['CampaignY','A2_6']:
	3050*BidDecision['CampaignY','A2_6'] >= 3000;

subject to PriceFloorConstraint['CampaignY','A2_7']:
	3050*BidDecision['CampaignY','A2_7'] >= 3000;

subject to PriceFloorConstraint['CampaignY','A3_4']:
	3000*BidDecision['CampaignY','A3_4'] >= 3000;

subject to PriceFloorConstraint['CampaignY','B1_1']:
	3100*BidDecision['CampaignY','B1_1'] >= 3000;

subject to PriceFloorConstraint['CampaignY','B1_3']:
	3150*BidDecision['CampaignY','B1_3'] >= 3000;

subject to PriceFloorConstraint['CampaignY','B1_6']:
	3050*BidDecision['CampaignY','B1_6'] >= 3000;

subject to PriceFloorConstraint['CampaignY','B2_2']:
	2900*BidDecision['CampaignY','B2_2'] >= 3000;

subject to PriceFloorConstraint['CampaignY','B2_6']:
	2900*BidDecision['CampaignY','B2_6'] >= 3000;

subject to PriceFloorConstraint['CampaignY','B2_7']:
	2900*BidDecision['CampaignY','B2_7'] >= 3000;

subject to PriceFloorConstraint['CampaignY','B3_4']:
	3200*BidDecision['CampaignY','B3_4'] >= 3000;

subject to PriceFloorConstraint['CampaignZ','A1_1']:
	0 >= 3000;

subject to PriceFloorConstraint['CampaignZ','A1_3']:
	0 >= 3000;

subject to PriceFloorConstraint['CampaignZ','A1_6']:
	0 >= 3000;

subject to PriceFloorConstraint['CampaignZ','A2_2']:
	0 >= 3000;

subject to PriceFloorConstraint['CampaignZ','A2_6']:
	0 >= 3000;

subject to PriceFloorConstraint['CampaignZ','A2_7']:
	0 >= 3000;

subject to PriceFloorConstraint['CampaignZ','A3_4']:
	0 >= 3000;

subject to PriceFloorConstraint['CampaignZ','B1_1']:
	0 >= 3000;

subject to PriceFloorConstraint['CampaignZ','B1_3']:
	0 >= 3000;

subject to PriceFloorConstraint['CampaignZ','B1_6']:
	0 >= 3000;

subject to PriceFloorConstraint['CampaignZ','B2_2']:
	0 >= 3000;

subject to PriceFloorConstraint['CampaignZ','B2_6']:
	0 >= 3000;

subject to PriceFloorConstraint['CampaignZ','B2_7']:
	0 >= 3000;

subject to PriceFloorConstraint['CampaignZ','B3_4']:
	0 >= 3000;
1 Like

Thank you @ fdabrandao for your prompt response.

Your suggestion to use the “solexpand” command has indeed helped identify the infeasible constraints that were causing the issue.

Regarding this issue, do you have any advice on how to construct my price floor constraints to avoid this issue. Or would it perhaps be better handled outside of the solver script (for example, pre-setting all bids that did not meet the price floor to 0 instead of building in the constraint)?

Is the objective to not bid to a campaign if the BidAmount[c, i] is less than PriceFloor[c, i]? If that is the case you can model that with:

subject to PriceFloorConstraint {c in CAMPAIGNS, i in ADSPACES: BidAmount[c, i] < PriceFloor[c, i]}:
    BidDecision[c, i] == 0;

or in the variable declaration itself with:

var BidDecision {c in CAMPAIGNS, i in ADSPACES} binary <= if BidAmount[c, i] >= PriceFloor[c, i] then 1 else 0;

On bigger models it is usually better to not include variables that will be fixed to zero in the model (i.e., BidDecision would need to be indexed over a set of variable pairs), but in this case the model size does not seem problematic.