Pooling Problem with Nonlinear and Setup Costs#
Description: pooling problem with extra nonlinear and setup costs, solved by Knitro with MP2NL
Tags: pooling, minimum-cost flow, blending, nonlinear, setup costs, semi-continuous, AMPLPY, Knitro, MP2NL
Notebook author: Gleb Belov <gleb@ampl.com>
Reference:
Milk pooling and blending. Hands-on optimization with AMPL in Python.
Standard pooling problem in Gurobi, accessed March 12, 2026.
# Install dependencies
%pip install -q amplpy pandas seaborn networkx
# Google Colab & Kaggle integration
from amplpy import AMPL, ampl_notebook
ampl = ampl_notebook(
modules=["knitro", "mp2nl"], # modules to install
license_uuid="default", # license to use
) # instantiate AMPL object and register magics
Motivation#
The pooling problem is a challenging problem in the petrochemical refining, wastewater treatment and mining industries. This problem can be regarded as a generalization of the minimum-cost flow problem and the blending problem. It is important because of the significant savings it can generate, so it comes at no surprise that it has been studied extensively.
We take the so-called Q-formulation as the basic model. We solve the standard case first, then add nonlinearities, discrete setup costs, and semi-continuity constraints. The corresponding expressions are written using AMPL logical constraint syntax. To solve the models with Artelys Knitro, we use meta-driver MP2NL.
The Q-formulation in AMPL#
Use %%ampl_eval to evaluate AMPL commands and declarations
%%ampl_eval
# AMPL Model for the Standard Pooling Problem (Q-Formulation)
# Sets
set SOURCES;
set POOLS;
set TARGETS;
set ATTRS;
# Edges for flow variables (defined dynamically based on data)
set S2T within {SOURCES, TARGETS};
set S2P within {SOURCES, POOLS};
set P2T within {POOLS, TARGETS};
# Parameters
param cost {SOURCES};
param supply {SOURCES};
param content {SOURCES, ATTRS};
param price {TARGETS};
param demand {TARGETS};
param min_tol {TARGETS, ATTRS};
param max_tol {TARGETS, ATTRS};
param cap {POOLS};
# Variables
var flow_s2t {(s,t) in S2T} >= 0 <= supply[s]; # Flow from source to target
var flow_p2t {(p,t) in P2T} >= 0 <= cap[p]; # Flow from pool to target
var prop_s2p {S2P} >= 0, <= 1; # Proportion from source to pool
# Defined variables
# They are essentially macros for readability and presolve
var pool_outflow {p in POOLS} =
sum {t in TARGETS: (p,t) in P2T} flow_p2t[p,t];
var source_pool_flow {(s,p) in S2P} = # flow_s2p: implicit
prop_s2p[s,p] * pool_outflow[p];
var source_outflow {s in SOURCES} =
sum {t in TARGETS: (s,t) in S2T} flow_s2t[s,t] +
sum {p in POOLS: (s,p) in S2P} source_pool_flow[s, p];
var target_inflow {t in TARGETS} =
sum {s in SOURCES: (s,t) in S2T} flow_s2t[s,t] +
sum {p in POOLS: (p,t) in P2T} flow_p2t[p,t];
var target_attr_inflow {t in TARGETS, attr in ATTRS} =
sum {s in SOURCES: (s,t) in S2T} content[s,attr] * flow_s2t[s,t] +
sum {p in POOLS: (p,t) in P2T}
flow_p2t[p,t] *
sum {s in SOURCES: (s,p) in S2P} content[s,attr] * prop_s2p[s,p];
# Objective Function: Maximize Total Profit
maximize TotalProfit:
sum {t in TARGETS} price[t] * target_inflow[t]
- sum {s in SOURCES} cost[s] * source_outflow[s];
# Constraints
# 1. Source capacity
subject to Source_capacity {s in SOURCES}:
source_outflow[s] <= supply[s];
# 2. Pool capacity
subject to Pool_capacity {p in POOLS}:
pool_outflow[p] <= cap[p];
# 3. Target demand
subject to Target_demand {t in TARGETS}:
target_inflow[t] >= demand[t];
# 4. Pool inflow (sum of proportions for each pool must be 1)
subject to Pool_inflow {p in POOLS}:
sum {s in SOURCES: (s,p) in S2P} prop_s2p[s,p] = 1;
# 5.1 Target (min) tolerances
subject to Target_min_tolerances {t in TARGETS, attr in ATTRS}:
target_attr_inflow[t, attr] >= min_tol[t,attr] * target_inflow[t];
# 5.2 Target (max) tolerances
subject to Target_max_tolerances {t in TARGETS, attr in ATTRS}:
target_attr_inflow[t, attr] <= max_tol[t,attr] * target_inflow[t];
Random instance data#
We generate the insatnce parameters randomly.
import random
import math
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
def generate_pooling_data(num_sources=3, num_pools=2, num_targets=3, num_attrs=4,
source_cost_range=(10, 50), source_supply_range=(500, 2000),
target_price_range=(100, 300), target_demand_range=(100, 1000),
pool_cap_range=(500, 2000),
s2t_density=0.5, s2p_density=0.8, p2t_density=0.8,
content_deviation_percent=0.05, # Max % deviation for source content from ref
tolerance_deviation_percent=0.10, # Max % deviation for min_tol from ref
tolerance_gap_percent=0.05): # Average % gap for max_tol above min_tol
sources = [f"s{i+1}" for i in range(num_sources)]
pools = [f"p{i+1}" for i in range(num_pools)]
targets = [f"t{i+1}" for i in range(num_targets)]
attrs = [f"attr{i+1}" for i in range(num_attrs)]
# Generate diverse reference ranges for attributes
# This mimics having some low-value attributes (like 'den') and some high-value ones (like 'roz')
attr_range_templates = [
{'ref_range': (0.5, 1.0)}, # Low values
{'ref_range': (2.0, 5.0)}, # Medium-low values
{'ref_range': (50.0, 70.0)}, # Medium-high values
{'ref_range': (90.0, 110.0)} # High values
]
reference_attr_configs = {}
for i, attr in enumerate(attrs):
# Assign a template in a round-robin fashion or randomly
template = random.choice(attr_range_templates)
reference_attr_configs[attr] = template
cost = {s: random.uniform(*source_cost_range) for s in sources}
supply = {s: random.uniform(*source_supply_range) for s in sources}
price = {t: random.uniform(*target_price_range) for t in targets}
demand = {t: random.uniform(*target_demand_range) for t in targets}
cap = {p: random.uniform(*pool_cap_range) for p in pools}
# 1. Generate reference content for each attribute
reference_content_values = {
attr: random.uniform(*config['ref_range'])
for attr, config in reference_attr_configs.items()
}
# 2. Generate source contents with deviation from reference
content = {}
for s in sources:
for a in attrs:
ref_val = reference_content_values[a]
dev_factor = random.uniform(1 - content_deviation_percent, 1 + content_deviation_percent)
content[s, a] = max(0.0, ref_val * dev_factor) # Ensure non-negative content
# 3. Generate target tolerances with deviation from reference and controlled gap
min_tol = {}
max_tol = {}
for t in targets:
for a in attrs:
ref_val = reference_content_values[a]
# Min tolerance deviation from reference
dev_min_factor = random.uniform(1 - tolerance_deviation_percent, 1)
min_t = max(0.0, ref_val * dev_min_factor)
# Max tolerance based on min_t and the gap parameter
gap_factor = random.uniform(1 + tolerance_gap_percent * 0.8, 1 + tolerance_gap_percent * 1.2)
max_t = min_t * gap_factor
max_t = max(min_t, max_t) # Ensure max_t is always >= min_t
min_tol[t, a] = min_t
max_tol[t, a] = max_t
s2t = [(s, t) for s in sources for t in targets if random.random() < s2t_density]
s2p = [(s, p) for s in sources for p in pools if random.random() < s2p_density]
p2t = [(p, t) for p in pools for t in targets if random.random() < p2t_density]
return {
"sources": sources,
"pools": pools,
"targets": targets,
"attrs": attrs,
"cost": cost,
"supply": supply,
"content": content,
"price": price,
"demand": demand,
"min_tol": min_tol,
"max_tol": max_tol,
"cap": cap,
"s2t": s2t,
"s2p": s2p,
"p2t": p2t,
}
# Generate random data with customizable parameters
# You can change these values to generate different problem instances
num_sources_param = 23
num_pools_param = 12
num_targets_param = 16
num_attrs_param = 5
random.seed(42) # Same seed for reproducibility
data = generate_pooling_data(
num_sources=num_sources_param,
num_pools=num_pools_param,
num_targets=num_targets_param,
num_attrs=num_attrs_param, # Pass the number of attributes
s2t_density=0.1, s2p_density=0.2, p2t_density=0.4,
content_deviation_percent=0.05, # Source content varies by up to +/- 5% from reference
tolerance_deviation_percent=0.005, # Min tolerance varies by up to +/- 10% from reference
tolerance_gap_percent=0.015 # Max tolerance is avg 5% above min tolerance (with variation)
)
Data statistics#
# Display data statistics
print("\n--- Data Statistics ---")
print(f"Number of Sources: {len(data['sources'])}")
print(f"Number of Pools: {len(data['pools'])}")
print(f"Number of Targets: {len(data['targets'])}")
print(f"Number of Attributes: {len(data['attrs'])}")
print("\nCost per Source (Min/Max):", round(min(data['cost'].values()),2), "/", round(max(data['cost'].values()),2))
print("Supply per Source (Min/Max):", round(min(data['supply'].values()),2), "/", round(max(data['supply'].values()),2))
print("Price per Target (Min/Max):", round(min(data['price'].values()),2), "/", round(max(data['price'].values()),2))
print("Demand per Target (Min/Max):", round(min(data['demand'].values()),2), "/", round(max(data['demand'].values()),2))
print("Capacity per Pool (Min/Max):", round(min(data['cap'].values()),2), "/", round(max(data['cap'].values()),2))
print(f"Number of Source-to-Target edges: {len(data['s2t'])}")
print(f"Number of Source-to-Pool edges: {len(data['s2p'])}")
print(f"Number of Pool-to-Target edges: {len(data['p2t'])}")
--- Data Statistics ---
Number of Sources: 23
Number of Pools: 12
Number of Targets: 16
Number of Attributes: 5
Cost per Source (Min/Max): 11.27 / 44.77
Supply per Source (Min/Max): 565.18 / 1977.83
Price per Target (Min/Max): 114.28 / 285.08
Demand per Target (Min/Max): 150.34 / 921.82
Capacity per Pool (Min/Max): 707.5 / 1995.99
Number of Source-to-Target edges: 27
Number of Source-to-Pool edges: 53
Number of Pool-to-Target edges: 76
Contents and tolerances#
print("\n--- Content of Attributes in Sources ---")
content_df = pd.Series(data['content']).unstack()
content_df.index.name = 'Source'
content_df.columns.name = 'Attribute'
display(content_df)
print("\n--- Minimum Tolerances for Attributes in Targets ---")
min_tol_df = pd.Series(data['min_tol']).unstack()
min_tol_df.index.name = 'Target'
min_tol_df.columns.name = 'Attribute'
display(min_tol_df)
print("\n--- Maximum Tolerances for Attributes in Targets ---")
max_tol_df = pd.Series(data['max_tol']).unstack()
max_tol_df.index.name = 'Target'
max_tol_df.columns.name = 'Attribute'
display(max_tol_df)
--- Content of Attributes in Sources ---
| Attribute | attr1 | attr2 | attr3 | attr4 | attr5 |
|---|---|---|---|---|---|
| Source | |||||
| s1 | 0.802453 | 0.723017 | 63.034043 | 3.272937 | 2.860222 |
| s10 | 0.806713 | 0.724535 | 64.573505 | 3.491046 | 2.806537 |
| s11 | 0.815202 | 0.685390 | 62.980816 | 3.361060 | 2.864306 |
| s12 | 0.794332 | 0.674929 | 59.218314 | 3.241103 | 2.769094 |
| s13 | 0.805264 | 0.658262 | 63.204673 | 3.253984 | 2.635094 |
| s14 | 0.760802 | 0.680643 | 62.005420 | 3.328740 | 2.750225 |
| s15 | 0.801336 | 0.707848 | 64.285399 | 3.430093 | 2.683458 |
| s16 | 0.796047 | 0.685949 | 59.405924 | 3.458270 | 2.714112 |
| s17 | 0.791109 | 0.717575 | 59.157296 | 3.456388 | 2.794504 |
| s18 | 0.763132 | 0.708185 | 63.778970 | 3.271139 | 2.669299 |
| s19 | 0.801101 | 0.667470 | 59.957997 | 3.391428 | 2.857385 |
| s2 | 0.818230 | 0.710981 | 60.928171 | 3.333854 | 2.660091 |
| s20 | 0.764312 | 0.713711 | 64.121836 | 3.267272 | 2.796147 |
| s21 | 0.801444 | 0.658786 | 59.399342 | 3.490467 | 2.681635 |
| s22 | 0.790734 | 0.691093 | 64.175602 | 3.541147 | 2.661875 |
| s23 | 0.758466 | 0.684797 | 64.558673 | 3.501212 | 2.695095 |
| s3 | 0.758553 | 0.707761 | 63.277982 | 3.564787 | 2.826393 |
| s4 | 0.798818 | 0.665132 | 62.693599 | 3.520459 | 2.756353 |
| s5 | 0.774171 | 0.683654 | 59.822156 | 3.558528 | 2.870591 |
| s6 | 0.831609 | 0.699234 | 61.847218 | 3.272024 | 2.716504 |
| s7 | 0.836943 | 0.713624 | 60.304515 | 3.315938 | 2.772794 |
| s8 | 0.764581 | 0.708441 | 63.874514 | 3.566863 | 2.763250 |
| s9 | 0.768333 | 0.703445 | 64.684556 | 3.290154 | 2.761864 |
--- Minimum Tolerances for Attributes in Targets ---
| Attribute | attr1 | attr2 | attr3 | attr4 | attr5 |
|---|---|---|---|---|---|
| Target | |||||
| t1 | 0.796994 | 0.691634 | 61.758848 | 3.390834 | 2.750603 |
| t10 | 0.796419 | 0.689067 | 61.897053 | 3.387808 | 2.749864 |
| t11 | 0.795625 | 0.691950 | 61.840210 | 3.391158 | 2.751487 |
| t12 | 0.795859 | 0.692122 | 61.735642 | 3.399640 | 2.742663 |
| t13 | 0.795740 | 0.690551 | 61.892522 | 3.401095 | 2.743541 |
| t14 | 0.795804 | 0.689162 | 61.716891 | 3.398695 | 2.745031 |
| t15 | 0.797714 | 0.690932 | 61.620024 | 3.393013 | 2.746481 |
| t16 | 0.794675 | 0.689580 | 61.743178 | 3.400856 | 2.753420 |
| t2 | 0.795465 | 0.690572 | 61.772610 | 3.395773 | 2.741415 |
| t3 | 0.797653 | 0.692181 | 61.787407 | 3.388524 | 2.748255 |
| t4 | 0.795254 | 0.690009 | 61.648698 | 3.394911 | 2.753357 |
| t5 | 0.796693 | 0.689268 | 61.764796 | 3.393069 | 2.743835 |
| t6 | 0.795962 | 0.689969 | 61.858049 | 3.398496 | 2.753303 |
| t7 | 0.797718 | 0.692002 | 61.656305 | 3.390714 | 2.749939 |
| t8 | 0.796231 | 0.692066 | 61.804547 | 3.387879 | 2.742273 |
| t9 | 0.794858 | 0.691365 | 61.642815 | 3.398891 | 2.740967 |
--- Maximum Tolerances for Attributes in Targets ---
| Attribute | attr1 | attr2 | attr3 | attr4 | attr5 |
|---|---|---|---|---|---|
| Target | |||||
| t1 | 0.810051 | 0.702680 | 62.570321 | 3.432714 | 2.784616 |
| t10 | 0.808029 | 0.698843 | 63.000875 | 3.435735 | 2.793866 |
| t11 | 0.807845 | 0.704296 | 62.925789 | 3.435159 | 2.787427 |
| t12 | 0.806266 | 0.703677 | 62.724612 | 3.445498 | 2.787116 |
| t13 | 0.805474 | 0.699665 | 62.765080 | 3.459689 | 2.787329 |
| t14 | 0.806684 | 0.700630 | 62.646127 | 3.456683 | 2.778426 |
| t15 | 0.808537 | 0.703300 | 62.580028 | 3.449739 | 2.795658 |
| t16 | 0.808500 | 0.698038 | 62.676706 | 3.455682 | 2.798637 |
| t2 | 0.805250 | 0.702669 | 62.534963 | 3.453868 | 2.775430 |
| t3 | 0.809157 | 0.702854 | 62.543589 | 3.442552 | 2.786451 |
| t4 | 0.807993 | 0.699389 | 62.627248 | 3.454574 | 2.786552 |
| t5 | 0.808944 | 0.699763 | 62.555060 | 3.435187 | 2.781453 |
| t6 | 0.808108 | 0.702322 | 62.796661 | 3.450587 | 2.788053 |
| t7 | 0.808557 | 0.703388 | 62.500413 | 3.438378 | 2.797011 |
| t8 | 0.806985 | 0.700581 | 62.853747 | 3.435314 | 2.791301 |
| t9 | 0.806504 | 0.701988 | 62.732062 | 3.442717 | 2.779931 |
Data visualization#
# Data Visualization (Histograms)
# Adjust subplot grid if num_attrs_param is large, or just plot one example
num_plots = min(len(data['attrs']), 6) # Plot up to 6 attribute distributions if many attrs
num_rows = math.ceil(num_plots / 3)
fig, axes = plt.subplots(num_rows, 3, figsize=(18, 5 * num_rows))
fig.suptitle('Distribution of Generated Data Parameters', fontsize=16)
# Flatten axes for easier iteration if there are multiple rows
if num_rows > 1:
axes = axes.flatten()
else: # Handle case where there's only one row (axes is a 1D array or single object)
if isinstance(axes, np.ndarray) and axes.ndim == 1:
pass # already flat
else:
axes = [axes] # make it iterable
current_plot_idx = 0
sns.histplot(list(data['cost'].values()), bins=5, kde=True, ax=axes[current_plot_idx], color='skyblue')
axes[current_plot_idx].set_title('Source Costs')
current_plot_idx += 1
sns.histplot(list(data['supply'].values()), bins=5, kde=True, ax=axes[current_plot_idx], color='lightcoral')
axes[current_plot_idx].set_title('Source Supplies')
current_plot_idx += 1
sns.histplot(list(data['price'].values()), bins=5, kde=True, ax=axes[current_plot_idx], color='lightgreen')
axes[current_plot_idx].set_title('Target Prices')
current_plot_idx += 1
sns.histplot(list(data['demand'].values()), bins=5, kde=True, ax=axes[current_plot_idx], color='lightsalmon')
axes[current_plot_idx].set_title('Target Demands')
current_plot_idx += 1
sns.histplot(list(data['cap'].values()), bins=5, kde=True, ax=axes[current_plot_idx], color='mediumpurple')
axes[current_plot_idx].set_title('Pool Capacities')
current_plot_idx += 1
# Plot distribution for one example attribute content
if len(data['attrs']) > 0:
attr_to_plot = data['attrs'][0]
attr_contents = [val for (s, a), val in data['content'].items() if a == attr_to_plot]
sns.histplot(attr_contents, bins=5, kde=True, ax=axes[current_plot_idx], color='gold')
axes[current_plot_idx].set_title(f'Content for {attr_to_plot} attribute')
current_plot_idx += 1
# Hide any remaining empty subplots
for i in range(current_plot_idx, len(axes)):
fig.delaxes(axes[i])
plt.tight_layout(rect=[0, 0.03, 1, 0.95])
plt.show()
Network visualization#
import networkx as nx
import matplotlib.pyplot as plt
def visualize_pooling_network(data):
G = nx.DiGraph()
# Add Source nodes with supply
for s in data['sources']:
G.add_node(s, node_type='source', capacity=data['supply'][s])
# Add Pool nodes with capacity
for p in data['pools']:
G.add_node(p, node_type='pool', capacity=data['cap'][p])
# Add Target nodes with demand
for t in data['targets']:
# Demand is a dictionary, might have multiple attributes. Let's sum for simplicity for visualization.
total_demand = sum(data['demand'].get(t, 0) for t_key in data['demand'] if t_key == t)
G.add_node(t, node_type='target', capacity=total_demand)
# Add edges
for s, t in data['s2t']:
G.add_edge(s, t, edge_type='s2t')
for s, p in data['s2p']:
G.add_edge(s, p, edge_type='s2p')
for p, t in data['p2t']:
G.add_edge(p, t, edge_type='p2t')
# Define node colors and labels
node_colors = []
node_labels = {}
for node in G.nodes():
if G.nodes[node]['node_type'] == 'source':
node_colors.append('skyblue')
node_labels[node] = f"{node}\nSupply: {G.nodes[node]['capacity']:.0f}"
elif G.nodes[node]['node_type'] == 'pool':
node_colors.append('lightgreen')
node_labels[node] = f"{node}\nCapacity: {G.nodes[node]['capacity']:.0f}"
else: # target
node_colors.append('salmon')
node_labels[node] = f"{node}\nDemand: {G.nodes[node]['capacity']:.0f}"
plt.figure(figsize=(12, 8))
# Use a layered layout to better visualize the tripartite graph
pos = {}
source_nodes = [n for n, attr in G.nodes(data=True) if attr['node_type'] == 'source']
pool_nodes = [n for n, attr in G.nodes(data=True) if attr['node_type'] == 'pool']
target_nodes = [n for n, attr in G.nodes(data=True) if attr['node_type'] == 'target']
# Position sources, pools, and targets in distinct columns
for i, node in enumerate(source_nodes):
pos[node] = (0, i)
for i, node in enumerate(pool_nodes):
pos[node] = (1, i)
for i, node in enumerate(target_nodes):
pos[node] = (2, i)
nx.draw(G, pos, with_labels=False, node_color=node_colors, node_size=3000, alpha=0.9, font_size=8, font_weight='bold')
nx.draw_networkx_labels(G, pos, labels=node_labels, font_size=8)
# No explicit arc capacities in the problem formulation, so we'll just show the arcs.
# If specific capacities were defined for each s2p, s2t, p2t flow, they could be added here.
plt.title('Pooling Problem Network Visualization with Node Capacities/Demands')
plt.axis('off')
# plt.tight_layout()
plt.show()
# Call the visualization function with the generated data
visualize_pooling_network(data)
Load data directly from Python data structures using amplpy#
# Set the data
# Sets
ampl.getSet('SOURCES').setValues(data['sources'])
ampl.getSet('POOLS').setValues(data['pools'])
ampl.getSet('TARGETS').setValues(data['targets'])
ampl.getSet('ATTRS').setValues(data['attrs'])
# Edges
ampl.getSet('S2T').setValues(data['s2t'])
ampl.getSet('S2P').setValues(data['s2p'])
ampl.getSet('P2T').setValues(data['p2t'])
# Parameters
ampl.getParameter('cost').setValues(data['cost'])
ampl.getParameter('supply').setValues(data['supply'])
ampl.getParameter('content').setValues(data['content'])
ampl.getParameter('price').setValues(data['price'])
ampl.getParameter('demand').setValues(data['demand'])
ampl.getParameter('min_tol').setValues(data['min_tol'])
ampl.getParameter('max_tol').setValues(data['max_tol'])
ampl.getParameter('cap').setValues(data['cap'])
print("AMPL model loaded and data assigned successfully.")
AMPL model loaded and data assigned successfully.
Solve the standard model#
Solve with Knitro#
ampl.option["solver"] = "knitro"
ampl.option["knitro_options"] = "outlev=1 ms_enable=1"
ampl.snapshot('pooling.run') # Debugging feature
print("\nSolving the AMPL model...")
ampl.solve()
# ampl.solve(solver="gurobi", gurobi_options="outlev=1 lim:time=30")
Solving the AMPL model...
Artelys Knitro 15.1.0: outlev=1
ms_enable=1
=======================================
Commercial License
Artelys Knitro 15.1.0
=======================================
Knitro using up to 8 threads.
Knitro presolve eliminated 0 variables and 0 constraints.
concurrent_evals 0
datacheck 0
feastol 1e-06
feastol_abs 0.001
findiff_numthreads 1
hessian_no_f 1
hessopt 1
ms_enable 1
opttol 1e-06
opttol_abs 0.001
outlev 1
Problem Characteristics | Presolved
-----------------------
Problem type: QCQP
Objective: maximize / quadratic
Number of variables: 155 | 155
bounds: lower upper range | lower upper range
0 0 155 | 0 0 155
free fixed | free fixed
0 0 | 0 0
Number of constraints: 220 | 220
eq. ineq. range | eq. ineq. range
linear: 11 29 0 | 11 29 0
quadratic: 0 180 0 | 0 180 0
Number of nonzeros:
objective Jacobian Hessian | objective Jacobian Hessian
linear: 103 1292 | 103 1292
quadratic: 122 4448 336 | 122 4448 336
total: 155 5040 336 | 155 5040 336
Knitro parallel multistart will run with 8 threads.
Return codes description
------------------------
0: The final solution satisfies the termination conditions for verifying optimality.
-100 to -199: A feasible approximate solution was found.
-200 to -299: Knitro terminated at an infeasible point.
-300 to -301: The problem was determined to be unbounded.
-400 to -499: Knitro terminated because it reached a pre-defined limit.
-400 to -409: A feasible point was found.
-410 to -419: No feasible point was found.
-500 to -599: Knitro terminated with an input error or some non-standard error.
A more detailed description of individual return codes and their corresponding
termination messages is provided at
https://www.artelys.com/app/docs/knitro/3_referenceManual/returnCodes.html
Solve Thrd Status Objective FeasError Opt Error Solve Time Real Time
----- ---- ------ ------------ ----------- ----------- ----------- -----------
5 7 0 4.16560e+06 3.14060e-11 1.64892e-06 5.15610e-02 0.664054
6 1 0 4.16560e+06 5.84134e-09 1.12709e-10 5.92010e-02 0.664054
9 1 0 4.16560e+06 7.02869e-11 3.29499e-06 3.84070e-02 0.664054
11 4 0 4.15307e+06 9.86802e-11 5.86301e-10 3.38190e-02 0.664054
7 4 0 4.23238e+06 1.11140e-09 4.26218e-09 0.104792 0.708017
20 0 0 4.14514e+06 3.85626e-10 9.48260e-08 3.63880e-02 0.708017
27 1 0 4.16560e+06 9.91918e-11 3.81120e-11 3.28230e-02 0.708017
29 1 0 4.16560e+06 7.52038e-11 1.12425e-07 4.82080e-02 0.708017
23 1 0 4.23238e+06 8.69562e-11 1.48566e-10 6.61640e-02 0.742399
24 6 0 4.23238e+06 8.75818e-07 5.52202e-06 9.33630e-02 0.742399
12 4 0 4.22041e+06 8.82494e-11 4.99180e-10 0.127042 0.762067
13 0 0 4.23238e+06 2.78237e-09 1.60785e-06 0.151476 0.762067
18 2 0 4.23238e+06 4.81671e-08 1.62282e-05 0.115582 0.762067
25 5 0 4.22805e+06 7.79892e-11 4.62167e-10 7.70020e-02 0.762067
31 1 0 4.23238e+06 5.85203e-11 8.23955e-10 0.114380 0.762067
19 6 0 4.22041e+06 9.92486e-11 3.89935e-11 0.133569 0.800481
16 5 0 4.13532e+06 2.29193e-10 9.89353e-11 0.174785 0.833429
3 0 0 4.23307e+06 4.15457e-09 1.49846e-06 0.255818 0.863843
0 3 0 4.15307e+06 8.92942e-09 2.07055e-05 0.268530 0.863843
14 4 0 4.22806e+06 1.06343e-09 1.86943e-06 0.236256 0.863843
8 7 0 4.22752e+06 3.99377e-08 2.60411e-06 0.280277 0.905410
1 5 0 4.22806e+06 3.81493e-07 2.93715e-05 0.326601 1.01695
4 2 0 4.22806e+06 3.81493e-07 2.93715e-05 0.343142 1.01695
2 6 0 4.22806e+06 3.81493e-07 2.93715e-05 0.345876 1.01695
30 5 0 4.23235e+06 9.21485e-14 1.00063e-08 0.290675 1.01695
28 6 0 4.22876e+06 4.11979e-07 5.18046e-06 0.354302 1.01695
10 1 0 4.22041e+06 9.50138e-11 7.94588e-07 0.379189 1.13170
36 4 0 4.23238e+06 7.51470e-11 2.15060e-10 6.17980e-02 1.21465
26 4 0 4.22752e+06 1.31680e-07 4.87632e-06 0.368114 1.23564
38 4 0 4.22041e+06 9.85949e-11 6.56479e-11 5.52360e-02 1.23564
41 0 0 4.16560e+06 9.77707e-11 7.16679e-11 3.74130e-02 1.23564
45 0 0 4.16560e+06 9.91349e-11 2.08384e-08 4.73410e-02 1.23564
21 0 0 4.22041e+06 9.76854e-11 7.32921e-11 0.381125 1.28601
39 4 0 4.23238e+06 1.60557e-11 2.77640e-08 9.01270e-02 1.28601
42 0 0 4.23235e+06 8.64384e-09 1.32977e-06 6.99580e-02 1.28601
34 7 0 4.22041e+06 3.92788e-11 4.65083e-06 0.152029 1.32603
33 0 0 4.15307e+06 5.69433e-13 1.16499e-07 0.152813 1.32603
17 7 0 4.23305e+06 1.91721e-08 4.01618e-07 0.437182 1.39924
32 1 0 4.22041e+06 1.21822e-08 1.00550e-06 0.255497 1.39924
40 7 0 4.23138e+06 9.44800e-14 3.05443e-09 0.192267 1.39924
46 0 0 4.16560e+06 3.62377e-11 2.66650e-09 0.115504 1.59283
50 3 0 4.16560e+06 1.38825e-08 3.01559e-07 2.57450e-02 1.59283
47 7 0 4.16560e+06 1.59702e-10 9.22583e-10 0.185864 1.59283
49 0 0 4.23238e+06 9.31806e-11 5.10428e-11 4.27970e-02 1.64141
51 0 0 4.15307e+06 9.34506e-10 1.43591e-07 3.35830e-02 1.64141
55 7 0 4.14514e+06 1.57652e-14 7.06713e-09 3.24890e-02 1.64141
48 5 0 4.23238e+06 9.47011e-11 4.56877e-11 9.71920e-02 1.66858
58 6 0 4.22752e+06 2.02657e-07 5.59106e-06 7.78810e-02 1.74544
61 6 0 4.23238e+06 2.87482e-08 1.99186e-05 3.79280e-02 1.74544
60 4 0 4.23238e+06 2.10450e-07 5.86487e-06 5.06160e-02 1.74544
62 3 0 4.15307e+06 8.17374e-11 4.81416e-07 4.87730e-02 1.74544
35 5 0 4.23227e+06 1.60026e-07 3.48267e-06 0.380754 1.81122
59 3 0 4.23234e+06 7.40670e-11 7.84315e-07 8.23170e-02 1.81122
63 6 0 4.22088e+06 6.28120e-10 2.45894e-08 7.31400e-02 1.81122
52 3 0 4.22876e+06 6.73792e-06 7.51703e-06 0.196180 1.98960
15 3 0 4.16560e+06 1.01863e-10 9.93907e-11 1.04730 2.03247
44 1 0 4.16373e+06 9.55254e-11 5.70179e-10 0.718007 2.06262
70 4 0 4.15307e+06 9.87711e-10 1.71643e-09 3.82710e-02 2.06262
65 3 0 4.13490e+06 9.61506e-11 1.98164e-10 0.164255 2.24235
68 4 0 4.23234e+06 2.65862e-05 7.56912e-06 5.46210e-02 2.24235
67 1 0 4.23238e+06 8.93721e-11 7.11136e-11 0.122412 2.24235
71 1 0 4.16560e+06 9.90497e-11 1.01892e-08 7.71180e-02 2.24235
73 0 0 4.16560e+06 1.58286e-08 2.40691e-05 2.98040e-02 2.24235
75 1 0 4.16560e+06 9.93623e-11 6.18300e-08 3.89790e-02 2.24235
22 2 0 4.15307e+06 6.80132e-11 1.67516e-09 1.04604 2.31005
37 6 0 4.22088e+06 5.47516e-10 1.87489e-10 0.582772 2.31005
43 4 0 4.15307e+06 9.18874e-11 1.00189e-09 0.504697 2.31005
64 4 0 4.23238e+06 3.12446e-09 9.70306e-06 0.225141 2.31005
69 3 0 4.23234e+06 6.40483e-11 2.27976e-09 0.105213 2.31005
72 4 0 4.16560e+06 9.98170e-11 2.32212e-11 9.08810e-02 2.31005
66 6 0 4.14512e+06 9.59233e-11 7.49477e-11 0.300217 2.61666
76 0 0 4.16560e+06 4.00746e-11 3.27201e-06 3.45040e-02 2.61666
77 7 0 4.23238e+06 8.52936e-11 1.19584e-10 4.77960e-02 2.69434
79 1 0 4.23238e+06 2.90034e-07 1.28003e-05 6.11930e-02 2.69434
84 5 0 4.16560e+06 4.12456e-10 6.55087e-06 3.88040e-02 2.69434
83 7 0 4.23238e+06 9.52980e-11 4.02209e-11 5.03290e-02 2.69434
85 5 0 4.16560e+06 1.00044e-10 3.55838e-11 4.67210e-02 2.69434
88 5 0 4.22041e+06 1.65019e-08 2.22784e-07 5.45270e-02 2.69434
89 6 0 4.16560e+06 8.73115e-10 5.69020e-11 3.47210e-02 2.69434
82 0 0 4.23235e+06 8.20677e-11 1.36321e-10 6.09460e-02 2.73431
92 6 0 4.16560e+06 2.97860e-11 5.60658e-06 4.11100e-02 2.73431
53 0 0 4.22752e+06 1.43700e-09 1.91897e-08 0.628788 2.77365
91 4 0 4.22876e+06 9.33278e-09 6.59006e-09 6.20970e-02 2.77365
56 7 0 4.16560e+06 8.97273e-11 2.38128e-09 0.784808 2.86152
78 6 0 4.13134e+06 8.79083e-11 3.11724e-08 0.198134 2.86152
80 4 0 4.22752e+06 4.54529e-08 4.16085e-06 0.173601 2.86152
96 2 0 4.15307e+06 1.02972e-10 7.66989e-10 3.08890e-02 2.86152
54 5 0 4.16560e+06 8.55778e-11 5.48605e-07 0.714723 2.89951
81 1 0 4.22041e+06 8.18090e-10 8.72009e-08 0.193241 2.89951
90 5 0 4.23307e+06 1.06102e-08 7.13089e-09 0.228707 2.96469
99 0 0 4.22752e+06 1.32219e-07 6.23840e-06 0.131633 2.96469
87 0 0 4.23235e+06 6.02085e-10 1.44694e-09 0.461309 3.04649
98 2 0 3.54130e+06 6.66019e-09 8.06140e-07 0.185895 3.04649
57 2 0 4.14514e+06 1.32590e-07 2.24896e-06 1.11303 3.08547
86 7 0 4.22752e+06 2.24177e-06 1.66898e-05 0.657243 3.12632
95 4 0 4.16560e+06 9.98170e-11 9.98170e-11 0.544570 3.20390
93 1 0 4.23307e+06 7.53744e-10 3.51764e-10 0.650838 3.26399
97 5 0 4.15307e+06 1.45815e-09 7.57731e-10 0.270789 3.29251
94 6 0 4.23227e+06 1.46081e-08 2.31986e-08 0.594754 3.33108
74 3 0 4.15307e+06 1.02737e-08 7.06233e-10 1.31564 3.33108
MULTISTART: Best locally optimal solution is returned.
EXIT: All multi-start solves have terminated.
100 solve(s) returned satisfactory solutions.
Final Statistics
----------------
Final objective value = 4.23306594644484e+06
Final feasibility error (abs / rel) = 4.15e-09 / 6.63e-15
Final optimality error (abs / rel) = 1.50e-06 / 1.49e-08
# of iterations = 11450
# of CG iterations = 0
# of function evaluations = 0
# of gradient evaluations = 0
# of Hessian evaluations = 0
Total program time (secs) = 3.33126 ( 20.763 CPU time)
================================================================================
Knitro 15.1.0: Locally optimal or satisfactory solution.
objective 4233065.946; feasibility error 4.15e-09
11450 iterations; 0 function evaluations
suffix feaserror OUT;
suffix opterror OUT;
suffix numfcevals OUT;
suffix numiters OUT;
Check and display solution#
def display_result(ampl):
# Check solver status
print(f"AMPL solve result: {ampl.solve_result}, solve code: {ampl.solve_result_num}")
if "solved" in ampl.solve_result or \
"limit" in ampl.solve_result and 410>ampl.solve_result_num:
# Retrieve and display results
# objective_value = ampl.getObjective(next(reversed(ampl.getObjectives()))).value()
# print(f"\nCurrent objective ({ampl.getObjectives()[-1].getName()}): {objective_value:.2f}")
ampl.eval('display _objname, _obj;')
print("\n--- Flow from Sources to Targets (flow_s2t) ---")
flow_s2t_df = ampl.getData('flow_s2t').toPandas().unstack()
if not flow_s2t_df.empty: # Check if DataFrame is not empty
df = flow_s2t_df[flow_s2t_df['flow_s2t'] > 1e-6]
nnz = (df > 1e-6).sum().sum()
df = df.round(2).replace({np.nan: '-'})
display(df)
print(f"Total non-zero values: {nnz}")
else:
print("No flow from sources to targets.")
print("\n--- Flow from Pools to Targets (flow_p2t) ---")
flow_p2t_df = ampl.getData('flow_p2t').toPandas().unstack()
if not flow_p2t_df.empty: # Check if DataFrame is not empty
df = flow_p2t_df[flow_p2t_df['flow_p2t'] > 1e-6]
nnz = (df > 1e-6).sum().sum()
df = df.round(2).replace({np.nan: '-'})
display(df)
print(f"Total non-zero values: {nnz}")
else:
print("No flow from pools to targets.")
print("\n--- Proportion from Sources to Pools (prop_s2p) ---")
prop_s2p_df = ampl.getData('prop_s2p').toPandas().unstack()
if not prop_s2p_df.empty: # Check if DataFrame is not empty
df = prop_s2p_df[prop_s2p_df['prop_s2p'] > 1e-6]
nnz = (df > 1e-6).sum().sum()
df = df.round(2).replace({np.nan: '-'})
display(df)
print(f"Total non-zero values: {nnz}")
else:
print("No proportion from sources to pools.")
else:
print("No optimal or feasible solution found.")
display_result(ampl)
AMPL solve result: solved, solve code: 0
: _objname _obj :=
1 TotalProfit 4233070
;
--- Flow from Sources to Targets (flow_s2t) ---
| flow_s2t | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| index1 | t1 | t10 | t11 | t12 | t13 | t14 | t15 | t16 | t2 | t3 | t4 | t5 | t6 | t8 | t9 |
| index0 | |||||||||||||||
| s10 | - | - | - | - | - | - | - | - | - | - | - | - | - | - | 71.26 |
| s12 | - | 72.05 | - | - | 140.67 | - | 165.93 | - | - | - | - | - | - | - | - |
| s15 | - | - | 226.84 | - | - | - | - | - | - | - | - | - | - | - | - |
| s17 | - | - | 101.34 | 1558.26 | - | - | - | - | - | - | - | - | - | - | - |
| s18 | - | 0.11 | - | - | - | - | - | - | 127.59 | - | - | - | - | - | - |
| s19 | 4.21 | - | - | - | - | 40.47 | - | 1738.3 | - | - | - | - | - | - | - |
| s20 | - | - | 87.39 | - | - | - | - | - | - | - | 392.07 | - | - | - | - |
| s21 | - | - | 203.07 | - | - | - | - | - | - | - | - | - | - | - | - |
| s22 | - | - | - | - | - | - | - | 978.29 | - | - | - | - | - | - | - |
| s3 | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - |
| s6 | - | - | - | 1189.14 | - | - | - | - | - | - | - | - | - | - | - |
| s7 | - | - | - | - | - | - | - | - | - | - | 415.92 | - | - | - | 86.62 |
| s9 | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - |
Total non-zero values: 19
--- Flow from Pools to Targets (flow_p2t) ---
| flow_p2t | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| index1 | t1 | t10 | t11 | t12 | t13 | t14 | t15 | t16 | t2 | t3 | t4 | t5 | t6 | t7 | t8 | t9 |
| index0 | ||||||||||||||||
| p1 | 132.17 | 382.03 | - | - | - | - | - | - | - | - | - | - | 866.04 | - | - | - |
| p10 | - | - | - | 729.26 | - | - | - | - | - | - | - | - | - | - | - | - |
| p11 | - | - | 203.87 | - | - | - | 136.92 | - | 358.37 | - | - | 40.82 | - | - | - | - |
| p12 | - | - | 73.71 | - | - | 185.2 | - | 678.37 | 353.66 | - | - | - | - | - | 229.78 | - |
| p2 | - | - | - | 1004.73 | - | - | - | - | - | - | - | 4.44 | - | - | - | 133.49 |
| p3 | - | 34.14 | - | - | - | - | 76.01 | 493.32 | - | - | - | - | - | - | - | - |
| p4 | - | 60.97 | - | - | - | - | - | - | - | - | 730.41 | - | 55.78 | - | - | - |
| p5 | - | - | - | 560.99 | - | - | - | - | - | 824.54 | - | - | - | 610.46 | - | - |
| p6 | - | - | - | 707.5 | - | - | - | - | - | - | - | - | - | - | - | - |
| p7 | - | - | - | - | - | - | - | 1233.23 | - | - | - | 7.04 | - | - | - | - |
| p8 | 13.97 | - | - | - | 567.96 | - | 354.64 | 197.55 | - | - | - | 103.52 | - | - | 396.03 | - |
| p9 | - | - | - | - | 72.06 | - | 36.99 | 97.87 | - | - | - | 3.75 | - | - | 120.31 | - |
Total non-zero values: 39
--- Proportion from Sources to Pools (prop_s2p) ---
| prop_s2p | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| index1 | p1 | p10 | p11 | p12 | p2 | p3 | p4 | p5 | p6 | p7 | p8 | p9 |
| index0 | ||||||||||||
| s1 | 0.35 | - | - | - | - | - | - | - | - | 0.28 | 0.14 | - |
| s10 | - | - | - | 0.31 | - | - | - | - | - | - | 0.24 | - |
| s11 | - | - | 0.5 | - | - | 1.0 | - | 0.24 | - | - | - | - |
| s13 | - | - | - | 0.29 | 0.51 | - | - | - | - | - | - | - |
| s14 | - | - | - | - | - | - | - | - | - | - | - | - |
| s15 | - | - | - | - | - | - | - | - | - | - | 0.23 | - |
| s16 | 0.18 | - | - | - | 0.05 | - | 0.39 | - | 0.33 | - | 0.39 | - |
| s17 | - | - | - | - | - | - | - | - | - | - | - | - |
| s18 | - | - | - | - | - | - | - | - | - | - | - | - |
| s19 | - | - | - | - | - | - | - | - | - | - | - | - |
| s2 | - | 0.23 | - | 0.06 | - | - | - | 0.39 | - | - | - | - |
| s20 | - | - | - | - | - | - | - | - | - | 0.6 | - | 0.08 |
| s22 | - | - | - | 0.13 | - | - | - | - | - | - | - | - |
| s23 | - | - | - | - | - | - | - | 0.01 | - | - | - | 0.49 |
| s3 | - | - | - | - | - | - | 0.15 | - | - | - | - | 0.41 |
| s4 | 0.37 | - | - | 0.08 | - | - | 0.32 | - | - | - | - | - |
| s5 | - | - | 0.5 | - | - | - | 0.14 | 0.04 | - | - | - | - |
| s7 | - | - | - | 0.12 | - | - | - | - | - | - | - | - |
| s8 | - | 0.77 | - | - | 0.45 | - | - | 0.33 | - | 0.12 | - | 0.02 |
| s9 | 0.1 | - | - | - | - | - | - | - | 0.67 | - | - | - |
Total non-zero values: 40
Nonlinear costs#
To make the model more realistic, we assume the costs are nonlinear. We replace the objective function by a new one.
New objective function#
%%ampl_eval
# Drop the original objective function
drop TotalProfit;
# Objective Function: Maximize Total Profit with Nonlinear Costs
maximize TotalProfitExpCosts:
sum {t in TARGETS} price[t] * target_inflow[t]
- sum {s in SOURCES} cost[s] * # Nonlinear functions of flow
(sum {t in TARGETS: (s,t) in S2T} exp(flow_s2t[s,t] / supply[s]) +
sum {p in POOLS: (s,p) in S2P} exp(source_pool_flow[s, p] / supply[s]));
Solve with Knitro#
ampl.option["solver"] = "knitro"
ampl.option["knitro_options"] = "outlev=1 ms_enable=1"
ampl.snapshot('pooling_expcosts.run') # Debugging feature
print("\nSolving the AMPL model...")
ampl.option["reset_initial_guesses"] = 1 # Do not send the previous solution as an initial guess
# This is done by default to enable iterative approaches
ampl.solve()
# ampl.solve(solver="gurobi", gurobi_options="outlev=1 lim:time=30 dualreductions=0")
# ampl.solve(solver="gurobi", gurobi_options="outlev=1 lim:time=30 alg:optimalitytarget=1")
Solving the AMPL model...
Artelys Knitro 15.1.0: outlev=1
ms_enable=1
=======================================
Commercial License
Artelys Knitro 15.1.0
=======================================
Knitro using up to 8 threads.
Knitro presolve eliminated 0 variables and 0 constraints.
concurrent_evals 0
datacheck 0
feastol 1e-06
feastol_abs 0.001
findiff_numthreads 1
hessian_no_f 1
hessopt 1
ms_enable 1
opttol 1e-06
opttol_abs 0.001
outlev 1
Problem Characteristics | Presolved
-----------------------
Problem type: NLP
Objective: maximize / general
Number of variables: 155 | 155
bounds: lower upper range | lower upper range
0 0 155 | 0 0 155
free fixed | free fixed
0 0 | 0 0
Number of constraints: 220 | 220
eq. ineq. range | eq. ineq. range
linear: 11 29 0 | 11 29 0
quadratic: 0 180 0 | 0 180 0
nonlinear: 0 0 0 | 0 0 0
Number of nonzeros:
objective Jacobian Hessian | objective Jacobian Hessian
linear: 0 1292 | 0 1292
quadratic: 0 4448 336 | 0 4448 336
nonlinear: 155 0 821 | 155 0 821
total: 155 5040 821 | 155 5040 821
Knitro parallel multistart will run with 8 threads.
Return codes description
------------------------
0: The final solution satisfies the termination conditions for verifying optimality.
-100 to -199: A feasible approximate solution was found.
-200 to -299: Knitro terminated at an infeasible point.
-300 to -301: The problem was determined to be unbounded.
-400 to -499: Knitro terminated because it reached a pre-defined limit.
-400 to -409: A feasible point was found.
-410 to -419: No feasible point was found.
-500 to -599: Knitro terminated with an input error or some non-standard error.
A more detailed description of individual return codes and their corresponding
termination messages is provided at
https://www.artelys.com/app/docs/knitro/3_referenceManual/returnCodes.html
Solve Thrd Status Objective FeasError Opt Error Solve Time Real Time
----- ---- ------ ------------ ----------- ----------- ----------- -----------
0 4 0 4.80720e+06 9.99592e-11 1.81192e-11 6.80590e-02 0.651907
19 7 0 4.75354e+06 2.22045e-16 1.02088e-08 4.39320e-02 0.651907
23 6 0 4.75354e+06 4.07338e-08 7.62473e-07 3.62700e-02 0.651907
2 0 0 4.75354e+06 2.22045e-16 6.93993e-08 8.22760e-02 0.678726
9 0 0 4.75354e+06 4.75779e-11 3.39335e-09 9.46610e-02 0.678726
11 5 0 4.81082e+06 4.17515e-11 3.09743e-11 0.106092 0.678726
20 1 0 4.75354e+06 9.79412e-11 8.45795e-11 8.47090e-02 0.678726
24 2 0 4.75354e+06 9.74865e-11 3.03673e-11 7.37230e-02 0.678726
3 1 0 4.81082e+06 1.20053e-10 1.66052e-10 0.129090 0.706201
15 5 0 4.75354e+06 1.52340e-10 1.34908e-10 0.143055 0.706201
6 5 0 4.71350e+06 2.35093e-06 7.33483e-08 0.160620 0.729097
12 0 0 4.80720e+06 7.83587e-11 1.59430e-09 0.165097 0.729097
17 3 0 4.81082e+06 2.13163e-12 3.70304e-09 0.139687 0.729097
1 6 0 4.81082e+06 4.50200e-11 7.23728e-10 0.202041 0.750151
4 2 0 4.71867e+06 1.01340e-09 2.82811e-09 0.209758 0.750151
13 6 0 4.75338e+06 1.35346e-04 8.11988e-07 0.223402 0.750151
18 0 0 4.80720e+06 7.87708e-11 4.27247e-10 0.176884 0.750151
22 5 0 4.81082e+06 1.07538e-06 2.94437e-07 0.180621 0.750151
26 3 0 4.71351e+06 1.00027e-06 1.77360e-08 0.161830 0.750151
28 2 0 4.75354e+06 4.35784e-09 2.11795e-10 0.141349 0.750151
8 4 0 4.81082e+06 2.22045e-16 3.25604e-10 0.252682 0.758347
10 1 0 4.80720e+06 1.59141e-07 4.88408e-07 0.268096 0.758347
14 2 0 4.80632e+06 1.38215e-04 6.78413e-07 0.224290 0.758347
30 4 0 4.75352e+06 1.13179e-04 6.95213e-07 0.180911 0.758347
31 5 0 4.71867e+06 1.10802e-06 2.82488e-07 0.165134 0.758347
16 4 0 4.81082e+06 5.16112e-05 7.28503e-07 0.230171 0.893743
29 0 0 4.75354e+06 2.22045e-16 1.71274e-09 0.218443 0.893743
5 3 0 4.75354e+06 5.91026e-08 6.82484e-08 0.335055 1.16022
7 7 0 4.80719e+06 1.66983e-09 5.59334e-09 0.354711 1.16022
27 1 0 4.75354e+06 9.04853e-07 1.40469e-08 0.242038 1.16022
21 7 0 4.75354e+06 1.12595e-07 2.02873e-07 0.292026 1.18010
38 4 0 4.75354e+06 9.56106e-11 1.27332e-09 6.05160e-02 1.21353
49 0 0 4.75354e+06 2.22045e-16 4.16841e-09 4.61000e-02 1.21353
37 0 0 4.81082e+06 9.52696e-11 1.73692e-07 7.39040e-02 1.27076
25 6 0 4.75354e+06 3.18283e-05 2.15201e-07 0.370360 1.27076
36 5 0 4.71867e+06 9.53833e-11 4.24122e-11 0.123659 1.27076
34 2 0 4.75354e+06 9.87654e-11 3.59103e-11 0.135109 1.27076
33 1 0 4.75354e+06 3.24576e-11 6.49424e-10 0.140438 1.27076
41 6 0 4.75354e+06 9.96181e-11 3.13031e-11 0.141039 1.29367
43 2 0 4.81082e+06 2.22045e-16 1.27893e-07 0.114574 1.29367
39 4 0 4.81082e+06 9.76002e-11 2.21413e-09 0.183443 1.32359
42 5 0 4.75354e+06 8.12292e-11 6.08915e-10 0.187649 1.32359
50 0 0 4.75354e+06 7.11769e-07 4.10453e-07 0.136514 1.32359
45 6 0 4.75354e+06 2.22045e-16 2.29383e-09 0.182450 1.50494
47 4 0 4.75354e+06 8.41055e-10 3.62314e-08 0.164165 1.50494
52 4 0 4.72565e+06 1.33227e-15 9.41115e-09 0.147974 1.50494
51 6 0 4.75354e+06 7.75877e-06 6.11884e-07 0.161116 1.50494
40 0 0 4.81082e+06 5.71845e-10 1.01192e-08 0.248018 1.90125
46 2 0 4.75354e+06 3.33067e-16 8.73314e-09 0.283988 1.95952
48 5 0 4.72565e+06 3.44183e-05 7.95369e-07 0.273454 1.95952
60 0 0 4.71350e+06 8.54072e-11 1.52518e-10 0.121599 1.99010
35 3 0 4.71867e+06 1.72008e-10 2.35573e-07 0.598790 2.01925
53 0 0 4.71867e+06 9.87654e-11 7.45902e-11 0.211806 2.01925
69 2 0 4.81082e+06 8.50662e-11 1.46315e-10 5.81400e-02 2.01925
59 3 0 4.75354e+06 1.65687e-09 1.28134e-07 0.150729 2.04914
55 7 0 4.75354e+06 1.07269e-07 8.91701e-09 0.210890 2.04914
32 7 0 4.80720e+06 1.01863e-10 6.28267e-11 0.511325 2.07214
63 0 0 4.80719e+06 2.28949e-10 1.28667e-09 0.295226 2.07214
65 1 0 4.80716e+06 2.22045e-16 5.04783e-07 0.231030 2.12495
67 0 0 4.81082e+06 9.34640e-05 7.81733e-09 0.197416 2.12495
58 5 0 4.81082e+06 0.00000e+00 1.15632e-09 0.295979 2.26969
68 3 0 4.75354e+06 2.22045e-16 1.00734e-08 0.204017 2.26969
66 7 0 4.71351e+06 2.22045e-16 6.80580e-10 0.233070 2.26969
61 3 0 4.75354e+06 7.97513e-11 1.08810e-10 0.401067 2.39166
44 1 0 4.81082e+06 1.57431e-04 8.94287e-07 0.893771 2.42085
62 7 0 4.75354e+06 2.27694e-07 2.84268e-09 0.389235 2.42085
54 2 0 4.81082e+06 1.00954e-10 7.74523e-11 0.633889 2.60189
72 6 0 4.75354e+06 1.80512e-09 2.30017e-09 0.121243 2.60189
70 2 0 4.75354e+06 4.10706e-07 1.76950e-07 0.159584 2.60189
75 4 0 4.75354e+06 9.93907e-11 4.40235e-11 0.142244 2.60189
56 4 0 4.81082e+06 5.73102e-05 6.28152e-07 0.807918 2.68523
76 7 0 4.81082e+06 6.19763e-05 7.78598e-07 0.165890 2.68523
73 0 0 4.75354e+06 1.18712e-09 8.48623e-08 0.203886 2.68523
77 6 0 4.75354e+06 1.75569e-08 1.86939e-08 0.193871 2.77721
82 6 0 4.81082e+06 9.90497e-11 3.99266e-11 0.140216 2.77721
83 2 0 4.81082e+06 4.44089e-16 3.96217e-09 3.44050e-02 2.77721
78 2 0 4.70508e+06 2.62882e-04 4.79669e-07 0.232917 2.82938
79 4 0 4.75354e+06 3.09102e-10 5.21631e-09 0.224003 2.82938
81 0 0 4.80720e+06 1.33454e-08 5.02885e-10 0.189898 2.82938
57 6 0 4.72469e+06 7.77156e-16 4.48276e-09 0.719195 2.89416
80 7 0 4.75354e+06 2.44942e-05 9.31332e-08 0.204140 2.89416
85 1 0 4.75354e+06 1.15557e-05 1.60133e-07 0.112418 3.05520
71 1 0 4.75354e+06 3.39787e-09 1.44722e-08 0.410618 3.10640
86 6 0 4.81082e+06 2.01340e-05 5.23906e-07 0.121734 3.10640
89 4 0 4.75354e+06 6.25391e-09 2.73332e-08 0.112000 3.10640
92 4 0 4.75354e+06 2.22045e-16 5.05025e-10 7.12840e-02 3.10640
87 2 0 4.81082e+06 7.94671e-11 2.20691e-11 0.157702 3.14380
88 7 0 4.75354e+06 1.82581e-10 7.84120e-09 0.174693 3.14380
90 1 0 4.80720e+06 9.91633e-11 2.98233e-11 0.172827 3.15998
74 3 0 4.81082e+06 6.18456e-10 1.55695e-09 0.824703 3.18734
96 4 0 4.75354e+06 8.69989e-11 2.27972e-10 0.202289 3.23663
93 2 0 4.71209e+06 1.14937e-10 2.67555e-10 0.272397 3.26144
97 1 0 4.75354e+06 4.27984e-04 2.28022e-08 0.211368 3.26144
98 3 0 4.75354e+06 1.33173e-05 2.15118e-08 0.220259 3.27682
91 6 0 4.81082e+06 1.09139e-10 9.99876e-11 0.421495 3.27682
99 0 0 4.80720e+06 9.88223e-11 2.08085e-11 0.212799 3.27682
94 5 0 4.81082e+06 8.88178e-11 3.09220e-10 0.448345 3.27682
84 0 0 4.81082e+06 9.80833e-11 1.68468e-11 0.449360 3.27689
64 5 0 4.75354e+06 2.51920e-07 1.29524e-07 1.18829 3.29383
95 7 0 4.72553e+06 3.55271e-15 2.26469e-07 0.543813 3.37336
MULTISTART: Best locally optimal solution is returned.
EXIT: All multi-start solves have terminated.
100 solve(s) returned satisfactory solutions.
Final Statistics
----------------
Final objective value = 4.81082184919915e+06
Final feasibility error (abs / rel) = 1.09e-10 / 1.74e-16
Final optimality error (abs / rel) = 1.00e-10 / 1.00e-10
# of iterations = 13596
# of CG iterations = 0
# of function evaluations = 15338
# of gradient evaluations = 13936
# of Hessian evaluations = 13616
Total program time (secs) = 3.37359 ( 22.190 CPU time)
================================================================================
Knitro 15.1.0: Locally optimal or satisfactory solution.
objective 4810821.849; feasibility error 1.09e-10
13596 iterations; 15338 function evaluations
Check and display solution#
display_result(ampl)
AMPL solve result: solved, solve code: 0
: _objname _obj :=
1 TotalProfitExpCosts 4810820
;
--- Flow from Sources to Targets (flow_s2t) ---
| flow_s2t | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| index1 | t1 | t10 | t11 | t12 | t13 | t14 | t15 | t16 | t2 | t3 | t4 | t5 | t6 | t8 | t9 |
| index0 | |||||||||||||||
| s10 | - | - | - | - | - | - | - | - | - | - | - | - | - | - | 76.42 |
| s12 | - | 92.53 | - | - | 175.66 | - | 177.17 | - | - | - | - | - | - | - | - |
| s15 | - | - | 162.33 | - | - | - | - | - | - | - | - | - | - | - | - |
| s17 | - | - | 106.02 | 1553.58 | - | - | - | - | - | - | - | - | - | - | - |
| s18 | - | - | - | - | - | - | - | - | 127.31 | - | - | - | - | - | - |
| s19 | 7.61 | - | - | - | - | 40.75 | - | 1734.62 | - | - | - | - | - | - | - |
| s20 | - | - | 104.6 | - | - | - | - | - | - | - | 383.47 | - | - | - | - |
| s21 | - | - | 198.11 | - | - | - | - | - | - | - | - | - | - | - | - |
| s22 | - | - | - | - | - | - | - | 969.09 | - | - | - | - | - | - | - |
| s3 | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - |
| s6 | - | - | - | 1189.14 | - | - | - | - | - | - | - | - | - | - | - |
| s7 | - | - | - | - | - | - | - | - | - | - | 416.25 | - | - | - | 79.85 |
| s9 | - | - | - | - | - | - | - | - | - | - | 1.02 | - | - | - | - |
Total non-zero values: 19
--- Flow from Pools to Targets (flow_p2t) ---
| flow_p2t | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| index1 | t1 | t10 | t11 | t12 | t13 | t14 | t15 | t16 | t2 | t3 | t4 | t5 | t6 | t7 | t8 | t9 |
| index0 | ||||||||||||||||
| p1 | 94.66 | 365.98 | - | - | - | - | - | - | - | - | - | - | 606.85 | - | - | - |
| p10 | - | - | - | 729.26 | - | - | - | - | - | - | - | - | - | - | - | - |
| p11 | - | - | 175.29 | - | - | - | 60.86 | - | 358.75 | - | - | 38.87 | - | - | - | - |
| p12 | - | - | 149.87 | - | - | 184.92 | - | 475.86 | 353.57 | - | - | - | 58.37 | - | 298.13 | - |
| p2 | - | - | - | 1006.1 | - | - | - | - | - | - | - | 1.46 | - | - | - | 135.09 |
| p3 | - | - | - | - | - | - | 96.93 | 642.57 | - | - | - | - | - | - | - | - |
| p4 | - | 90.8 | - | - | - | - | - | - | - | - | 759.46 | - | 192.74 | - | - | - |
| p5 | - | - | - | 560.99 | - | - | - | - | - | 824.54 | - | - | - | 610.46 | - | - |
| p6 | 14.39 | - | - | 554.07 | 139.04 | - | - | - | - | - | - | - | - | - | - | - |
| p7 | - | - | - | - | - | - | - | 1159.59 | - | - | - | 16.82 | 63.86 | - | - | - |
| p8 | 33.69 | - | - | - | 803.38 | - | 382.78 | - | - | - | - | 102.41 | - | - | 311.43 | - |
| p9 | - | - | - | - | 11.13 | - | 52.76 | 288.04 | - | - | - | - | - | - | 136.57 | - |
Total non-zero values: 40
--- Proportion from Sources to Pools (prop_s2p) ---
| prop_s2p | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| index1 | p1 | p10 | p11 | p12 | p2 | p3 | p4 | p5 | p6 | p7 | p8 | p9 |
| index0 | ||||||||||||
| s1 | 0.45 | - | - | - | - | - | - | - | - | 0.41 | 0.05 | - |
| s10 | - | - | - | 0.31 | - | - | - | - | - | - | 0.24 | - |
| s11 | - | - | 0.5 | - | - | 1.0 | - | 0.19 | - | - | - | - |
| s13 | - | - | - | 0.29 | 0.52 | - | - | - | - | - | - | - |
| s14 | - | - | - | - | - | - | - | - | - | - | - | - |
| s15 | - | - | - | - | - | - | - | - | - | - | 0.27 | - |
| s16 | 0.05 | - | - | - | 0.09 | - | 0.46 | - | 0.19 | - | 0.44 | - |
| s17 | - | - | - | - | - | - | - | - | - | - | - | - |
| s18 | - | - | - | - | - | - | - | - | - | - | - | - |
| s19 | - | - | - | - | - | - | - | - | - | - | - | - |
| s2 | - | 0.17 | - | 0.06 | - | - | - | 0.42 | - | - | - | - |
| s20 | - | - | - | - | - | - | - | - | - | 0.49 | - | 0.28 |
| s22 | - | - | - | 0.14 | - | - | - | - | - | - | - | - |
| s23 | - | - | - | - | - | - | - | - | - | - | - | - |
| s3 | - | - | - | - | - | - | 0.2 | - | - | - | - | 0.53 |
| s4 | 0.46 | - | - | 0.08 | - | - | 0.28 | - | - | - | - | - |
| s5 | - | - | 0.5 | - | - | - | 0.06 | 0.1 | - | - | - | - |
| s7 | - | - | - | 0.13 | - | - | - | - | - | - | - | - |
| s8 | - | 0.83 | - | - | 0.39 | - | - | 0.29 | - | 0.1 | - | 0.19 |
| s9 | 0.04 | - | - | - | - | - | - | - | 0.81 | - | - | - |
Total non-zero values: 38
Setup costs#
We modify the objective function again to account for any actually used pipes.
Objective function with setup costs#
%%ampl_eval
# Drop the previous objective function
drop TotalProfitExpCosts;
param pipe_setup_cost default 10000;
# Objective Function: Maximize Total Profit with Nonlinear Costs
maximize TotalProfitExpAndSetupCosts:
sum {t in TARGETS} price[t] * target_inflow[t]
- sum {s in SOURCES} cost[s] * source_outflow[s]
- sum {s in SOURCES} # Pipe setup costs. Note the brackets
((sum {t in TARGETS: (s,t) in S2T} if flow_s2t[s,t]>0 then pipe_setup_cost) +
(sum {p in POOLS: (s,p) in S2P} if source_pool_flow[s, p]>0 then pipe_setup_cost))
;
Solve with Knitro#
ampl.option["solver"] = "knitro"
ampl.option["knitro_options"] = "outlev=1 ms_enable=1 numthreads=8 convex=0"
ampl.snapshot('pooling_expandsetupcosts.run') # Debugging feature
print("\nSolving the AMPL model...")
ampl.option["reset_initial_guesses"] = 1 # Do not send the previous solution as an initial guess
# This is done by default to enable iterative approaches
ampl.solve()
# ampl.solve(solver="gurobi", gurobi_options="outlev=1 lim:time=300 dualreductions=0")
Solving the AMPL model...
Artelys Knitro 15.1.0: outlev=1
ms_enable=1
numthreads=8
convex=0
=======================================
Commercial License
Artelys Knitro 15.1.0
=======================================
Knitro using up to 8 threads.
Knitro presolve eliminated 0 variables and 0 constraints.
concurrent_evals 0
convex 0
datacheck 0
feastol 1e-06
feastol_abs 0.001
findiff_numthreads 1
hessian_no_f 1
hessopt 1
ms_enable 1
numthreads 8
opttol 1e-06
opttol_abs 0.001
outlev 1
Problem Characteristics | Presolved
-----------------------
Problem type: NLP
Objective: maximize / general
Number of variables: 155 | 155
bounds: lower upper range | lower upper range
0 0 155 | 0 0 155
free fixed | free fixed
0 0 | 0 0
Number of constraints: 220 | 220
eq. ineq. range | eq. ineq. range
linear: 11 29 0 | 11 29 0
quadratic: 0 180 0 | 0 180 0
nonlinear: 0 0 0 | 0 0 0
Number of nonzeros:
objective Jacobian Hessian | objective Jacobian Hessian
linear: 0 1292 | 0 1292
quadratic: 0 4448 336 | 0 4448 336
nonlinear: 155 0 773 | 155 0 773
total: 155 5040 773 | 155 5040 773
Knitro parallel multistart will run with 8 threads.
Return codes description
------------------------
0: The final solution satisfies the termination conditions for verifying optimality.
-100 to -199: A feasible approximate solution was found.
-200 to -299: Knitro terminated at an infeasible point.
-300 to -301: The problem was determined to be unbounded.
-400 to -499: Knitro terminated because it reached a pre-defined limit.
-400 to -409: A feasible point was found.
-410 to -419: No feasible point was found.
-500 to -599: Knitro terminated with an input error or some non-standard error.
A more detailed description of individual return codes and their corresponding
termination messages is provided at
https://www.artelys.com/app/docs/knitro/3_referenceManual/returnCodes.html
Solve Thrd Status Objective FeasError Opt Error Solve Time Real Time
----- ---- ------ ------------ ----------- ----------- ----------- -----------
3 7 0 2.74130e+06 4.04691e-06 1.63707e-05 3.53140e-02 0.642444
6 3 0 3.34513e+06 5.03872e-05 1.55964e-05 8.75660e-02 0.661585
11 0 0 3.35307e+06 7.81313e-11 1.85859e-09 7.48630e-02 0.661585
14 0 0 3.33134e+06 1.27682e-08 2.42176e-06 7.86360e-02 0.661585
27 2 0 3.36560e+06 5.09317e-10 1.21141e-08 3.06120e-02 0.661585
31 0 0 3.36560e+06 5.28235e-09 1.10241e-08 5.11160e-02 0.661585
18 7 0 3.43238e+06 9.51701e-11 4.28664e-11 9.35830e-02 0.668807
19 2 0 3.36560e+06 9.46457e-08 5.79029e-07 9.92360e-02 0.668807
23 2 0 3.36560e+06 9.83107e-11 7.78615e-11 7.71010e-02 0.668807
30 3 0 3.39560e+06 1.50525e-07 1.32912e-07 5.95640e-02 0.668807
2 1 0 3.33134e+06 7.60849e-11 7.51825e-08 0.127349 0.691704
9 3 0 3.36560e+06 7.59610e-09 6.52470e-08 0.134322 0.691704
12 6 0 3.42752e+06 2.20098e-10 4.46271e-08 0.141241 0.691704
16 6 0 3.36560e+06 9.39906e-11 5.03927e-08 0.130712 0.691704
20 5 0 3.36560e+06 1.32705e-06 2.17366e-06 0.113392 0.691704
10 1 0 3.40560e+06 3.57687e-07 1.27614e-08 0.170523 0.716050
13 3 0 3.36560e+06 1.52082e-07 3.44953e-07 0.187695 0.716050
17 0 0 3.43307e+06 5.37621e-08 1.60050e-07 0.134236 0.716050
25 0 0 2.73078e+06 8.11315e-09 2.44388e-07 0.141741 0.716050
26 5 0 3.45307e+06 1.16706e-08 1.00566e-07 0.150546 0.716050
0 0 0 3.36532e+06 1.10504e-10 8.71707e-09 0.178661 0.743383
5 6 0 3.18808e+06 2.86491e-10 9.50019e-10 0.187270 0.743383
21 3 0 3.42041e+06 9.81117e-11 7.08477e-11 0.196674 0.743383
29 2 0 3.36560e+06 8.67431e-11 6.24780e-10 0.151757 0.743383
8 7 0 3.42876e+06 1.49828e-09 7.66228e-08 0.310798 1.07710
28 4 0 3.43876e+06 1.41881e-10 6.01410e-11 0.275619 1.07710
4 5 0 3.42876e+06 1.18903e-08 9.82118e-07 0.377668 1.10922
24 6 0 3.45752e+06 3.32657e-08 1.72789e-07 0.287464 1.10922
7 2 0 3.42088e+06 2.02488e-09 8.37155e-08 0.358904 1.13545
34 5 0 3.36560e+06 2.16858e-11 4.05297e-09 0.137244 1.13545
33 1 0 3.37560e+06 1.45519e-10 5.25496e-10 0.138687 1.13545
36 2 0 3.35307e+06 7.98250e-13 8.48083e-08 0.118646 1.13545
35 0 0 3.36560e+06 9.54685e-11 2.46795e-10 0.164354 1.13545
42 0 0 3.36560e+06 9.71559e-08 3.40489e-07 9.26730e-02 1.13545
15 1 0 3.36560e+06 4.44634e-08 6.88703e-07 0.413218 1.18923
40 1 0 3.38224e+06 2.04705e-09 1.35223e-06 0.139164 1.18923
47 5 0 3.38560e+06 5.13126e-10 2.63254e-08 8.44860e-02 1.18923
41 2 0 3.36560e+06 2.05910e-09 5.85713e-09 0.173684 1.27647
39 5 0 3.40307e+06 1.90441e-07 1.30131e-05 0.191196 1.27647
45 1 0 3.36560e+06 1.26951e-07 6.41529e-07 0.113698 1.27647
1 4 0 3.42876e+06 1.86135e-10 2.08454e-09 0.559284 1.42311
49 1 0 3.36560e+06 9.05800e-11 1.64805e-08 2.57780e-02 1.42311
37 6 0 3.43307e+06 1.69791e-09 2.52192e-07 0.212153 1.58486
38 4 0 3.44041e+06 4.06419e-09 4.81859e-08 0.236602 1.58486
51 3 0 3.38560e+06 4.36557e-10 4.44356e-11 8.04520e-02 1.60178
60 7 0 3.36560e+06 1.14824e-10 2.84875e-08 5.88680e-02 1.60178
44 0 0 3.44307e+06 9.03856e-08 4.38136e-06 0.243143 1.63476
52 1 0 3.36560e+06 9.96181e-11 9.69465e-11 0.140921 1.67009
50 5 0 3.38134e+06 9.34306e-08 1.77567e-06 0.153298 1.67009
53 0 0 3.36307e+06 9.86802e-11 2.68402e-09 0.134336 1.67009
46 2 0 3.33532e+06 9.40048e-11 8.58777e-09 0.358064 1.70238
55 7 0 3.35307e+06 3.28626e-14 1.43680e-09 0.114396 1.70238
62 4 0 3.36560e+06 9.76814e-06 1.76247e-05 8.73040e-02 1.70238
61 7 0 3.36560e+06 8.78515e-11 3.18521e-09 0.121910 1.78844
32 3 0 3.36560e+06 1.88684e-06 9.78442e-06 0.429023 1.98831
58 0 0 3.44752e+06 3.33406e-07 2.32579e-06 0.221738 1.98831
65 7 0 3.43234e+06 8.65475e-09 1.23083e-07 5.27000e-02 2.01409
67 2 0 3.43752e+06 4.07606e-07 2.22209e-06 7.70830e-02 2.04383
59 2 0 3.42041e+06 9.85381e-11 8.34190e-11 0.273823 2.08856
22 7 0 3.42876e+06 3.31566e-07 1.95927e-06 0.863764 2.11685
43 6 0 3.38309e+06 3.27649e-06 1.51565e-05 0.651742 2.11685
66 4 0 3.42806e+06 9.52411e-11 3.38705e-11 0.124660 2.11685
70 2 0 3.36560e+06 5.39148e-07 2.34909e-06 0.104194 2.11685
72 2 0 3.35307e+06 7.09974e-11 1.37270e-09 0.103400 2.11685
73 1 0 3.36560e+06 1.44511e-08 1.95829e-07 0.131560 2.11685
48 4 0 3.42014e+06 1.34485e-09 6.30818e-06 0.436145 2.18233
75 0 0 3.42041e+06 2.04722e-08 5.97176e-07 0.141132 2.33419
76 1 0 3.36560e+06 7.78414e-10 4.37673e-09 5.50070e-02 2.33419
54 3 0 3.43238e+06 1.73627e-08 7.27690e-08 0.501714 2.36566
56 1 0 3.35307e+06 5.20686e-11 1.00105e-09 0.563763 2.36566
63 0 0 3.44752e+06 3.39154e-07 2.44713e-06 0.440181 2.36566
79 0 0 3.34134e+06 9.78844e-11 3.61027e-10 6.17290e-02 2.36566
69 3 0 3.43752e+06 4.31282e-09 1.04229e-08 0.291310 2.40114
78 7 0 3.43234e+06 9.89786e-11 3.02020e-09 7.19210e-02 2.40114
80 1 0 3.36560e+06 7.23446e-09 5.33268e-08 0.130860 2.45381
82 0 0 3.42806e+06 2.85127e-10 1.09554e-07 8.95730e-02 2.45381
84 4 0 3.44088e+06 2.70666e-09 1.82559e-10 0.105303 2.45381
85 6 0 3.18808e+06 1.01494e-10 3.51988e-11 0.148519 2.59222
68 7 0 3.47752e+06 1.03930e-07 1.95220e-07 0.394193 2.67227
71 4 0 3.43307e+06 1.09491e-07 9.43463e-06 0.439196 2.69303
83 5 0 3.36560e+06 1.41162e-06 4.35724e-06 0.231339 2.69303
92 3 0 3.36560e+06 3.55067e-09 1.35445e-08 4.44460e-02 2.69303
64 6 0 3.38307e+06 9.02219e-10 1.42130e-10 0.626282 2.73133
87 0 0 3.36560e+06 8.78106e-09 2.13188e-08 0.199729 2.73133
93 4 0 3.36560e+06 9.55822e-11 8.59607e-09 8.98820e-02 2.76701
57 5 0 3.43238e+06 1.77015e-06 1.41027e-05 0.904280 2.80287
88 4 0 3.36560e+06 9.56106e-11 1.94220e-10 0.165204 2.80287
86 1 0 3.42752e+06 8.11779e-07 5.09739e-06 0.300188 2.80287
96 3 0 2.73078e+06 5.14092e-10 2.77567e-08 0.110254 2.80287
89 6 0 3.36560e+06 1.64377e-06 1.86754e-05 0.225645 2.82259
77 3 0 3.43041e+06 3.74823e-08 1.06752e-06 0.448914 2.84585
81 7 0 3.38224e+06 1.92973e-07 5.57229e-06 0.394760 2.84585
90 5 0 3.43806e+06 2.83535e-10 4.68926e-08 0.198072 2.84585
94 7 0 3.37309e+06 2.72310e-05 1.41563e-05 0.167731 2.84585
74 2 0 3.44752e+06 2.41591e-07 2.00572e-06 0.796626 2.89509
91 0 0 3.39373e+06 4.83669e-09 1.03890e-07 0.282069 2.92198
99 5 0 3.42041e+06 1.00499e-10 1.39093e-10 0.164768 2.94591
98 6 0 3.47752e+06 1.86442e-06 4.59599e-06 0.259439 2.99233
97 4 0 3.33054e+06 1.46997e-09 1.14230e-08 0.308214 2.99233
95 1 0 3.36560e+06 5.41404e-07 2.23729e-06 0.550739 3.15442
MULTISTART: Best locally optimal solution is returned.
EXIT: All multi-start solves have terminated.
100 solve(s) returned satisfactory solutions.
Final Statistics
----------------
Final objective value = 3.47752463854000e+06
Final feasibility error (abs / rel) = 1.86e-06 / 2.98e-12
Final optimality error (abs / rel) = 4.60e-06 / 2.45e-07
# of iterations = 13308
# of CG iterations = 0
# of function evaluations = 14992
# of gradient evaluations = 13658
# of Hessian evaluations = 13333
Total program time (secs) = 3.15462 ( 20.770 CPU time)
================================================================================
Knitro 15.1.0: Locally optimal or satisfactory solution.
objective 3477524.639; feasibility error 1.86e-06
13308 iterations; 14992 function evaluations
Check and display solution#
display_result(ampl)
AMPL solve result: solved, solve code: 0
: _objname _obj :=
1 TotalProfitExpAndSetupCosts 3477520
;
--- Flow from Sources to Targets (flow_s2t) ---
| flow_s2t | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| index1 | t1 | t10 | t11 | t12 | t13 | t14 | t15 | t16 | t2 | t3 | t4 | t5 | t6 | t8 | t9 |
| index0 | |||||||||||||||
| s10 | - | - | - | - | - | - | - | - | - | - | - | - | - | - | 74.45 |
| s12 | - | 86.92 | - | - | 87.15 | - | 153.89 | - | - | - | - | - | - | - | - |
| s15 | - | - | 230.15 | - | - | - | - | - | - | - | - | - | - | - | - |
| s17 | - | - | 101.45 | 1558.15 | - | - | - | - | - | - | - | - | - | - | - |
| s18 | - | 16.74 | - | - | - | - | - | - | 129.39 | - | - | - | - | - | - |
| s19 | 38.41 | - | - | - | - | 38.72 | - | 1705.84 | - | - | - | - | - | - | - |
| s20 | - | - | 87.43 | - | - | - | - | - | - | - | 338.98 | - | - | - | - |
| s21 | - | - | 203.93 | - | - | - | - | - | - | - | - | - | - | - | - |
| s22 | - | - | - | - | - | - | - | 1035.89 | - | - | - | - | - | - | - |
| s3 | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - |
| s6 | - | - | - | 1189.14 | - | - | - | - | - | - | - | - | - | - | - |
| s7 | - | - | - | - | - | - | - | - | - | - | 460.38 | - | - | - | 82.44 |
| s9 | - | - | - | - | - | - | - | - | - | - | 145.11 | - | - | - | - |
Total non-zero values: 20
--- Flow from Pools to Targets (flow_p2t) ---
| flow_p2t | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| index1 | t1 | t10 | t11 | t12 | t13 | t14 | t15 | t16 | t2 | t3 | t4 | t5 | t6 | t7 | t8 | t9 |
| index0 | ||||||||||||||||
| p1 | 22.74 | 445.64 | - | - | - | - | 199.51 | - | - | - | - | - | 231.46 | - | - | - |
| p10 | - | - | - | 729.26 | - | - | - | - | - | - | - | - | - | - | - | - |
| p11 | - | - | 204.29 | - | - | - | 9.78 | - | 355.98 | - | - | 39.19 | - | - | - | - |
| p12 | - | - | 68.96 | - | - | 186.94 | - | 445.12 | 354.25 | - | - | - | 198.44 | - | 267.01 | - |
| p2 | - | - | - | 1008.17 | - | - | - | - | - | - | - | - | - | - | - | 134.48 |
| p3 | - | - | - | - | - | - | - | 542.58 | - | - | - | - | 85.53 | - | - | - |
| p4 | - | - | - | - | - | - | - | - | - | - | 865.13 | - | 177.87 | - | - | - |
| p5 | - | - | - | 560.99 | - | - | - | - | - | 824.54 | - | - | - | 610.46 | - | - |
| p6 | - | - | - | 707.5 | - | - | - | - | - | - | - | - | - | - | - | - |
| p7 | - | - | - | - | - | - | - | 999.77 | - | - | - | 11.98 | 228.53 | - | - | - |
| p8 | 79.16 | - | - | - | 488.02 | - | 405.38 | 195.57 | - | - | - | 108.4 | - | - | 357.14 | - |
| p9 | 10.03 | - | - | - | 45.03 | - | 1.93 | 349.7 | - | - | - | - | - | - | 121.97 | - |
Total non-zero values: 39
--- Proportion from Sources to Pools (prop_s2p) ---
| prop_s2p | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| index1 | p1 | p10 | p11 | p12 | p2 | p3 | p4 | p5 | p6 | p7 | p8 | p9 |
| index0 | ||||||||||||
| s1 | 0.4 | - | - | - | - | - | - | - | - | 0.44 | 0.1 | - |
| s10 | - | - | - | 0.32 | - | - | - | - | - | - | 0.23 | - |
| s11 | - | - | 0.51 | - | - | 1.0 | - | 0.25 | - | - | - | - |
| s13 | - | - | - | 0.29 | 0.51 | - | - | - | - | - | - | - |
| s14 | - | - | - | - | - | - | - | - | - | - | 0.04 | - |
| s15 | - | - | - | - | - | - | - | - | - | - | 0.23 | - |
| s16 | 0.08 | - | - | - | 0.07 | - | 0.43 | - | 0.33 | - | 0.4 | - |
| s17 | - | - | - | - | - | - | - | - | - | - | - | - |
| s18 | - | - | - | - | - | - | - | - | - | - | - | - |
| s19 | - | - | - | - | - | - | - | - | - | - | - | - |
| s2 | - | 0.2 | - | 0.09 | - | - | - | 0.38 | - | - | - | - |
| s20 | - | - | - | - | - | - | - | - | - | 0.44 | - | 0.7 |
| s22 | - | - | - | 0.09 | - | - | - | - | - | - | - | - |
| s23 | - | - | - | - | - | - | - | 0.02 | - | - | - | 0.19 |
| s3 | - | - | - | - | - | - | 0.1 | - | - | - | - | 0.12 |
| s4 | 0.45 | - | - | 0.11 | - | - | 0.31 | - | - | - | - | - |
| s5 | 0.08 | - | 0.49 | - | - | - | 0.16 | 0.01 | - | - | - | - |
| s7 | - | - | - | 0.09 | - | - | - | - | - | - | - | - |
| s8 | - | 0.8 | - | - | 0.41 | - | - | 0.34 | - | 0.12 | - | - |
| s9 | - | - | - | - | - | - | - | - | 0.67 | - | - | - |
Total non-zero values: 40
Solve with MP2NL+Knitro#
While Knitro accepts the if-then-else expressions (they are evaluated by the AMPL Solver Library’s callbacks), they seem not to influence the solution. Let us linearize the model with MP2NL.
ampl.option["solver"] = "mp2nl"
ampl.option["mp2nl_options"] = "solver=knitro outlev=1"
ampl.option["knitro_options"] = ""
# ampl.option["knitro_options"] = \
# "outlev=1 ms_enable=1 mip_multistart=1 maxtime=300 numthreads=8 mip_numthreads=8 mip_root_nlpalg=5 convex=0"
# ampl.snapshot('pooling_expandsetupcosts.run') # Debugging feature
print("\nSolving the AMPL model...")
ampl.option["reset_initial_guesses"] = 0 # Do not send the previous solution as an initial guess
# This is done by default to enable iterative approaches
ampl.solve()
# ampl.solve(solver="gurobi", gurobi_options="outlev=1 lim:time=300")
Solving the AMPL model...
MP2NL 0.1: nl:solver = knitro
tech:outlev = 1
AMPL MP initial flat model has 155 variables (0 integer, 0 binary);
Objectives: 1 linear;
Constraints: 106 linear; 181 quadratic;
Algebraic expressions: 80 ifthen;
Logical expressions: 28 conditional (in)equalitie(s); 52 conditional quadratic (in)equalitie(s); 80 not;
AMPL MP final model has 612 variables (80 integer, 160 binary);
Objectives: 1 nonlinear;
Constraints: 134 linear; 148 quadratic; 232 nonlinear;
Artelys Knitro 15.1.0:
=======================================
Commercial License
Artelys Knitro 15.1.0
=======================================
Knitro changing mip_method from AUTO to 1.
MINLP solver shifted start point to satisfy bounds (2 variables).
concurrent_evals 0
datacheck 0
feastol 1e-06
feastol_abs 1e-06
findiff_numthreads 1
hessian_no_f 1
hessopt 1
opttol 1e-06
opttol_abs 0.001
Knitro changing mip_root_nlpalg from AUTO to 1.
Knitro changing mip_node_nlpalg from AUTO to 1.
Knitro changing mip_branchrule from AUTO to 2.
Knitro changing mip_selectrule from AUTO to 2.
Knitro changing mip_mir from AUTO to 2.
Knitro changing mip_clique from AUTO to 0.
Knitro changing mip_zerohalf from AUTO to 0.
Knitro changing mip_liftproject from AUTO to 0.
Knitro changing mip_knapsack from AUTO to 2.
Knitro changing mip_gomory from AUTO to 0.
Knitro changing mip_cut_flowcover from AUTO to 2.
Knitro changing mip_cut_probing from AUTO to 1.
Knitro changing mip_rounding from AUTO to 3.
Knitro changing mip_heuristic_strategy from AUTO to 1.
Knitro changing mip_heuristic_feaspump from AUTO to 1.
Knitro changing mip_heuristic_misqp from AUTO to 0.
Knitro changing mip_heuristic_mpec from AUTO to 1.
Knitro changing mip_heuristic_diving from AUTO to 0.
Knitro changing mip_heuristic_lns from AUTO to 0.
Knitro changing mip_heuristic_localsearch from AUTO to 1.
Knitro changing mip_heuristic_fixpropagate from AUTO to 1.
Knitro changing mip_pseudoinit from AUTO to 1.
Problem Characteristics | Presolved
-----------------------
Problem type: MIQCQP
Objective: maximize / quadratic
Number of variables: 612 | 612
bounds: lower upper range | lower upper range
0 0 235 | 0 0 235
free fixed | free fixed
66 311 | 66 311
cont. binary integer | cont. binary integer
532 80 0 | 532 80 0
Number of constraints: 366 | 366
eq. ineq. range | eq. ineq. range
linear: 77 57 0 | 77 57 0
quadratic: 0 232 0 | 0 232 0
Number of nonzeros:
objective Jacobian Hessian | objective Jacobian Hessian
linear: 184 1801 | 184 1801
quadratic: 63 1608 402 | 63 1608 402
total: 247 2709 402 | 247 2709 402
Knitro using Branch and Bound method with 8 threads.
Initial points
--------------
Read root node initial point:
Objective value: 3.757575e+06
Feasibility error: 1.894570e+05
Feasible: no
Read MIP primal point:
Objective value: 4.557575e+06
Feasibility error: 1.894570e+05
Feasible: no, Knitro will try to repair it
Coefficient range:
linear objective: [8e+01, 8e+05] | [8e-01, 1e+02]
linear constraints: [2e-04, 2e+04] | [8e-05, 1e+02]
quadratic objective: [1e+01, 4e+01] | [1e-01, 4e-01]
quadratic constraints: [1e+00, 1e+00] | [6e-03, 1e+00]
variable bounds: [1e+00, 1e+04] | [1e+00, 2e+03]
constraint bounds: [1e+00, 2e+04] | [1e+00, 2e+03]
Root node relaxation
--------------------
Iter Objective Feasibility Optimality Time
error error (secs)
---- --------- ----------- ---------- ------
1 4.06605e+06 178771. 630.572 0.006
2 4.06753e+06 177950. 630.282 0.009
3 4.06331e+06 177119. 629.766 0.011
4 4.05547e+06 175622. 628.659 0.014
5 4.10367e+06 174472. 626.963 0.017
6 4.09160e+06 174136. 319.870 0.023
7 4.06854e+06 174486. 99.9564 0.025
8 4.05856e+06 174510. 99.9588 0.026
9 4.05115e+06 174462. 99.9604 0.027
10 4.04539e+06 174420. 99.9609 0.029
11 4.04401e+06 174407. 99.9995 0.031
12 4.04106e+06 174389. 99.9995 0.033
13 4.03846e+06 174372. 99.9995 0.035
14 4.03603e+06 174355. 99.9995 0.037
15 4.03295e+06 174332. 99.9995 0.039
16 4.03067e+06 174314. 99.9995 0.041
17 4.02854e+06 174296. 99.9995 0.043
18 4.02647e+06 174277. 99.9995 0.045
19 4.02446e+06 174258. 99.9995 0.047
20 4.02246e+06 174237. 99.9995 0.049
30 3.99921e+06 173965. 99.9995 0.069
40 3.97603e+06 170403. 99.9995 0.089
50 3.96579e+06 163238. 99.9995 0.131
60 3.91301e+06 146034. 99.9995 0.146
70 3.82787e+06 109806. 99.9996 0.165
80 3.75026e+06 84842.0 99.9995 0.182
90 3.63921e+06 49122.3 99.9995 0.201
100 3.53300e+06 32412.9 99.9995 0.219
110 3.44715e+06 27852.0 99.9999 0.237
120 3.37961e+06 23950.3 116.653 0.253
130 3.53130e+06 15573.4 123.867 0.272
140 3.54588e+06 7204.28 333.161 0.290
150 4.23085e+06 3555.20 546.089 0.303
160 4.23075e+06 832.519 455.156 0.317
170 4.15422e+06 5.58683 60.7852 0.327
180 4.15853e+06 4.38798e-07 6.78479e-04 0.340
MP2NL 0.1: NLSolver: call "knitro /var/folders/6r/cc3gs1ps1zz2h44w2kq3_96c0000gr/T/nlw2_60543244FD50904A_oqzav8/EFA4B71B4944DF64 -AMPL " failed (code 10).
Check and display solution#
display_result(ampl)
AMPL solve result: failure, solve code: 500
No optimal or feasible solution found.
Minimal flow#
A practical constraint might be a minimal amount of flow whenever a pipe is used. We model this by logical constraints.
Semi-continuous flow as logical constraints#
%%ampl_eval
param min_flow default 50;
# Constraints making pipe flows semi-continuous
subject to MinFlowS2T {(s,t) in S2T}:
flow_s2t[s,t]<=0 or flow_s2t[s,t]>=min_flow;
subject to MinFlowS2P {(s,p) in S2P}:
source_pool_flow[s,p]<=0 or source_pool_flow[s,p]>=min_flow;
subject to MinFlowP2T {(p,t) in P2T}:
flow_p2t[p,t]<=0 or flow_p2t[p,t]>=min_flow;
Solve with MP2NL+Knitro#
ampl.option["solver"] = "mp2nl"
ampl.option["mp2nl_options"] = "solver=knitro outlev=1"
ampl.option["knitro_options"] =\
"outlev=1 ms_enable=1 mip_multistart=1 maxtime=300 numthreads=8 mip_numthreads=8 mip_root_nlpalg=5 convex=0"
ampl.snapshot('pooling_expandsetupcosts_minflow.run') # Debugging feature
print("\nSolving the AMPL model...")
ampl.option["reset_initial_guesses"] = 0 # Do not send the previous solution as an initial guess
# This is done by default to enable iterative approaches
ampl.solve()
# ampl.solve(solver="gurobi", gurobi_options="outlev=1 lim:time=300")
Solving the AMPL model...
MP2NL 0.1: nl:solver = knitro
tech:outlev = 1
AMPL MP initial flat model has 155 variables (0 integer, 0 binary);
Objectives: 1 linear;
Constraints: 106 linear; 181 quadratic;
Algebraic expressions: 80 ifthen;
Logical expressions: 208 conditional (in)equalitie(s); 104 conditional quadratic (in)equalitie(s); 80 not; 156 or;
AMPL MP final model has 1000 variables (80 integer, 548 binary);
Objectives: 1 nonlinear;
Constraints: 470 linear; 148 quadratic; 284 nonlinear;
Artelys Knitro 15.1.0: outlev=1
ms_enable=1
mip_multistart=1
maxtime=300
numthreads=8
mip_numthreads=8
mip_root_nlpalg=5
convex=0
=======================================
Commercial License
Artelys Knitro 15.1.0
=======================================
Knitro changing mip_method from AUTO to 1.
MINLP solver shifted start point to satisfy bounds (158 variables).
concurrent_evals 0
convex 0
datacheck 0
feastol 1e-06
feastol_abs 1e-06
findiff_numthreads 1
hessian_no_f 1
hessopt 1
maxtime 300
mip_multistart 1
mip_numthreads 8
mip_root_nlpalg 5
ms_enable 1
numthreads 8
opttol 1e-06
opttol_abs 0.001
outlev 1
Knitro changing mip_node_nlpalg from AUTO to 1.
Knitro changing mip_branchrule from AUTO to 2.
Knitro changing mip_selectrule from AUTO to 2.
Knitro changing mip_mir from AUTO to 2.
Knitro changing mip_clique from AUTO to 0.
Knitro changing mip_zerohalf from AUTO to 0.
Knitro changing mip_liftproject from AUTO to 0.
Knitro changing mip_knapsack from AUTO to 2.
Knitro changing mip_gomory from AUTO to 0.
Knitro changing mip_cut_flowcover from AUTO to 2.
Knitro changing mip_cut_probing from AUTO to 1.
Knitro changing mip_rounding from AUTO to 3.
Knitro changing mip_heuristic_strategy from AUTO to 1.
Knitro changing mip_heuristic_feaspump from AUTO to 1.
Knitro changing mip_heuristic_misqp from AUTO to 0.
Knitro changing mip_heuristic_mpec from AUTO to 1.
Knitro changing mip_heuristic_diving from AUTO to 0.
Knitro changing mip_heuristic_lns from AUTO to 0.
Knitro changing mip_heuristic_localsearch from AUTO to 1.
Knitro changing mip_heuristic_fixpropagate from AUTO to 1.
Knitro changing mip_pseudoinit from AUTO to 1.
WARNING: Problem marked as non-convex by user.
The Knitro mixed integer solver is designed for convex problems.
For non-convex problems it is only a heuristic, and the reported
bounds and optimality claims cannot be verified.
Problem Characteristics | Presolved
-----------------------
Problem type: MIQCQP
Objective: maximize / quadratic
Number of variables: 1000 | 1000
bounds: lower upper range | lower upper range
0 0 467 | 0 0 467
free fixed | free fixed
66 467 | 66 467
cont. binary integer | cont. binary integer
688 312 0 | 688 312 0
Number of constraints: 754 | 754
eq. ineq. range | eq. ineq. range
linear: 77 393 0 | 77 393 0
quadratic: 0 284 0 | 0 284 0
Number of nonzeros:
objective Jacobian Hessian | objective Jacobian Hessian
linear: 184 2686 | 184 2686
quadratic: 63 1712 402 | 63 1712 402
total: 247 3698 402 | 247 3698 402
Knitro using Branch and Bound method with 8 threads.
Initial points
--------------
Read root node initial point:
Objective value: 3.757575e+06
Feasibility error: 1.894570e+05
Feasible: no
Read MIP primal point:
Objective value: 4.557575e+06
Feasibility error: 1.894570e+05
Feasible: no, Knitro will try to repair it
Coefficient range:
linear objective: [8e+01, 8e+05] | [8e-01, 1e+02]
linear constraints: [2e-04, 2e+04] | [8e-05, 1e+02]
quadratic objective: [1e+01, 4e+01] | [1e-01, 4e-01]
quadratic constraints: [1e+00, 1e+00] | [6e-03, 1e+00]
variable bounds: [1e+00, 1e+04] | [1e+00, 2e+03]
constraint bounds: [1e+00, 2e+04] | [1e+00, 2e+03]
Root node relaxation
--------------------
Iter Objective Feasibility Optimality Time
error error (secs)
---- --------- ----------- ---------- ------
1 4.13463e+06 185912. 490.643 0.007
2 4.15639e+06 184941. 488.821 0.008
3 4.20216e+06 181708. 485.109 0.009
4 4.24522e+06 176656. 484.329 0.010
5 4.28361e+06 165709. 479.156 0.011
6 4.35059e+06 136843. 469.506 0.012
7 4.41488e+06 85788.3 408.395 0.014
8 4.47797e+06 71649.9 265.588 0.015
9 4.50338e+06 48791.8 804.647 0.016
10 4.24654e+06 26166.3 1826.09 0.018
11 4.21610e+06 23996.8 1465.26 0.019
12 4.11275e+06 16435.0 14339.3 0.021
13 4.11862e+06 12829.1 3454.00 0.022
14 4.14593e+06 10363.6 7841.79 0.023
15 4.13260e+06 9369.80 7437.72 0.024
16 4.12202e+06 7682.23 6411.38 0.025
17 4.11804e+06 6620.29 5383.05 0.027
18 4.01769e+06 4783.42 14208.3 0.028
19 3.97744e+06 4180.46 14861.0 0.029
20 3.77611e+06 2913.99 13622.6 0.031
30 3.78721e+06 161.564 5491.55 0.049
40 4.07927e+06 1.20164e-05 5.60874 0.064
Root node cutting planes
------------------------
Iter Cuts Best solution Best bound Gap Time
value value (secs)
---- ---- ------------- ---------- --- ------
0 0 inf 0.080
Tree search
-----------
Nodes Best solution Best bound Gap Time
Expl | Unexpl value value (secs)
--------------- ------------- ---------- --- ------
1 1 inf 0.356
4 1 3.32508e+06 RFP inf 1.808
98 1 3.32508e+06 inf 39.678
198 1 3.32508e+06 inf 78.578
200 0 3.32508e+06 -inf 79.417
EXIT: Optimal solution found (assuming convexity).
Final Statistics for MIP
------------------------
Final objective value = 3.32508019560285192e+06
Final bound value = -inf
Final optimality gap (abs / rel) = -inf / inf
# of root cutting plane rounds = 1
# of restarts = 0
# of nodes processed = 200 (79.283s)
# of strong branching evaluations = 0 (0.000s)
# of function evaluations = 0 (0.000s)
# of gradient evaluations = 0 (0.000s)
# of hessian evaluations = 0 (0.000s)
# of hessian-vector evaluations = 0
# of subproblems processed = 207 (88.400s)
Total program time (secs) = 79.41748 (109.829 CPU time)
Time spent in evaluations (secs) = 0.00000
Cuts statistics (gen / add)
---------------------------
Knapsack cuts = 0 / 0
Mixed-integer rounding cuts = 0 / 0
Flow-cover cuts = 0 / 0
Probing cuts = 464 / 104
Heuristics statistics (calls / successes / time)
------------------------------------------------
Feasibility pump = 1 / 1 / 0.112s
Rounding heuristic = 1 / 0 / 0.000s
MPEC heuristic = 1 / 0 / 9.117s
Local search heuristic = 5 / 0 / 0.049s
Fix-and-propagate heuristics = 0 / 0 / 0.000s
===========================================================================
MP2NL 0.1: Knitro 15.1.0: Locally optimal or satisfactory solution.
objective 3325080.196; optimality gap 2.26e-313
200 nodes; 207 subproblem solves
suffix relaxbnd OUT;
suffix incumbent OUT;
Check and display solution#
display_result(ampl)
AMPL solve result: solved, solve code: 0
: _objname _obj :=
1 TotalProfitExpAndSetupCosts 3325080
;
--- Flow from Sources to Targets (flow_s2t) ---
| flow_s2t | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| index1 | t1 | t10 | t11 | t12 | t13 | t14 | t15 | t16 | t2 | t3 | t4 | t5 | t6 | t8 | t9 |
| index0 | |||||||||||||||
| s10 | - | - | - | - | - | - | - | - | - | 50.0 | - | - | 50.0 | - | 60.99 |
| s12 | - | - | - | - | 50.0 | - | 145.69 | - | - | - | - | - | - | - | - |
| s15 | - | - | 113.79 | - | - | - | - | - | - | - | - | - | - | - | - |
| s17 | - | - | 77.48 | 1197.24 | - | - | - | - | - | - | - | - | - | - | - |
| s18 | - | - | - | - | - | - | - | - | 105.73 | - | - | - | - | - | - |
| s19 | 50.0 | - | - | - | - | 50.0 | - | 1632.98 | - | - | - | - | - | - | - |
| s20 | - | - | 96.93 | - | - | - | - | - | - | - | 460.26 | - | - | - | - |
| s21 | - | - | 194.11 | - | - | - | - | - | - | - | - | - | - | - | - |
| s22 | - | - | - | - | - | - | - | 1016.3 | - | - | - | - | - | - | - |
| s3 | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - |
| s6 | - | - | - | 1189.14 | - | - | - | - | - | - | - | - | - | - | - |
| s7 | - | - | - | - | - | - | - | - | - | - | 551.82 | - | - | - | 85.42 |
| s9 | - | - | - | - | - | - | - | - | - | - | 157.82 | - | - | - | - |
Total non-zero values: 20
--- Flow from Pools to Targets (flow_p2t) ---
| flow_p2t | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| index1 | t1 | t10 | t11 | t12 | t13 | t14 | t15 | t16 | t2 | t3 | t4 | t5 | t6 | t7 | t8 | t9 |
| index0 | ||||||||||||||||
| p1 | 50.0 | 335.01 | - | - | - | - | 79.55 | - | - | - | - | - | 458.35 | - | - | - |
| p10 | - | - | - | 579.26 | - | - | - | 50.0 | - | - | 50.0 | - | - | 50.0 | - | - |
| p11 | - | - | 147.43 | - | - | - | - | - | 335.77 | - | - | 67.71 | - | - | - | - |
| p12 | - | - | 116.47 | - | - | 180.98 | - | 476.23 | 298.12 | - | - | - | 50.0 | - | 398.92 | - |
| p2 | 50.0 | 50.0 | - | 647.7 | - | - | 50.0 | - | 50.0 | - | - | 50.0 | 50.0 | 50.0 | - | 144.96 |
| p3 | - | 50.0 | - | - | - | - | 50.0 | - | - | - | - | - | - | - | - | - |
| p4 | - | 50.0 | - | - | - | - | - | - | - | - | 941.48 | - | 51.51 | - | - | - |
| p5 | - | - | 50.0 | - | - | - | 50.0 | 474.6 | - | 774.54 | - | 50.0 | - | 596.85 | - | - |
| p6 | - | 64.3 | 50.0 | 593.2 | - | - | - | - | - | - | - | - | - | - | - | - |
| p7 | - | - | - | - | - | - | - | 928.32 | 50.0 | - | 50.0 | - | 211.96 | - | - | - |
| p8 | 99.0 | - | 50.0 | - | 230.58 | - | 395.25 | 515.05 | - | - | 50.0 | 50.0 | 50.0 | - | 191.55 | - |
| p9 | - | - | - | - | - | - | - | 281.23 | - | - | - | - | - | 50.0 | 155.65 | - |
Total non-zero values: 56
--- Proportion from Sources to Pools (prop_s2p) ---
| prop_s2p | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| index1 | p1 | p10 | p11 | p12 | p2 | p3 | p4 | p5 | p6 | p7 | p8 | p9 |
| index0 | ||||||||||||
| s1 | 0.36 | - | - | - | - | - | - | - | - | 0.52 | 0.06 | - |
| s10 | - | - | - | 0.22 | - | - | - | - | - | - | 0.27 | - |
| s11 | 0.05 | - | 0.57 | 0.04 | - | 1.0 | - | 0.46 | - | - | - | - |
| s13 | - | - | - | 0.18 | 0.43 | - | - | - | - | - | - | - |
| s14 | - | - | - | - | - | - | - | - | - | - | - | - |
| s15 | - | - | - | - | - | - | - | - | - | - | 0.3 | - |
| s16 | 0.39 | - | - | - | 0.04 | - | 0.27 | - | 0.28 | - | 0.37 | - |
| s17 | - | - | - | - | - | - | - | - | 0.07 | - | - | - |
| s18 | - | - | - | - | - | - | - | - | - | - | - | - |
| s19 | 0.05 | - | - | - | - | - | - | - | - | - | - | - |
| s2 | - | - | - | 0.28 | - | - | - | 0.31 | - | - | - | - |
| s20 | - | - | - | - | - | - | - | - | - | 0.23 | - | 0.21 |
| s22 | - | - | - | 0.11 | - | - | - | - | - | - | - | - |
| s23 | - | - | - | - | - | - | - | 0.03 | - | - | - | - |
| s3 | - | - | - | - | - | - | 0.05 | - | - | - | - | 0.79 |
| s4 | 0.14 | - | - | 0.14 | - | - | 0.53 | - | - | - | - | - |
| s5 | - | - | 0.43 | - | - | - | 0.15 | 0.09 | - | - | - | - |
| s7 | - | - | - | 0.03 | - | - | - | - | - | - | - | - |
| s8 | - | 1.0 | - | - | 0.52 | - | - | 0.13 | - | 0.25 | - | - |
| s9 | - | - | - | - | - | - | - | - | 0.65 | - | - | - |
Total non-zero values: 40
Conclusion#
Artelys Knitro can be used with AMPL extended logical constraint syntax via the MP2NL meta-driver.