Commit 5f487878 authored by Thomas Fenz's avatar Thomas Fenz

upload files

parent f64cb593
# Created by .ignore support plugin (hsz.mobi)
### Python template
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
### Windows template
# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
### Linux template
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea*
.idea/*
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/dictionaries
.idea/**/shelf
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# CMake
cmake-build-debug/
cmake-build-release/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
### macOS template
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### Gurobi export
gurobi.log
# 2019-networking
# Overview 2019-networking
Public repository for reproducibility of our IFIP Networking 2019 paper
\ No newline at end of file
This repository contains a simple framework for routing for reconfigurable demand-aware networks.
The code is written in **Python3.6** and requires some few packages (see next section)
The code has been the basis for computational evaluations within the following publication:
**[1]** Thomas Fenz, Klaus-Tycho Foerster, Stefan Schmid, Anaïs Villedieu: **"Efficient Non-Segregated Routing for Reconfigurable Demand-Aware Networks"**. IFIP Networking 2019 Conference.
# Dependencies and Requirements
Python 3.6. Required python libraries: gurobipy, networkx, munkres, matplotlib.
**Note**: Our source is tested only on Linux (Ubuntu 18.04.1 LTS) and macOs (Mojave 10.14.3).
# Structure
* The folder **[algorithms/heuristics](algorithms/heuristics/)** contains all implemented heuristic algorithms.
* The folder **[algorithms/ilps](algorithms/ilps/)** contains all different versions of the implemented ilp algorithm.
* The folder **[data_sets](data_sets/)** contains two sets of input data to test the algorithms (static topology, optical topology, demands).
# Code Structure
The code is structured as follows:
* **run_simple_tests.py** is the main entry point of the program. It fetches the input data from the data sets and executes all implemented algorithm.
* **data_sets/simple_data_set1.py** contains simple input data (static topology, optical topology, demands)
* **data_sets/simple_data_set2.py** contains simple input data (static topology, optical topology, demands)
* **algorithms/heuristics/demand_first_directed.py** contains the implementation of the Demand First (directed) algorithm
* **algorithms/heuristics/demand_first_undirected.py** contains the implementation of the Demand First (undirected) algorithm
* **algorithms/heuristics/gain_demand_directed.py** contains the implementation of the Gain Demand (directed) algorithm
* **algorithms/heuristics/gain_demand_undirected.py** contains the implementation of the Gain Demand (undirected) algorithm
* **algorithms/heuristics/gain_update_directed.py** contains the implementation of the Gain Update (directed) algorithm
* **algorithms/heuristics/gain_update_undirected.py** contains the implementation of the Gain Update (undirected) algorithm
* **algorithms/heuristics/greedy_links_directed.py** contains the implementation of the Greedy Links (directed) algorithm
* **algorithms/heuristics/greedy_links_undirected.py** contains the implementation of the Greedy Links (undirected) algorithm
* **algorithms/heuristics/heuristics_helper_directed.py** contains shared methods used by various heuristic algorithms
* **algorithms/heuristics/heuristics_helper_undirected.py** contains shared methods used by various heuristic algorithms
* **algorithms/heuristics/segregated_directed.py** contains the implementation of the Segregated (directed) algorithm
* **algorithms/heuristics/segregated_undirected.py** contains the implementation of the Segregated (undirected) algorithm
* **algorithms/ilps/ilp_directed.py** contains the implementation of the Ilp (directed) algorithm
* **algorithms/ilps/ilp_directed_quadratic_constraints.py** contains the implementation of the Ilp (directed) algorithm
* **algorithms/ilps/ilp_helper.py** contains shared methods used by various ilp algorithms
* **algorithms/ilps/ilp_undirected.py** contains the implementation Ilp (undirected) algorithm
* **algorithms/ilps/ilp_undirected_quadratic_constraints.py** contains the implementation of the Ilp (undirected) algorithm
import networkx as nx
import heuristics_helper_directed as helper
def __demand_first(G, nx_static, D, optical_topology, nN, nR):
demand_values = []
demand_pair = []
for i, j in D:
demand_pair += [(i, j)]
demand_values += [D[(i, j)]]
for k in range(len(D)):
max_demand = max(demand_values)
max_index = demand_values.index(max_demand)
(start, end) = demand_pair[max_index]
if nx.shortest_path_length(nx_static, start, end, "weight") > nx.shortest_path_length(G, start, end, "weight"):
helper.update_graph(G, nx_static, nx.shortest_path(G, start, end, "weight"), True, optical_topology, nN, nR)
del demand_values[max_index]
del demand_pair[max_index]
return (nx_static)
def solve(s, o, D):
ex = None
nx_full_topology = nx.MultiDiGraph() # represents all currently possible edges
nx_static_topology = nx.MultiDiGraph() # represents static edges and matchings made
all_arcs_ij = set([(i, j) for _, i, j in o])
all_arcs_ij.update(s)
nN = int(max(max(i, j) for i, j in all_arcs_ij) + 1)
nR = int(max(R for R, _, _ in o) + 1)
optical_topology = o
for i, j in s:
nx_static_topology.add_edge(i, j, weight=s[(i, j)])
nx_full_topology.add_edge(i, j, key=0, weight=s[(i, j)])
for r, i, j in o:
nx_full_topology.add_edge(i, j, key=r + 1, weight=o[(r, i, j)])
try:
solution = helper.get_objective(
__demand_first(nx_full_topology, nx_static_topology, D, optical_topology, nN, nR), D)
except ex as Exception:
return False, str(ex), ""
return True, "", solution
import copy
import heuristics_helper_undirected as helper
# not optimal if triangular inequality in optical links not respected
def __demand_first(stopology, otopology, demand):
"""
find the biggest demand
make the best matching for it
delete it
repeat until no more demands
"""
s_topology = copy.deepcopy(stopology)
o_topology = copy.deepcopy(otopology)
newdemand = copy.deepcopy(demand)
max_demand = 0
max_index = 0
for k in range(len(demand)):
maxstart = 0
maxend = 0
for i, j in newdemand.keys():
if newdemand[(i, j)] > max_demand:
max_demand = newdemand[(i, j)]
maxstart = i
maxend = j
[path, distance] = helper.shortest_path(s_topology, o_topology, maxstart, maxend, nN, nR)
(s_topology, o_topology) = helper.update_graph(s_topology, o_topology, path, True, nN, nR)
del newdemand[(maxstart, maxend)]
max_demand = 0
return (s_topology)
def solve(s, o, D):
ex = None
global nN # todo this is ugly, but i don't have time to refactor the whole code
global nR
global optical_topology
all_arcs_ij = set([(i, j) for _, i, j in o])
all_arcs_ij.update(s)
nN = int(max(max(i, j) for i, j in all_arcs_ij) + 1)
nR = int(max(R for R, _, _ in o) + 1)
optical_topology = o
try:
solution = helper.get_objective(__demand_first(s, optical_topology, D), D, nN)
except ex as Exception:
return False, str(ex), ""
return True, "", solution
import networkx as nx
import heuristics_helper_directed as helper
def __gain_demand(G, nx_static, D, optical_topology, nN, nR):
demand_list = []
obj_function_list = []
temp_static = nx_static.copy()
temp_G = G.copy()
for i, j in D:
demand_list += [[i, j]]
if nx.shortest_path_length(temp_static, i, j, "weight") > nx.shortest_path_length(temp_G, i, j, "weight"):
temp_static = helper.update_graph(temp_G, temp_static, nx.shortest_path(G, i, j, "weight"), False,
optical_topology, nN, nR)
obj_function_list += [helper.get_objective(temp_static, D)]
else:
obj_function_list += [helper.get_objective(temp_static, D)]
for k in range(len(D)):
min_value = min(obj_function_list)
min_index = obj_function_list.index(min_value)
[start, end] = demand_list[min_index]
if nx.shortest_path_length(nx_static, start, end, "weight") > nx.shortest_path_length(G, start, end, "weight"):
helper.update_graph(G, nx_static, nx.shortest_path(G, start, end, "weight"), True, optical_topology, nN, nR)
del obj_function_list[min_index]
del demand_list[min_index]
return (nx_static)
def solve(s, o, D):
ex = None
nx_full_topology = nx.MultiDiGraph() # represents all currently possible edges
nx_static_topology = nx.MultiDiGraph() # represents static edges and matching made
all_arcs_ij = set([(i, j) for _, i, j in o])
all_arcs_ij.update(s)
nN = int(max(max(i, j) for i, j in all_arcs_ij) + 1)
nR = int(max(R for R, _, _ in o) + 1)
optical_topology = o
for i, j in s:
nx_static_topology.add_edge(i, j, weight=s[(i, j)])
nx_full_topology.add_edge(i, j, key=0, weight=s[(i, j)])
for r, i, j in o:
nx_full_topology.add_edge(i, j, key=r + 1, weight=o[(r, i, j)])
try:
solution = helper.get_objective(
__gain_demand(nx_full_topology, nx_static_topology, D, optical_topology, nN, nR)
, D)
except ex as Exception:
return False, str(ex), ""
return True, "", solution
import copy
import heuristics_helper_undirected as helper
# not optimal if triangular inequality in optical links not respected
def __gain_demand(stopology, otopology, demand):
"""
find the best graph for each demand
find the value of the objective function in each of these graphs
match the demand that got the smallest objective function
delete it
repeat until no more demands
"""
s_topology = copy.deepcopy(stopology)
o_topology = copy.deepcopy(otopology)
staticpathlength = []
for i, j in demand:
(s_topology, o_topology) = helper.update_graph(s_topology, o_topology,
helper.shortest_path(s_topology, o_topology, i, j, nN, nR)[0],
False, nN, nR)
gain = helper.get_objective(s_topology, demand, nN)
staticpathlength += [[i, j, gain]]
s_topology = copy.deepcopy(stopology)
o_topology = copy.deepcopy(otopology)
min = staticpathlength[0][2]
for i in range(len(demand)):
min = staticpathlength[0][2]
index = 0
start = staticpathlength[0][0]
end = staticpathlength[0][1]
for k in range(len(staticpathlength)):
if staticpathlength[k][2] < min:
index = k
min = staticpathlength[k][2]
start = staticpathlength[k][0]
end = staticpathlength[k][1]
[path, distance] = helper.shortest_path(s_topology, o_topology, start, end, nN, nR)
topology = helper.update_graph(s_topology, o_topology, path, True, nN, nR)
del staticpathlength[index]
return (s_topology)
def solve(s, o, D):
ex = None
global nN
global nR
global optical_topology
all_arcs_ij = set([(i, j) for _, i, j in o])
all_arcs_ij.update(s)
nN = int(max(max(i, j) for i, j in all_arcs_ij) + 1)
nR = int(max(R for R, _, _ in o) + 1)
optical_topology = o
try:
solution = helper.get_objective(__gain_demand(s, optical_topology, D), D, nN)
except ex as Exception:
return False, str(ex), ""
return True, "", solution
import networkx as nx
import heuristics_helper_directed as helper
def __gain_update(G, nx_static, D, optical_topology, nN, nR):
obj_function_list = []
demands = []
temp_static = nx_static.copy()
temp_G = G.copy()
current_obj_fct_value = -1
for (i, j) in D:
demands += [(i, j)]
for k in range(len(D)):
for i, j in demands:
if nx.shortest_path_length(temp_static, i, j, "weight") > nx.shortest_path_length(temp_G, i, j, "weight"):
temp_static = helper.update_graph(temp_G, temp_static, nx.shortest_path(G, i, j, "weight"), False,
optical_topology, nN, nR)
obj_function_list += [helper.get_objective(temp_static, D)]
else:
obj_function_list += [helper.get_objective(temp_static, D)]
temp_static = nx_static.copy()
temp_G = G.copy()
min_distance = min(obj_function_list)
if min_distance == current_obj_fct_value:
return (nx_static)
else:
current_obj_fct_value = min_distance
min_index = obj_function_list.index(min_distance)
(start, end) = demands[min_index]
if nx.shortest_path_length(nx_static, start, end, "weight") > nx.shortest_path_length(G, start, end, "weight"):
helper.update_graph(G, nx_static, nx.shortest_path(G, start, end, "weight"), True, optical_topology, nN, nR)
obj_function_list = []
demands.remove((start, end))
return (nx_static)
def solve(s, o, D):
ex = None
nx_full_topology = nx.MultiDiGraph() # represents all currently possible edges
nx_static_topology = nx.MultiDiGraph() # represents static edges and matching made
all_arcs_ij = set([(i, j) for _, i, j in o])
all_arcs_ij.update(s)
nN = int(max(max(i, j) for i, j in all_arcs_ij) + 1)
nR = int(max(R for R, _, _ in o) + 1)
optical_topology = o
for i, j in s:
nx_static_topology.add_edge(i, j, weight=s[(i, j)])
nx_full_topology.add_edge(i, j, key=0, weight=s[(i, j)])
for r, i, j in o:
nx_full_topology.add_edge(i, j, key=r + 1, weight=o[(r, i, j)])
try:
solution = helper.get_objective(
__gain_update(nx_full_topology, nx_static_topology, D, optical_topology, nN, nR), D)
except ex as Exception:
return False, str(ex), ""
return True, "", solution
import copy
import heuristics_helper_undirected as helper
# not optimal if triangular inequality in optical links not respected
def __gain_update(stopology, otopology, demand):
"""
find the best graph for each demand
find the value of the objective function in each of these graphs
match the demand that got the smallest objective function
delete the demand
repeat everything until no more demand
"""
s_topology = copy.deepcopy(stopology)
o_topology = copy.deepcopy(otopology)
s_temp = copy.deepcopy(s_topology)
o_temp = copy.deepcopy(o_topology)
pathlength = []
demands = []
current_obj_fct_value = -1
for (i, j) in demand:
demands += [[i, j]]
for k in range(len(demand)):
for i in demands:
(s_temp, o_temp) = helper.update_graph(s_temp, o_temp,
helper.shortest_path(s_temp, o_temp, i[0], i[1], nN, nR)[0], False,
nN, nR)
pathlength += [helper.get_objective(s_temp, demand, nN)]
s_temp = copy.deepcopy(s_topology)
o_temp = copy.deepcopy(o_topology)
min_distance = min(pathlength)
if min_distance == current_obj_fct_value:
return (s_topology)
else:
current_obj_fct_value = min_distance
min_index = pathlength.index(min_distance)
[path, distance] = helper.shortest_path(s_topology, o_topology, demands[min_index][0], demands[min_index][1],
nN, nR)
helper.update_graph(s_topology, o_topology, path, True, nN, nR)
del demands[min_index]
pathlength = []
return (s_topology)
def solve(s, o, D):
ex = None
global nN
global nR
global optical_topology
all_arcs_ij = set([(i, j) for _, i, j in o])
all_arcs_ij.update(s)
nN = int(max(max(i, j) for i, j in all_arcs_ij) + 1)
nR = int(max(R for R, _, _ in o) + 1)
optical_topology = o
try:
solution = helper.get_objective(__gain_update(s, optical_topology, D), D, nN)
except ex as Exception:
return False, str(ex), ""
return True, "", solution
import networkx as nx
import heuristics_helper_directed as helper
def __greedy_links(G, nx_static, optical_topology, D, nN, nR):
obj_function_list = []
links = []
temp_static = nx_static.copy()
temp_G = G.copy()
current_obj_fct_value = -1
for (s, i, j) in optical_topology:
links += [(i, j)]
for k in range(len(links)):
for (i, j) in links:
if nx.shortest_path_length(temp_static, i, j, "weight") > nx.shortest_path_length(temp_G, i, j, "weight"):
temp_static = helper.update_graph(temp_G, temp_static, nx.shortest_path(G, i, j, "weight"), False,
optical_topology, nN, nR)
obj_function_list += [helper.get_objective(temp_static, D)]
else:
obj_function_list += [helper.get_objective(temp_static, D)]
temp_static = nx_static.copy()
temp_G = G.copy()
min_distance = min(obj_function_list)
if min_distance == current_obj_fct_value:
return nx_static
else:
current_obj_fct_value = min_distance
min_index = obj_function_list.index(min_distance)
(start, end) = links[min_index]
if nx.shortest_path_length(nx_static, start, end, "weight") > nx.shortest_path_length(G, start, end, "weight"):
helper.update_graph(G, nx_static, nx.shortest_path(G, start, end, "weight"), True, optical_topology, nN, nR)
obj_function_list = []
links.remove((start, end))
return nx_static
def solve(s, o, D):
ex = None
nx_full_topology = nx.MultiDiGraph() # represents all currently possible edges
nx_static_topology = nx.MultiDiGraph() # represents static edges and matching made
all_arcs_ij = set([(i, j) for _, i, j in o])
all_arcs_ij.update(s)
nN = int(max(max(i, j) for i, j in all_arcs_ij) + 1)
nR = int(max(R for R, _, _ in o) + 1)
for i, j in s:
nx_static_topology.add_edge(i, j, weight=s[(i, j)])
nx_full_topology.add_edge(i, j, key=0, weight=s[(i, j)])
for r, i, j in o:
nx_full_topology.add_edge(i, j, key=r + 1, weight=o[(r, i, j)])
try:
solution = helper.get_objective(
__greedy_links(nx_full_topology.copy(), nx_static_topology.copy(), o, D, nN, nR), D)
except ex as Exception:
return False, str(ex), ""
return True, "", solution
import copy
import heuristics_helper_undirected as helper
# not optimal if triangular inequality in optical links not respected
def __greedy_links(stopology, otopology, demand): # this is really slow but can be made better see lower comment
"""
match one optical link
find the value of the objective function in this new graph
repeat for all links
match the link that got the smallest objective function
repeat from the start until no more link
"""
s_topology = copy.deepcopy(stopology)
o_topology = copy.deepcopy(otopology)
s_temp = copy.deepcopy(s_topology)
o_temp = copy.deepcopy(o_topology)
pathlength = []
links = []
current_obj_fct_value = -1
for (s, i, j) in o_topology:
links += [[i, j]]
for k in range(len(links)):
# instead of doing that it should be end when no more matches can be made not that hard but annoying
for i in links:
(s_temp, o_temp) = helper.update_graph(s_temp, o_temp,
helper.shortest_path(s_temp, o_temp, i[0], i[1], nN, nR)[0], False,
nN, nR)
pathlength += [helper.get_objective(s_temp, demand, nN)]
s_temp = copy.deepcopy(s_topology)
o_temp = copy.deepcopy(o_topology)
min_distance = min(pathlength)
if min_distance == current_obj_fct_value:
return (s_topology)
else:
current_obj_fct_value = min_distance
min_index = pathlength.index(min_distance)
[path, distance] = helper.shortest_path(s_topology, o_topology, links[min_index][0], links[min_index][1], nN,
nR)
helper.update_graph(s_topology, o_topology, path, True, nN, nR)