finish air routes

main
Ziyang Hu 2 years ago
parent 5b12d18a2d
commit d0e6fcb9f1

@ -26,8 +26,8 @@ rule_apply = {ident ~ "[" ~ apply_args ~ "]"}
disjunction = {(atom ~ "or" )* ~ atom}
atom = _{grouped | triple | negation | rule_apply | unify_multi | unify | expr }
unify = {var ~ "is" ~ expr}
unify_multi = {var ~ "is_in" ~ expr}
unify = {var ~ ("is" | "<-") ~ expr}
unify_multi = {var ~ ("is_in" | ("<-" ~ "..")) ~ expr}
negation = {"not" ~ atom}
triple = { "[" ~ (expr | triple_pull) ~ compound_ident ~ (expr | triple_pull) ~ "]"}
triple_pull = {compound_ident ~ "[" ~ expr ~ "]"}

@ -839,14 +839,6 @@ fn op_nth(args: &[DataValue]) -> Result<DataValue> {
})
}
define_op!(OP_NEGATE, 1, false, true);
fn op_negate(args: &[DataValue]) -> Result<DataValue> {
match &args[0] {
DataValue::Bool(b) => Ok(DataValue::Bool(!*b)),
v => bail!("cannot negate {:?}", v)
}
}
pub(crate) fn get_op(name: &str) -> Option<&'static Op> {
Some(match name {
"list" => &OP_LIST,
@ -916,7 +908,6 @@ pub(crate) fn get_op(name: &str) -> Option<&'static Op> {
"nth" => &OP_NTH,
"first" => &OP_FIRST,
"last" => &OP_LAST,
"negate" => &OP_NEGATE,
_ => return None,
})
}

