success_result_count: u64,
failure_loss_sum: f64,
failure_result_count: u64,
+ no_data_success_loss_sum: f64,
+ no_data_success_result_count: u64,
+ no_data_failure_loss_sum: f64,
+ no_data_failure_result_count: u64,
}
/// Creates a new [`State`] before any probe results are processed.
success_result_count: 0,
failure_loss_sum: 0.0,
failure_result_count: 0,
+ no_data_success_loss_sum: 0.0,
+ no_data_success_result_count: 0,
+ no_data_failure_loss_sum: 0.0,
+ no_data_failure_result_count: 0,
}
}
for hop in result.channels_with_sufficient_liquidity.iter() {
// You can get additional information about the channel from the network_graph:
let _chan = network_graph.channels().get(&hop.short_channel_id).unwrap();
+ let mut no_data = false;
let mut model_probability =
state.scorer.historical_estimated_payment_success_probability(hop.short_channel_id, &hop.dst_node_id, hop.amount_msat, &Default::default())
- .unwrap_or_else(||
+ .unwrap_or_else(|| {
+ no_data = true;
// If LDK doesn't have sufficient historical state it will fall back to (roughly) the live model.
state.scorer
.live_estimated_payment_success_probability(hop.short_channel_id, &hop.dst_node_id, hop.amount_msat, &Default::default())
.expect("We should have some estimated probability, even without history data")
- );
+ });
if model_probability < 0.01 { model_probability = 0.01; }
state.success_loss_sum -= model_probability.log2();
state.success_result_count += 1;
+ if no_data {
+ state.no_data_success_loss_sum -= model_probability.log2();
+ state.no_data_success_result_count += 1;
+ }
}
if let Some(hop) = &result.channel_that_rejected_payment {
// You can get additional information about the channel from the network_graph:
let _chan = network_graph.channels().get(&hop.short_channel_id).unwrap();
+ let mut no_data = false;
let mut model_probability =
state.scorer.historical_estimated_payment_success_probability(hop.short_channel_id, &hop.dst_node_id, hop.amount_msat, &Default::default())
- .unwrap_or_else(||
+ .unwrap_or_else(|| {
+ no_data = true;
// If LDK doesn't have sufficient historical state it will fall back to (roughly) the live model.
state.scorer
.live_estimated_payment_success_probability(hop.short_channel_id, &hop.dst_node_id, hop.amount_msat, &Default::default())
.expect("We should have some estimated probability, even without history data")
- );
+ });
if model_probability > 0.99 { model_probability = 0.99; }
state.failure_loss_sum -= (1.0 - model_probability).log2();
state.failure_result_count += 1;
+ if no_data {
+ state.no_data_failure_loss_sum -= (1.0 - model_probability).log2();
+ state.no_data_failure_result_count += 1;
+ }
}
// Update the model with the information we learned
/// This is run after all probe results have been processed, and should be used for printing
/// results or any required teardown.
pub fn results_complete(state: State) {
- // We break out log-loss for failure and success hops as there are substantially more
- // succeeding hops than there are failing hops.
- println!("Avg success log-loss {}", state.success_loss_sum / (state.success_result_count as f64));
- println!("Avg failure log-loss {}", state.failure_loss_sum / (state.failure_result_count as f64));
+ // We break out log-loss for failure and success hops and print averages between the two
+ // (rather than in aggregate) as there are substantially more succeeding hops than there are
+ // failing hops.
+ let no_data_suc = state.no_data_success_loss_sum / (state.no_data_success_result_count as f64);
+ let no_data_fail = state.no_data_failure_loss_sum / (state.no_data_failure_result_count as f64);
+ println!("Avg no-data success log-loss {}", no_data_suc);
+ println!("Avg no-data failure log-loss {}", no_data_fail);
+ println!("Avg no-data success+failure log-loss {}", (no_data_suc + no_data_fail) / 2.0);
+ println!();
+ let avg_hist_suc = (state.success_loss_sum - state.no_data_success_loss_sum) / ((state.success_result_count - state.no_data_success_result_count) as f64);
+ let avg_hist_fail = (state.failure_loss_sum - state.no_data_failure_loss_sum) / ((state.failure_result_count - state.no_data_failure_result_count) as f64);
+ println!("Avg historical data success log-loss {}", avg_hist_suc);
+ println!("Avg historical data failure log-loss {}", avg_hist_fail);
+ println!("Avg hist data suc+fail average log-loss {}", (avg_hist_suc + avg_hist_fail) / 2.0);
+ println!();
+ let avg_suc = state.success_loss_sum / (state.success_result_count as f64);
+ let avg_fail = state.failure_loss_sum / (state.failure_result_count as f64);
+ println!("Avg success log-loss {}", avg_suc);
+ println!("Avg failure log-loss {}", avg_fail);
+ println!("Avg success+failure average log-loss {}", (avg_suc + avg_fail) / 2.0);
+ println!();
let loss_sum = state.success_loss_sum + state.failure_loss_sum;
let result_count = state.success_result_count + state.failure_result_count;
println!("Avg log-loss {}", loss_sum / (result_count as f64));