Skip to content

Commit

Permalink
Merge branch 'edge_weight'
Browse files Browse the repository at this point in the history
  • Loading branch information
ifsmirnov committed Mar 21, 2017
2 parents 633caef + b8226cf commit fbd2fd3
Show file tree
Hide file tree
Showing 17 changed files with 1,704 additions and 407 deletions.
7 changes: 7 additions & 0 deletions array.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,19 @@ class GenericArray : public ReprProxy<GenericArray<T>>, public std::vector<T> {
// TODO(ifsmirnov): 'use' all methods and make inheritance private
using Base::at;
using Base::size;
using Base::resize;
using Base::begin;
using Base::end;
using Base::insert;
using Base::clear;
using Base::erase;

void extend(size_t requiredSize) {
if (requiredSize > size()) {
resize(requiredSize);
}
}

template<typename F, typename ...Args>
static GenericArray<T> randomf(size_t size, F func, const Args& ... args);
template<typename F, typename ...Args>
Expand Down
2 changes: 1 addition & 1 deletion dsu.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class Dsu {
return true;
}

bool connected() const { return components <= 1; }
bool isConnected() const { return components <= 1; }

private:
std::vector<int> parent;
Expand Down
294 changes: 229 additions & 65 deletions generic_graph.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "array.h"
#include "dsu.h"
#include "printers.h"
#include "weight.h"

#include <algorithm>
#include <iostream>
Expand All @@ -20,38 +21,64 @@ class GenericGraph {
virtual int n() const { return adjList_.size(); }
virtual int m() const { return numEdges_; }

virtual void addEdge(int u, int v);
virtual bool connected() const { return dsu_.connected(); }
// u, v: labels
virtual void addEdge(int u, int v, const Weight& w = Weight{});
virtual bool isConnected() const { return dsu_.isConnected(); }

virtual int vertexLabel(int v) const { return vertexLabel_[v]; }
virtual int vertexByLabel(int v) const { return vertexByLabel_[v]; }

virtual Array edges(int v) const {
// v: label
// return: array<label>
virtual Array edges(int v) const;

// return: array<label, label>
virtual Arrayp edges() const;

// order: by labels
// TODO: think about ordering here
virtual void setVertexWeights(const WeightArray& weights) {
ensure(static_cast<int>(weights.size()) == n());
vertexWeights_.resize(n());
for (int i = 0; i < n(); ++i) {
vertexWeights_[i] = weights[vertexByLabel(i)];
}
}

// v: label
virtual void setVertexWeight(int v, const Weight& weight) {
ensure(v < n());
v = vertexByLabel(v);

Array result;
std::transform(
adjList_[v].begin(),
adjList_[v].end(),
std::back_inserter(result),
[this](int x) { return vertexLabel(x); }
);
return result;
}

virtual Arrayp edges() const {
Arrayp result;
for (int id = 0; id < n(); ++id) {
int v = vertexByLabel(id);
size_t pos = result.size();
for (int to: edges(v)) {
if (v <= to) {
result.emplace_back(vertexLabel(v), vertexLabel(to));
}
}
std::sort(result.begin() + pos, result.end());
vertexWeights_.extend(v + 1);
vertexWeights_[v] = weight;
}

virtual void setEdgeWeights(const WeightArray& weights) {
ensure(static_cast<int>(weights.size()) == m());
edgeWeights_ = weights;
}

virtual void setEdgeWeight(size_t index, const Weight& weight) {
ensure(static_cast<int>(index) < m());
edgeWeights_.extend(index + 1);
edgeWeights_[index] = weight;
}

// v: label
virtual Weight vertexWeight(int v) const {
size_t index = vertexByLabel(v);
if (index < vertexWeights_.size()) {
return Weight{};
}
return vertexWeights_[index];
}

virtual Weight edgeWeight(size_t index) const {
if (index < edgeWeights_.size()) {
return Weight{};
}
return result;
return edgeWeights_[index];
}

// TODO: should it really be public?
Expand All @@ -63,66 +90,179 @@ class GenericGraph {
virtual bool operator<(const GenericGraph& other) const;

protected:
void doShuffle() {
if (vertexLabel_.size() < static_cast<size_t>(n())) {
vertexLabel_ = Array::id(n());
}
vertexLabel_.shuffle();
vertexByLabel_ = vertexLabel_.inverse();
edgesShuffled_ = true;
}
void doShuffle();

void extend(size_t size) {
size_t oldSize = n();
if (size > oldSize) {
adjList_.resize(size);
vertexLabel_ += Array::id(size - oldSize, oldSize);
vertexByLabel_ += Array::id(size - oldSize, oldSize);
}
}
void extend(size_t size);

void addEdgeUnsafe(int u, int v) {
adjList_[u].push_back(v);
if (u != v) {
adjList_[v].push_back(u);
}
++numEdges_;
}
// u, v: edge numbers
void addEdgeUnsafe(int u, int v);

// v: edge number
// returns: edge number
int edgeOtherEnd(int v, int edgeId);

void permuteEdges(const Array& order);

void normalizeEdges();

int compareTo(const GenericGraph& other) const;

int numEdges_ = 0;

bool edgesShuffled_ = false;
bool directed_ = false;

Dsu dsu_;
std::vector<std::vector<int>> adjList_;
std::vector<Array> adjList_;
Array vertexLabel_;
Array vertexByLabel_;
Arrayp edges_;

WeightArray vertexWeights_;
WeightArray edgeWeights_;
};

inline void GenericGraph::addEdge(int u, int v) {
extend(std::max(u, v) + 1);
dsu_.link(u, v);
addEdgeUnsafe(u, v);
Array GenericGraph::edges(int v) const {
v = vertexByLabel(v);

Array result;
std::transform(
adjList_[v].begin(),
adjList_[v].end(),
std::back_inserter(result),
[this, v](int x) { return vertexLabel(edgeOtherEnd(v, x)); }
);
return result;
}

inline void GenericGraph::doPrintEdges(
std::ostream& out, const OutputModifier& mod) const
{
Arrayp edges;
Arrayp GenericGraph::edges() const {
auto edges = edges_;
for (auto& e: edges) {
e.first = vertexLabel(e.first);
e.second = vertexLabel(e.second);
}
return edges;
}

inline void GenericGraph::doShuffle() {
if (vertexLabel_.size() < static_cast<size_t>(n())) {
vertexLabel_ = Array::id(n());
}
vertexLabel_.shuffle();
vertexByLabel_ = vertexLabel_.inverse();

if (!directed_) {
for (auto& edge: edges_) {
if (rnd.next(2)) {
std::swap(edge.first, edge.second);
}
}
}

permuteEdges(Array::id(numEdges_).shuffled());
}

inline void GenericGraph::extend(size_t size) {
size_t oldSize = n();
if (size > oldSize) {
adjList_.resize(size);
vertexLabel_ += Array::id(size - oldSize, oldSize);
vertexByLabel_ += Array::id(size - oldSize, oldSize);
}
}

void GenericGraph::addEdgeUnsafe(int u, int v) {
int id = numEdges_++;
edges_.emplace_back(u, v);

adjList_[u].push_back(id);
if (u != v) {
adjList_[v].push_back(id);
}
}

int GenericGraph::edgeOtherEnd(int v, int edgeId) {
ensure(edgeId < numEdges_);
const auto& edge = edges_[edgeId];
if (edge.first == v) {
return edge.second;
}
ensure(!directed_);
ensure(edge.second == v);
return edge.first;
}

void GenericGraph::permuteEdges(const Array& order) {
edges_ = edges_.subseq(order);

auto newByOld = order.inverse();
for (int v = 0; v < n(); ++v) {
for (int to: this->edges(v)) {
if (v <= to) {
edges.emplace_back(vertexLabel(v), vertexLabel(to));
for (auto& x: adjList_[v]) {
x = newByOld[x];
}
}

if (edgeWeights_.hasNonEmpty()) {
edgeWeights_.extend(m());
edgeWeights_ = edgeWeights_.subseq(order);
}
}

void GenericGraph::normalizeEdges() {
ensure(
vertexLabel_ == Array::id(n()),
"Can call normalizeEdges() only on newly created graph");

if (!directed_) {
for (auto& edge: edges_) {
if (edge.first > edge.second) {
std::swap(edge.first, edge.second);
}
}
}

if (edgesShuffled_) {
edges.shuffle();
auto order = Array::id(numEdges_).sorted(
[this](int i, int j) {
return edges_[i] < edges_[j];
});

permuteEdges(order);
}

inline void GenericGraph::addEdge(int u, int v, const Weight& w) {
extend(std::max(u, v) + 1);

u = vertexByLabel(u);
v = vertexByLabel(v);

dsu_.link(u, v);
addEdgeUnsafe(u, v);

if (!w.empty()) {
setEdgeWeight(m() - 1, w);
}
}

namespace {

WeightArray prepareWeightArray(WeightArray a, int requiredSize) {
ensure(a.hasNonEmpty(), "INTERNAL ASSERT");

a.extend(requiredSize);
int type = a.anyType();
for (auto& x: a) {
if (x.empty()) {
x.setType(type);
}
}

return a;
}

} // namespace

inline void GenericGraph::doPrintEdges(
std::ostream& out, const OutputModifier& mod) const
{
if (mod.printN) {
out << n();
if (mod.printM) {
Expand All @@ -133,11 +273,36 @@ inline void GenericGraph::doPrintEdges(
out << m() << "\n";
}

if (vertexWeights_.hasNonEmpty()) {
auto vertexWeights = prepareWeightArray(vertexWeights_, n());
for (int i = 0; i < n(); ++i) {
if (i > 0) {
out << " ";
}
JNGEN_PRINT_NO_MOD(vertexWeights[vertexByLabel(i)]);
}
out << "\n";
}

auto t(mod);
{
auto mod(t);

Arrayp edges = this->edges();
mod.printN = false;
JNGEN_PRINT(edges);
if (edgeWeights_.hasNonEmpty()) {
auto edgeWeights = prepareWeightArray(edgeWeights_, m());
for (int i = 0; i < m(); ++i) {
if (i > 0) {
out << "\n";
}
JNGEN_PRINT(edges[i]);
out << " ";
JNGEN_PRINT_NO_MOD(edgeWeights[i]);
}
} else {
JNGEN_PRINT(edges);
}
}
}

Expand All @@ -149,7 +314,6 @@ inline bool GenericGraph::operator<(const GenericGraph& other) const {
return compareTo(other) == -1;
}

// TODO: this should compare by vertex labels actually
inline int GenericGraph::compareTo(const GenericGraph& other) const {
if (n() != other.n()) {
return n() < other.n() ? -1 : 1;
Expand Down
Loading

0 comments on commit fbd2fd3

Please sign in to comment.