@ -449,8 +449,8 @@ mod tests {
friend_of_friend[?a, ?b] := friend_of_friend[?a, ?c], [?c person.friend ?b];
?[?a, ?b] := [?a person.friend ?b], [?a person.age ?age], ?age > 18 + 9;
:limit = 20;
:offset = 30;
:limit 20;
:offset 30;
"#;
let parsed = parse_query_to_json(src).unwrap();
// println!("{}", to_string_pretty(&parsed).unwrap());

@ -68,7 +68,7 @@ fn air_routes() -> Result<()> {
let simple_query_time = Instant::now();
let res = db.run_script(r#"
?[?c, ?code, ?desc] := [?c country.code 'CU'] or ?c is 10000239, [?c country.code ?code], [?c country.desc ?desc];
?[?c, ?code, ?desc] := [?c country.code 'CU'] or ?c <- 10000239, [?c country.code ?code], [?c country.desc ?desc];
"#)?;
dbg!(simple_query_time.elapsed());
assert_eq!(
@ -159,7 +159,7 @@ fn air_routes() -> Result<()> {
let most_out_routes_time_inv = Instant::now();
let res = db.run_script(
r#"
route_count[count(?r), ?a, ?x] := [?r route.src ?a], ?x is 1;
route_count[count(?r), ?a, ?x] := [?r route.src ?a], ?x <- 1;
?[?code, ?n] := route_count[?n, ?a, ?_], ?n > 180, [?a airport.iata ?code];
:sort -?n;
"#,
@ -272,7 +272,7 @@ fn air_routes() -> Result<()> {
airports_by_country[?c, count(?a)] := [?a airport.country ?c];
country_count[?c, max(?count)] := airports_by_country[?c, ?count];
?[?code, ?count] := [?c country.code ?code], country_count[?c, ?count];
?[?code, ?count] := [?c country.code ?code], not country_count[?c, ?_], ?count is 0;
?[?code, ?count] := [?c country.code ?code], not country_count[?c, ?_], ?count <- 0;
:order ?count;
",
@ -316,7 +316,7 @@ fn air_routes() -> Result<()> {
r#"
airports_by_continent[?c, count(?a)] := [?a airport.iata ?_], [?c geo.contains ?a];
?[?cont, max(?count)] := airports_by_continent[?c, ?count], [?c continent.code ?cont];
?[?cont, max(?count)] := [?_ continent.code ?cont], ?count is 0;
?[?cont, max(?count)] := [?_ continent.code ?cont], ?count <- 0;
"#,
)?;
dbg!(n_airports_by_continent_time.elapsed());
@ -366,7 +366,7 @@ fn air_routes() -> Result<()> {
[?r1 route.src ?aus],
[?r1 route.dst ?a],
[?r route.src ?a];
?[max(?total), collect(?coll)] := two_hops[?total], out_by_runways[?n, ?ct], ?coll is [?n, ?ct];
?[max(?total), collect(?coll)] := two_hops[?total], out_by_runways[?n, ?ct], ?coll <- [?n, ?ct];
"#)?;
dbg!(out_from_aus_time.elapsed());
assert_eq!(
@ -378,7 +378,7 @@ fn air_routes() -> Result<()> {
let const_return_time = Instant::now();
let res = db.run_script(
r#"
?[?name, count(?a)] := [?a airport.region 'US-OK'], ?name is 'OK';
?[?name, count(?a)] := [?a airport.region 'US-OK'], ?name <- 'OK';
"#,
)?;
dbg!(const_return_time.elapsed());
@ -406,7 +406,7 @@ fn air_routes() -> Result<()> {
let multi_unification_time = Instant::now();
let res = db.run_script(r#"
target_airports[collect(?a, 5)] := [?a airport.iata ?_];
?[?code, count(?r)] := target_airports[?targets], ?a is_in ?targets, [?a airport.iata ?code], [?r route.src ?a];
?[?code, count(?r)] := target_airports[?targets], ?a <- ..?targets, [?a airport.iata ?code], [?r route.src ?a];
"#)?;
dbg!(multi_unification_time.elapsed());
assert_eq!(
@ -426,7 +426,7 @@ fn air_routes() -> Result<()> {
[?r route.src ?a],
[?r route.dst ?a2],
[?a2 airport.country ?us];
?[?n] := routes[?rs], ?n is length(?rs);
?[?n] := routes[?rs], ?n <- length(?rs);
"#,
)?;
dbg!(num_routes_from_eu_to_us_time.elapsed());
@ -513,7 +513,7 @@ fn air_routes() -> Result<()> {
[?r route.src ?a],
[?r route.dst ?a2],
[?a2 airport.city ?city_name],
?n is length(?city_name);
?n <- length(?city_name);
"#,
)?;
dbg!(len_of_names_count_time.elapsed());
@ -524,7 +524,7 @@ fn air_routes() -> Result<()> {
r#"
route_count[count(?r), ?a] := [?r route.src ?a];
rc[max(?n), ?a] := route_count[?n, ?a];
rc[max(?n), ?a] := [?a airport.iata ?_], ?n is 0;
rc[max(?n), ?a] := [?a airport.iata ?_], ?n <- 0;
?[?n, count(?a)] := rc[?n, ?a];
:order ?n;
:limit 10;
@ -543,7 +543,7 @@ fn air_routes() -> Result<()> {
let res = db.run_script(
r#"
route_count[count(?r), ?a] := [?r route.src ?a];
rc[max(?n), ?a] := route_count[?n, ?a] or ([?a airport.iata ?_], ?n is 0);
rc[max(?n), ?a] := route_count[?n, ?a] or ([?a airport.iata ?_], ?n <- 0);
?[mean(?n)] := rc[?n, ?_];
"#,
)?;
@ -616,7 +616,7 @@ fn air_routes() -> Result<()> {
eng_aps[?a] := [?a airport.region 'GB-ENG'];
?[?pair] := eng_aps[?a1], [?r route.src ?a1], [?r route.dst ?a2], eng_aps[?a2],
[?a1 airport.iata ?src], [?a2 airport.iata ?dst],
?pair is sort([?src, ?dst]);
?pair <- sort([?src, ?dst]);
"#,
)?;
dbg!(routes_within_england_time_no_dup.elapsed());
@ -638,10 +638,10 @@ fn air_routes() -> Result<()> {
r#"
reachable[?a, choice(?p)] := [?s airport.iata 'AUS'],
[?r route.src ?s], [?r route.dst ?a],
[?a airport.iata ?code], ?code != 'YYZ', ?p is ['AUS', ?code];
[?a airport.iata ?code], ?code != 'YYZ', ?p <- ['AUS', ?code];
reachable[?a, choice(?p)] := reachable[?b, ?prev],
[?r route.src ?b], [?r route.dst ?a], [?a airport.iata ?code],
?code != 'YYZ', ?p is append(?prev, ?code);
?code != 'YYZ', ?p <- append(?prev, ?code);
?[?p] := reachable[?a, ?p], [?a airport.iata 'YPO'];
:limit 1;
@ -663,7 +663,7 @@ fn air_routes() -> Result<()> {
[?r route.src ?ind_a], [?r route.dst ?na_a],
[?na_a airport.country ?dst_country],
[?dst_country country.code ?dst_country_name],
?dst_country_name is_in ['US', 'CA'],
?dst_country_name <- ..['US', 'CA'],
[?ind_a airport.iata ?ind_c], [?na_a airport.iata ?na_c];
"#,
@ -705,7 +705,7 @@ fn air_routes() -> Result<()> {
r#"
?[?code] := [?a airport.iata 'CLT'], [?r route.src ?a], [?r route.dst ?a2],
[?cont geo.contains ?a2], [?cont continent.code ?c_name],
?c_name is_in ['EU', 'SA'],
?c_name <- ..['EU', 'SA'],
[?a2 airport.iata ?code];
"#,
)?;
@ -721,7 +721,7 @@ fn air_routes() -> Result<()> {
let london_to_us_time = Instant::now();
let res = db.run_script(
r#"
?[?l_code, ?us_code] := ?l_code is_in ['LHR', 'LCY', 'LGW', 'LTN', 'STN'],
?[?l_code, ?us_code] := ?l_code <- ..['LHR', 'LCY', 'LGW', 'LTN', 'STN'],
[?a airport.iata ?l_code],
[?r route.src ?a], [?r route.dst ?a2],
[?us country.code 'US'],
@ -794,7 +794,7 @@ fn air_routes() -> Result<()> {
let three_cities_time = Instant::now();
let res = db.run_script(
r#"
three[?a] := ?city is_in ['London', 'Munich', 'Paris'], [?a airport.city ?city];
three[?a] := ?city <- ..['London', 'Munich', 'Paris'], [?a airport.city ?city];
?[?src, ?dst] := three[?s], [?r route.src ?s], [?r route.dst ?d], three[?d],
[?s airport.iata ?src], [?d airport.iata ?dst];
"#,
@ -894,7 +894,7 @@ fn air_routes() -> Result<()> {
let total_distance_from_three_cities_time = Instant::now();
let res = db.run_script(
r#"
three[?a] := ?city is_in ['London', 'Munich', 'Paris'], [?a airport.city ?city];
three[?a] := ?city <- ..['London', 'Munich', 'Paris'], [?a airport.city ?city];
?[sum(?dist)] := three[?a], [?r route.src ?a], [?r route.distance ?dist];
"#,
)?;
@ -904,7 +904,7 @@ fn air_routes() -> Result<()> {
let total_distance_within_three_cities_time = Instant::now();
let res = db.run_script(
r#"
three[?a] := ?city is_in ['London', 'Munich', 'Paris'], [?a airport.city ?city];
three[?a] := ?city <- ..['London', 'Munich', 'Paris'], [?a airport.city ?city];
?[sum(?dist)] := three[?a], [?r route.src ?a], [?r route.dst ?a2], three[?a2],
[?r route.distance ?dist];
"#,
@ -939,7 +939,7 @@ fn air_routes() -> Result<()> {
r#"
?[?code, ?dist] := [?s airport.iata 'AUS'], [?r1 route.src ?s], [?r1 route.dst ?a],
[?r2 route.src ?a], [?r2 route.dst ?d], [?d airport.iata 'LHR'],
[?r1 route.distance ?dis1], [?r2 route.distance ?dis2], ?dist is ?dis1 + ?dis2,
[?r1 route.distance ?dis1], [?r2 route.distance ?dis2], ?dist <- ?dis1 + ?dis2,
[?a airport.iata ?code];
:order ?dist;
:limit 10;
@ -979,7 +979,7 @@ fn air_routes() -> Result<()> {
let north_of_77_time = Instant::now();
let res = db.run_script(r#"
?[?city, ?latitude] := [?a airport.lat ?lat], ?lat > 77, [?a airport.city ?city], ?latitude is round(?lat);
?[?city, ?latitude] := [?a airport.lat ?lat], ?lat > 77, [?a airport.city ?city], ?latitude <- round(?lat);
"#)?;
dbg!(north_of_77_time.elapsed());
assert_eq!(
@ -1019,7 +1019,7 @@ fn air_routes() -> Result<()> {
[?us country.code 'US'],
[?r route.src ?dfw],
[?r route.dst ?a], [?a airport.country ?us],
?region is_in ['US-CA', 'US-TX', 'US-FL', 'US-CO', 'US-IL'],
?region <- ..['US-CA', 'US-TX', 'US-FL', 'US-CO', 'US-IL'],
[?a airport.region ?region],
[?a airport.iata ?code];
"#,
@ -1039,7 +1039,7 @@ fn air_routes() -> Result<()> {
r#"
?[?deg_diff] := [?a airport.iata 'SFO'], [?a airport.lat ?a_lat], [?a airport.lon ?a_lon],
[?b airport.iata 'NRT'], [?b airport.lat ?b_lat], [?b airport.lon ?b_lon],
?deg_diff is round(haversine_deg(?a_lat, ?a_lon, ?b_lat, ?b_lon));
?deg_diff <- round(haversine_deg(?a_lat, ?a_lon, ?b_lat, ?b_lon));
"#,
)?;
dbg!(great_circle_distance.elapsed());
@ -1053,11 +1053,11 @@ fn air_routes() -> Result<()> {
routes[?a2, shortest(?path)] := [?a airport.iata 'AUS'], [?r route.src ?a],
[?r route.dst ?a2], us_uk_airports[?a2],
[?a2 airport.iata ?dst],
?path is ['AUS', ?dst];
?path <- ['AUS', ?dst];
routes[?a2, shortest(?path)] := routes[?a, ?prev], [?r route.src ?a],
[?r route.dst ?a2], us_uk_airports[?a2],
[?a2 airport.iata ?dst],
?path is append(?prev, ?dst);
?path <- append(?prev, ?dst);
?[?path] := [?edi airport.iata 'EDI'], routes[?edi, ?path];
"#,
)?;
@ -1070,12 +1070,12 @@ fn air_routes() -> Result<()> {
routes[?a2, shortest(?path)] := [?a airport.iata 'LHR'], [?r route.src ?a],
[?r route.dst ?a2],
[?a2 airport.iata ?dst],
?path is ['LHR', ?dst];
?path <- ['LHR', ?dst];
routes[?a2, shortest(?path)] := routes[?a, ?prev], [?r route.src ?a],
[?r route.dst ?a2],
[?a2 airport.iata ?dst],
?path is append(?prev, ?dst);
?[?len, ?path] := routes[?_, ?path], ?len is length(?path);
?path <- append(?prev, ?dst);
?[?len, ?path] := routes[?_, ?path], ?len <- length(?path);
:order -?len;
:limit 10;
@ -1104,28 +1104,34 @@ fn air_routes() -> Result<()> {
[?r route.dst ?a2],
[?r route.distance ?dist],
[?a2 airport.iata ?dst],
?path is ['LHR', ?dst],
?cost_pair is [?path, ?dist];
?path <- ['LHR', ?dst],
?cost_pair <- [?path, ?dist];
routes[?a2, min_cost(?cost_pair)] := routes[?a, ?prev], [?r route.src ?a],
[?r route.dst ?a2],
[?r route.distance ?dist],
[?a2 airport.iata ?dst],
?path is append(first(?prev), ?dst),
?cost_pair is [?path, last(?prev) + ?dist];
?[?cost, ?path] := routes[?dst, ?cost_pair], ?cost is last(?cost_pair), ?path is first(?cost_pair);
?path <- append(first(?prev), ?dst),
?cost_pair <- [?path, last(?prev) + ?dist];
?[?cost, ?path] := routes[?dst, ?cost_pair], ?cost <- last(?cost_pair), ?path <- first(?cost_pair);
:order -?cost;
:limit 10;
"#,
)?;
dbg!(furtherest_from_lhr.elapsed());
assert_eq!(res, serde_json::Value::from_str(r#"
assert_eq!(
res,
serde_json::Value::from_str(
r#"
[[12922,["LHR","JNB","HLE","ASI","BZZ"]],[12114,["LHR","PVG","BNE","CHC","IVC"]],
[12030,["LHR","PVG","BNE","CHC","DUD"]],[12015,["LHR","NRT","AKL","WLG","TIU"]],
[11921,["LHR","PVG","BNE","CHC","HKK"]],[11910,["LHR","NRT","AKL","WLG","WSZ"]],
[11826,["LHR","PVG","BNE","CHC"]],[11766,["LHR","PVG","BNE","ZQN"]],
[11758,["LHR","NRT","AKL","BHE"]],[11751,["LHR","NRT","AKL","NSN"]]]
"#).unwrap());
"#
)
.unwrap()
);
Ok(())
}

Loading…
Cancel
Save