From 7085d0c071affa49614d245da78cb10e9e936de7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pedro=20L=2E=20Magalh=C3=A3es?= <pmlpm@posteo.de>
Date: Mon, 22 Apr 2024 11:18:13 +0200
Subject: [PATCH] Adds tests for limiting the number of incoming directed arcs.

---
 src/topupopt/problems/esipp/model.py   |  35 ++-
 src/topupopt/problems/esipp/problem.py |  21 +-
 src/topupopt/problems/esipp/utils.py   |  20 +-
 tests/test_esipp_problem.py            | 193 +++++++++++---
 tests/test_solvers.py                  | 356 +------------------------
 5 files changed, 205 insertions(+), 420 deletions(-)

diff --git a/src/topupopt/problems/esipp/model.py b/src/topupopt/problems/esipp/model.py
index 2f828b3..b19f63b 100644
--- a/src/topupopt/problems/esipp/model.py
+++ b/src/topupopt/problems/esipp/model.py
@@ -2673,9 +2673,9 @@ def create_model(
     # there can only one incoming arc at most, if there are no outgoing arcs
 
     def rule_constr_max_incoming_directed_arcs(m, g, l):
-        # check if the constraint should be ignored
-
+        # check if the node is not among those subject to a limited number of incoming arcs
         if l not in m.set_L_max_in_g[g]:
+            # it is not, skip this constraint
             return pyo.Constraint.Skip
 
         # max number of directed incoming arcs
@@ -2691,7 +2691,7 @@ def create_model(
             if l_line not in m.set_L_imp[g]
             if (g, l_line, l) in m.set_J
         )
-
+        
         # check the maximum number of incoming arcs
 
         if n_max_dir_in <= 1:
@@ -2711,7 +2711,7 @@ def create_model(
             # the big m
 
             M_gl = n_max_dir_in - 1  # has to be positive since n_max_dir_in > 1
-
+            # TODO: put parenthesis to avoid funny results
             temp_constr = (
                 sum(
                     # *********************************************************
@@ -2747,7 +2747,7 @@ def create_model(
                     +
                     # *********************************************************
                     # interfaced arcs
-                    sum(
+                    (sum(
                         m.var_xi_arc_inv_gllj[(g, l_circ, l, j_circ)]
                         for j_circ in m.set_J[(g, l_circ, l)]
                         if j_circ not in m.set_J_und[(g, l_circ, l)]  # directed
@@ -2755,10 +2755,10 @@ def create_model(
                         if j_circ not in m.set_J_col[(g, l_circ, l)]  # individual
                     )
                     if (g, l_circ, l) in m.set_J
-                    else 0 +
+                    else 0) +
                     # *********************************************************
                     # optional non-interfaced arcs
-                    sum(
+                    (sum(
                         sum(
                             m.var_delta_arc_inv_glljh[(g, l_circ, l, j_dot, h_dot)]
                             for h_dot in m.set_H_gllj[(g, l_circ, l, j_dot)]
@@ -2770,25 +2770,25 @@ def create_model(
                         if j_dot not in m.set_J_mdt[(g, l_circ, l)]  # optional
                     )
                     if (g, l_circ, l) in m.set_J
-                    else 0 +
+                    else 0) +
                     # *********************************************************
                     # preexisting directed arcs
-                    sum(
+                    (sum(
                         1
                         for j_pre_dir in m.set_J_pre[(g, l_circ, l)]  # preexisting
                         if j_pre_dir not in m.set_J_und[(g, l_circ, l)]  # directed
                     )
                     if (g, l_circ, l) in m.set_J_pre
-                    else 0 +
+                    else 0) +
                     # *********************************************************
                     # mandatory directed arcs
-                    sum(
+                    (sum(
                         1
                         for j_mdt_dir in m.set_J_mdt[(g, l_circ, l)]
                         if j_mdt_dir not in m.set_J_und[(g, l_circ, l)]  # directed
                     )
                     if (g, l_circ, l) in m.set_J_mdt
-                    else 0
+                    else 0)
                     # *********************************************************
                     for l_circ in m.set_L[g]
                     if l_circ not in m.set_L_exp[g]
@@ -2912,14 +2912,11 @@ def create_model(
                 #     if l_diamond != l
                 #     )
             )
-
-            if temp_constr == True:
-                return pyo.Constraint.Feasible
-
-            elif temp_constr == False:
-                return pyo.Constraint.Infeasible
-
+            if type(temp_constr) == bool:
+                # trivial outcome
+                return pyo.Constraint.Feasible if temp_constr else pyo.Constraint.Infeasible
             else:
+                # constraint is relevant
                 return temp_constr
 
     model.constr_max_incoming_directed_arcs = pyo.Constraint(
diff --git a/src/topupopt/problems/esipp/problem.py b/src/topupopt/problems/esipp/problem.py
index 28ae2fa..7d3c9e5 100644
--- a/src/topupopt/problems/esipp/problem.py
+++ b/src/topupopt/problems/esipp/problem.py
@@ -3742,14 +3742,15 @@ class InfrastructurePlanningProblem(EnergySystem):
             for key, net in self.networks.items():
                 # check each edge
                 for edge_key in net.edges(keys=True):
-                    if not entries_are_invariant(
-                            net.edges[edge_key][Network.KEY_ARC_TECH].efficiency,
-                            qk_tuples
-                            ):
-                        # entries are not time invariant, remove q from consideration
-                        set_q.remove(q)
-                        q_meets_criteria = False
-                        break # break out of net.edges() for loop
+                    if net.edges[edge_key][Network.KEY_ARC_TECH].has_proportional_losses():
+                        if not entries_are_invariant(
+                                net.edges[edge_key][Network.KEY_ARC_TECH].efficiency,
+                                qk_tuples
+                                ):
+                            # entries are not time invariant, remove q from consideration
+                            set_q.remove(q)
+                            q_meets_criteria = False
+                            break # break out of net.edges() for loop
                 if not q_meets_criteria:
                     break # break out of self.networks.items():
                 
@@ -4070,13 +4071,13 @@ class InfrastructurePlanningProblem(EnergySystem):
         
         # self.param_c_wgt_q
         new_assessment_weights = {
-            q: self.assessment_weights[q] if q in self.assessment_weights else 1
+            q: self.assessment_weights[q] if (type(self.assessment_weights) == dict and q in self.assessment_weights) else 1
             for q in self.time_frame.assessments # original assessments
             if q not in q_ref_tuples # non-P&T
             #if q != q_peak
             }
         new_assessment_weights.update({
-            q_total: self.assessment_weights[q_ref] if q_ref in self.assessment_weights else 1
+            q_total: self.assessment_weights[q_ref] if (type(self.assessment_weights) == dict and q_ref in self.assessment_weights) else 1
             for q_total, q_ref in zip(q_total_tuples, q_ref_tuples)
             })
         new_assessment_weights[q_peak] = 1
diff --git a/src/topupopt/problems/esipp/utils.py b/src/topupopt/problems/esipp/utils.py
index 0c9fec7..db692f8 100644
--- a/src/topupopt/problems/esipp/utils.py
+++ b/src/topupopt/problems/esipp/utils.py
@@ -317,8 +317,8 @@ def compute_network_performance(solved_problem: InfrastructurePlanningProblem):
             # local demand
             network_flows_dict["gross_demand_gq"][(g, q)]
         )
-        for q in solved_problem.assessment_keys
-        for p in solved_problem.reporting_periods[q]
+        for q in solved_problem.time_frame.assessments
+        for p in solved_problem.time_frame.reporting_periods[q]
         for g in solved_problem.networks
     }
 
@@ -457,8 +457,8 @@ def compute_gross_network_flows(problem: InfrastructurePlanningProblem) -> dict:
                 for node_key in end_use_node_keys
                 if net.nodes[node_key][Network.KEY_NODE_BASE_FLOW][(q, k)] >= 0
             )
-            for q in problem.assessment_keys
-            for k in range(problem.number_time_intervals[q])
+            for q in problem.time_frame.assessments
+            for k in problem.time_frame.time_intervals[q]
         }
 
         gross_supply_qk = {
@@ -467,8 +467,8 @@ def compute_gross_network_flows(problem: InfrastructurePlanningProblem) -> dict:
                 for node_key in end_use_node_keys
                 if net.nodes[node_key][Network.KEY_NODE_BASE_FLOW][(q, k)] < 0
             )
-            for q in problem.assessment_keys
-            for k in range(problem.number_time_intervals[q])
+            for q in problem.time_frame.assessments
+            for k in problem.time_frame.time_intervals[q]
         }
 
         # (g,q,k)
@@ -482,18 +482,18 @@ def compute_gross_network_flows(problem: InfrastructurePlanningProblem) -> dict:
             {
                 (g, q): sum(
                     gross_supply_qk[(g, q, k)]
-                    for k in range(problem.number_time_intervals[q])
+                    for k in problem.time_frame.time_intervals[q]
                 )
-                for q in problem.assessment_keys
+                for q in problem.time_frame.assessments
             }
         )
         gross_demand_gq.update(
             {
                 (g, q): sum(
                     gross_demand_qk[(g, q, k)]
-                    for k in range(problem.number_time_intervals[q])
+                    for k in problem.time_frame.time_intervals[q]
                 )
-                for q in problem.assessment_keys
+                for q in problem.time_frame.assessments
             }
         )
 
diff --git a/tests/test_esipp_problem.py b/tests/test_esipp_problem.py
index af3ca63..288e5c1 100644
--- a/tests/test_esipp_problem.py
+++ b/tests/test_esipp_problem.py
@@ -16,15 +16,20 @@ from src.topupopt.problems.esipp.network import ArcsWithoutStaticLosses
 from src.topupopt.problems.esipp.resource import ResourcePrice
 from src.topupopt.problems.esipp.utils import compute_cost_volume_metrics
 from src.topupopt.problems.esipp.time import EconomicTimeFrame
-from src.topupopt.problems.esipp.converter import Converter
+# from src.topupopt.problems.esipp.converter import Converter
 
 # *****************************************************************************
 # *****************************************************************************
 
 class TestESIPPProblem:
+    
+    solver = 'glpk'
+    # solver = 'scip'
+    # solver = 'cbc'
+    
     def build_solve_ipp(
         self,
-        solver: str = "glpk",
+        # solver: str = "glpk",
         solver_options: dict = None,
         use_sos_arcs: bool = False,
         arc_sos_weight_key: str = (InfrastructurePlanningProblem.SOS1_ARC_WEIGHTS_NONE),
@@ -221,7 +226,7 @@ class TestESIPPProblem:
         
         # optimise
         ipp.optimise(
-            solver_name=solver,
+            solver_name=self.solver,
             solver_options=solver_options,
             output_options={},
             print_solver_output=print_solver_output,
@@ -572,7 +577,6 @@ class TestESIPPProblem:
 
         # no sos, regular time intervals
         ipp = self.build_solve_ipp(
-            # solver=solver,
             solver_options={},
             perform_analysis=False,
             plot_results=False,  # True,
@@ -664,15 +668,7 @@ class TestESIPPProblem:
 
         # no sos, regular time intervals
         ipp = self.build_solve_ipp(
-            # solver=solver,
             solver_options={},
-            # use_sos_arcs=use_sos_arcs,
-            # arc_sos_weight_key=sos_weight_key,
-            # arc_use_real_variables_if_possible=use_real_variables_if_possible,
-            # use_sos_sense=use_sos_sense,
-            # sense_sos_weight_key=sense_sos_weight_key,
-            # sense_use_real_variables_if_possible=sense_use_real_variables_if_possible,
-            # sense_use_arc_interfaces=use_arc_interfaces,
             perform_analysis=False,
             plot_results=False,  # True,
             print_solver_output=False,
@@ -681,10 +677,7 @@ class TestESIPPProblem:
             static_losses_mode=True,  # just to reach a line,
             mandatory_arcs=[],
             max_number_parallel_arcs={},
-            # init_aux_sets=init_aux_sets,
-            simplify_problem=False,
-            # reporting_periods={0: (0,)},
-            # discount_rates={0: (0.0,)},
+            simplify_problem=False
         )
 
         assert not ipp.has_peak_total_assessments()
@@ -784,15 +777,7 @@ class TestESIPPProblem:
 
         # no sos, regular time intervals
         ipp = self.build_solve_ipp(
-            # solver=solver,
             solver_options={},
-            # use_sos_arcs=use_sos_arcs,
-            # arc_sos_weight_key=sos_weight_key,
-            # arc_use_real_variables_if_possible=use_real_variables_if_possible,
-            # use_sos_sense=use_sos_sense,
-            # sense_sos_weight_key=sense_sos_weight_key,
-            # sense_use_real_variables_if_possible=sense_use_real_variables_if_possible,
-            # sense_use_arc_interfaces=use_arc_interfaces,
             perform_analysis=False,
             plot_results=False,  # True,
             print_solver_output=False,
@@ -801,10 +786,7 @@ class TestESIPPProblem:
             static_losses_mode=True,  # just to reach a line,
             mandatory_arcs=[],
             max_number_parallel_arcs={},
-            # init_aux_sets=init_aux_sets,
             simplify_problem=False,
-            # reporting_periods={0: (0,)},
-            # discount_rates={0: (0.0,)},
         )
 
         assert not ipp.has_peak_total_assessments()
@@ -1086,7 +1068,6 @@ class TestESIPPProblem:
         # no sos, regular time intervals
 
         ipp = self.build_solve_ipp(
-            # solver=solver,
             solver_options={},
             perform_analysis=False,
             plot_results=False,  # True,
@@ -1230,7 +1211,6 @@ class TestESIPPProblem:
 
         # no sos, regular time intervals
         ipp = self.build_solve_ipp(
-            # solver=solver,
             solver_options={},
             perform_analysis=False,
             plot_results=False,  # True,
@@ -1317,7 +1297,6 @@ class TestESIPPProblem:
 
         # no sos, regular time intervals
         ipp = self.build_solve_ipp(
-            # solver=solver,
             solver_options={},
             perform_analysis=False,
             plot_results=False,  # True,
@@ -1444,7 +1423,6 @@ class TestESIPPProblem:
 
         # no sos, regular time intervals
         ipp = self.build_solve_ipp(
-            # solver=solver,
             solver_options={},
             perform_analysis=False,
             plot_results=False,  # True,
@@ -6195,7 +6173,7 @@ class TestESIPPProblem:
                 ]:
             # TODO: make this work with GLPK and SCIP
             ipp = self.build_solve_ipp(
-                solver='cbc', # does not work with GLPK nor SCIP
+                # solver='cbc', # does not work with GLPK nor SCIP
                 solver_options={},
                 perform_analysis=False,
                 plot_results=False,  # True,
@@ -7624,7 +7602,7 @@ class TestESIPPProblem:
         # no sos, regular time intervals
     
         ipp = self.build_solve_ipp(
-            solver='cbc', # TODO: make this work with other solvers
+            # solver='cbc', # TODO: make this work with other solvers
             solver_options={},
             plot_results=False,  # True,
             print_solver_output=False,
@@ -7899,7 +7877,7 @@ class TestESIPPProblem:
     
         # no sos, regular time intervals    
         ipp = self.build_solve_ipp(
-            solver='cbc', # TODO: make this work with other solvers
+            # solver='cbc', # TODO: make this work with other solvers
             solver_options={},
             plot_results=False,  # True,
             print_solver_output=False,
@@ -8120,6 +8098,153 @@ class TestESIPPProblem:
     
     # TODO: test non-simplifiable problems with time varying prices on select assessments
     # TODO: test non-simplifiable problems with volume varying prices on select assessments
+    
+        
+    # *************************************************************************
+    # *************************************************************************
+    
+    def test_problem_with_tree_network(self):
+        
+        # assessment
+        q = 0
+        tf = EconomicTimeFrame(
+            discount_rate=3.5/100,
+            reporting_periods={q: (0,)},
+            reporting_period_durations={q: (365 * 24 * 3600,)},
+            time_intervals={q: (0,)},
+            time_interval_durations={q: (1,)},
+        )
+
+        # 2 nodes: one import, one regular
+        mynet = Network()
+
+        # import node
+        node_IMP = "thatimpnode"
+        mynet.add_import_node(
+            node_key=node_IMP,
+            prices={
+                qpk: ResourcePrice(prices=1.0, volumes=None)
+                for qpk in tf.qpk()
+            },
+        )
+
+        # node A
+        node_A = "thatnodea"
+        mynet.add_source_sink_node(
+            node_key=node_A,
+            base_flow={(q, 0): 0.50},
+        )
+        # node B
+        node_B = "thatnodeb"
+        mynet.add_source_sink_node(
+            node_key=node_B,
+            base_flow={(q, 0): 0.25},
+        )
+        # node C
+        node_C = "thatnodec"
+        mynet.add_source_sink_node(
+            node_key=node_C,
+            base_flow={(q, 0): 1.25},
+        )
+        
+        list_imp_arcs = [
+            (node_IMP, node_A), # IA
+            (node_IMP, node_B), # IB
+            (node_IMP, node_C), # IC
+            ]
+        for i, node_pair in enumerate(list_imp_arcs):
+        
+            # import arcs: IA, IB, IC
+            new_arc = Arcs(
+                name="IA",
+                efficiency=None,
+                efficiency_reverse=None,
+                static_loss=None,
+                capacity=[2],
+                minimum_cost=[6],
+                specific_capacity_cost=i,
+                capacity_is_instantaneous=False,
+                validate=False,
+            )
+            mynet.add_directed_arc(*node_pair, arcs=new_arc)        
+        
+        # arcs: AB, BA, BC, CB, AC, CA
+        
+        list_other_arcs = [
+            (node_A, node_B), # AB
+            (node_B, node_A), # BA
+            (node_B, node_C), # BC
+            (node_C, node_B), # CB
+            (node_A, node_C), # AC
+            (node_C, node_A), # CA
+            ]
+        
+        for node_pair in list_other_arcs:
+            # arc
+            new_arc_tech = Arcs(
+                name="any",
+                efficiency=None,
+                efficiency_reverse=None,
+                static_loss=None,
+                capacity=[3],
+                minimum_cost=[2],
+                specific_capacity_cost=0,
+                capacity_is_instantaneous=False,
+                validate=False,
+            )
+            mynet.add_directed_arc(*node_pair, arcs=new_arc_tech)
+
+        # identify node types
+        mynet.identify_node_types()
+
+        # no sos, regular time intervals
+        ipp = self.build_solve_ipp(
+            solver_options={},
+            perform_analysis=False,
+            plot_results=False,  # True,
+            print_solver_output=True,
+            time_frame=tf,
+            networks={"mynet": mynet},
+            static_losses_mode=True,  # just to reach a line,
+            mandatory_arcs=[],
+            max_number_parallel_arcs={},
+            simplify_problem=True,
+        )
+
+        assert ipp.has_peak_total_assessments()
+        assert ipp.results["Problem"][0]["Number of constraints"] == 61 
+        assert ipp.results["Problem"][0]["Number of variables"] == 53 
+        assert ipp.results["Problem"][0]["Number of nonzeros"] == 143
+        
+        # *********************************************************************
+        # *********************************************************************
+
+        # validation
+
+        # only the IA arc should be installed
+        true_imp_arcs_selected = [True, False, False]
+        for node_pair, true_arc_decision in zip(list_imp_arcs, true_imp_arcs_selected):
+            assert (
+                true_arc_decision
+                in ipp.networks["mynet"]
+                .edges[(*node_pair, 0)][Network.KEY_ARC_TECH]
+                .options_selected
+            )
+        # only two arcs between A, B and C can be installed
+        arcs_selected = tuple(
+            1
+            for node_pair in list_other_arcs
+            if True in ipp.networks["mynet"]
+            .edges[(*node_pair, 0)][Network.KEY_ARC_TECH]
+            .options_selected
+            )
+        assert sum(arcs_selected) == 2
+        # the network must be tree-shaped
+        assert ipp.networks["mynet"].has_tree_topology()
+        # capex
+        assert math.isclose(pyo.value(ipp.instance.var_capex), 10.0, abs_tol=1e-3)
+        # the objective function
+        assert math.isclose(pyo.value(ipp.instance.obj_f), -1.193236715e+01, abs_tol=1e-3)
 
 # *****************************************************************************
 # *****************************************************************************
\ No newline at end of file
diff --git a/tests/test_solvers.py b/tests/test_solvers.py
index 48773c6..7f0a728 100644
--- a/tests/test_solvers.py
+++ b/tests/test_solvers.py
@@ -38,342 +38,9 @@ class TestSolvers:
             "tee": True,
         }
 
-        solver_name = "glpk"
+        solver_name = "scip"
 
         results, solver_interface = self.optimise(solver_name, solver_options, problem)
-        
-    # *************************************************************************
-    # *************************************************************************
-
-    def test_problems_scip(self):
-        # test a collection of problems using different solvers
-
-        solver = "scip"
-        scip_exec_path = '/usr/bin/scip'
-        solver_options = {'executable': scip_exec_path}
-        # solver_options = {}
-
-        # 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),
-        ]
-
-        # list of problem types
-
-        list_problem_types = [
-            SolverInterface.PROBLEM_QP,
-            SolverInterface.PROBLEM_QP,
-            SolverInterface.PROBLEM_LP,
-            SolverInterface.PROBLEM_LP,
-            SolverInterface.PROBLEM_LP,
-            SolverInterface.PROBLEM_MILP,
-            SolverInterface.PROBLEM_MILP,
-            SolverInterface.PROBLEM_MILP,
-            SolverInterface.PROBLEM_MILP,
-            SolverInterface.PROBLEM_MILP,
-            "unknown_problem_type",
-        ]
-
-        # expected
-
-        list_problem_termination_conditions = [
-            TerminationCondition.optimal,
-            TerminationCondition.infeasible,
-            TerminationCondition.unbounded,
-            TerminationCondition.infeasible,
-            TerminationCondition.optimal,
-            TerminationCondition.unbounded,
-            TerminationCondition.infeasible,
-            TerminationCondition.optimal,
-            None,  # if we don't know what to expect,
-            None,  # if we don't know what to expect,
-            None,  # if we don't know what to expect
-        ]
-
-        list_problem_optimisation_sucess = [
-            True,
-            True,
-            False,
-            False,
-            True,
-            False,
-            False,
-            True,
-            True,
-            True,
-            True,
-        ]
-
-        # solver settings
-        solver_timelimit = 10
-        solver_abs_mip_gap = 0.001
-        solver_rel_mip_gap = 0.01
-        solver_options.update(
-            {
-                "time_limit": solver_timelimit,
-                "relative_mip_gap": solver_rel_mip_gap,
-                "absolute_mip_gap": solver_abs_mip_gap,
-            }
-        )
-        
-        for problem_index, problem in enumerate(list_concrete_models):
-            print('******************')
-            print(problem_index)
-            
-            # check problem and solver compatibility
-
-            problem_type = list_problem_types[problem_index]
-
-            if not SolverInterface.problem_and_solver_are_compatible(
-                    solver, problem_type
-                ):
-                continue
-            
-            try:
-                # optimise
-                results, solver_interface = self.optimise(
-                    solver, solver_options, problem, print_solver_output=False
-                )
-            except ApplicationError:
-                print(problem_index)
-                print(problem)
-                assert False
-
-            except SolverInterface.UnknownSolverError:
-                continue
-
-            except SolverInterface.UnknownProblemTypeError:
-                continue
-
-            # *************************************************************
-            # *************************************************************
-
-            # termination condition
-
-            exp_term_cond = list_problem_termination_conditions[problem_index]
-
-            term_cond = results.solver.termination_condition
-
-            if (
-                exp_term_cond == None
-                or (
-                    solver == "glpk"
-                    and exp_term_cond == TerminationCondition.unbounded
-                )
-                or (
-                    solver == "cplex"
-                    and exp_term_cond == TerminationCondition.unbounded
-                )
-                or (
-                    solver == "cplex"
-                    and exp_term_cond == TerminationCondition.optimal
-                )
-                or (
-                    solver == "cplex"
-                    and exp_term_cond == TerminationCondition.infeasible
-                )
-            ):
-                # exceptions in need of correction
-
-                pass
-
-            else:
-                # print(solver_name)
-                # print(results)
-                assert exp_term_cond == term_cond
-
-        # *********************************************************************
-        # *********************************************************************
-
-            # solver status
-
-            if (
-                (
-                    solver == "glpk"
-                    and term_cond == TerminationCondition.infeasible
-                )
-                or (
-                    solver == "cplex"
-                    and term_cond == TerminationCondition.unknown
-                )
-                or (
-                    solver == "cplex"
-                    and exp_term_cond == TerminationCondition.unbounded
-                )
-                or (
-                    solver == "cplex"
-                    and exp_term_cond == TerminationCondition.infeasible
-                )
-            ):
-                pass
-
-            else:
-                # check if the solver status matches the one one would expect
-                # if the termination condition was correct
-
-                assert (
-                    TerminationCondition.to_solver_status(term_cond)
-                    == results.solver.status
-                )
-
-                # if valid, it means the results object is coherent
-
-        # *********************************************************************
-        # *********************************************************************
-
-            if (
-                exp_term_cond == None
-                or (
-                    solver == "glpk"
-                    and exp_term_cond == TerminationCondition.unbounded
-                )
-                or (
-                    solver == "glpk"
-                    and exp_term_cond == TerminationCondition.infeasible
-                )
-                or (
-                    solver == "cplex"
-                    and exp_term_cond == TerminationCondition.unknown
-                )
-                or (
-                    solver == "cplex"
-                    and exp_term_cond == TerminationCondition.unbounded
-                )
-                or (
-                    solver == "cplex"
-                    and exp_term_cond == TerminationCondition.infeasible
-                )
-            ):
-                pass
-
-            else:
-                # check if the solver status matches the one one would expect
-                # if the termination condition predicted was obtained
-
-                assert (
-                    TerminationCondition.to_solver_status(exp_term_cond)
-                    == results.solver.status
-                )
-
-                # if valid, the solver status is correct despite other issues
-
-            # *************************************************************
-            # *************************************************************
-
-            # make sure the optimisation went as expected
-
-            exp_optim_result = list_problem_optimisation_sucess[problem_index]
-
-            if (
-                TerminationCondition.to_solver_status(
-                    results.solver.termination_condition
-                )
-                != results.solver.status
-            ):
-                # this can be removed once the aforementioned issues have
-                # been fixed (e.g. for the cplex and glpk solvers)
-
-                pass
-
-            else:
-                optim_result = solver_interface.was_optimisation_sucessful(
-                    results, problem_type
-                )
-
-            # *************************************************************
-            # *************************************************************
-
-            if (
-                TerminationCondition.to_solver_status(
-                    results.solver.termination_condition
-                )
-                != results.solver.status
-                or exp_term_cond == TerminationCondition.unbounded
-            ):
-                # this can be removed once the aforementioned issues have
-                # been fixed (e.g. for the cplex and glpk solvers)
-
-                pass
-
-            else:
-                assert optim_result == exp_optim_result
-
-            # *************************************************************
-            # *************************************************************
-
-            # test additional scenarios
-
-            if optim_result == False:
-                continue
-
-            # force unknown solver status error
-
-            results.solver.status = "false_solver_status"
-
-            try:
-                _ = solver_interface.was_optimisation_sucessful(
-                    results, problem_type
-                )
-
-            except solver_interface.UnknownSolverStatusError:
-                assert True
-
-            # force unknown termination condition error
-
-            results.solver.termination_condition = "false_termin_condition"
-
-            try:
-                _ = solver_interface.was_optimisation_sucessful(
-                    results, problem_type
-                )
-
-            except solver_interface.UnknownTerminationConditionError:
-                assert True
-
-            # force an InconsistentSolverStatusError
-
-            results.solver.termination_condition = TerminationCondition.optimal
-
-            results.solver.status = TerminationCondition.to_solver_status(
-                results.solver.termination_condition
-            )
-
-            results.solver.termination_condition = TerminationCondition.unknown
-
-            try:
-                _ = solver_interface.was_optimisation_sucessful(
-                    results, problem_type
-                )
-
-            except solver_interface.InconsistentSolverStatusError:
-                assert True
-
-            # force an InconsistentProblemTypeAndSolverError
-
-            if problem_type == SolverInterface.PROBLEM_LP and solver == "glpk":
-                problem_type = SolverInterface.PROBLEM_QP
-
-                try:
-                    _ = solver_interface.was_optimisation_sucessful(
-                        results, problem_type
-                    )
-
-                except solver_interface.InconsistentProblemTypeAndSolverError:
-                    assert True
-
-        # *********************************************************************
-        # *********************************************************************
 
     # *************************************************************************
     # *************************************************************************
@@ -381,11 +48,11 @@ class TestSolvers:
     def test_problems(self):
         # 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 = "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'
@@ -397,15 +64,15 @@ class TestSolvers:
             "cbc",
             "glpk",
             "scip",
-            #'cplex'
+            'cplex'
         ]
 
         list_solver_options = [
             None,  # fake
             None,  # cbc
             {"tee": False},  # glpk
-            None,  # scip
-            # cplex
+            None,  # scip {'executable': scip_exec_path},  
+            None, # cplex
             # {'executable': cplex_exec_path},
         ]
 
@@ -759,23 +426,18 @@ class TestSolvers:
         print_solver_output: bool = True,
     ):
         # configure common solver interface
-
         solver_interface = SolverInterface(solver_name=solver_name, **solver_options)
 
         # get the solver handler
-
         solver_handler = solver_interface.get_solver_handler(**solver_options)
 
         # solve
-
         if "tee" not in solver_options:
             results = solver_handler.solve(problem, tee=print_solver_output)
-
         else:
             results = solver_handler.solve(problem)
 
         # return
-
         return results, solver_interface
 
     # *************************************************************************
-- 
GitLab