Skip to content

docs: network-hhmodel example: Separate contact from disease progression#847

Open
swo wants to merge 8 commits intomainfrom
swo_doc_hh_example
Open

docs: network-hhmodel example: Separate contact from disease progression#847
swo wants to merge 8 commits intomainfrom
swo_doc_hh_example

Conversation

@swo
Copy link
Copy Markdown
Contributor

@swo swo commented Apr 15, 2026

  • seir.rs looks for the infected people, then asks network.rs who they contact via get_contacts(). This is a nicer separation of concerns.
  • Make the period of the periodic plan explicit, so that get_contacts() needs a duration argument, that says what contacts will happen over what time period.
  • It's still clunky/non-DRY that there's no loop over edge types.

I'm having some trouble with getting the cargo +nightly fmt check to stabilize

@swo swo force-pushed the swo_doc_hh_example branch from 652087b to 64a6698 Compare April 16, 2026 18:14
github-actions Bot added a commit that referenced this pull request Apr 16, 2026
github-actions Bot added a commit that referenced this pull request Apr 16, 2026
github-actions Bot added a commit that referenced this pull request Apr 16, 2026
@github-actions

This comment was marked as off-topic.

@swo swo marked this pull request as ready for review April 16, 2026 19:19
github-actions Bot added a commit that referenced this pull request Apr 16, 2026
@github-actions

This comment was marked as off-topic.

@CDCgov CDCgov deleted a comment from github-actions Bot Apr 20, 2026
@CDCgov CDCgov deleted a comment from github-actions Bot Apr 20, 2026
@RobertJacobsonCDC
Copy link
Copy Markdown
Collaborator

Awesome! I think we've all felt the need for someone with modeling expertise to take a close look at our examples for quite some time now, so it's great that you're doing this. If you want to look over any other of the examples—or even add new ones that you think are conspicuously missing—definitely feel free to! But obviously don't feel obligated.

I'll look into the failing lints and get back to you. Sometimes they feel like a moving target...

@RobertJacobsonCDC
Copy link
Copy Markdown
Collaborator

I think it's not failing because of the lints. I think it's failing because the example never terminates: Cancelled after 365m.

github-actions Bot added a commit that referenced this pull request Apr 20, 2026
@github-actions
Copy link
Copy Markdown

Benchmark Results

Hyperfine

Command Mean [ms] Min [ms] Max [ms] Relative
large_sir::baseline 2.9 ± 0.1 2.8 3.1 1.00
large_sir::entities 11.9 ± 0.2 11.5 12.5 4.13 ± 0.10

Criterion

