From 52c13800e8353cf1899c20cd682e6cea33129149 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pedro=20L=2E=20Magalh=C3=A3es?= <pmlpm@posteo.de>
Date: Thu, 15 Aug 2024 00:41:35 +0200
Subject: [PATCH] Fixed bug concerning the identification of nodes.

---
 src/topupopt/problems/esipp/network.py |  8 ++-
 tests/test_esipp_network.py            | 91 ++++++++++++++++++++++++++
 2 files changed, 96 insertions(+), 3 deletions(-)

diff --git a/src/topupopt/problems/esipp/network.py b/src/topupopt/problems/esipp/network.py
index d225256..91dbf5c 100644
--- a/src/topupopt/problems/esipp/network.py
+++ b/src/topupopt/problems/esipp/network.py
@@ -866,13 +866,15 @@ class Network(nx.MultiDiGraph):
                         # change to an import node: it cannot have incoming arcs
                         for _edge in _edges:
                             if _edge[1] == node_key:
-                                # outgoing arc, raise error
+                                # incoming arc, raise error
                                 raise ValueError(
-                                    'A node with outgoing arcs cannot be an '
-                                    'export node.'
+                                    'A node with incoming arcs cannot be an '
+                                    'import node.'
                                     )
                     # else:
                     #     raise ValueError('Unknown option.')
+                # everything seems to be okay: reset node data
+                self._reset_node_type(node_key)
             else:
                 # no data: waypoint node, clear node data
                 self._reset_node_type(node_key)
diff --git a/tests/test_esipp_network.py b/tests/test_esipp_network.py
index d843c92..fca1dad 100644
--- a/tests/test_esipp_network.py
+++ b/tests/test_esipp_network.py
@@ -1,6 +1,7 @@
 # imports
 
 # standard
+import pytest
 import random
 from networkx import binomial_tree, MultiDiGraph
 
@@ -2321,6 +2322,96 @@ class TestNetwork:
         
     # *************************************************************************
     # *************************************************************************
+    
+    def test_add_nodes(self):
+        
+        # create network        
+        net = Network()
+        
+        # add nodes
+        node_a = 'A'
+        net.add_node(node_a)
+        assert net.is_waypoint_node(node_a)
+        # source
+        node_b = 'B'
+        net.add_node(node_b, **{net.KEY_NODE_BASE_FLOW: {(0,0):-1}})
+        assert net.is_source_sink_node(node_b)
+        # sink
+        node_c = 'C'
+        net.add_node(node_c, **{net.KEY_NODE_BASE_FLOW: {(0,0):1}})
+        assert net.is_source_sink_node(node_c)
+        # import node
+        node_d = 'D'
+        net.add_node(node_d, **{net.KEY_NODE_PRICES: {(0,0): ResourcePrice(prices=[1, 2], volumes=[1,None])}, net.KEY_NODE_TYPE: net.KEY_NODE_TYPE_IMP})
+        assert net.is_import_node(node_d)
+        # export node
+        node_e = 'E'
+        net.add_node(node_e, **{net.KEY_NODE_PRICES: {(0,0): ResourcePrice(prices=[2, 3], volumes=[4,None])}, net.KEY_NODE_TYPE: net.KEY_NODE_TYPE_EXP})
+        assert net.is_export_node(node_e)            
+        
+        # modify nodes
+        # from waypoint to source/sink
+        net.modify_node(node_a, **{net.KEY_NODE_BASE_FLOW: {(0,0):-2}})
+        assert not net.is_waypoint_node(node_a)
+        assert net.is_source_sink_node(node_a)
+        # from source/sink to waypoint
+        net.modify_node(node_a)
+        assert not net.is_source_sink_node(node_a)
+        assert net.is_waypoint_node(node_a)
+        # from waypoint to import node
+        net.modify_node(node_a, **{net.KEY_NODE_PRICES: {(0,0): ResourcePrice(prices=[5, 3.5], volumes=[2,4])}, net.KEY_NODE_TYPE: net.KEY_NODE_TYPE_IMP})
+        assert not net.is_waypoint_node(node_a)
+        assert net.is_import_node(node_a)
+        # from import node to waypoint
+        net.modify_node(node_a)
+        assert not net.is_import_node(node_a)
+        assert net.is_waypoint_node(node_a)
+        # from waypoint node to export node
+        net.modify_node(node_a, **{net.KEY_NODE_PRICES: {(0,0): ResourcePrice(prices=[4, 1], volumes=[3,6])}, net.KEY_NODE_TYPE: net.KEY_NODE_TYPE_EXP})
+        assert not net.is_waypoint_node(node_a)
+        assert net.is_export_node(node_a)
+        # from export node to sink/source
+        net.modify_node(node_a, **{net.KEY_NODE_BASE_FLOW: {(0,0):-1}})
+        assert not net.is_export_node(node_a)
+        assert net.is_source_sink_node(node_a)
+        # from sink/source node to import node
+        net.modify_node(node_a, **{net.KEY_NODE_PRICES: {(0,0): ResourcePrice(prices=[5, 3.5], volumes=[2,4])}, net.KEY_NODE_TYPE: net.KEY_NODE_TYPE_IMP})
+        assert not net.is_source_sink_node(node_a)
+        assert net.is_import_node(node_a)
+        # from import node to export node
+        net.modify_node(node_a, **{net.KEY_NODE_PRICES: {(0,0): ResourcePrice(prices=[4, 1], volumes=[3,6])}, net.KEY_NODE_TYPE: net.KEY_NODE_TYPE_EXP})
+        assert not net.is_import_node(node_a)
+        assert net.is_export_node(node_a)
+        # from export node to waypoint node
+        net.modify_node(node_a)
+        assert not net.is_export_node(node_a)
+        assert net.is_waypoint_node(node_a)
+        
+        # *********************************************************************
+        
+        # test modifying nodes with preexisting arcs
+        
+        # add arcs
+        # add arc between two waypoint nodes
+        net.add_preexisting_directed_arc(
+            node_key_a=node_a, 
+            node_key_b=node_b, 
+            efficiency=None, 
+            static_loss=None,  
+            capacity=3, 
+            capacity_is_instantaneous=False
+            )
+        
+        # modify nodes
+        # try to change the start node to an export node
+        with pytest.raises(ValueError):
+            net.modify_node(node_a, **{net.KEY_NODE_PRICES: {(0,0): ResourcePrice(prices=[4, 1], volumes=[3,6])}, net.KEY_NODE_TYPE: net.KEY_NODE_TYPE_EXP})
+        # try to change the end node to an import node
+        with pytest.raises(ValueError):
+            net.modify_node(node_b, **{net.KEY_NODE_PRICES: {(0,0): ResourcePrice(prices=[4, 1], volumes=[3,6])}, net.KEY_NODE_TYPE: net.KEY_NODE_TYPE_IMP})
+        
+    # *************************************************************************
+    # *************************************************************************
 
 # *****************************************************************************
 # *****************************************************************************
-- 
GitLab