import argparse
import csv
import json
import pathlib
import ecole as ec
import numpy as np
import sys
import torch
import random
def eval(env, instance, initial_primal_bound, policy):
# reset the environment
observation, action_set, reward, done, info = env.reset(instance, objective_limit=initial_primal_bound)
cumulated_reward = 0 # discard initial reward
# loop over the environment
while not done:
action, _ = policy(action_set, observation)
observation, action_set, reward, done, info = env.step(action.item())
cumulated_reward += reward
return info, cumulated_reward
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument(
'problem',
help='Problem benchmark to process.',
choices=['item_placement', 'capacitated_facility_location', 'set_cover'],
)
parser.add_argument(
'-t', '--timelimit',
help='Episode time limit (in seconds).',
default=argparse.SUPPRESS,
type=float,
)
args = parser.parse_args()
args.task = 'dual'
args.problem = 'set_cover'
seed = 6 # 4,5,6,7,8
torch.manual_seed(seed)
np.random.seed(seed)
random.seed(seed)
# check the Ecole version installed
print(ec.__version__)
print(f"Evaluating the {args.task} task agent on the {args.problem} problem.")
# collect the instance files
if args.problem == 'item_placement':
instances_path = pathlib.Path(f"instances/1_item_placement/test/")
instances = list(instances_path.glob('*.mps.gz'))
elif args.problem == 'capacitated_facility_location':
import ecole
instances = ecole.instance.CapacitatedFacilityLocationGenerator(n_customers=200, n_facilities=50)
instances.seed(seed)
elif args.problem == 'set_cover':
import ecole
instances = ecole.instance.SetCoverGenerator(n_rows=700, n_cols=500, density=0.05)
instances.seed(seed)
rl_primal = pathlib.Path(f"submissions/{args.task}/primal/hard_{args.problem}_seed_{seed}.csv")
rl_nodes = pathlib.Path(f"submissions/{args.task}/nodes/hard_{args.problem}_seed_{seed}.csv")
# rl_file = pathlib.Path(f"submissions/{args.task}/rl/hard_{args.problem}_seed_{seed}.csv")
# gcn_file = pathlib.Path(f"submissions/{args.task}/gcn/hard_{args.problem}_seed_{seed}.csv")
# expert_file = pathlib.Path(f"submissions/{args.task}/expert/hard_{args.problem}_seed_{seed}.csv")
# strong_branch_file = pathlib.Path(f"submissions/{args.task}/sb/medium_{args.problem}_seed_{seed}.csv")
results_fieldnames = ['instance', 'instance_number', 'initial_primal_bound', 'initial_dual_bound', 'objective_offset', 'cumulated_reward', 'time', 'number_of_nodes', 'primal_bound', 'dual_bound', 'status']
rl_primal.parent.mkdir(parents=True, exist_ok=True)
with open(rl_primal, mode='w') as csv_file:
primal_writer = csv.DictWriter(csv_file, fieldnames=results_fieldnames)
primal_writer.writeheader()
rl_nodes.parent.mkdir(parents=True, exist_ok=True)
with open(rl_nodes, mode='w') as csv_file:
node_writer = csv.DictWriter(csv_file, fieldnames=results_fieldnames)
node_writer.writeheader()
# expert_file.parent.mkdir(parents=True, exist_ok=True)
# with open(expert_file, mode='w') as csv_file:
# expert_writer = csv.DictWriter(csv_file, fieldnames=results_fieldnames)
# expert_writer.writeheader()
# strong_branch_file.parent.mkdir(parents=True, exist_ok=True)
# with open(strong_branch_file, mode='w') as csv_file:
# strong_branch_writer = csv.DictWriter(csv_file, fieldnames=results_fieldnames)
# strong_branch_writer.writeheader()
import sys
sys.path.insert(1, str(pathlib.Path.cwd()))
if args.task == "dual":
from submissions.dual.agents.rl import Policy as RLPolicy
from submissions.dual.agents.baseline import Policy as GCNPolicy
from submissions.dual.agents.baseline import ObservationFunction
from common.environments import Branching as Environment
from common.rewards import TimeLimitPrimalIntegral as BoundIntegral
from common.environments import Configuring, StrongBrancher
time_limit = 5*60
memory_limit = 8796093022207 # maximum
# override from command-line argument if provided
# time_limit = getattr(args, "timelimit", time_limit)
observation_function = ObservationFunction(problem=args.problem)
# rl_policy = RLPolicy(problem=args.problem)
# gcn_policy = GCNPolicy(problem=args.problem)
primal_policy = RLPolicy(problem=args.problem, reward='primal')
nodes_policy = RLPolicy(problem=args.problem, reward='nodes')
# seed both the agent and the environment (deterministic behavior)
# evaluation loop
for p, instance in enumerate(instances):
integral_function = BoundIntegral()
primal_env = Environment(
time_limit=time_limit,
observation_function=observation_function,
reward_function=-integral_function, # negated integral (minimization)
scip_params={'limits/memory': memory_limit},
)
# default SCIP solver
nodes_env = Environment(
time_limit=time_limit,
observation_function=observation_function,
reward_function=-ecole.reward.NNodes(),
scip_params={'limits/memory': memory_limit},
)
# nodes_env = Configuring(
# time_limit=time_limit,
# observation_function=None,
# reward_function=-ecole.reward.NNodes(),
# scip_params={'limits/memory': memory_limit},
# )
# vanillafullstrong_env = StrongBrancher(
# time_limit=time_limit,
# observation_function=None,
# reward_function=-integral_function,
# scip_params={'limits/memory': memory_limit},
# )
observation_function.seed(seed)
primal_policy.seed(seed)
nodes_policy.seed(seed)
primal_env.seed(seed)
nodes_env.seed(seed)
# vanillafullstrong_env.seed(seed)
# set up the reward function parameters for that instance
if args.problem == 'item_placement':
with open(instance.with_name(instance.stem).with_suffix('.json')) as f:
instance_info = json.load(f)
initial_primal_bound = instance_info["primal_bound"]
initial_dual_bound = instance_info["dual_bound"]
else:
initial_primal_bound = instance.primal_bound
initial_dual_bound = instance.dual_bound
objective_offset = 0
integral_function.set_parameters(
initial_primal_bound=initial_primal_bound,
initial_dual_bound=initial_dual_bound,
objective_offset=objective_offset)
print()
print(f"Instance {instance.name}")
print(f" instance number: {p}")
print(f" initial primal bound: {initial_primal_bound}")
print(f" initial dual bound: {initial_dual_bound}")
print(f" objective offset: {objective_offset}")
info, cumulated_reward = eval(primal_env, instance, initial_primal_bound, primal_policy)
# save instance results
with open(rl_primal, mode='a') as csv_file:
primal_writer = csv.DictWriter(csv_file, fieldnames=results_fieldnames)
primal_writer.writerow({
'instance': str(instance),
'instance_number': p,
'initial_primal_bound': initial_primal_bound,
'initial_dual_bound': initial_dual_bound,
'objective_offset': objective_offset,
'cumulated_reward': cumulated_reward,
'time': info['solvingtime'],
'number_of_nodes': info['nnodes'],
'primal_bound': info['primal_bound'],
'dual_bound': info['dual_bound'],
'status': info['status']
})
info, cumulated_reward = eval(nodes_env, instance, initial_primal_bound, nodes_policy)
# save instance results
with open(rl_nodes, mode='a') as csv_file:
node_writer = csv.DictWriter(csv_file, fieldnames=results_fieldnames)
node_writer.writerow({
'instance': str(instance),
'instance_number': p,
'initial_primal_bound': initial_primal_bound,
'initial_dual_bound': initial_dual_bound,
'objective_offset': objective_offset,
'cumulated_reward': cumulated_reward,
'time': info['solvingtime'],
'number_of_nodes': info['nnodes'],
'primal_bound': info['primal_bound'],
'dual_bound': info['dual_bound'],
'status': info['status']
})
# Solve using SCIP
# relpscost_env.reset(instance)
# _, _, cumulated_reward, _, default_info = relpscost_env.step({})
# with open(expert_file, mode='a') as csv_file:
# expert_writer = csv.DictWriter(csv_file, fieldnames=results_fieldnames)
# expert_writer.writerow({
# 'instance': str(instance),
# 'instance_number': p,
# 'initial_primal_bound': initial_primal_bound,
# 'initial_dual_bound': initial_dual_bound,
# 'objective_offset': objective_offset,
# 'cumulated_reward': cumulated_reward,
# 'time': default_info['solvingtime'],
# 'number_of_nodes': default_info['nnodes'],
# 'primal_bound': default_info['primal_bound'],
# 'dual_bound': default_info['dual_bound'],
# 'status': default_info['status']
# })
# vanillafullstrong_env.reset(instance)
# _, _, cumulated_reward, _, default_info = vanillafullstrong_env.step({})
# with open(strong_branch_file, mode='a') as csv_file:
# strong_branch_writer = csv.DictWriter(csv_file, fieldnames=results_fieldnames)
# strong_branch_writer.writerow({
# 'instance': str(instance),
# 'instance_number': p,
# 'initial_primal_bound': initial_primal_bound,
# 'initial_dual_bound': initial_dual_bound,
# 'objective_offset': objective_offset,
# 'cumulated_reward': cumulated_reward,
# 'time': default_info['solvingtime'],
# 'number_of_nodes': default_info['nnodes'],
# 'primal_bound': default_info['primal_bound'],
# 'dual_bound': default_info['dual_bound'],
# 'status': default_info['status']
# })
if p == 9:
print(f"finished evaluation.")
break