Regressions (slower)
Group Bench Param Change CI Lower CI Upper
indexing query_people_count_indexed_multi-property_entities 29.641% 29.435% 29.808%
indexing query_people_single_indexed_property_entities 18.436% 15.261% 21.345%
counts concrete_plus_derived_unindexed_entities 14.357% 13.765% 14.947%
large_dataset bench_match_entity 11.641% 11.337% 12.066%
large_dataset bench_query_population_derived_property_entities 11.191% 9.808% 12.447%
sampling count_and_sampling_single_unindexed_concrete_plus_derived_entiti 8.094% 7.948% 8.212%
large_dataset bench_query_population_multi_unindexed_entities 6.421% 4.541% 8.391%
sample_entity sample_entity_whole_population 100000 4.061% 3.704% 4.361%
indexing query_people_indexed_multi-property_entities 3.430% 3.091% 3.794%
sampling sampling_single_l_reservoir_entities 2.730% 2.356% 3.050%
sampling count_and_sampling_single_known_length_entities 1.956% 1.279% 2.626%
counts multi_property_unindexed_entities 1.493% 1.073% 1.914%
Improvements (faster)
Group Bench Param Change CI Lower CI Upper
sample_entity sample_entity_single_property_unindexed 1000 -20.698% -21.835% -19.262%
large_dataset bench_filter_unindexed_entity -16.667% -18.878% -14.351%
indexing query_people_count_single_indexed_property_entities -12.648% -12.976% -12.218%
indexing with_query_results_single_indexed_property_entities -9.443% -10.612% -8.151%
sample_entity sample_entity_multi_property_indexed 1000 -7.862% -8.471% -7.233%
sample_entity sample_entity_multi_property_indexed 100000 -7.158% -7.520% -6.698%
sample_entity sample_entity_multi_property_indexed 10000 -5.657% -6.740% -4.117%
examples example-basic-infection -5.379% -5.816% -5.010%
sample_entity sample_entity_single_property_indexed 10000 -5.140% -7.038% -3.608%
sample_entity sample_entity_single_property_indexed 1000 -4.447% -5.984% -3.025%
counts single_property_unindexed_entities -4.299% -5.064% -3.350%
indexing query_people_multiple_individually_indexed_properties_entities -4.054% -4.234% -3.880%
sampling sampling_single_unindexed_concrete_plus_derived_entities -3.888% -6.678% -1.478%
sample_entity sample_entity_single_property_indexed 100000 -3.103% -3.571% -2.627%
sample_entity sample_entity_single_property_unindexed 10000 -1.784% -2.339% -1.203%
algorithm_benches algorithm_sampling_multiple_known_length -1.758% -2.268% -1.218%
Unchanged / inconclusive (CI crosses 0%)
Group Bench Param Change CI Lower CI Upper
large_dataset bench_query_population_indexed_property_entities -1.589% -3.674% 0.101%
algorithm_benches algorithm_sampling_multiple_l_reservoir -1.053% -1.532% -0.675%
counts single_property_indexed_entities -0.988% -1.670% -0.340%
sampling sampling_multiple_l_reservoir_entities -0.937% -1.187% -0.680%
large_dataset bench_filter_indexed_entity 0.936% -6.252% 9.145%
counts index_after_adding_entities -0.891% -1.529% -0.285%
large_dataset bench_query_population_multi_indexed_entities -0.817% -1.115% -0.486%
sampling sampling_multiple_known_length_entities 0.550% -0.055% 1.204%
algorithm_benches algorithm_sampling_single_known_length -0.548% -1.010% -0.197%
sampling sampling_single_unindexed_entities -0.533% -0.732% -0.412%
indexing with_query_results_indexed_multi-property_entities -0.516% -1.347% 0.243%
sample_entity sample_entity_single_property_unindexed 100000 0.472% 0.097% 0.847%
examples example-births-deaths -0.466% -2.155% 1.368%
algorithm_benches algorithm_sampling_single_l_reservoir -0.416% -0.779% -0.102%
sampling sampling_single_known_length_entities 0.326% -0.155% 0.838%
sampling sampling_multiple_unindexed_entities 0.319% 0.211% 0.430%
counts multi_property_indexed_entities 0.253% -0.566% 1.125%
algorithm_benches algorithm_sampling_single_rand_reservoir 0.245% -0.086% 0.516%
counts reindex_after_adding_more_entities -0.121% -0.229% -0.019%
indexing query_people_count_multiple_individually_indexed_properties_enti 0.114% 0.027% 0.196%
indexing with_query_results_multiple_individually_indexed_properties_enti -0.085% -0.513% 0.249%
sample_entity sample_entity_whole_population 1000 -0.067% -0.999% 0.681%
large_dataset bench_query_population_property_entities 0.047% -0.324% 0.551%
sample_entity sample_entity_whole_population 10000 0.015% -0.634% 0.447%

@github-actions
Copy link
Copy Markdown

Benchmark Results

Hyperfine

Command Mean [ms] Min [ms] Max [ms] Relative
large_sir::baseline 3.1 ± 0.0 3.0 3.2 1.00
large_sir::entities 11.9 ± 0.3 11.5 13.1 3.88 ± 0.10

Criterion

