Option to limit amount of transfers.
This commit is contained in:
parent
e36f1558ef
commit
404ceb39b9
4 changed files with 46 additions and 7 deletions
|
@ -41,7 +41,7 @@ fn main() {
|
|||
return;
|
||||
}
|
||||
|
||||
if args.len() < 4 {
|
||||
if args.len() < 5 {
|
||||
println!("Usage: cli [--csv] [--safes] <from> <to> <edges.dat> [--dot <dotfile>]");
|
||||
println!(
|
||||
"Usage: cli [--csv] [--safes] <from> <to> <edges.dat> <max_hops> [--dot <dotfile>]"
|
||||
|
@ -49,12 +49,16 @@ fn main() {
|
|||
println!(
|
||||
"Usage: cli [--csv] [--safes] <from> <to> <edges.dat> <max_hops> <max_flow> [--dot <dotfile>]"
|
||||
);
|
||||
println!(
|
||||
"Usage: cli [--csv] [--safes] <from> <to> <edges.dat> <max_hops> <max_flow> <max_transfers> [--dot <dotfile>]"
|
||||
);
|
||||
println!("Option --csv reads edges.dat in csv format instead of binary.");
|
||||
println!("Option --safes reads a safes.dat file instead of an edges.dat file.");
|
||||
return;
|
||||
}
|
||||
let mut max_hops = None;
|
||||
let mut max_flow = U256::MAX;
|
||||
let mut max_transfers: Option<u64> = None;
|
||||
let (from_str, to_str, edges_file) = (&args[1], &args[2], &args[3]);
|
||||
if args.len() >= 5 {
|
||||
max_hops = Some(
|
||||
|
@ -64,6 +68,9 @@ fn main() {
|
|||
);
|
||||
if args.len() >= 6 {
|
||||
max_flow = args[5].as_str().into();
|
||||
if args.len() >= 7 {
|
||||
max_transfers = Some(args[6].as_str().parse::<i64>().unwrap() as u64);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,6 +90,7 @@ fn main() {
|
|||
&edges,
|
||||
max_flow,
|
||||
max_hops,
|
||||
max_transfers,
|
||||
);
|
||||
println!("Found flow: {}", flow.to_decimal());
|
||||
//println!("{:?}", transfers);
|
||||
|
|
|
@ -13,6 +13,7 @@ pub fn compute_flow(
|
|||
edges: &EdgeDB,
|
||||
requested_flow: U256,
|
||||
max_distance: Option<u64>,
|
||||
max_transfers: Option<u64>,
|
||||
) -> (U256, Vec<Edge>) {
|
||||
let mut adjacencies = Adjacencies::new(edges);
|
||||
let mut used_edges: HashMap<Node, HashMap<Node, U256>> = HashMap::new();
|
||||
|
@ -59,6 +60,15 @@ pub fn compute_flow(
|
|||
flow = requested_flow + still_to_prune;
|
||||
}
|
||||
|
||||
if let Some(max_transfers) = max_transfers {
|
||||
let lost = reduce_transfers(max_transfers * 3, &mut used_edges);
|
||||
println!(
|
||||
"Capacity lost by transfer count reduction: {}",
|
||||
lost.to_decimal_fraction()
|
||||
);
|
||||
flow -= lost;
|
||||
}
|
||||
|
||||
let transfers = if flow == U256::from(0) {
|
||||
vec![]
|
||||
} else {
|
||||
|
@ -219,6 +229,25 @@ fn prune_flow(
|
|||
flow_to_prune
|
||||
}
|
||||
|
||||
fn reduce_transfers(
|
||||
max_transfers: u64,
|
||||
used_edges: &mut HashMap<Node, HashMap<Node, U256>>,
|
||||
) -> U256 {
|
||||
let mut reduced_flow = U256::from(0);
|
||||
while used_edges.len() > max_transfers as usize {
|
||||
let all_edges = used_edges
|
||||
.iter()
|
||||
.flat_map(|(f, e)| e.iter().map(|(t, c)| ((f.clone(), t.clone()), c)));
|
||||
if all_edges.clone().count() <= max_transfers as usize {
|
||||
return reduced_flow;
|
||||
}
|
||||
let ((f, t), c) = all_edges.min_by_key(|(_, c)| *c).unwrap();
|
||||
reduced_flow += *c;
|
||||
prune_edge(used_edges, (&f, &t), *c);
|
||||
}
|
||||
reduced_flow
|
||||
}
|
||||
|
||||
/// Returns a map from the negative shortest path length to the edge.
|
||||
/// The shortest path length is negative so that it is sorted by
|
||||
/// longest paths first - those are the ones we want to eliminate first.
|
||||
|
@ -531,7 +560,7 @@ mod test {
|
|||
token: t,
|
||||
capacity: U256::from(10),
|
||||
}]);
|
||||
let flow = compute_flow(&a, &b, &edges, U256::MAX, None);
|
||||
let flow = compute_flow(&a, &b, &edges, U256::MAX, None, None);
|
||||
assert_eq!(
|
||||
flow,
|
||||
(
|
||||
|
@ -563,7 +592,7 @@ mod test {
|
|||
capacity: U256::from(8),
|
||||
},
|
||||
]);
|
||||
let flow = compute_flow(&a, &c, &edges, U256::MAX, None);
|
||||
let flow = compute_flow(&a, &c, &edges, U256::MAX, None, None);
|
||||
assert_eq!(
|
||||
flow,
|
||||
(
|
||||
|
@ -615,7 +644,7 @@ mod test {
|
|||
capacity: U256::from(8),
|
||||
},
|
||||
]);
|
||||
let mut flow = compute_flow(&a, &d, &edges, U256::MAX, None);
|
||||
let mut flow = compute_flow(&a, &d, &edges, U256::MAX, None, None);
|
||||
flow.1.sort();
|
||||
assert_eq!(
|
||||
flow,
|
||||
|
@ -649,7 +678,7 @@ mod test {
|
|||
]
|
||||
)
|
||||
);
|
||||
let mut pruned_flow = compute_flow(&a, &d, &edges, U256::from(6), None);
|
||||
let mut pruned_flow = compute_flow(&a, &d, &edges, U256::from(6), None, None);
|
||||
pruned_flow.1.sort();
|
||||
assert_eq!(
|
||||
pruned_flow,
|
||||
|
@ -707,7 +736,7 @@ mod test {
|
|||
capacity: U256::from(8),
|
||||
},
|
||||
]);
|
||||
let mut flow = compute_flow(&a, &d, &edges, U256::MAX, None);
|
||||
let mut flow = compute_flow(&a, &d, &edges, U256::MAX, None, None);
|
||||
flow.1.sort();
|
||||
println!("{:?}", &flow.1);
|
||||
assert_eq!(flow.0, U256::from(9));
|
||||
|
|
|
@ -143,6 +143,7 @@ fn compute_transfer(
|
|||
} else {
|
||||
vec![None]
|
||||
};
|
||||
let max_transfers = request.params["max_transfers"].as_u64();
|
||||
for max_distance in max_distances {
|
||||
let (flow, transfers) = graph::compute_flow(
|
||||
&Address::from(request.params["from"].to_string().as_str()),
|
||||
|
@ -154,6 +155,7 @@ fn compute_transfer(
|
|||
U256::MAX
|
||||
},
|
||||
max_distance,
|
||||
max_transfers,
|
||||
);
|
||||
println!("Computed flow with max distance {max_distance:?}: {flow}");
|
||||
socket.write_all(
|
||||
|
|
|
@ -61,7 +61,7 @@ fn test_flow(
|
|||
requested_flow: U256,
|
||||
max_distance: Option<u64>,
|
||||
) {
|
||||
let transfers = compute_flow(source, sink, edges, requested_flow, max_distance);
|
||||
let transfers = compute_flow(source, sink, edges, requested_flow, max_distance, None);
|
||||
println!("{transfers:?}");
|
||||
|
||||
let token_owners = transfers
|
||||
|
|
Loading…
Reference in a new issue