Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions Telecom/NetworkPartitioner.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using System.Collections.Generic;
using System.Linq;
using CommNet;

namespace σκοπός {
public class NetworkPartitioner {
public NetworkPartitioner() { }

public readonly List<HashSet<CommNode>> partitions_ = new List<HashSet<CommNode>>();
public readonly HashSet<CommNode> disconnected_partition_ = new HashSet<CommNode>();
public readonly Dictionary<CommNode, HashSet<CommNode>> node_to_partition_map_ = new Dictionary<CommNode, HashSet<CommNode>>();

private readonly HashSet<CommNode> nodesToCover_ = new HashSet<CommNode>();
private readonly HashSet<CommNode> candidates_ = new HashSet<CommNode>();

private void ClearPartitions() {
foreach (var partition in partitions_) {
partition.Clear();
}
}

private void BuildPartition(CommNode start, HashSet<CommNode> partition, HashSet<CommNode> allNodes) {
candidates_.Add(start);
while (candidates_.Count > 0) {
var candidate = candidates_.First();
candidates_.Remove(candidate);
partition.Add(candidate);
allNodes.Remove(candidate);
foreach (var node in candidate.Keys.Where(x => allNodes.Contains(x))) {
candidates_.Add(node);
}
}
}
private void MapNodesToPartitions() {
node_to_partition_map_.Clear();
foreach (var partition in partitions_) {
foreach (var node in partition) {
node_to_partition_map_.Add(node, partition);
}
}
}
public void DiscoverPartitions(IEnumerable<CommNode> network) {
ClearPartitions();
if (partitions_.Count == 0) {
partitions_.Add(disconnected_partition_);
}

nodesToCover_.Clear();
foreach (var n in network) {
nodesToCover_.Add(n);
}

disconnected_partition_.Clear();
foreach (var n in nodesToCover_.Where(x => x.Keys.Count == 0)) {
disconnected_partition_.Add(n);
}
nodesToCover_.RemoveWhere(x => x.Keys.Count == 0);

int numUsedPartitions = 1;
while (nodesToCover_.Count > 0) {
if (++numUsedPartitions > partitions_.Count) {
partitions_.Add(new HashSet<CommNode>());
}
var partition = partitions_[numUsedPartitions - 1];
BuildPartition(nodesToCover_.First(), partition, nodesToCover_);
}

MapNodesToPartitions();
}
}
}
1 change: 1 addition & 0 deletions Telecom/Telecom.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@
<Compile Include="fake_principia_logging.cs" />
<Compile Include="kerbalism.cs" />
<Compile Include="main_window.cs" />
<Compile Include="NetworkPartitioner.cs" />
<Compile Include="priority_queue.cs" />
<Compile Include="RuntimeMetrics.cs" />
<Compile Include="service.cs" />
Expand Down
8 changes: 4 additions & 4 deletions Telecom/connection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,12 @@ public void AttemptConnection(Routing routing, Network network, double t) {
circuit = routing.FindAndUseAvailableCircuit(
network.GetStation(trx_names[0]).Comm,
network.GetStation(trx_names[1]).Comm,
latency_limit, data_rate, this);
latency_limit, data_rate, network.partioner_, this);
} else {
circuit = routing.FindCircuitInIsolation(
network.GetStation(trx_names[0]).Comm,
network.GetStation(trx_names[1]).Comm,
latency_limit, data_rate);
latency_limit, data_rate, network.partioner_);
}
basic_service.ReportAvailability(circuit != null, t);
actual_latency = circuit?.round_trip_latency;
Expand Down Expand Up @@ -127,10 +127,10 @@ public void AttemptConnection(Routing routing, Network network, double t) {
Routing.Channel[] channels;
if (exclusive) {
routing.FindAndUseAvailableChannels(
tx, rx, latency_limit, data_rate, out channels, this);
tx, rx, latency_limit, data_rate, network.partioner_, out channels, this);
} else {
routing.FindChannelsInIsolation(
tx, rx, latency_limit, data_rate, out channels);
tx, rx, latency_limit, data_rate, network.partioner_, out channels);
}
for (int i = 0; i < channels.Length; ++i) {
Routing.Channel channel = channels[i];
Expand Down
18 changes: 14 additions & 4 deletions Telecom/connection_inspector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ protected override void RenderWindowContents(int window_id) {
new[]{rx.Comm},
connection_.latency_limit,
connection_.data_rate,
telecom_.network.partioner_,
out channels);
if (channels[0] != null) {
capacity_limited = true;
Expand All @@ -291,6 +292,7 @@ protected override void RenderWindowContents(int window_id) {
new[]{rx.Comm},
latency_limit: double.PositiveInfinity,
connection_.data_rate,
telecom_.network.partioner_,
out channels);
bool purely_latency_limited = channels[0] != null;
if (purely_latency_limited) {
Expand All @@ -304,6 +306,7 @@ protected override void RenderWindowContents(int window_id) {
new[]{rx.Comm},
connection_.latency_limit,
data_rate: 0,
telecom_.network.partioner_,
out channels);
bool purely_rate_limited = channels[0] != null;
if (purely_rate_limited) {
Expand All @@ -321,6 +324,7 @@ protected override void RenderWindowContents(int window_id) {
new[]{rx.Comm},
latency_limit: double.PositiveInfinity,
data_rate: 0,
telecom_.network.partioner_,
out channels);
if (channels[0] != null) {
string max_data_rate = RATools.PrettyPrintDataRate(
Expand Down Expand Up @@ -365,7 +369,8 @@ protected override void RenderWindowContents(int window_id) {
trx0.Comm,
trx1.Comm,
connection_.latency_limit,
connection_.data_rate);
connection_.data_rate,
telecom_.network.partioner_);
if (circuit != null) {
capacity_limited = true;
UnityEngine.GUILayout.Label(
Expand All @@ -377,12 +382,14 @@ protected override void RenderWindowContents(int window_id) {
new[] { trx1.Comm },
connection_.latency_limit,
connection_.data_rate,
telecom_.network.partioner_,
out Routing.Channel[] forward);
telecom_.network.routing_.FindChannelsInIsolation(
trx1.Comm,
new[] { trx0.Comm },
connection_.latency_limit,
connection_.data_rate,
telecom_.network.partioner_,
out Routing.Channel[] backward);
if (forward[0] != null && backward[0] != null) {
capacity_limited = true;
Expand All @@ -398,7 +405,8 @@ protected override void RenderWindowContents(int window_id) {
trx0.Comm,
trx1.Comm,
round_trip_latency_limit: double.PositiveInfinity,
connection_.data_rate);
connection_.data_rate,
telecom_.network.partioner_);
bool purely_latency_limited = circuit != null;
if (purely_latency_limited) {
UnityEngine.GUILayout.Label(
Expand All @@ -410,7 +418,8 @@ protected override void RenderWindowContents(int window_id) {
trx0.Comm,
trx1.Comm,
connection_.latency_limit,
one_way_data_rate: 0);
one_way_data_rate: 0,
telecom_.network.partioner_);
bool purely_rate_limited = circuit != null;
if (purely_rate_limited) {
string max_data_rate = RATools.PrettyPrintDataRate(
Expand All @@ -428,7 +437,8 @@ protected override void RenderWindowContents(int window_id) {
trx0.Comm,
trx1.Comm,
round_trip_latency_limit: double.PositiveInfinity,
one_way_data_rate: 0);
one_way_data_rate: 0,
telecom_.network.partioner_);
if (circuit != null) {
string max_data_rate = RATools.PrettyPrintDataRate(
Math.Min(
Expand Down
2 changes: 2 additions & 0 deletions Telecom/network.cs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ private void UpdateConnections() {
from station in tx_only_ select station.Comm,
from station in rx_only_ select station.Comm,
from station in stations_.Values select station.Comm);
partioner_.DiscoverPartitions(network.Nodes);
foreach (var connection in connections_.Values) {
if (contracted_connections.Contains(connection)) {
connection.AttemptConnection(routing_, this, Telecom.Instance.last_universal_time);
Expand Down Expand Up @@ -245,6 +246,7 @@ public IEnumerable<RACommNetHome> AllGround() {
public readonly HashSet<RACommNetHome> rx_only_ = new HashSet<RACommNetHome>();
public string[] names_ = { };
public Routing routing_ = new Routing();
public readonly NetworkPartitioner partioner_ = new NetworkPartitioner();

public Dictionary<Contracts.Contract, List<Connection>> connections_by_contract { get; } =
new Dictionary<Contracts.Contract, List<Connection>>();
Expand Down
32 changes: 24 additions & 8 deletions Telecom/routing.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,26 +151,30 @@ public Circuit FindCircuitInIsolation(
RACommNode source,
RACommNode destination,
double round_trip_latency_limit,
double one_way_data_rate) {
double one_way_data_rate,
NetworkPartitioner partitioner) {
return FindCircuit(source,
destination,
round_trip_latency_limit,
one_way_data_rate,
NetworkUsage.None);
NetworkUsage.None,
partitioner);
}

public Circuit FindAndUseAvailableCircuit(
RACommNode source,
RACommNode destination,
double round_trip_latency_limit,
double one_way_data_rate,
NetworkPartitioner partitioner,
Connection connection) {
Circuit circuit = FindCircuit(
source,
destination,
round_trip_latency_limit,
one_way_data_rate,
current_network_usage_);
current_network_usage_,
partitioner);
if (circuit != null) {
foreach (OrientedLink link in circuit.forward.links) {
current_network_usage_.UseLinks(
Expand All @@ -191,12 +195,14 @@ public PointToMultipointAvailability FindChannelsInIsolation(
IList<RACommNode> destinations,
double latency_limit,
double data_rate,
NetworkPartitioner partitioner,
out Channel[] channels) {
return FindChannels(source,
destinations,
latency_limit,
data_rate,
NetworkUsage.None,
partitioner,
out channels);
}

Expand All @@ -205,6 +211,7 @@ public PointToMultipointAvailability FindAndUseAvailableChannels(
IList<RACommNode> destinations,
double latency_limit,
double data_rate,
NetworkPartitioner partitioner,
out Channel[] channels,
Connection connection) {
PointToMultipointAvailability availability = FindChannels(
Expand All @@ -213,6 +220,7 @@ public PointToMultipointAvailability FindAndUseAvailableChannels(
latency_limit,
data_rate,
current_network_usage_,
partitioner,
out channels);
if (availability != Unavailable) {
var links_by_tx_antenna =
Expand All @@ -230,12 +238,14 @@ private Circuit FindCircuit(RACommNode source,
RACommNode destination,
double round_trip_latency_limit,
double one_way_data_rate,
NetworkUsage usage) {
NetworkUsage usage,
NetworkPartitioner partitioner) {
if (FindChannels(source,
new[]{destination},
round_trip_latency_limit,
one_way_data_rate,
usage,
partitioner,
out Channel[] forward) == Unavailable) {
return null;
}
Expand All @@ -249,6 +259,7 @@ private Circuit FindCircuit(RACommNode source,
round_trip_latency_limit - forward[0].latency,
one_way_data_rate,
usage_with_forward_channel,
partitioner,
out Channel[] backward) == Unavailable) {
return null;
}
Expand All @@ -261,6 +272,7 @@ private PointToMultipointAvailability FindChannels(
double latency_limit,
double data_rate,
NetworkUsage usage,
NetworkPartitioner partitioner,
out Channel[] channels) {
const double c = 299792458;
// TODO(egg): consider using the stock intrusive data structure.
Expand All @@ -269,23 +281,27 @@ private PointToMultipointAvailability FindChannels(
var boundary = new PriorityQueue<RACommNode, double>();
var interior = new HashSet<RACommNode>();

channels = new Channel[destinations.Count];
int num_channels_to_find = destinations.Where(x => !partitioner.disconnected_partition_.Contains(x) && partitioner.node_to_partition_map_[source] == partitioner.node_to_partition_map_[x]).Count();
if (partitioner.disconnected_partition_.Contains(source) || num_channels_to_find == 0) {
return PointToMultipointAvailability.Unavailable;
}
// Dijkstra’s algorithm without DecreaseKey.
distances[source] = 0;
boundary.Enqueue(source, 0);
previous[source] = null;
int rx_found = 0;
channels = new Channel[destinations.Count];
bool is_point_to_multipoint = destinations.Count > 1;
while (boundary.TryDequeue(out RACommNode tx, out double tx_distance)) {
if (tx_distance != distances[tx]) {
// We have already considered `tx` through a shorter path.
continue;
}
int i = destinations.IndexOf(tx);
if (tx_distance > latency_limit * c) {
// We have run out of latency, no need to keep searching.
return rx_found == 0 ? Unavailable : Partial;
} else if (destinations.Contains(tx)) {
int i = destinations.IndexOf(tx);
} else if (i > -1) {
channels[i] = new Channel();
for (OrientedLink link = previous[tx];
link != null;
Expand All @@ -295,7 +311,7 @@ private PointToMultipointAvailability FindChannels(
channels[i].links.Reverse();
channels[i].latency = tx_distance / c;
++rx_found;
if (rx_found == channels.Length) {
if (rx_found == num_channels_to_find) {
return PointToMultipointAvailability.Available;
}
}
Expand Down
Loading