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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ profile.json

.vscode/*
.idea
.codex
.copilot
.claude

# Generated by Cargo
# will have compiled files and executables
Expand Down
25 changes: 25 additions & 0 deletions docs/book/src/migration_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,31 @@ Adding a new entity with just one property value:
let person_id = context.add_entity(with!(Person, Age(25))).unwrap();
```

### Query syntax

Property-based queries are now entity-scoped. Raw tuples such as
`(Age(25),)` and `(Age(25), InfectionStatus::Infected)` no longer implement
the public query API.

Use `with!(Entity, ...)` instead:

```rust
let count = context.query_entity_count(with!(Person, Age(25), InfectionStatus::Infected));

context.with_query_results(with!(Person, Age(25)), &mut |people| {
let _ = people;
});

let sampled = context.sample_entity(MyRng, with!(Person, Age(25)));
```

For whole-population queries, use the entity type itself or `with!(Entity)`:

```rust
let any_person = context.sample_entity(MyRng, Person);
let everyone = context.query_entity_count(with!(Person));
```

### Getting a property value for an entity

```rust
Expand Down
6 changes: 4 additions & 2 deletions examples/basic-infection/src/infection_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ mod test {
use ixa::prelude::*;

use crate::infection_manager::InfectionStatusEvent;
use crate::people::InfectionStatus;
use crate::people::{InfectionStatus, Person};

define_data_plugin!(RecoveryPlugin, usize, 0);

Expand All @@ -66,7 +66,9 @@ mod test {

let population_size = 10;
for _ in 0..population_size {
let person_id = context.add_entity((InfectionStatus::S,)).unwrap();
let person_id = context
.add_entity(with!(Person, InfectionStatus::S,))
.unwrap();
context.set_property(person_id, InfectionStatus::I);
}

Expand Down
32 changes: 28 additions & 4 deletions examples/network-hhmodel/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,13 @@ struct PeopleRecord {

fn create_person_from_record(context: &mut Context, record: &PeopleRecord) -> PersonId {
context
.add_entity((record.id, record.age_group, record.sex, record.household_id))
.add_entity(with!(
Person,
record.id,
record.age_group,
record.sex,
record.household_id
))
.unwrap()
}

Expand Down Expand Up @@ -94,19 +100,37 @@ mod tests {
let person = people[0];
assert!(context.match_entity(
person,
(Id(676), AgeGroup::Age18to64, Sex::Female, HouseholdId(1))
with!(
Person,
Id(676),
AgeGroup::Age18to64,
Sex::Female,
HouseholdId(1)
)
));

let person = people[246];
assert!(context.match_entity(
person,
(Id(213), AgeGroup::AgeUnder5, Sex::Female, HouseholdId(162))
with!(
Person,
Id(213),
AgeGroup::AgeUnder5,
Sex::Female,
HouseholdId(162)
)
));

let person = people[1591];
assert!(context.match_entity(
person,
(Id(1591), AgeGroup::Age65Plus, Sex::Male, HouseholdId(496))
with!(
Person,
Id(1591),
AgeGroup::Age65Plus,
Sex::Male,
HouseholdId(496)
)
));
}
}
6 changes: 3 additions & 3 deletions examples/network-hhmodel/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ fn create_household_networks(context: &mut Context, people: &[PersonId]) {
let household_id: HouseholdId = context.get_property(*person_id);
if households.insert(household_id) {
let mut members: Vec<PersonId> = Vec::new();
context.with_query_results((household_id,), &mut |results| {
context.with_query_results(with!(Person, household_id), &mut |results| {
members = results.to_owned_vec()
});
// create a dense network
Expand All @@ -43,13 +43,13 @@ fn load_edge_list<ET: EdgeType<Person>>(context: &mut Context, file_name: &str,
for result in reader.deserialize() {
let record: EdgeRecord = result.expect("Failed to parse edge");
let mut p1_vec = Vec::new();
context.with_query_results((Id(record.v1),), &mut |people| {
context.with_query_results(with!(Person, Id(record.v1)), &mut |people| {
p1_vec = people.to_owned_vec()
});
assert_eq!(p1_vec.len(), 1);
let p1 = p1_vec[0];
let mut p2_vec = Vec::new();
context.with_query_results((Id(record.v2),), &mut |people| {
context.with_query_results(with!(Person, Id(record.v2)), &mut |people| {
p2_vec = people.to_owned_vec()
});
assert_eq!(p2_vec.len(), 1);
Expand Down
16 changes: 9 additions & 7 deletions examples/network-hhmodel/seir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,13 @@ fn calculate_waiting_time(context: &Context, shape: f64, mean_period: f64) -> f6
}

fn expose_network<ET: EdgeType<Person>>(context: &mut Context, beta: f64) {
let infectious_people = context.query((DiseaseStatus::I,)).to_owned_vec();
let infectious_people = context
.query(with!(Person, DiseaseStatus::I))
.to_owned_vec();

for infectious in infectious_people {
let edges = context.get_matching_edges::<Person, ET>(infectious, |context, edge| {
context.match_entity(edge.neighbor, (DiseaseStatus::S,))
context.match_entity(edge.neighbor, with!(Person, DiseaseStatus::S))
});

for e in edges {
Expand Down Expand Up @@ -187,7 +189,7 @@ mod tests {
network::init(&mut context, &people);

let mut to_infect = Vec::<PersonId>::new();
context.with_query_results((Id(71),), &mut |people| {
context.with_query_results(with!(Person, Id(71)), &mut |people| {
to_infect.extend(people);
});

Expand All @@ -196,19 +198,19 @@ mod tests {
context.execute();

assert_eq!(
context.query_entity_count::<Person, _>((DiseaseStatus::S,)),
context.query_entity_count::<Person, _>(with!(Person, DiseaseStatus::S)),
399
);
assert_eq!(
context.query_entity_count::<Person, _>((DiseaseStatus::E,)),
context.query_entity_count::<Person, _>(with!(Person, DiseaseStatus::E)),
0
);
assert_eq!(
context.query_entity_count::<Person, _>((DiseaseStatus::I,)),
context.query_entity_count::<Person, _>(with!(Person, DiseaseStatus::I)),
0
);
assert_eq!(
context.query_entity_count::<Person, _>((DiseaseStatus::R,)),
context.query_entity_count::<Person, _>(with!(Person, DiseaseStatus::R)),
1207
);
}
Expand Down
6 changes: 3 additions & 3 deletions integration-tests/ixa-runner-tests/bin/runner_generic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ define_entity!(Person);

fn main() {
run_with_args(|context, _args, _| {
let _: PersonId = context.add_entity(()).unwrap();
let _: PersonId = context.add_entity(()).unwrap();
let _: PersonId = context.add_entity(()).unwrap();
let _: PersonId = context.add_entity(Person).unwrap();
let _: PersonId = context.add_entity(Person).unwrap();
let _: PersonId = context.add_entity(Person).unwrap();

trace!("A TRACE message");
debug!("A DEBUG message");
Expand Down
7 changes: 4 additions & 3 deletions integration-tests/ixa-runner-tests/tests/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ mod tests {

// Entity properties: add a Person with TestPropU32
let pid: EntityId<Person> = ctx
.add_entity((
.add_entity(with!(
Person,
TestPropU32(10u32),
TestPropU32b(20u32),
TestPropOpt(Some(3u8)),
Expand All @@ -83,10 +84,10 @@ mod tests {

// Edge type (entity-based network): create two people and add an edge of type TestEdge
let p1 = ctx
.add_entity((TestPropU32(1u32), TestPropU32b(1u32)))
.add_entity(with!(Person, TestPropU32(1u32), TestPropU32b(1u32)))
.unwrap();
let p2 = ctx
.add_entity((TestPropU32(2u32), TestPropU32b(2u32)))
.add_entity(with!(Person, TestPropU32(2u32), TestPropU32b(2u32)))
.unwrap();
ctx.add_edge::<Person, TestEdge>(p1, p2, 1.0, TestEdge)
.unwrap();
Expand Down
6 changes: 4 additions & 2 deletions integration-tests/ixa-wasm-tests/src/infection_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ mod test {
use ixa::prelude::*;

use crate::infection_manager::InfectionStatusEvent;
use crate::people::InfectionStatus;
use crate::people::{InfectionStatus, Person};

define_data_plugin!(RecoveryPlugin, usize, 0);

Expand All @@ -68,7 +68,9 @@ mod test {

let population_size = 10;
for _ in 0..population_size {
let person_id = context.add_entity((InfectionStatus::S,)).unwrap();
let person_id = context
.add_entity(with!(Person, InfectionStatus::S,))
.unwrap();
context.set_property(person_id, InfectionStatus::I);
}

Expand Down
2 changes: 1 addition & 1 deletion integration-tests/ixa-wasm-tests/src/people.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ define_property!(
pub fn init(context: &mut Context) {
trace!("Initializing people");
for _ in 0..POPULATION {
let _: PersonId = context.add_entity(()).unwrap();
let _: PersonId = context.add_entity(Person).unwrap();
}
}
4 changes: 2 additions & 2 deletions integration-tests/ixa-wasm-tests/src/transmission_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ define_rng!(TransmissionRng);
fn attempt_infection(context: &mut Context) {
trace!("Attempting infection");
let population_size: usize = context.get_entity_count::<Person>();
let person_to_infect: PersonId = context.sample_entity(TransmissionRng, ()).unwrap(); //.sample_range(TransmissionRng, 0..population_size);
let person_to_infect: PersonId = context.sample_entity(TransmissionRng, Person).unwrap(); //.sample_range(TransmissionRng, 0..population_size);

let person_status: InfectionStatus = context.get_property(person_to_infect);

Expand Down Expand Up @@ -52,7 +52,7 @@ mod test {
fn test_attempt_infection() {
let mut context = Context::new();
context.init_random(SEED);
let person_id: PersonId = context.add_entity(()).unwrap();
let person_id: PersonId = context.add_entity(Person).unwrap();
attempt_infection(&mut context);
let person_status: InfectionStatus = context.get_property(person_id);
assert_eq!(person_status, InfectionStatus::I);
Expand Down
24 changes: 15 additions & 9 deletions ixa-bench/criterion/counts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ fn populate_entities(context: &mut Context, n: usize) {
context.init_random(SEED);

for person in generate_population_with_seed(n, 0.2, 10.0, Some(SEED)) {
let _ = context.add_entity((
let _ = context.add_entity(with!(
Person,
Age(person.age),
HomeId(person.home_id as u32),
SchoolId(person.school_id as u32),
Expand All @@ -59,37 +60,42 @@ pub fn criterion_benchmark(c: &mut Criterion) {
// Unindexed single property
group.bench_function("single_property_unindexed_entities", |bencher| {
bencher.iter(|| {
black_box(context.query_entity_count(black_box((HomeId(HOME_VAL),))));
black_box(context.query_entity_count(black_box(with!(Person, HomeId(HOME_VAL),))));
});
});

// Unindexed concrete + unindexed derived property
group.bench_function("concrete_plus_derived_unindexed_entities", |bencher| {
bencher.iter(|| {
black_box(context.query_entity_count(black_box((HomeId(HOME_VAL), AgeGroupFoi(1)))));
black_box(context.query_entity_count(black_box(with!(
Person,
HomeId(HOME_VAL),
AgeGroupFoi(1)
))));
});
});

// Indexed single property
context.index_property::<Person, HomeId>();
group.bench_function("single_property_indexed_entities", |bencher| {
bencher.iter(|| {
black_box(context.query_entity_count(black_box((HomeId(HOME_VAL),))));
black_box(context.query_entity_count(black_box(with!(Person, HomeId(HOME_VAL),))));
});
});

// Unindexed multi-property
group.bench_function("multi_property_unindexed_entities", |bencher| {
bencher.iter(|| {
black_box(context.query_entity_count(black_box((Age(30), SchoolId(1)))));
black_box(context.query_entity_count(black_box(with!(Person, Age(30), SchoolId(1)))));
});
});

// Indexed multi-property
context.index_property::<Person, (Age, SchoolId, WorkplaceId)>();
group.bench_function("multi_property_indexed_entities", |bencher| {
bencher.iter(|| {
black_box(context.query_entity_count(black_box((
black_box(context.query_entity_count(black_box(with!(
Person,
Age(30),
SchoolId(1),
WorkplaceId(1),
Expand All @@ -107,7 +113,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
},
|mut ctx| {
ctx.index_property::<Person, HomeId>();
black_box(ctx.query_entity_count(black_box((HomeId(HOME_VAL),))));
black_box(ctx.query_entity_count(black_box(with!(Person, HomeId(HOME_VAL),))));
},
);
});
Expand All @@ -119,13 +125,13 @@ pub fn criterion_benchmark(c: &mut Criterion) {
let mut ctx = Context::new();
populate_entities(&mut ctx, 5_000);
ctx.index_property::<Person, HomeId>();
black_box(ctx.query_entity_count(black_box((HomeId(HOME_VAL),))));
black_box(ctx.query_entity_count(black_box(with!(Person, HomeId(HOME_VAL),))));
ctx
},
|mut ctx| {
populate_entities(&mut ctx, 2_000);
ctx.index_property::<Person, HomeId>();
black_box(ctx.query_entity_count(black_box((HomeId(HOME_VAL),))));
black_box(ctx.query_entity_count(black_box(with!(Person, HomeId(HOME_VAL),))));
},
);
});
Expand Down
Loading
Loading