An evolutionary algorithm for solving the minimum cost network flow with minimum quantities problem.
(Suggestion: install miniconda)
conda install matplotlibconda install -c anaconda networkx- Download graphviz: https://www.graphviz.org/download/
- Also install python bindings:
conda install --channel conda-forge pygraphviz
In repository root:
python python/VisualNetwork.py tp0/tp0/output_network.json tp0/tp0/output_solution.json
tp0/tp0/output_network.jsonis the path to the network JSONtp0/tp0/output_solution.jsonis the path to the flow JSON
Problem instance:
- directed graph
G = (V, E) - a source
s ∈ V, a sinkt ∈ V - flow value
F ∈ N - arc costs
c : E → N_0 - arc capacities
u : E → N(upper bound) - minimum quantities
λ : E → N_0(variable lower bound) - optionally (?) variable lower bounds
vlb : E -> bool
Task:
Find a feasible f : E → N_0 of flow value F in G
such that the flow cost SUM[e ∈ E] f(e) * c(e) is minimized.
Everything important for implementing the C++ parts of the algorithm is defined in cpp/network.hpp:
Networkstruct represents an instance of an MCNF-MQ problemFlowtypedef (std::unordered_map<edge_key, int>) represents a flow over a networkint flow_value(Flow& f, Network& network)computes total flow offinnetwork(unimplemented)int flow_cost(Flow& f, Network& network)computes cost offinnetwork(unimplemented)
Network objects can be imported from or exported into text files, see data/exported_network_example.json.
Doing that provides a language/tool-agnostic way of defining data sets (JSON is easy to import into Python etc.)
This is the (current) structure of an instance (Network or exported file):
n_nodes: number of nodes in the networksource: key of the source vertexsink: key of the sink vertexflow_value: desired flow valueoutgoing[vertex_key],incoming[vertex_key]: for vertexvertex_keythese are sets of vertices that it's connected to (this is for easier lookups etc.)costs[edge_key],capacities[edge_key],minimum_quantities[edge_key]: map edges to integers as in the problem definition.
Utility functions:
edge_key get_edge_key(vertex_key v_from, vertex_key v_to): the edge(v_from, v_to)sadly needs to be wrapped into anedge_keyobjectstd::pair<vertex_key, vertex_key> get_vertex_keys(edge_key edge):pair.firstisv_from,pair.secondisv_tobool Network::exists_path(vertex_key v_from, vertex_key v_to): DFS fromv_fromtov_tobool Network::exists_edge(vertex_key v_from, vertex_key v_to): just a lookup in one of the above maps
- TODO: implement the generator as described in paper (1)
- this will be the
Network generate_instance_paper_one(ParametersOne p)function
- this will be the
Input to the generator is at the moment (as fields of Parameters defined in cpp/generator.hpp):
n_nodes: number of nodes the generated network will have (current generator doesn't utilize them all, working on a new one)flow_value: as beforecost_max: edge cost is a random whole number from[0, cost_max]capacity_max: variable lower bound (minimum quantity) is in[0, capacity_max]upper bound (capacity) is in[1, capacity_max], but ensuringlower<=upper
Current generator Network generate_instance(Parameters p) works as we discussed, but is otherwise quite bad.
Should be enough to test the solver.
Currently working on a better one.
- on Windows with MSYS2 or on Linux:
g++ -o test_serialization test_serialization.cpp generator.cpp network.cpp flow.cpp --std=c++17 -static-libgcc -static-libstdc++ -Wall
g++ -o test_ga_solver test_ga_solver.cpp generator.cpp network.cpp flow.cpp ga_solver.cpp --std=c++17 -static-libgcc -static-libstdc++ -Wall