Regressions (slower)
Group Bench Param Change CI Lower CI Upper
sample_entity sample_entity_multi_property_indexed 10000 8.894% 8.411% 9.410%
sample_entity sample_entity_multi_property_indexed 1000 8.217% 7.688% 8.677%
sample_entity sample_entity_multi_property_indexed 100000 7.748% 6.891% 8.350%
sample_entity sample_entity_single_property_indexed 1000 7.450% 6.847% 8.050%
sample_entity sample_entity_single_property_indexed 100000 5.784% 5.103% 6.507%
sample_entity sample_entity_single_property_indexed 10000 4.573% 3.872% 5.116%
sampling sampling_single_l_reservoir_entities 3.217% 2.779% 3.560%
sample_entity sample_entity_single_property_unindexed 10000 2.554% 1.879% 3.250%
examples example-births-deaths 1.900% 1.619% 2.214%
sample_entity sample_entity_single_property_unindexed 1000 1.420% 1.098% 1.870%
Improvements (faster)
Group Bench Param Change CI Lower CI Upper
sample_entity sample_entity_single_property_unindexed 100000 -24.033% -25.364% -22.516%
large_dataset bench_filter_unindexed_entity -20.601% -23.138% -18.027%
indexing with_query_results_single_indexed_property_entities -13.641% -14.511% -13.008%
indexing query_people_count_single_indexed_property_entities -12.532% -12.706% -12.330%
indexing query_people_indexed_multi-property_entities -7.333% -7.881% -6.674%
indexing query_people_single_indexed_property_entities -6.428% -8.325% -4.579%
large_dataset bench_match_entity -5.483% -7.845% -2.507%
indexing query_people_multiple_individually_indexed_properties_entities -4.509% -4.824% -4.204%
counts reindex_after_adding_more_entities -4.038% -4.182% -3.900%
large_dataset bench_query_population_multi_unindexed_entities -3.140% -3.997% -2.628%
indexing query_people_count_multiple_individually_indexed_properties_enti -2.786% -3.179% -2.378%
sampling sampling_single_unindexed_entities -2.242% -2.633% -1.869%
large_dataset bench_query_population_derived_property_entities -1.956% -2.593% -1.286%
sample_entity sample_entity_whole_population 1000 -1.858% -2.210% -1.514%
counts single_property_indexed_entities -1.770% -2.346% -1.182%
counts index_after_adding_entities -1.730% -2.105% -1.412%
sampling sampling_multiple_unindexed_entities -1.252% -1.330% -1.152%
Unchanged / inconclusive (CI crosses 0%)
Group Bench Param Change CI Lower CI Upper
sample_entity sample_entity_whole_population 10000 -1.617% -2.280% -0.958%
algorithm_benches algorithm_sampling_single_known_length -1.206% -1.637% -0.889%
indexing query_people_count_indexed_multi-property_entities -1.131% -1.354% -0.876%
large_dataset bench_query_population_indexed_property_entities -1.065% -1.615% -0.524%
large_dataset bench_query_population_multi_indexed_entities -1.016% -1.783% -0.332%
examples example-basic-infection -1.013% -1.422% -0.614%
sampling count_and_sampling_single_unindexed_concrete_plus_derived_entiti -0.837% -1.109% -0.593%
sampling sampling_multiple_known_length_entities 0.722% 0.080% 1.454%
sampling sampling_single_unindexed_concrete_plus_derived_entities 0.704% 0.330% 1.055%
counts multi_property_unindexed_entities 0.575% 0.289% 0.980%
sample_entity sample_entity_whole_population 100000 -0.539% -1.100% 0.017%
counts concrete_plus_derived_unindexed_entities 0.489% -0.206% 1.339%
algorithm_benches algorithm_sampling_multiple_l_reservoir 0.418% 0.212% 0.641%
algorithm_benches algorithm_sampling_single_l_reservoir 0.370% 0.075% 0.588%
sampling count_and_sampling_single_known_length_entities 0.348% -0.179% 0.746%
large_dataset bench_filter_indexed_entity -0.343% -8.593% 8.263%
algorithm_benches algorithm_sampling_single_rand_reservoir 0.330% 0.219% 0.435%
indexing with_query_results_multiple_individually_indexed_properties_enti -0.285% -0.960% 0.145%
large_dataset bench_query_population_property_entities -0.237% -0.741% 0.117%
sampling sampling_single_known_length_entities 0.143% -0.416% 0.587%
sampling sampling_multiple_l_reservoir_entities 0.095% -0.078% 0.274%
counts multi_property_indexed_entities -0.058% -0.876% 1.015%
algorithm_benches algorithm_sampling_multiple_known_length -0.055% -0.487% 0.329%
indexing with_query_results_indexed_multi-property_entities -0.037% -0.220% 0.168%
counts single_property_unindexed_entities -0.013% -0.550% 0.513%

github-actions Bot added a commit that referenced this pull request Apr 20, 2026
@swo
Copy link
Copy Markdown
Contributor Author

swo commented Apr 21, 2026

@bbbruce -- Robert asked for another pair of eyes on this example. Would you take a look? I could do a more full-blown analysis to check for correctness if we consider the prior state to be a gold standard.

@swo
Copy link
Copy Markdown
Contributor Author

swo commented Apr 28, 2026

