Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
Loading items

Target

Select target project
  • pmag/topupopt
1 result
Select Git revision
Loading items
Show changes
......@@ -321,12 +321,12 @@ class TestGisCalculate:
true_length_3_points = true_length_2_points_a + true_length_2_points_b
# make sure the function fails with a single point (sanity check)
error_triggered = False
error_raised = False
try:
line = LineString(list_1_points)
except Exception:
error_triggered = True
assert error_triggered
error_raised = True
assert error_raised
# make sure it works with 2 points
......
......@@ -4215,7 +4215,7 @@ class TestGisIdentify:
# not allowed
error_triggered = False
error_raised = False
try:
# inconsistent edge key format
gis_iden.is_edge_path(
......@@ -4224,8 +4224,8 @@ class TestGisIdentify:
allow_multiple_formats=False,
)
except ValueError:
error_triggered = True
assert error_triggered
error_raised = True
assert error_raised
# *********************************************************************
# *********************************************************************
......@@ -4294,15 +4294,15 @@ class TestGisIdentify:
# not allowed
error_triggered = False
error_raised = False
try:
# inconsistent edge key format
gis_iden.is_edge_path(
network, path=[(10, 8, 0), (8, 9)], allow_multiple_formats=False
)
except ValueError:
error_triggered = True
assert error_triggered
error_raised = True
assert error_raised
# inconsistent edge key format
......@@ -4314,15 +4314,15 @@ class TestGisIdentify:
# not allowed
error_triggered = False
error_raised = False
try:
# inconsistent edge key format
gis_iden.is_edge_path(
network, path=[(6, 5), (5, 4, 0), (4, 3)], allow_multiple_formats=False
)
except ValueError:
error_triggered = True
assert error_triggered
error_raised = True
assert error_raised
# *********************************************************************
# *********************************************************************
......
# imports
# standard
import sys
from ast import literal_eval
import random
......@@ -1121,7 +1121,7 @@ class TestGisUtils:
# trigger the error
error_triggered = False
error_raised = False
try:
(
node_keys,
......@@ -1129,8 +1129,8 @@ class TestGisUtils:
_,
) = gis_utils.prepare_node_data_from_geodataframe(gdf=gdf)
except ValueError:
error_triggered = True
assert error_triggered
error_raised = True
assert error_raised
# *****************************************************************************
# *****************************************************************************
......@@ -1322,18 +1322,18 @@ class TestGisUtils:
# mismatched longitudes and latitudes
error_triggered = False
error_raised = False
try:
_ = gis_utils.create_node_geodataframe(
longitudes=(_longitude, 528), latitudes=(_latitude,)
)
except ValueError:
error_triggered = True
assert error_triggered
error_raised = True
assert error_raised
# mismatched longitudes/latitudes and osmids
error_triggered = False
error_raised = False
try:
_ = gis_utils.create_node_geodataframe(
longitudes=(_longitude, 528),
......@@ -1341,8 +1341,8 @@ class TestGisUtils:
osmids=(59, 482, 135),
)
except ValueError:
error_triggered = True
assert error_triggered
error_raised = True
assert error_raised
# *************************************************************************
# *************************************************************************
......@@ -1881,12 +1881,12 @@ class TestGisUtils:
gdf.to_file(filename_gpkg)
else: # incompatible: errors are expected
error_triggered = False
error_raised = False
try:
gdf.to_file(filename_gpkg)
except Exception:
error_triggered = True
assert error_triggered
error_raised = True
assert error_raised
# *********************************************************************
# *********************************************************************
......@@ -2603,6 +2603,21 @@ class TestGisUtils:
# *************************************************************************
def test_simplify_network_osmnx(self):
# BUG: there is a bug here, therefore we are printing the seed number
# it seems to occur if all the nodes around 1106295281 are simplified
# seed: 5785034948163332129
# for edge_key in network.edges(keys=True):
# > assert len(tuple(gis_iden.get_edges_between_two_nodes(network, *edge_key[0:2]))) == 1
# E assert 2 == 1
# E + where 2 = len(((1106295281, 1106295315, 0), (1106295315, 1106295281, 0)))
# E + where ((1106295281, 1106295315, 0), (1106295315, 1106295281, 0)) = tuple([(1106295281, 1106295315, 0), (1106295315, 1106295281, 0)])
# E + where [(1106295281, 1106295315, 0), (1106295315, 1106295281, 0)] = <function get_edges_between_two_nodes at 0x7f8d07bc9ee0>(<networkx.classes.multidigraph.MultiDiGraph object at 0x7f8d00d17410>, *(1106295281, 1106295315))
# E + where <function get_edges_between_two_nodes at 0x7f8d07bc9ee0> = gis_iden.get_edges_between_two_nodes
seed = random.randrange(sys.maxsize)
random.seed(seed)
print("Seed was:", seed)
# get a network
network = ox.graph_from_point(
(55.71654, 9.11728),
......@@ -2618,6 +2633,11 @@ class TestGisUtils:
node_keys[random.randint(0, len(node_keys) - 1)]
for i in range(number_nodes_protected)
]
# protected_nodes.append(1106295281)
# assert 1 == 0
# E + where 1 = len([[317212013, 1106295281, 1106295315]])
# E + where [[317212013, 1106295281, 1106295315]] = <function find_simplifiable_paths at 0x7f9ac0cf22a0>(<networkx.classes.multidigraph.MultiDiGraph object at 0x7f9ab2c7b350>, [115838, 317195115, 5031764839, 317811652, 5076232388, 615539272, ...])
# E + where <function find_simplifiable_paths at 0x7f9ac0cf22a0> = gis_iden.find_simplifiable_paths
# try simplifying it
gis_utils.simplify_network(network, protected_nodes=protected_nodes)
# protected nodes must still exist
......
......@@ -5,29 +5,99 @@ from src.topupopt.solvers.interface import SolverInterface
from pyomo.opt.results.solver import TerminationCondition
import pyomo.environ as pyo
from pyomo.common.errors import ApplicationError
from pyomo.opt import check_available_solvers
import random
import pytest
# *****************************************************************************
# *****************************************************************************
@pytest.mark.parametrize(
"solver",
['glpk',
'cbc',
'scip',
'fakesolver']
)
class TestSolvers:
# *************************************************************************
# *************************************************************************
def test_solver_factory_arguments(self):
# test a collection of problems using different solvers
def test_inexistent_solver(self, solver):
# try using a fake solver and a problem incompatible with another solver
problem = self.problem_milp_feasible()
# list of problems: one compatible, one incompatible
list_problems = [
problem_milp_feasible(20, seed_number=50),
problem_lp_optimal(),
problem_qp_optimal(),
problem_qp_optimal(),
]
# problem types
list_problem_types = [
SolverInterface.PROBLEM_LP,
SolverInterface.PROBLEM_LP,
SolverInterface.PROBLEM_QP,
"fake_problem_type",
]
# solver settings
solver_timelimit = 30
solver_abs_mip_gap = 0
solver_rel_mip_gap = 0.01
solver_options = {
"time_limit": solver_timelimit,
"relative_mip_gap": solver_rel_mip_gap,
"absolute_mip_gap": solver_abs_mip_gap,
}
solver_timelimit = 10
# *********************************************************************
# *********************************************************************
solver_abs_mip_gap = 0.001
for index, problem in enumerate(list_problems):
# optimise
try:
# test problem-solver compatibility
problem_type = list_problem_types[index]
if not SolverInterface.problem_and_solver_are_compatible(
solver, problem_type):
continue
except SolverInterface.UnknownSolverError:
assert True
except SolverInterface.UnknownProblemTypeError:
assert True
# test the solver interface
try:
# configure common solver interface
_ = SolverInterface(solver_name=solver, **solver_options)
except SolverInterface.UnknownSolverError:
assert True
# *************************************************************************
# *************************************************************************
# @pytest.mark.skipif(True, reason="requires python3.10 or higher")
def test_solver_factory_arguments(self, solver):
# skip test if the solver is not available
if not bool(check_available_solvers(solver)):
return
# test a feasible problem
problem = problem_milp_feasible()
# solver settings
solver_timelimit = 10
solver_abs_mip_gap = 0.001
solver_rel_mip_gap = 0.01
solver_options = {
......@@ -35,61 +105,30 @@ class TestSolvers:
"relative_mip_gap": solver_rel_mip_gap,
"absolute_mip_gap": solver_abs_mip_gap,
# special option
"tee": True,
"tee": False,
}
solver_name = "scip"
results, solver_interface = self.optimise(solver_name, solver_options, problem)
results, solver_interface = optimise(solver, solver_options, problem)
# *************************************************************************
# *************************************************************************
def test_problems(self):
def test_problems(self, solver):
# test a collection of problems using different solvers
# solver = "scip"
# # scip_exec_path = '/usr/bin/scip'
# # solver_options = {'executable': scip_exec_path}
# solver_options = {}
# solver = 'cplex'
# # cplex_exec_path = '/home/pmlpm/Software/CPLEX/cplex/bin/x86-64_linux/cplex'
# cplex_exec_path = '/home/pmlpm/CPLEX/cplex/bin/x86-64_linux/cplex'
# #solver_options = {}
# solver_options = {'executable':cplex_exec_path}
list_solvers = [
"fake_solver",
"cbc",
"glpk",
"scip",
'cplex'
]
list_solver_options = [
None, # fake
None, # cbc
{"tee": False}, # glpk
None, # scip {'executable': scip_exec_path},
None, # cplex
# {'executable': cplex_exec_path},
]
# list of problems
list_concrete_models = [
self.problem_qp_optimal(),
self.problem_qp_infeasible(),
self.problem_lp_unbounded(),
self.problem_lp_infeasible(),
self.problem_lp_optimal(),
self.problem_milp_unbounded(),
self.problem_milp_infeasible(),
self.problem_milp_optimal(),
self.problem_milp_feasible(),
self.problem_milp_feasible(15, 64),
self.problem_milp_feasible(10, 46),
problem_qp_optimal(),
problem_qp_infeasible(),
problem_lp_unbounded(),
problem_lp_infeasible(),
problem_lp_optimal(),
problem_milp_unbounded(),
problem_milp_infeasible(),
problem_milp_optimal(),
problem_milp_feasible(),
problem_milp_feasible(15, 64),
problem_milp_feasible(10, 46),
]
# list of problem types
......@@ -138,29 +177,10 @@ class TestSolvers:
True,
]
# list of solvers
list_solvers = ["fake_solver", "cbc", "glpk", "scip", "cplex"]
# solver settings
solver_timelimit = 10
solver_abs_mip_gap = 0.001
solver_rel_mip_gap = 0.01
for solver_name, solver_options in zip(list_solvers, list_solver_options):
if type(solver_options) == dict:
solver_options.update(
{
"time_limit": solver_timelimit,
"relative_mip_gap": solver_rel_mip_gap,
"absolute_mip_gap": solver_abs_mip_gap,
}
)
else:
solver_options = {
"time_limit": solver_timelimit,
"relative_mip_gap": solver_rel_mip_gap,
......@@ -175,7 +195,7 @@ class TestSolvers:
if (
SolverInterface.problem_and_solver_are_compatible(
solver_name, problem_type
solver, problem_type
)
== False
):
......@@ -183,8 +203,8 @@ class TestSolvers:
# optimise
results, solver_interface = self.optimise(
solver_name, solver_options, problem, print_solver_output=False
results, solver_interface = optimise(
solver, solver_options, problem, print_solver_output=False
)
except SolverInterface.UnknownSolverError:
......@@ -205,19 +225,19 @@ class TestSolvers:
if (
exp_term_cond == None
or (
solver_name == "glpk"
solver == "glpk"
and exp_term_cond == TerminationCondition.unbounded
)
or (
solver_name == "cplex"
solver == "cplex"
and exp_term_cond == TerminationCondition.unbounded
)
or (
solver_name == "cplex"
solver == "cplex"
and exp_term_cond == TerminationCondition.optimal
)
or (
solver_name == "cplex"
solver == "cplex"
and exp_term_cond == TerminationCondition.infeasible
)
):
......@@ -226,7 +246,7 @@ class TestSolvers:
pass
else:
# print(solver_name)
# print(solver)
# print(results)
assert exp_term_cond == term_cond
......@@ -237,19 +257,19 @@ class TestSolvers:
if (
(
solver_name == "glpk"
solver == "glpk"
and term_cond == TerminationCondition.infeasible
)
or (
solver_name == "cplex"
solver == "cplex"
and term_cond == TerminationCondition.unknown
)
or (
solver_name == "cplex"
solver == "cplex"
and exp_term_cond == TerminationCondition.unbounded
)
or (
solver_name == "cplex"
solver == "cplex"
and exp_term_cond == TerminationCondition.infeasible
)
):
......@@ -272,23 +292,23 @@ class TestSolvers:
if (
exp_term_cond == None
or (
solver_name == "glpk"
solver == "glpk"
and exp_term_cond == TerminationCondition.unbounded
)
or (
solver_name == "glpk"
solver == "glpk"
and exp_term_cond == TerminationCondition.infeasible
)
or (
solver_name == "cplex"
solver == "cplex"
and exp_term_cond == TerminationCondition.unknown
)
or (
solver_name == "cplex"
solver == "cplex"
and exp_term_cond == TerminationCondition.unbounded
)
or (
solver_name == "cplex"
solver == "cplex"
and exp_term_cond == TerminationCondition.infeasible
)
):
......@@ -398,7 +418,7 @@ class TestSolvers:
# force an InconsistentProblemTypeAndSolverError
if problem_type == SolverInterface.PROBLEM_LP and solver_name == "glpk":
if problem_type == SolverInterface.PROBLEM_LP and solver == "glpk":
problem_type = SolverInterface.PROBLEM_QP
try:
......@@ -415,10 +435,12 @@ class TestSolvers:
# *************************************************************************
# *************************************************************************
# *****************************************************************************
# *****************************************************************************
# carry out optimisations
def optimise(
self,
solver_name: str,
solver_options: dict,
# solver_interface: SolverInterface,
......@@ -440,10 +462,11 @@ class TestSolvers:
# return
return results, solver_interface
# *************************************************************************
# *************************************************************************
def problem_qp_optimal(self):
# *****************************************************************************
# *****************************************************************************
def problem_qp_optimal():
model = pyo.ConcreteModel("qp_optimal")
model.x = pyo.Var(within=pyo.NonNegativeReals)
......@@ -466,10 +489,10 @@ class TestSolvers:
return model
# *************************************************************************
# *************************************************************************
# *****************************************************************************
# *****************************************************************************
def problem_qp_infeasible(self):
def problem_qp_infeasible():
model = pyo.ConcreteModel("qp_infeasible")
# model.x = pyo.Var(within=pyo.NonNegativeReals, bounds=(0,5))
......@@ -495,10 +518,10 @@ class TestSolvers:
return model
# *************************************************************************
# *************************************************************************
# *****************************************************************************
# *****************************************************************************
def problem_lp_optimal(self):
def problem_lp_optimal():
model = pyo.ConcreteModel("lp_optimal")
model.x = pyo.Var([1, 2], domain=pyo.NonNegativeReals)
......@@ -509,10 +532,10 @@ class TestSolvers:
return model
# *************************************************************************
# *************************************************************************
# *****************************************************************************
# *****************************************************************************
def problem_lp_infeasible(self):
def problem_lp_infeasible():
model = pyo.ConcreteModel("lp_infeasible")
model.x = pyo.Var([1, 2], domain=pyo.NonNegativeReals)
......@@ -523,10 +546,10 @@ class TestSolvers:
return model
# *************************************************************************
# *************************************************************************
# *****************************************************************************
# *****************************************************************************
def problem_lp_unbounded(self):
def problem_lp_unbounded():
model = pyo.ConcreteModel("lp_unbounded")
model.x = pyo.Var([1, 2], domain=pyo.NonNegativeReals)
......@@ -539,10 +562,10 @@ class TestSolvers:
return model
# *************************************************************************
# *************************************************************************
# *****************************************************************************
# *****************************************************************************
def problem_milp_optimal(self):
def problem_milp_optimal():
model = pyo.ConcreteModel("milp_optimal")
model.x = pyo.Var([1, 2], domain=pyo.Binary)
......@@ -553,10 +576,10 @@ class TestSolvers:
return model
# *************************************************************************
# *************************************************************************
# *****************************************************************************
# *****************************************************************************
def problem_milp_infeasible(self):
def problem_milp_infeasible():
model = pyo.ConcreteModel("milp_infeasible")
model.x = pyo.Var([1, 2], domain=pyo.Binary)
......@@ -567,10 +590,10 @@ class TestSolvers:
return model
# *************************************************************************
# *************************************************************************
# *****************************************************************************
# *****************************************************************************
def problem_milp_unbounded(self):
def problem_milp_unbounded():
model = pyo.ConcreteModel("milp_unbounded")
model.x = pyo.Var([1, 2], domain=pyo.NonNegativeReals)
......@@ -585,10 +608,10 @@ class TestSolvers:
return model
# *************************************************************************
# *************************************************************************
# *****************************************************************************
# *****************************************************************************
def problem_milp_feasible(self, number_binary_variables=25, seed_number=None):
def problem_milp_feasible(number_binary_variables=25, seed_number=None):
if seed_number != None:
random.seed(seed_number)
......@@ -624,91 +647,5 @@ class TestSolvers:
return model
# *************************************************************************
# *************************************************************************
def test_inexistent_solver(self):
fake_solver = "fake_solver"
good_solver = "glpk"
# solver_options: dict = None
# try using a fake solver and a problem incompatible with another solver
# list of problems: one compatible, one incompatible
list_problems = [
self.problem_milp_feasible(20, seed_number=50),
self.problem_lp_optimal(),
self.problem_qp_optimal(),
self.problem_qp_optimal(),
]
# problem types
list_problem_types = [
SolverInterface.PROBLEM_LP,
SolverInterface.PROBLEM_LP,
SolverInterface.PROBLEM_QP,
"fake_problem_type",
]
# list of solvers: one fake, one real
list_solvers = [fake_solver, good_solver]
# solver settings
solver_timelimit = 30
solver_abs_mip_gap = 0
solver_rel_mip_gap = 0.01
solver_options = {
"time_limit": solver_timelimit,
"relative_mip_gap": solver_rel_mip_gap,
"absolute_mip_gap": solver_abs_mip_gap,
}
# *********************************************************************
# *********************************************************************
for solver_name in list_solvers:
for index, problem in enumerate(list_problems):
# optimise
try:
# test problem-solver compatibility
problem_type = list_problem_types[index]
if (
SolverInterface.problem_and_solver_are_compatible(
solver_name, problem_type
)
== False
):
continue
except SolverInterface.UnknownSolverError:
assert True
except SolverInterface.UnknownProblemTypeError:
assert True
# test the solver interface
try:
# configure common solver interface
_ = SolverInterface(solver_name=solver_name, **solver_options)
except SolverInterface.UnknownSolverError:
assert True
# **************************************************************************
# **************************************************************************
# ******************************************************************************
# ******************************************************************************
# *****************************************************************************
# *****************************************************************************