3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-29 11:55:51 +00:00

WIP on min cost flow problem

Remarks:
1. Follow the template structure of diff_logic.h
2. Try to reuse dl_graph<Ext> with some ready-to-use graph algorithms
3. Need to add 'explanation' to 'GExt' in order to instantiate
dl_graph<_>
This commit is contained in:
Anh-Dung Phan 2013-10-24 17:58:15 -07:00
parent be81e77c70
commit ebed5fa037
4 changed files with 271 additions and 69 deletions

102
src/smt/network_flow.h Normal file
View file

@ -0,0 +1,102 @@
/*++
Copyright (c) 2013 Microsoft Corporation
Module Name:
network_flow.h
Abstract:
Implements Network Simplex algorithm for min cost flow problem
Author:
Anh-Dung Phan (t-anphan) 2013-10-24
Notes:
This will be used to solve the dual of min cost flow problem
i.e. optimization of difference constraint.
We need a function to reduce DL constraints to min cost flow problem
and another function to convert from min cost flow solution to DL solution.
It remains unclear how to convert DL assignment to a basic feasible solution of Network Simplex.
A naive approach is to run an algorithm on max flow in order to get a spanning tree.
The network_simplex class hasn't had multiple pivoting strategies yet.
--*/
#ifndef _NETWORK_FLOW_H_
#define _NETWORK_FLOW_H_
#include"inf_rational.h"
#include"diff_logic.h"
namespace smt {
// Solve minimum cost flow problem using Network Simplex algorithm
template<typename Ext>
class network_flow : private Ext {
struct GExt : public Ext {
typedef literal explanation;
};
typedef dl_var node;
typedef dl_edge<GExt> edge;
typedef dl_graph<GExt> graph;
typedef typename Ext::numeral numeral;
graph m_graph;
// Denote supply/demand b_i on node i
vector<numeral> m_balances;
vector<numeral> m_potentials;
// Keep optimal solution of the min cost flow problem
inf_rational m_objective;
// Basic feasible flows
vector<numeral> m_flows;
// Denote the spanning tree of basic edges
vector<edge> m_basics;
// Denote non-basic edges with flow 0 for uncapicitated networks
vector<edge> m_nonbasics;
// Store the parent of a node in the spanning tree
svector<node> m_pred;
// Store the number of edge on the path to the root
svector<int> m_depth;
// Store the pointer to the next node in depth first search ordering
svector<node> m_thread;
public:
// Initialize the network with a feasible spanning tree
void initialize();
void compute_potentials();
void compute_flows();
// If all reduced costs are non-negative, the current flow is optimal
// If not optimal, return a violating edge in the corresponding variable
bool is_optimal(edge & violating_edge);
// Send as much flow as possible around the cycle, the first basic edge with flow 0 will leave
edge choose_leaving_edge(const edge & entering_edge);
void update_basics(const edge & entering_edge, const edge & leaving_edge);
bool is_unbounded();
// Compute the optimal solution
void get_optimal_solution(numeral & objective, vector<numeral> & flows);
// Minimize cost flows
// Return true if found an optimal solution, and return false if unbounded
bool min_cost();
};
}
#endif