@bbbruce I reworked a little bit as per our discussion:

  • Don't use network module; instead define an Edge entity
  • I define Node1 and Node2 as two separate properties. (My first instinct was to define Nodes(node1, node2), but I couldn't figure out how to context.query() for only part of a tuple property, like .query(with!(Edge, Nodes(_, some_person))).)
  • I opted for directional edges, which make the queries easier (rather than unidirectional edges, which requires half the entities but makes the queries more complicated).
  • I'm having trouble figuring out how to test this. I'd like to say "look for person with data ID 826. They should have 5 contacts." That requires me to (1) query a Person, (2) get their PersonId, and (3) use that PersonId to find the relevant edges. Step 2 has me stumped. Any ideas?

@github-actions
Copy link
Copy Markdown

Benchmark Results

Hyperfine

Command Mean [ms] Min [ms] Max [ms] Relative
large_sir::baseline 2.4 ± 0.2 2.3 3.8 1.00
large_sir::entities 9.7 ± 0.1 9.5 10.0 4.01 ± 0.35

Criterion

Regressions (slower)
Group Bench Param Change CI Lower CI Upper
large_dataset bench_query_population_multi_indexed_entities 58.220% 56.884% 59.430%
sample_entity sample_entity_single_property_unindexed 10000 55.604% 55.136% 56.066%
counts multi_property_indexed_entities 54.628% 53.705% 55.398%
sampling count_and_sampling_single_unindexed_concrete_plus_derived_entiti 40.148% 38.424% 41.800%
sample_entity sample_entity_multi_property_indexed 100000 32.269% 31.962% 32.596%
sample_entity sample_entity_multi_property_indexed 10000 31.433% 31.019% 32.111%
sample_entity sample_entity_multi_property_indexed 1000 31.427% 30.769% 32.076%
indexing with_query_results_indexed_multi-property_entities 28.066% 27.065% 28.816%
indexing query_people_count_indexed_multi-property_entities 24.021% 23.535% 24.424%
sampling sampling_single_unindexed_concrete_plus_derived_entities 22.737% 18.670% 26.591%
large_dataset bench_query_population_multi_unindexed_entities 9.687% 7.902% 11.598%
examples example-basic-infection 5.794% 4.893% 6.617%
sampling sampling_multiple_known_length_entities 2.959% 2.095% 3.702%
sampling sampling_single_known_length_entities 2.236% 1.406% 3.006%
sampling sampling_single_l_reservoir_entities 1.794% 1.189% 2.542%
Improvements (faster)
Group Bench Param Change CI Lower CI Upper
indexing with_query_results_single_indexed_property_entities -14.431% -14.662% -14.195%
indexing query_people_single_indexed_property_entities -13.997% -14.121% -13.864%
indexing query_people_count_single_indexed_property_entities -12.092% -12.462% -11.825%
large_dataset bench_filter_unindexed_entity -11.850% -14.385% -9.138%
large_dataset bench_match_entity -11.085% -11.408% -10.619%
sample_entity sample_entity_single_property_indexed 100000 -9.837% -10.161% -9.584%
sample_entity sample_entity_single_property_indexed 1000 -9.780% -10.062% -9.529%
sample_entity sample_entity_single_property_indexed 10000 -9.369% -9.564% -9.134%
examples example-births-deaths -8.775% -9.547% -8.156%
large_dataset bench_query_population_derived_property_entities -4.910% -5.784% -4.090%
sampling sampling_single_unindexed_entities -4.661% -4.822% -4.502%
counts reindex_after_adding_more_entities -4.476% -4.626% -4.326%
indexing query_people_indexed_multi-property_entities -3.672% -4.039% -3.394%
sample_entity sample_entity_single_property_unindexed 1000 -2.657% -2.947% -2.336%
indexing with_query_results_multiple_individually_indexed_properties_enti -1.999% -2.184% -1.784%
sampling sampling_multiple_unindexed_entities -1.690% -2.316% -1.059%
Unchanged / inconclusive (CI crosses 0%)
Group Bench Param Change CI Lower CI Upper
large_dataset bench_query_population_property_entities -1.367% -2.368% -0.543%
counts concrete_plus_derived_unindexed_entities -1.234% -1.614% -0.945%
sample_entity sample_entity_whole_population 1000 -1.230% -1.641% -0.925%
sample_entity sample_entity_single_property_unindexed 100000 1.156% 0.849% 1.412%
indexing query_people_multiple_individually_indexed_properties_entities 1.138% 0.673% 1.498%
counts single_property_indexed_entities -1.105% -1.901% -0.401%
algorithm_benches algorithm_sampling_multiple_l_reservoir 1.052% 0.735% 1.393%
sampling sampling_multiple_l_reservoir_entities -0.954% -2.068% -0.017%
large_dataset bench_filter_indexed_entity 0.873% -6.322% 9.397%
sample_entity sample_entity_whole_population 10000 -0.793% -1.047% -0.497%
large_dataset bench_query_population_indexed_property_entities 0.717% 0.355% 1.168%
algorithm_benches algorithm_sampling_single_known_length -0.533% -1.394% 0.233%
sample_entity sample_entity_whole_population 100000 -0.533% -0.974% -0.204%
algorithm_benches algorithm_sampling_multiple_known_length -0.405% -0.776% 0.161%
indexing query_people_count_multiple_individually_indexed_properties_enti -0.331% -0.523% -0.134%
sampling count_and_sampling_single_known_length_entities 0.310% -0.426% 1.069%
counts multi_property_unindexed_entities -0.282% -0.617% 0.171%
counts single_property_unindexed_entities 0.271% -0.094% 0.719%
algorithm_benches algorithm_sampling_single_l_reservoir -0.232% -0.471% 0.081%
counts index_after_adding_entities 0.156% -0.106% 0.528%
algorithm_benches algorithm_sampling_single_rand_reservoir -0.143% -0.862% 0.680%

github-actions Bot added a commit that referenced this pull request Apr 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants