diff --git a/.github/workflows/build_artifacts.yaml b/.github/workflows/build_artifacts.yaml index ac9246fa..d85a2068 100644 --- a/.github/workflows/build_artifacts.yaml +++ b/.github/workflows/build_artifacts.yaml @@ -1,95 +1,84 @@ -name: Build artifacts +name: Build Artifacts on: - pull_request: - branches: - - main workflow_dispatch: + push: jobs: - build-macos: + macos: + name: Build MacOS runs-on: macos-latest steps: - uses: actions/checkout@v3 with: submodules: 'true' - - uses: arduino/setup-protoc@v1.1.2 + - uses: arduino/setup-protoc@v2 with: repo-token: ${{ secrets.GITHUB_TOKEN }} - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true + - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 with: cache-on-failure: true - - name: Build - uses: actions-rs/cargo@v1 + - name: cargo build --release + uses: clechasseur/rs-cargo@v1 with: command: build args: --release - - name: Upload artifacts - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: reveaal-macos - path: target/release/Reveaal + path: target/release/reveaal if-no-files-found: error + retention-days: 7 - build-win: + win: + name: Build Windows runs-on: windows-latest steps: - uses: actions/checkout@v3 with: submodules: 'true' - - uses: arduino/setup-protoc@v1.1.2 + - uses: arduino/setup-protoc@v2 with: repo-token: ${{ secrets.GITHUB_TOKEN }} - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true + - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 with: cache-on-failure: true - - name: Build - uses: actions-rs/cargo@v1 + - name: cargo build --release + uses: clechasseur/rs-cargo@v1 with: command: build args: --release - - name: Upload artifacts - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: reveaal-windows - path: target/release/Reveaal.exe + path: target/release/reveaal.exe if-no-files-found: error - - build-ubuntu: + retention-days: 7 + + ubuntu: + name: Build Ubuntu runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: submodules: 'true' - - uses: arduino/setup-protoc@v1.1.2 + - uses: arduino/setup-protoc@v2 with: repo-token: ${{ secrets.GITHUB_TOKEN }} - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true + - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 with: cache-on-failure: true - - name: Build - uses: actions-rs/cargo@v1 + - name: cargo build --release + uses: clechasseur/rs-cargo@v1 with: command: build args: --release - - name: Upload artifacts - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: reveaal-ubuntu - path: target/release/Reveaal - if-no-files-found: error \ No newline at end of file + path: target/release/reveaal + if-no-files-found: error + retention-days: 7 diff --git a/.github/workflows/check_format.yaml b/.github/workflows/check_format.yaml new file mode 100644 index 00000000..a47c29c2 --- /dev/null +++ b/.github/workflows/check_format.yaml @@ -0,0 +1,45 @@ +name: Check formatting + +on: + workflow_dispatch: + push: + +jobs: + fmt: + name: cargo fmt + runs-on: ubuntu-latest + steps: + - run: sudo apt-get install llvm protobuf-compiler + - uses: actions/checkout@v3 + with: + submodules: 'true' + - uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt + - uses: Swatinem/rust-cache@v2 + with: + cache-on-failure: true + - name: cargo fmt --all + uses: clechasseur/rs-cargo@v1 + with: + command: fmt + args: --all -- --check + + clippy: + name: Clippy lint and check + runs-on: ubuntu-latest + steps: + - run: sudo apt-get install llvm protobuf-compiler + - uses: actions/checkout@v3 + with: + submodules: 'true' + - uses: dtolnay/rust-toolchain@stable + with: + components: clippy + - uses: Swatinem/rust-cache@v2 + with: + cache-on-failure: true + - name: clippy --all-targets --all-features + uses: clechasseur/rs-clippy-check@v3 + with: + args: --all-targets --all-features -- -D warnings diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml deleted file mode 100644 index e0bff840..00000000 --- a/.github/workflows/ci.yaml +++ /dev/null @@ -1,61 +0,0 @@ -on: - - push - -name: Validation - -jobs: - test: - name: Test Suite - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - submodules: 'true' - - name: Install llvm-config - run: sudo apt-get install llvm protobuf-compiler - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - - uses: actions-rs/cargo@v1 - with: - command: test - fmt: - name: Check code is formatted - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - submodules: 'true' - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - components: rustfmt - - uses: actions-rs/cargo@v1 - with: - command: fmt - args: --all -- --check - - check: - name: Lint and check - runs-on: ubuntu-latest - steps: - - name: Install llvm-config - run: sudo apt-get install llvm protobuf-compiler - - uses: actions/checkout@v2 - with: - submodules: 'true' - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - components: clippy - - uses: Swatinem/rust-cache@v2 - - uses: actions-rs/clippy-check@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} - args: --all-targets --all-features -- -D warnings diff --git a/.github/workflows/run_tests.yaml b/.github/workflows/run_tests.yaml new file mode 100644 index 00000000..e25e31ef --- /dev/null +++ b/.github/workflows/run_tests.yaml @@ -0,0 +1,25 @@ +name: Run Tests + +on: + workflow_dispatch: + push: + +jobs: + ubuntu: + name: Tests Ubuntu + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + submodules: 'true' + - run: sudo apt-get install llvm protobuf-compiler + - uses: dtolnay/rust-toolchain@stable + with: + components: clippy + - uses: Swatinem/rust-cache@v2 + with: + cache-on-failure: true + - name: cargo test + uses: clechasseur/rs-cargo@v1 + with: + command: test \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index f685af44..62938471 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,3 @@ [submodule "Ecdar-ProtoBuf"] path = Ecdar-ProtoBuf - url = https://github.com/Ecdar/Ecdar-ProtoBuf.git - branch = main + url = https://github.com/ECDAR-AAU-SW-P5/Ecdar-ProtoBuf.git diff --git a/Cargo.toml b/Cargo.toml index d6aa05d3..60db2d87 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ name = "reveaal" path = "src/lib.rs" [[bin]] -name = "Reveaal" +name = "reveaal" path = "src/main.rs" [features] diff --git a/README.md b/README.md index cb101a22..b14f9fc2 100644 --- a/README.md +++ b/README.md @@ -6,25 +6,32 @@ This is a model checking engine for ECDAR (Environment for Compositional Design #### DBM Library The engine uses the ECDAR DBM Library for operations on zones of time (https://www.github.com/ECDAR/EDBM). -## Prerequisites +## Building + +### Prerequisites - A rust compiler installed (https://www.rust-lang.org/learn/get-started) - A folder containing the model components to check - Download ProtoBuf definitions with ```git submodule update --init --recursive``` -### Compiling on Linux -You may need the ProtoBuf compiler protoc (for the Ubuntu linux distribution ```apt install protobuf-compiler```) +**Windows**: +We recommend installing and using the default ```x86_64-pc-windows-msvc``` Rust targets. +If you instead (not recommended) are using ```x86_64-pc-windows-gnu``` targets on Windows you need to install mingw and add it to your PATH variable to build. + +#### Protobuf +**Debian based (Ubuntu, mint etc.)**: ```apt install protobuf-compiler``` + +**Arch based (Endeavour etc.)**: ```yay protobuf-c``` -### Compiling on Windows -We recommend installing and using the default `x86_64-pc-windows-msvc` Rust targets. -If you instead (not recommended) are using `x86_64-pc-windows-gnu` targets on Windows you need to install mingw and add it to your PATH variable to build. +**Windows**: Download protobuf (https://github.com/protocolbuffers/protobuf/releases/) +Add the bin folder to your path environment variable (https://www.computerhope.com/issues/ch000549.htm) -## Building the project -- Build the project using `cargo build` -- Optionally run the tests using `cargo test` +### Compiling and running +- Build the project using ```cargo build``` +- Optionally run the tests using ```cargo test``` -## Cross compiling from Linux +#### Cross compiling The project is pure Rust so one should be able to crosscompile to any platform with a rust target. -### Compiling to Windows from Linux -Make sure you have mingw installed `sudo apt-get install mingw-w64` and the rustc windows target is installed with `rustup target add x86_64-pc-windows-gnu` and build with cargo: -`cargo build --target x86_64-pc-windows-gnu` \ No newline at end of file +**Debian -> windows** +Make sure you have mingw installed ```sudo apt-get install mingw-w64``` and the rustc windows target is installed with ```rustup target add x86_64-pc-windows-gnu``` and build with cargo: +```cargo build --target x86_64-pc-windows-gnu``` \ No newline at end of file diff --git a/benches/clock_reduction_bench.rs b/benches/clock_reduction_bench.rs index 4b3c459d..cc2fc101 100644 --- a/benches/clock_reduction_bench.rs +++ b/benches/clock_reduction_bench.rs @@ -75,7 +75,6 @@ static SAMPLES: u64 = 10; mod bench_helper; use reveaal::parse_queries::parse_to_query; -use reveaal::TransitionSystems::TransitionSystem; // const QUERY: &str = "refinement: (((((Adm2 && HalfAdm1 && HalfAdm2) || Machine || Researcher) && ((Adm2 && HalfAdm1) || Machine || Researcher) && ((Adm2 && HalfAdm2) || Machine || Researcher) && ((HalfAdm1 && HalfAdm2) || Machine || Researcher) && (Adm2 || Machine || Researcher)) // (Adm2 && HalfAdm1 && HalfAdm2)) // Researcher) <= (((((Adm2 && HalfAdm1 && HalfAdm2) || Machine || Researcher) && ((Adm2 && HalfAdm1) || Machine || Researcher) && ((Adm2 && HalfAdm2) || Machine || Researcher) && ((HalfAdm1 && HalfAdm2) || Machine || Researcher) && (Adm2 || Machine || Researcher)) // (Adm2 && HalfAdm1 && HalfAdm2)) // Researcher)"; const REACHABILITY_QUERY: &str = "reachability: Machine || Researcher @ Machine.L5 && Researcher.L6 -> Machine.L4 && Researcher.L9"; diff --git a/benches/reachability_bench.rs b/benches/reachability_bench.rs index 8a8c0415..c99b400f 100644 --- a/benches/reachability_bench.rs +++ b/benches/reachability_bench.rs @@ -3,7 +3,7 @@ pub mod bench_helper; pub mod flamegraph; use flamegraph::flamegraph_profiler::FlamegraphProfiler; use reveaal::extract_system_rep::create_executable_query; -use reveaal::ModelObjects::Query; +use reveaal::model_objects::Query; use reveaal::{parse_queries, ComponentLoader}; fn bench_reachability(c: &mut Criterion, query: &str, loader: &mut Box) { diff --git a/benches/refinement_bench.rs b/benches/refinement_bench.rs index 027c47da..c151211f 100644 --- a/benches/refinement_bench.rs +++ b/benches/refinement_bench.rs @@ -5,9 +5,9 @@ pub mod flamegraph; use flamegraph::flamegraph_profiler::FlamegraphProfiler; use reveaal::extract_system_rep::create_executable_query; -use reveaal::ModelObjects::Query; -use reveaal::System::executable_query::ExecutableQuery; -use reveaal::System::query_failures::QueryResult; +use reveaal::model_objects::Query; +use reveaal::system::executable_query::ExecutableQuery; +use reveaal::system::query_failures::QueryResult; use reveaal::{parse_queries, ComponentLoader}; fn construct_query<'a>( diff --git a/benches/simulation_bench.rs b/benches/simulation_bench.rs index 0a76e05f..2ed3cd49 100644 --- a/benches/simulation_bench.rs +++ b/benches/simulation_bench.rs @@ -2,13 +2,13 @@ use criterion::{criterion_group, criterion_main, Criterion}; mod bench_helper; pub mod flamegraph; use flamegraph::flamegraph_profiler::FlamegraphProfiler; -use reveaal::DataReader::json_writer::component_to_json; -use reveaal::ModelObjects::Component; -use reveaal::ProtobufServer::services::component::Rep::Json; -use reveaal::ProtobufServer::services::{Component as ProtoComp, ComponentsInfo, SimulationInfo}; +use reveaal::data_reader::json_writer::component_to_json; +use reveaal::model_objects::Component; +use reveaal::protobuf_server::services::component::Rep::Json; +use reveaal::protobuf_server::services::{Component as ProtoComp, ComponentsInfo, SimulationInfo}; use reveaal::{ - DataReader::component_loader::ModelCache, - ProtobufServer::{ + data_reader::component_loader::ModelCache, + protobuf_server::{ services::{SimulationStartRequest, SimulationStepRequest}, ConcreteEcdarBackend, }, @@ -74,13 +74,16 @@ fn take_simulation_step(c: &mut Criterion, id: &str, request: SimulationStepRequ fn simulation(c: &mut Criterion) { let mut loader = bench_helper::get_uni_loader(false); - let start_request_1 = - construct_start_request(&[loader.get_component("Machine").clone()], "(Machine)", 1); + let start_request_1 = construct_start_request( + &[loader.get_component("Machine").unwrap().clone()], + "(Machine)", + 1, + ); let start_request_2 = construct_start_request( &[ - loader.get_component("HalfAdm1").clone(), - loader.get_component("HalfAdm2").clone(), + loader.get_component("HalfAdm1").unwrap().clone(), + loader.get_component("HalfAdm2").unwrap().clone(), ], "(HalfAdm1 && HalfAdm2)", 2, @@ -88,9 +91,9 @@ fn simulation(c: &mut Criterion) { let start_request_3 = construct_start_request( &[ - loader.get_component("Machine").clone(), - loader.get_component("Administration").clone(), - loader.get_component("Researcher").clone(), + loader.get_component("Machine").unwrap().clone(), + loader.get_component("Administration").unwrap().clone(), + loader.get_component("Researcher").unwrap().clone(), ], "(Administration || Machine || Researcher)", 3, @@ -98,17 +101,17 @@ fn simulation(c: &mut Criterion) { let start_request_4 = construct_start_request( &[ - loader.get_component("Machine").clone(), - loader.get_component("HalfAdm1").clone(), - loader.get_component("HalfAdm2").clone(), - loader.get_component("Researcher").clone(), + loader.get_component("Machine").unwrap().clone(), + loader.get_component("HalfAdm1").unwrap().clone(), + loader.get_component("HalfAdm2").unwrap().clone(), + loader.get_component("Researcher").unwrap().clone(), ], "((HalfAdm1 && HalfAdm2) || Machine || Researcher)", 4, ); let step_request_1 = construct_step_request( - &[loader.get_component("Machine").clone()], + &[loader.get_component("Machine").unwrap().clone()], "(Machine)", 1, &start_request_1, @@ -116,8 +119,8 @@ fn simulation(c: &mut Criterion) { let step_request_2 = construct_step_request( &[ - loader.get_component("HalfAdm1").clone(), - loader.get_component("HalfAdm2").clone(), + loader.get_component("HalfAdm1").unwrap().clone(), + loader.get_component("HalfAdm2").unwrap().clone(), ], "(HalfAdm1 && HalfAdm2)", 2, @@ -126,9 +129,9 @@ fn simulation(c: &mut Criterion) { let step_request_3 = construct_step_request( &[ - loader.get_component("Machine").clone(), - loader.get_component("Administration").clone(), - loader.get_component("Researcher").clone(), + loader.get_component("Machine").unwrap().clone(), + loader.get_component("Administration").unwrap().clone(), + loader.get_component("Researcher").unwrap().clone(), ], "(Administration || Machine || Researcher)", 3, @@ -137,10 +140,10 @@ fn simulation(c: &mut Criterion) { let step_request_4 = construct_step_request( &[ - loader.get_component("Machine").clone(), - loader.get_component("HalfAdm1").clone(), - loader.get_component("HalfAdm2").clone(), - loader.get_component("Researcher").clone(), + loader.get_component("Machine").unwrap().clone(), + loader.get_component("HalfAdm1").unwrap().clone(), + loader.get_component("HalfAdm2").unwrap().clone(), + loader.get_component("Researcher").unwrap().clone(), ], "((HalfAdm1 && HalfAdm2) || Machine || Researcher)", 4, diff --git a/benches/threadpool_bench.rs b/benches/threadpool_bench.rs index 2bcd40fc..324d8def 100644 --- a/benches/threadpool_bench.rs +++ b/benches/threadpool_bench.rs @@ -1,8 +1,8 @@ use std::vec; use criterion::{black_box, criterion_group, criterion_main, Criterion}; -use reveaal::DataReader::json_writer::component_to_json; -use reveaal::ProtobufServer::{ +use reveaal::data_reader::json_writer::component_to_json; +use reveaal::protobuf_server::{ services::{ component::Rep, ecdar_backend_server::EcdarBackend, Component as ProtoComp, ComponentsInfo, QueryRequest, @@ -18,7 +18,7 @@ use futures::StreamExt; mod bench_helper; pub mod flamegraph; use flamegraph::flamegraph_profiler::FlamegraphProfiler; -use reveaal::ModelObjects::Component; +use reveaal::model_objects::Component; const NUM_OF_REQUESTS: u32 = 512; @@ -72,9 +72,9 @@ fn construct_components(json: &[String]) -> Vec { fn threadpool_cache(c: &mut Criterion) { let mut loader = bench_helper::get_uni_loader(false); let comps = vec![ - loader.get_component("Administration").clone(), - loader.get_component("Researcher").clone(), - loader.get_component("Machine").clone(), + loader.get_component("Administration").unwrap().clone(), + loader.get_component("Researcher").unwrap().clone(), + loader.get_component("Machine").unwrap().clone(), ]; let expensive_query = String::from("determinism: Administration || Researcher || Machine"); let cheap_query = String::from("determinism: Machine"); diff --git a/samples/json/PopulateClocks/Components/Component1.json b/samples/json/PopulateClocks/Components/Component1.json new file mode 100644 index 00000000..8d179674 --- /dev/null +++ b/samples/json/PopulateClocks/Components/Component1.json @@ -0,0 +1,253 @@ +{ + "name": "Component1", + "declarations": "clock x, y, z, i;", + "locations": [ + { + "id": "L0", + "nickname": "", + "invariant": "", + "type": "INITIAL", + "urgency": "NORMAL", + "x": 30.000000000000007, + "y": 290.0, + "color": "9", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 50.0, + "invariantY": 30.0 + }, + { + "id": "L2", + "nickname": "", + "invariant": "i \u003c 5", + "type": "NORMAL", + "urgency": "NORMAL", + "x": 262.60002, + "y": 290.23333333333335, + "color": "9", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 20.0, + "invariantY": 40.0 + }, + { + "id": "L3", + "nickname": "", + "invariant": "", + "type": "NORMAL", + "urgency": "NORMAL", + "x": 363.7833533333333, + "y": 293.78333333333336, + "color": "9", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + }, + { + "id": "L4", + "nickname": "", + "invariant": "y\u003e1", + "type": "NORMAL", + "urgency": "NORMAL", + "x": 152.60002999999998, + "y": 369.7, + "color": "9", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 10.0, + "invariantY": 30.0 + }, + { + "id": "L1", + "nickname": "", + "invariant": "x\u003e1", + "type": "NORMAL", + "urgency": "NORMAL", + "x": 121.41668666666664, + "y": 200.0, + "color": "9", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 20.0, + "invariantY": -40.0 + } + ], + "edges": [ + { + "id": "E0", + "group": "", + "sourceLocation": "L0", + "targetLocation": "L2", + "status": "OUTPUT", + "select": "", + "guard": "x\u003e2", + "update": "i\u003d2", + "sync": "foo", + "isLocked": false, + "nails": [ + { + "x": 100.0, + "y": 290.0, + "propertyType": "GUARD", + "propertyX": 10.0, + "propertyY": 0.0 + }, + { + "x": 140.0, + "y": 290.0, + "propertyType": "UPDATE", + "propertyX": 10.0, + "propertyY": 0.0 + }, + { + "x": 167.75, + "y": 289.5833333333333, + "propertyType": "SYNCHRONIZATION", + "propertyX": 0.0, + "propertyY": 29.999999999999996 + } + ] + }, + { + "id": "E1", + "group": "", + "sourceLocation": "L2", + "targetLocation": "L3", + "status": "INPUT", + "select": "", + "guard": "", + "update": "", + "sync": "bar", + "isLocked": false, + "nails": [ + { + "x": 313.1333333333333, + "y": 290.76666666666665, + "propertyType": "SYNCHRONIZATION", + "propertyX": 0.0, + "propertyY": 40.0 + } + ] + }, + { + "id": "E2", + "group": "", + "sourceLocation": "L0", + "targetLocation": "L4", + "status": "INPUT", + "select": "", + "guard": "y\u003e3", + "update": "", + "sync": "baz", + "isLocked": false, + "nails": [ + { + "x": 30.0, + "y": 330.0, + "propertyType": "GUARD", + "propertyX": 10.0, + "propertyY": 0.0 + }, + { + "x": 69.46666666666667, + "y": 364.31666666666666, + "propertyType": "SYNCHRONIZATION", + "propertyX": 10.0, + "propertyY": 0.0 + } + ] + }, + { + "id": "E3", + "group": "", + "sourceLocation": "L4", + "targetLocation": "L2", + "status": "INPUT", + "select": "", + "guard": "z\u003e2", + "update": "", + "sync": "baz", + "isLocked": false, + "nails": [ + { + "x": 189.99999999999997, + "y": 370.0, + "propertyType": "GUARD", + "propertyX": 10.0, + "propertyY": 0.0 + }, + { + "x": 231.3, + "y": 344.31666666666666, + "propertyType": "SYNCHRONIZATION", + "propertyX": 10.0, + "propertyY": 0.0 + } + ] + }, + { + "id": "E4", + "group": "", + "sourceLocation": "L2", + "targetLocation": "L1", + "status": "OUTPUT", + "select": "", + "guard": "x\u003e2", + "update": "", + "sync": "foo", + "isLocked": false, + "nails": [ + { + "x": 209.99999999999997, + "y": 250.0, + "propertyType": "GUARD", + "propertyX": 10.0, + "propertyY": 0.0 + }, + { + "x": 171.3, + "y": 226.03333333333333, + "propertyType": "SYNCHRONIZATION", + "propertyX": 10.0, + "propertyY": 0.0 + } + ] + }, + { + "id": "E5", + "group": "", + "sourceLocation": "L1", + "targetLocation": "L0", + "status": "INPUT", + "select": "", + "guard": "i\u003e4", + "update": "", + "sync": "bar", + "isLocked": false, + "nails": [ + { + "x": 89.99999999999994, + "y": 230.0, + "propertyType": "GUARD", + "propertyX": 10.0, + "propertyY": 0.0 + }, + { + "x": 57.099999999999994, + "y": 254.85, + "propertyType": "SYNCHRONIZATION", + "propertyX": 10.0, + "propertyY": 0.0 + } + ] + } + ], + "description": "", + "x": 257.0, + "y": 96.0, + "width": 450.0, + "height": 600.0, + "color": "9", + "includeInPeriodicCheck": true +} \ No newline at end of file diff --git a/samples/json/PopulateClocks/Components/Component3.json b/samples/json/PopulateClocks/Components/Component3.json new file mode 100644 index 00000000..49182933 --- /dev/null +++ b/samples/json/PopulateClocks/Components/Component3.json @@ -0,0 +1,218 @@ +{ + "name": "Component3", + "declarations": "clock h,j,k;", + "locations": [ + { + "id": "L7", + "nickname": "", + "invariant": "", + "type": "INITIAL", + "urgency": "NORMAL", + "x": 75.00000000000003, + "y": 280.0, + "color": "5", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + }, + { + "id": "L8", + "nickname": "", + "invariant": "", + "type": "NORMAL", + "urgency": "NORMAL", + "x": 271.5384715384615, + "y": 377.30769230769226, + "color": "5", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + }, + { + "id": "L9", + "nickname": "", + "invariant": "", + "type": "NORMAL", + "urgency": "NORMAL", + "x": 223.07693307692307, + "y": 211.9230769230769, + "color": "5", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + }, + { + "id": "L10", + "nickname": "", + "invariant": "", + "type": "NORMAL", + "urgency": "NORMAL", + "x": 385.76924076923075, + "y": 280.0, + "color": "5", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + } + ], + "edges": [ + { + "id": "E8", + "group": "", + "sourceLocation": "L8", + "targetLocation": "L7", + "status": "OUTPUT", + "select": "", + "guard": "", + "update": "h \u003d 0 ", + "sync": "output2", + "isLocked": false, + "nails": [ + { + "x": 207.3076923076923, + "y": 343.46153846153845, + "propertyType": "SYNCHRONIZATION", + "propertyX": -30.0, + "propertyY": 30.0 + }, + { + "x": 140.0, + "y": 310.0, + "propertyType": "UPDATE", + "propertyX": -59.999999999999986, + "propertyY": 29.999999999999996 + } + ] + }, + { + "id": "E9", + "group": "", + "sourceLocation": "L7", + "targetLocation": "L9", + "status": "INPUT", + "select": "", + "guard": "h \u003e 3 || k \u003e 5", + "update": "", + "sync": "input1", + "isLocked": false, + "nails": [ + { + "x": 130.0, + "y": 250.0, + "propertyType": "GUARD", + "propertyX": -50.0, + "propertyY": -40.0 + }, + { + "x": 175.0, + "y": 235.38461538461536, + "propertyType": "SYNCHRONIZATION", + "propertyX": -10.0, + "propertyY": -49.999999999999986 + } + ] + }, + { + "id": "E10", + "group": "", + "sourceLocation": "L9", + "targetLocation": "L8", + "status": "OUTPUT", + "select": "", + "guard": "h \u003e 10", + "update": "", + "sync": "output1", + "isLocked": false, + "nails": [ + { + "x": 239.99999999999997, + "y": 250.0, + "propertyType": "GUARD", + "propertyX": 10.0, + "propertyY": 0.0 + }, + { + "x": 245.38461538461536, + "y": 310.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": 20.0, + "propertyY": -20.0 + } + ] + }, + { + "id": "E11", + "group": "", + "sourceLocation": "L8", + "targetLocation": "L10", + "status": "OUTPUT", + "select": "", + "guard": "k \u003e 11", + "update": "", + "sync": "output3", + "isLocked": false, + "nails": [ + { + "x": 310.0, + "y": 350.0, + "propertyType": "GUARD", + "propertyX": 0.0, + "propertyY": 20.0 + }, + { + "x": 341.15384615384613, + "y": 323.46153846153845, + "propertyType": "SYNCHRONIZATION", + "propertyX": 10.0, + "propertyY": 0.0 + } + ] + }, + { + "id": "E12", + "group": "", + "sourceLocation": "L9", + "targetLocation": "L9", + "status": "OUTPUT", + "select": "", + "guard": "", + "update": "j \u003d 0", + "sync": "output3", + "isLocked": false, + "nails": [ + { + "x": 243.07693307692307, + "y": 131.9230769230769, + "propertyType": "SYNCHRONIZATION", + "propertyX": -19.999999999999996, + "propertyY": -40.0 + }, + { + "x": 320.0, + "y": 150.0, + "propertyType": "UPDATE", + "propertyX": 10.0, + "propertyY": 0.0 + }, + { + "x": 343.07693307692307, + "y": 221.9230769230769, + "propertyType": "NONE", + "propertyX": 0.0, + "propertyY": 0.0 + } + ] + } + ], + "description": "", + "x": 137.5, + "y": 102.0, + "width": 450.0, + "height": 600.0, + "color": "5", + "includeInPeriodicCheck": true +} \ No newline at end of file diff --git a/samples/json/PopulateClocks/Components/Component7_global_clocks.json b/samples/json/PopulateClocks/Components/Component7_global_clocks.json new file mode 100644 index 00000000..68f3bfb1 --- /dev/null +++ b/samples/json/PopulateClocks/Components/Component7_global_clocks.json @@ -0,0 +1,183 @@ +{ + "name": "Component7_global_clocks", + "declarations": "clock x, y, z;", + "locations": [ + { + "id": "L16", + "nickname": "", + "invariant": "", + "type": "INITIAL", + "urgency": "NORMAL", + "x": 95.00000000000001, + "y": 290.0, + "color": "8", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + }, + { + "id": "L17", + "nickname": "", + "invariant": "", + "type": "NORMAL", + "urgency": "NORMAL", + "x": 270.00001, + "y": 289.4, + "color": "8", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + }, + { + "id": "L18", + "nickname": "", + "invariant": "", + "type": "NORMAL", + "urgency": "NORMAL", + "x": 200.00001, + "y": 379.4, + "color": "8", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + }, + { + "id": "L19", + "nickname": "", + "invariant": "", + "type": "NORMAL", + "urgency": "NORMAL", + "x": 410.00001, + "y": 295.20000000000005, + "color": "8", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + } + ], + "edges": [ + { + "id": "E9", + "group": "", + "sourceLocation": "L16", + "targetLocation": "L17", + "status": "INPUT", + "select": "", + "guard": "x\u003e10", + "update": "", + "sync": "", + "isLocked": false, + "nails": [ + { + "x": 139.99999999999994, + "y": 270.0, + "propertyType": "GUARD", + "propertyX": 10.000000000000057, + "propertyY": -40.0 + }, + { + "x": 182.06666666666666, + "y": 286.8, + "propertyType": "SYNCHRONIZATION", + "propertyX": 10.0, + "propertyY": 0.0 + } + ] + }, + { + "id": "E10", + "group": "", + "sourceLocation": "L17", + "targetLocation": "L19", + "status": "INPUT", + "select": "", + "guard": "x\u003c5", + "update": "", + "sync": "", + "isLocked": false, + "nails": [ + { + "x": 289.99999999999994, + "y": 240.0, + "propertyType": "GUARD", + "propertyX": 10.0, + "propertyY": 0.0 + }, + { + "x": 349.1666666666667, + "y": 264.43333333333334, + "propertyType": "SYNCHRONIZATION", + "propertyX": 10.0, + "propertyY": 0.0 + } + ] + }, + { + "id": "E11", + "group": "", + "sourceLocation": "L16", + "targetLocation": "L18", + "status": "INPUT", + "select": "", + "guard": "y\u003e5", + "update": "", + "sync": "", + "isLocked": false, + "nails": [ + { + "x": 119.99999999999994, + "y": 350.0, + "propertyType": "GUARD", + "propertyX": 10.0, + "propertyY": 0.0 + }, + { + "x": 160.76666666666668, + "y": 333.90000000000003, + "propertyType": "SYNCHRONIZATION", + "propertyX": 10.0, + "propertyY": 0.0 + } + ] + }, + { + "id": "E12", + "group": "", + "sourceLocation": "L18", + "targetLocation": "L17", + "status": "INPUT", + "select": "", + "guard": "z\u003e5", + "update": "", + "sync": "", + "isLocked": false, + "nails": [ + { + "x": 249.99999999999994, + "y": 370.0, + "propertyType": "GUARD", + "propertyX": 30.00000000000003, + "propertyY": 0.0 + }, + { + "x": 259.7, + "y": 346.26666666666665, + "propertyType": "SYNCHRONIZATION", + "propertyX": 10.0, + "propertyY": 0.0 + } + ] + } + ], + "description": "", + "x": 65.0, + "y": 14.5, + "width": 450.0, + "height": 600.0, + "color": "8", + "includeInPeriodicCheck": true +} \ No newline at end of file diff --git a/samples/json/PopulateClocks/Components/Component7_global_groups.json b/samples/json/PopulateClocks/Components/Component7_global_groups.json new file mode 100644 index 00000000..2f5c2f86 --- /dev/null +++ b/samples/json/PopulateClocks/Components/Component7_global_groups.json @@ -0,0 +1,183 @@ +{ + "name": "Component7_global_groups", + "declarations": "clock x, y, z;", + "locations": [ + { + "id": "L16", + "nickname": "", + "invariant": "", + "type": "INITIAL", + "urgency": "NORMAL", + "x": 95.00000000000001, + "y": 290.0, + "color": "8", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + }, + { + "id": "L17", + "nickname": "", + "invariant": "", + "type": "NORMAL", + "urgency": "NORMAL", + "x": 270.00001, + "y": 289.4, + "color": "8", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + }, + { + "id": "L18", + "nickname": "", + "invariant": "", + "type": "NORMAL", + "urgency": "NORMAL", + "x": 200.00001, + "y": 379.4, + "color": "8", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + }, + { + "id": "L19", + "nickname": "", + "invariant": "", + "type": "NORMAL", + "urgency": "NORMAL", + "x": 410.00001, + "y": 295.20000000000005, + "color": "8", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + } + ], + "edges": [ + { + "id": "E9", + "group": "", + "sourceLocation": "L16", + "targetLocation": "L17", + "status": "INPUT", + "select": "", + "guard": "x\u003e10", + "update": "", + "sync": "", + "isLocked": false, + "nails": [ + { + "x": 139.99999999999994, + "y": 270.0, + "propertyType": "GUARD", + "propertyX": 10.000000000000057, + "propertyY": -40.0 + }, + { + "x": 182.06666666666666, + "y": 286.8, + "propertyType": "SYNCHRONIZATION", + "propertyX": 10.0, + "propertyY": 0.0 + } + ] + }, + { + "id": "E10", + "group": "", + "sourceLocation": "L17", + "targetLocation": "L19", + "status": "INPUT", + "select": "", + "guard": "x\u003c5", + "update": "", + "sync": "", + "isLocked": false, + "nails": [ + { + "x": 289.99999999999994, + "y": 240.0, + "propertyType": "GUARD", + "propertyX": 10.0, + "propertyY": 0.0 + }, + { + "x": 349.1666666666667, + "y": 264.43333333333334, + "propertyType": "SYNCHRONIZATION", + "propertyX": 10.0, + "propertyY": 0.0 + } + ] + }, + { + "id": "E11", + "group": "", + "sourceLocation": "L16", + "targetLocation": "L18", + "status": "INPUT", + "select": "", + "guard": "y\u003e5", + "update": "", + "sync": "", + "isLocked": false, + "nails": [ + { + "x": 119.99999999999994, + "y": 350.0, + "propertyType": "GUARD", + "propertyX": 10.0, + "propertyY": 0.0 + }, + { + "x": 160.76666666666668, + "y": 333.90000000000003, + "propertyType": "SYNCHRONIZATION", + "propertyX": 10.0, + "propertyY": 0.0 + } + ] + }, + { + "id": "E12", + "group": "", + "sourceLocation": "L18", + "targetLocation": "L17", + "status": "INPUT", + "select": "", + "guard": "", + "update": "y \u003d 0, z \u003d 0", + "sync": "", + "isLocked": false, + "nails": [ + { + "x": 249.99999999999994, + "y": 370.0, + "propertyType": "GUARD", + "propertyX": 30.00000000000003, + "propertyY": 0.0 + }, + { + "x": 259.7, + "y": 346.26666666666665, + "propertyType": "SYNCHRONIZATION", + "propertyX": 10.0, + "propertyY": 0.0 + } + ] + } + ], + "description": "", + "x": 65.0, + "y": 14.5, + "width": 450.0, + "height": 600.0, + "color": "8", + "includeInPeriodicCheck": true +} \ No newline at end of file diff --git a/samples/json/PopulateClocks/Components/Machine.json b/samples/json/PopulateClocks/Components/Machine.json new file mode 100644 index 00000000..9ff047a4 --- /dev/null +++ b/samples/json/PopulateClocks/Components/Machine.json @@ -0,0 +1,176 @@ +{ + "name": "Machine", + "declarations": "clock y;", + "locations": [ + { + "id": "L4", + "nickname": "", + "invariant": "y\u003c\u003d6", + "type": "NORMAL", + "urgency": "NORMAL", + "x": 140.0, + "y": 300.0, + "color": "7", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": -10.0 + }, + { + "id": "L5", + "nickname": "", + "invariant": "", + "type": "INITIAL", + "urgency": "NORMAL", + "x": 140.0, + "y": 100.0, + "color": "7", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + } + ], + "edges": [ + { + "id": "E25", + "group": "", + "sourceLocation": "L4", + "targetLocation": "L5", + "status": "OUTPUT", + "select": "", + "guard": "y\u003e\u003d4", + "update": "", + "sync": "cof", + "isLocked": false, + "nails": [ + { + "x": 100.0, + "y": 230.0, + "propertyType": "GUARD", + "propertyX": -70.0, + "propertyY": -10.0 + }, + { + "x": 100.0, + "y": 180.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": -70.0, + "propertyY": -10.0 + } + ] + }, + { + "id": "E26", + "group": "", + "sourceLocation": "L4", + "targetLocation": "L5", + "status": "OUTPUT", + "select": "", + "guard": "", + "update": "", + "sync": "tea", + "isLocked": false, + "nails": [ + { + "x": 210.0, + "y": 200.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": 20.0, + "propertyY": -10.0 + } + ] + }, + { + "id": "E27", + "group": "", + "sourceLocation": "L5", + "targetLocation": "L4", + "status": "INPUT", + "select": "", + "guard": "", + "update": "y\u003d0", + "sync": "coin", + "isLocked": false, + "nails": [ + { + "x": 140.0, + "y": 220.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": 20.0, + "propertyY": -10.0 + }, + { + "x": 140.0, + "y": 190.0, + "propertyType": "UPDATE", + "propertyX": 10.0, + "propertyY": -10.0 + } + ] + }, + { + "id": "E28", + "group": "", + "sourceLocation": "L4", + "targetLocation": "L4", + "status": "INPUT", + "select": "", + "guard": "", + "update": "", + "sync": "coin", + "isLocked": false, + "nails": [ + { + "x": 130.0, + "y": 350.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": -60.0, + "propertyY": -10.0 + }, + { + "x": 160.0, + "y": 350.0, + "propertyType": "NONE", + "propertyX": 0.0, + "propertyY": 0.0 + } + ] + }, + { + "id": "E29", + "group": "", + "sourceLocation": "L5", + "targetLocation": "L5", + "status": "OUTPUT", + "select": "", + "guard": "y\u003e\u003d2", + "update": "", + "sync": "tea", + "isLocked": false, + "nails": [ + { + "x": 170.0, + "y": 60.0, + "propertyType": "GUARD", + "propertyX": 10.0, + "propertyY": -20.0 + }, + { + "x": 140.0, + "y": 60.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": -20.0, + "propertyY": -30.0 + } + ] + } + ], + "description": "", + "x": 5.0, + "y": 5.0, + "width": 300.0, + "height": 390.0, + "color": "7", + "includeInPeriodicCheck": false +} \ No newline at end of file diff --git a/samples/json/PopulateClocks/Components/Machine4.json b/samples/json/PopulateClocks/Components/Machine4.json new file mode 100644 index 00000000..34461b0d --- /dev/null +++ b/samples/json/PopulateClocks/Components/Machine4.json @@ -0,0 +1,176 @@ +{ + "name": "Machine4", + "declarations": "clock y;", + "locations": [ + { + "id": "L4", + "nickname": "", + "invariant": "y\u003c\u003d6", + "type": "NORMAL", + "urgency": "NORMAL", + "x": 140.0, + "y": 300.0, + "color": "7", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": -10.0 + }, + { + "id": "L5", + "nickname": "", + "invariant": "", + "type": "INITIAL", + "urgency": "NORMAL", + "x": 140.0, + "y": 100.0, + "color": "7", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + } + ], + "edges": [ + { + "id": "E1", + "group": "", + "sourceLocation": "L4", + "targetLocation": "L5", + "status": "OUTPUT", + "select": "", + "guard": "y\u003e\u003d4", + "update": "", + "sync": "cof", + "isLocked": false, + "nails": [ + { + "x": 100.0, + "y": 230.0, + "propertyType": "GUARD", + "propertyX": -70.0, + "propertyY": -10.0 + }, + { + "x": 100.0, + "y": 180.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": -70.0, + "propertyY": -10.0 + } + ] + }, + { + "id": "E2", + "group": "", + "sourceLocation": "L4", + "targetLocation": "L5", + "status": "OUTPUT", + "select": "", + "guard": "", + "update": "", + "sync": "tea", + "isLocked": false, + "nails": [ + { + "x": 210.0, + "y": 200.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": 20.0, + "propertyY": -10.0 + } + ] + }, + { + "id": "E3", + "group": "", + "sourceLocation": "L5", + "targetLocation": "L4", + "status": "INPUT", + "select": "", + "guard": "", + "update": "y\u003d0", + "sync": "coin", + "isLocked": false, + "nails": [ + { + "x": 140.0, + "y": 220.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": 20.0, + "propertyY": -10.0 + }, + { + "x": 140.0, + "y": 190.0, + "propertyType": "UPDATE", + "propertyX": 10.0, + "propertyY": -10.0 + } + ] + }, + { + "id": "E4", + "group": "", + "sourceLocation": "L4", + "targetLocation": "L4", + "status": "INPUT", + "select": "", + "guard": "", + "update": "", + "sync": "coin", + "isLocked": false, + "nails": [ + { + "x": 130.0, + "y": 350.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": -60.0, + "propertyY": -10.0 + }, + { + "x": 160.0, + "y": 350.0, + "propertyType": "NONE", + "propertyX": 0.0, + "propertyY": 0.0 + } + ] + }, + { + "id": "E5", + "group": "", + "sourceLocation": "L5", + "targetLocation": "L5", + "status": "OUTPUT", + "select": "", + "guard": "y\u003c0", + "update": "", + "sync": "tea", + "isLocked": false, + "nails": [ + { + "x": 170.0, + "y": 60.0, + "propertyType": "GUARD", + "propertyX": 10.0, + "propertyY": -20.0 + }, + { + "x": 140.0, + "y": 60.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": -20.0, + "propertyY": -30.0 + } + ] + } + ], + "description": "", + "x": 5.0, + "y": 5.0, + "width": 300.0, + "height": 390.0, + "color": "7", + "includeInPeriodicCheck": false +} \ No newline at end of file diff --git a/samples/json/PopulateClocks/Components/Researcher2.json b/samples/json/PopulateClocks/Components/Researcher2.json new file mode 100644 index 00000000..6c492b52 --- /dev/null +++ b/samples/json/PopulateClocks/Components/Researcher2.json @@ -0,0 +1,414 @@ +{ + "name": "Researcher2", + "declarations": "clock x, y, z, k;", + "locations": [ + { + "id": "L7", + "nickname": "", + "invariant": "x \u003c\u003d8", + "type": "NORMAL", + "urgency": "NORMAL", + "x": 310.0, + "y": 300.0, + "color": "8", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": -20.0, + "invariantY": 30.0 + }, + { + "id": "L9", + "nickname": "", + "invariant": "x\u003c\u003d4", + "type": "NORMAL", + "urgency": "NORMAL", + "x": 110.0, + "y": 130.0, + "color": "8", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 10.0, + "invariantY": 20.0 + }, + { + "id": "L6", + "nickname": "", + "invariant": "", + "type": "INITIAL", + "urgency": "NORMAL", + "x": 310.0, + "y": 130.0, + "color": "8", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + }, + { + "id": "U0", + "nickname": "", + "invariant": "", + "type": "UNIVERSAL", + "urgency": "NORMAL", + "x": 450.0, + "y": 130.0, + "color": "8", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + } + ], + "edges": [ + { + "id": "E6", + "group": "", + "sourceLocation": "L9", + "targetLocation": "L9", + "status": "INPUT", + "select": "", + "guard": "", + "update": "", + "sync": "cof", + "isLocked": false, + "nails": [ + { + "x": 70.0, + "y": 110.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": -50.0, + "propertyY": -20.0 + }, + { + "x": 70.0, + "y": 130.0, + "propertyType": "NONE", + "propertyX": 0.0, + "propertyY": 0.0 + } + ] + }, + { + "id": "E7", + "group": "", + "sourceLocation": "L9", + "targetLocation": "L9", + "status": "INPUT", + "select": "", + "guard": "", + "update": "", + "sync": "tea", + "isLocked": false, + "nails": [ + { + "x": 90.0, + "y": 170.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": -20.0, + "propertyY": 10.0 + }, + { + "x": 110.0, + "y": 170.0, + "propertyType": "NONE", + "propertyX": 0.0, + "propertyY": 0.0 + } + ] + }, + { + "id": "E8", + "group": "", + "sourceLocation": "L7", + "targetLocation": "L7", + "status": "INPUT", + "select": "", + "guard": "", + "update": "", + "sync": "cof", + "isLocked": false, + "nails": [ + { + "x": 270.0, + "y": 300.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": -60.0, + "propertyY": -10.0 + }, + { + "x": 270.0, + "y": 320.0, + "propertyType": "NONE", + "propertyX": 0.0, + "propertyY": 0.0 + } + ] + }, + { + "id": "E9", + "group": "", + "sourceLocation": "L7", + "targetLocation": "L7", + "status": "INPUT", + "select": "", + "guard": "", + "update": "", + "sync": "tea", + "isLocked": false, + "nails": [ + { + "x": 350.0, + "y": 320.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": 20.0, + "propertyY": -10.0 + }, + { + "x": 350.0, + "y": 300.0, + "propertyType": "NONE", + "propertyX": 0.0, + "propertyY": 0.0 + } + ] + }, + { + "id": "E10", + "group": "", + "sourceLocation": "L6", + "targetLocation": "L9", + "status": "INPUT", + "select": "", + "guard": "", + "update": "x\u003d0", + "sync": "cof", + "isLocked": false, + "nails": [ + { + "x": 240.0, + "y": 140.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": -20.0, + "propertyY": 10.0 + }, + { + "x": 200.0, + "y": 140.0, + "propertyType": "UPDATE", + "propertyX": -20.0, + "propertyY": 10.0 + } + ] + }, + { + "id": "E11", + "group": "", + "sourceLocation": "L6", + "targetLocation": "L7", + "status": "INPUT", + "select": "", + "guard": "x\u003c\u003d15", + "update": "x\u003d0", + "sync": "tea", + "isLocked": false, + "nails": [ + { + "x": 290.0, + "y": 200.0, + "propertyType": "GUARD", + "propertyX": -70.0, + "propertyY": -10.0 + }, + { + "x": 290.0, + "y": 220.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": -70.0, + "propertyY": -10.0 + }, + { + "x": 290.0, + "y": 240.0, + "propertyType": "UPDATE", + "propertyX": -70.0, + "propertyY": -10.0 + } + ] + }, + { + "id": "E12", + "group": "", + "sourceLocation": "L9", + "targetLocation": "L6", + "status": "OUTPUT", + "select": "", + "guard": "x\u003e\u003d2", + "update": "x\u003d0", + "sync": "pub", + "isLocked": false, + "nails": [ + { + "x": 170.0, + "y": 110.0, + "propertyType": "GUARD", + "propertyX": -40.0, + "propertyY": -40.0 + }, + { + "x": 200.0, + "y": 110.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": -20.0, + "propertyY": -40.0 + }, + { + "x": 240.0, + "y": 110.0, + "propertyType": "UPDATE", + "propertyX": -20.0, + "propertyY": -40.0 + } + ] + }, + { + "id": "E13", + "group": "", + "sourceLocation": "L7", + "targetLocation": "L6", + "status": "OUTPUT", + "select": "", + "guard": "x\u003e\u003d4", + "update": "x\u003d0", + "sync": "pub", + "isLocked": false, + "nails": [ + { + "x": 340.0, + "y": 240.0, + "propertyType": "GUARD", + "propertyX": 10.0, + "propertyY": -10.0 + }, + { + "x": 340.0, + "y": 220.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": 10.0, + "propertyY": -10.0 + }, + { + "x": 330.0, + "y": 200.0, + "propertyType": "UPDATE", + "propertyX": 20.0, + "propertyY": -10.0 + } + ] + }, + { + "id": "E14", + "group": "", + "sourceLocation": "U0", + "targetLocation": "U0", + "status": "INPUT", + "select": "", + "guard": "", + "update": "", + "sync": "*", + "isLocked": true, + "nails": [ + { + "x": 410.0, + "y": 120.0, + "propertyType": "NONE", + "propertyX": 0.0, + "propertyY": 0.0 + }, + { + "x": 390.0, + "y": 130.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": -30.0, + "propertyY": -10.0 + }, + { + "x": 410.0, + "y": 140.0, + "propertyType": "NONE", + "propertyX": 0.0, + "propertyY": 0.0 + } + ] + }, + { + "id": "E15", + "group": "", + "sourceLocation": "U0", + "targetLocation": "U0", + "status": "OUTPUT", + "select": "", + "guard": "", + "update": "", + "sync": "*", + "isLocked": true, + "nails": [ + { + "x": 490.0, + "y": 120.0, + "propertyType": "NONE", + "propertyX": 0.0, + "propertyY": 0.0 + }, + { + "x": 510.0, + "y": 130.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": 10.0, + "propertyY": -10.0 + }, + { + "x": 490.0, + "y": 140.0, + "propertyType": "NONE", + "propertyX": 0.0, + "propertyY": 0.0 + } + ] + }, + { + "id": "E16", + "group": "", + "sourceLocation": "L6", + "targetLocation": "U0", + "status": "INPUT", + "select": "", + "guard": "x\u003e15", + "update": "", + "sync": "tea", + "isLocked": false, + "nails": [ + { + "x": 350.0, + "y": 90.0, + "propertyType": "GUARD", + "propertyX": -20.0, + "propertyY": -40.0 + }, + { + "x": 400.0, + "y": 90.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": -20.0, + "propertyY": -40.0 + } + ] + } + ], + "description": "", + "x": 5.0, + "y": 5.0, + "width": 560.0, + "height": 360.0, + "color": "8", + "includeInPeriodicCheck": false +} \ No newline at end of file diff --git a/samples/json/PopulateClocks/Components/Update.json b/samples/json/PopulateClocks/Components/Update.json new file mode 100644 index 00000000..f9101541 --- /dev/null +++ b/samples/json/PopulateClocks/Components/Update.json @@ -0,0 +1,176 @@ +{ + "name": "Update", + "declarations": "clock y, x;", + "locations": [ + { + "id": "L4", + "nickname": "", + "invariant": "y\u003c\u003d6", + "type": "NORMAL", + "urgency": "NORMAL", + "x": 140.0, + "y": 300.0, + "color": "7", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": -10.0 + }, + { + "id": "L5", + "nickname": "", + "invariant": "", + "type": "INITIAL", + "urgency": "NORMAL", + "x": 140.0, + "y": 100.0, + "color": "7", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + } + ], + "edges": [ + { + "id": "E25", + "group": "", + "sourceLocation": "L4", + "targetLocation": "L5", + "status": "OUTPUT", + "select": "", + "guard": "y\u003e\u003d4", + "update": "", + "sync": "cof", + "isLocked": false, + "nails": [ + { + "x": 100.0, + "y": 230.0, + "propertyType": "GUARD", + "propertyX": -70.0, + "propertyY": -10.0 + }, + { + "x": 100.0, + "y": 180.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": -70.0, + "propertyY": -10.0 + } + ] + }, + { + "id": "E26", + "group": "", + "sourceLocation": "L4", + "targetLocation": "L5", + "status": "OUTPUT", + "select": "", + "guard": "", + "update": "", + "sync": "tea", + "isLocked": false, + "nails": [ + { + "x": 210.0, + "y": 200.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": 20.0, + "propertyY": -10.0 + } + ] + }, + { + "id": "E27", + "group": "", + "sourceLocation": "L5", + "targetLocation": "L4", + "status": "INPUT", + "select": "", + "guard": "", + "update": "y\u003dx", + "sync": "coin", + "isLocked": false, + "nails": [ + { + "x": 140.0, + "y": 220.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": 20.0, + "propertyY": -10.0 + }, + { + "x": 140.0, + "y": 190.0, + "propertyType": "UPDATE", + "propertyX": 10.0, + "propertyY": -10.0 + } + ] + }, + { + "id": "E28", + "group": "", + "sourceLocation": "L4", + "targetLocation": "L4", + "status": "INPUT", + "select": "", + "guard": "", + "update": "", + "sync": "coin", + "isLocked": false, + "nails": [ + { + "x": 130.0, + "y": 350.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": -60.0, + "propertyY": -10.0 + }, + { + "x": 160.0, + "y": 350.0, + "propertyType": "NONE", + "propertyX": 0.0, + "propertyY": 0.0 + } + ] + }, + { + "id": "E29", + "group": "", + "sourceLocation": "L5", + "targetLocation": "L5", + "status": "OUTPUT", + "select": "", + "guard": "y\u003e\u003d2", + "update": "", + "sync": "tea", + "isLocked": false, + "nails": [ + { + "x": 170.0, + "y": 60.0, + "propertyType": "GUARD", + "propertyX": 10.0, + "propertyY": -20.0 + }, + { + "x": 140.0, + "y": 60.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": -20.0, + "propertyY": -30.0 + } + ] + } + ], + "description": "", + "x": 5.0, + "y": 5.0, + "width": 300.0, + "height": 390.0, + "color": "7", + "includeInPeriodicCheck": false +} \ No newline at end of file diff --git a/samples/json/PopulateClocks/Components/Updates1.json b/samples/json/PopulateClocks/Components/Updates1.json new file mode 100644 index 00000000..efa3383b --- /dev/null +++ b/samples/json/PopulateClocks/Components/Updates1.json @@ -0,0 +1,183 @@ +{ + "name": "Updates1", + "declarations": "clock x, y, z;", + "locations": [ + { + "id": "L16", + "nickname": "", + "invariant": "", + "type": "INITIAL", + "urgency": "NORMAL", + "x": 95.00000000000001, + "y": 290.0, + "color": "8", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + }, + { + "id": "L17", + "nickname": "", + "invariant": "", + "type": "NORMAL", + "urgency": "NORMAL", + "x": 270.00001, + "y": 289.4, + "color": "8", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + }, + { + "id": "L18", + "nickname": "", + "invariant": "", + "type": "NORMAL", + "urgency": "NORMAL", + "x": 200.00001, + "y": 379.4, + "color": "8", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + }, + { + "id": "L19", + "nickname": "", + "invariant": "", + "type": "NORMAL", + "urgency": "NORMAL", + "x": 410.00001, + "y": 295.20000000000005, + "color": "8", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + } + ], + "edges": [ + { + "id": "E9", + "group": "", + "sourceLocation": "L16", + "targetLocation": "L17", + "status": "INPUT", + "select": "", + "guard": "x\u003e10", + "update": "", + "sync": "", + "isLocked": false, + "nails": [ + { + "x": 139.99999999999994, + "y": 270.0, + "propertyType": "GUARD", + "propertyX": 10.000000000000057, + "propertyY": -40.0 + }, + { + "x": 182.06666666666666, + "y": 286.8, + "propertyType": "SYNCHRONIZATION", + "propertyX": 10.0, + "propertyY": 0.0 + } + ] + }, + { + "id": "E10", + "group": "", + "sourceLocation": "L17", + "targetLocation": "L19", + "status": "INPUT", + "select": "", + "guard": "x\u003c5", + "update": "", + "sync": "", + "isLocked": false, + "nails": [ + { + "x": 289.99999999999994, + "y": 240.0, + "propertyType": "GUARD", + "propertyX": 10.0, + "propertyY": 0.0 + }, + { + "x": 349.1666666666667, + "y": 264.43333333333334, + "propertyType": "SYNCHRONIZATION", + "propertyX": 10.0, + "propertyY": 0.0 + } + ] + }, + { + "id": "E11", + "group": "", + "sourceLocation": "L16", + "targetLocation": "L18", + "status": "INPUT", + "select": "", + "guard": "y\u003e5", + "update": "", + "sync": "", + "isLocked": false, + "nails": [ + { + "x": 119.99999999999994, + "y": 350.0, + "propertyType": "GUARD", + "propertyX": 10.0, + "propertyY": 0.0 + }, + { + "x": 160.76666666666668, + "y": 333.90000000000003, + "propertyType": "SYNCHRONIZATION", + "propertyX": 10.0, + "propertyY": 0.0 + } + ] + }, + { + "id": "E12", + "group": "", + "sourceLocation": "L18", + "targetLocation": "L17", + "status": "INPUT", + "select": "", + "guard": "", + "update": "y \u003d 0, z \u003d 0", + "sync": "", + "isLocked": false, + "nails": [ + { + "x": 249.99999999999994, + "y": 370.0, + "propertyType": "GUARD", + "propertyX": 30.00000000000003, + "propertyY": 0.0 + }, + { + "x": 259.7, + "y": 346.26666666666665, + "propertyType": "SYNCHRONIZATION", + "propertyX": 10.0, + "propertyY": 0.0 + } + ] + } + ], + "description": "", + "x": 65.0, + "y": 14.5, + "width": 450.0, + "height": 600.0, + "color": "8", + "includeInPeriodicCheck": true +} \ No newline at end of file diff --git a/samples/json/PopulateClocks/Components/Updates2.json b/samples/json/PopulateClocks/Components/Updates2.json new file mode 100644 index 00000000..d3349a84 --- /dev/null +++ b/samples/json/PopulateClocks/Components/Updates2.json @@ -0,0 +1,183 @@ +{ + "name": "Updates2", + "declarations": "clock x, y, z;", + "locations": [ + { + "id": "L16", + "nickname": "", + "invariant": "", + "type": "INITIAL", + "urgency": "NORMAL", + "x": 95.00000000000001, + "y": 290.0, + "color": "8", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + }, + { + "id": "L17", + "nickname": "", + "invariant": "", + "type": "NORMAL", + "urgency": "NORMAL", + "x": 270.00001, + "y": 289.4, + "color": "8", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + }, + { + "id": "L18", + "nickname": "", + "invariant": "", + "type": "NORMAL", + "urgency": "NORMAL", + "x": 200.00001, + "y": 379.4, + "color": "8", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + }, + { + "id": "L19", + "nickname": "", + "invariant": "", + "type": "NORMAL", + "urgency": "NORMAL", + "x": 410.00001, + "y": 295.20000000000005, + "color": "8", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + } + ], + "edges": [ + { + "id": "E9", + "group": "", + "sourceLocation": "L16", + "targetLocation": "L17", + "status": "INPUT", + "select": "", + "guard": "x\u003e10", + "update": "", + "sync": "", + "isLocked": false, + "nails": [ + { + "x": 139.99999999999994, + "y": 270.0, + "propertyType": "GUARD", + "propertyX": 10.000000000000057, + "propertyY": -40.0 + }, + { + "x": 182.06666666666666, + "y": 286.8, + "propertyType": "SYNCHRONIZATION", + "propertyX": 10.0, + "propertyY": 0.0 + } + ] + }, + { + "id": "E10", + "group": "", + "sourceLocation": "L17", + "targetLocation": "L19", + "status": "INPUT", + "select": "", + "guard": "x\u003c5", + "update": "", + "sync": "", + "isLocked": false, + "nails": [ + { + "x": 289.99999999999994, + "y": 240.0, + "propertyType": "GUARD", + "propertyX": 10.0, + "propertyY": 0.0 + }, + { + "x": 349.1666666666667, + "y": 264.43333333333334, + "propertyType": "SYNCHRONIZATION", + "propertyX": 10.0, + "propertyY": 0.0 + } + ] + }, + { + "id": "E11", + "group": "", + "sourceLocation": "L16", + "targetLocation": "L18", + "status": "INPUT", + "select": "", + "guard": "y\u003e5", + "update": "", + "sync": "", + "isLocked": false, + "nails": [ + { + "x": 119.99999999999994, + "y": 350.0, + "propertyType": "GUARD", + "propertyX": 10.0, + "propertyY": 0.0 + }, + { + "x": 160.76666666666668, + "y": 333.90000000000003, + "propertyType": "SYNCHRONIZATION", + "propertyX": 10.0, + "propertyY": 0.0 + } + ] + }, + { + "id": "E12", + "group": "", + "sourceLocation": "L18", + "targetLocation": "L17", + "status": "INPUT", + "select": "", + "guard": "", + "update": "y \u003d 3, z \u003d 4", + "sync": "", + "isLocked": false, + "nails": [ + { + "x": 249.99999999999994, + "y": 370.0, + "propertyType": "GUARD", + "propertyX": 30.00000000000003, + "propertyY": 0.0 + }, + { + "x": 259.7, + "y": 346.26666666666665, + "propertyType": "SYNCHRONIZATION", + "propertyX": 10.0, + "propertyY": 0.0 + } + ] + } + ], + "description": "", + "x": 65.0, + "y": 14.5, + "width": 450.0, + "height": 600.0, + "color": "8", + "includeInPeriodicCheck": true +} \ No newline at end of file diff --git a/samples/json/PopulateClocks/Components/Updates3.json b/samples/json/PopulateClocks/Components/Updates3.json new file mode 100644 index 00000000..854ec0ea --- /dev/null +++ b/samples/json/PopulateClocks/Components/Updates3.json @@ -0,0 +1,183 @@ +{ + "name": "Updates3", + "declarations": "clock x, y, z;", + "locations": [ + { + "id": "L16", + "nickname": "", + "invariant": "", + "type": "INITIAL", + "urgency": "NORMAL", + "x": 95.00000000000001, + "y": 290.0, + "color": "8", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + }, + { + "id": "L17", + "nickname": "", + "invariant": "", + "type": "NORMAL", + "urgency": "NORMAL", + "x": 270.00001, + "y": 289.4, + "color": "8", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + }, + { + "id": "L18", + "nickname": "", + "invariant": "", + "type": "NORMAL", + "urgency": "NORMAL", + "x": 200.00001, + "y": 379.4, + "color": "8", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + }, + { + "id": "L19", + "nickname": "", + "invariant": "", + "type": "NORMAL", + "urgency": "NORMAL", + "x": 410.00001, + "y": 295.20000000000005, + "color": "8", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + } + ], + "edges": [ + { + "id": "E9", + "group": "", + "sourceLocation": "L16", + "targetLocation": "L17", + "status": "INPUT", + "select": "", + "guard": "x\u003e10", + "update": "", + "sync": "", + "isLocked": false, + "nails": [ + { + "x": 139.99999999999994, + "y": 270.0, + "propertyType": "GUARD", + "propertyX": 10.000000000000057, + "propertyY": -40.0 + }, + { + "x": 182.06666666666666, + "y": 286.8, + "propertyType": "SYNCHRONIZATION", + "propertyX": 10.0, + "propertyY": 0.0 + } + ] + }, + { + "id": "E10", + "group": "", + "sourceLocation": "L17", + "targetLocation": "L19", + "status": "INPUT", + "select": "", + "guard": "x\u003c5", + "update": "", + "sync": "", + "isLocked": false, + "nails": [ + { + "x": 289.99999999999994, + "y": 240.0, + "propertyType": "GUARD", + "propertyX": 10.0, + "propertyY": 0.0 + }, + { + "x": 349.1666666666667, + "y": 264.43333333333334, + "propertyType": "SYNCHRONIZATION", + "propertyX": 10.0, + "propertyY": 0.0 + } + ] + }, + { + "id": "E11", + "group": "", + "sourceLocation": "L16", + "targetLocation": "L18", + "status": "INPUT", + "select": "", + "guard": "y\u003e5", + "update": "", + "sync": "", + "isLocked": false, + "nails": [ + { + "x": 119.99999999999994, + "y": 350.0, + "propertyType": "GUARD", + "propertyX": 10.0, + "propertyY": 0.0 + }, + { + "x": 160.76666666666668, + "y": 333.90000000000003, + "propertyType": "SYNCHRONIZATION", + "propertyX": 10.0, + "propertyY": 0.0 + } + ] + }, + { + "id": "E12", + "group": "", + "sourceLocation": "L18", + "targetLocation": "L17", + "status": "INPUT", + "select": "", + "guard": "", + "update": "y \u003d 3+4/2, z \u003d 8-4%3", + "sync": "", + "isLocked": false, + "nails": [ + { + "x": 249.99999999999994, + "y": 370.0, + "propertyType": "GUARD", + "propertyX": 30.00000000000003, + "propertyY": 0.0 + }, + { + "x": 259.7, + "y": 346.26666666666665, + "propertyType": "SYNCHRONIZATION", + "propertyX": 10.0, + "propertyY": 0.0 + } + ] + } + ], + "description": "", + "x": 65.0, + "y": 14.5, + "width": 450.0, + "height": 600.0, + "color": "8", + "includeInPeriodicCheck": true +} \ No newline at end of file diff --git a/samples/json/PopulateClocks/GlobalDeclarations.json b/samples/json/PopulateClocks/GlobalDeclarations.json new file mode 100644 index 00000000..91995933 --- /dev/null +++ b/samples/json/PopulateClocks/GlobalDeclarations.json @@ -0,0 +1,4 @@ +{ + "name": "Global Declarations", + "declarations": "broadcast chan pub, grant, patent, coin, tea, cof;" +} \ No newline at end of file diff --git a/samples/json/PopulateClocks/Queries.json b/samples/json/PopulateClocks/Queries.json new file mode 100644 index 00000000..a13e0daa --- /dev/null +++ b/samples/json/PopulateClocks/Queries.json @@ -0,0 +1,66 @@ +[ + { + "query": "specification: (Administration || Machine || Researcher)", + "comment": "", + "isPeriodic": false, + "ignoredInputs": {}, + "ignoredOutputs": {}, + "backend": 1 + }, + { + "query": "specification: Spec", + "comment": "", + "isPeriodic": false, + "ignoredInputs": {}, + "ignoredOutputs": {}, + "backend": 1 + }, + { + "query": "consistency: (Administration || Machine || Researcher)", + "comment": "", + "isPeriodic": false, + "ignoredInputs": {}, + "ignoredOutputs": {}, + "backend": 1 + }, + { + "query": "consistency: (Administration || Machine || Researcher)", + "comment": "", + "isPeriodic": false, + "ignoredInputs": {}, + "ignoredOutputs": {}, + "backend": 1 + }, + { + "query": "refinement: (Administration || Machine || Researcher) \u003c\u003d Spec", + "comment": "", + "isPeriodic": false, + "ignoredInputs": {}, + "ignoredOutputs": {}, + "backend": 1 + }, + { + "query": "refinement: Machine3 \u003c\u003d Machine3", + "comment": "", + "isPeriodic": false, + "ignoredInputs": {}, + "ignoredOutputs": {}, + "backend": 1 + }, + { + "query": "refinement: (HalfAdm1 \u0026\u0026 HalfAdm2) \u003c\u003d Adm2", + "comment": "", + "isPeriodic": false, + "ignoredInputs": {}, + "ignoredOutputs": {}, + "backend": 1 + }, + { + "query": "refinement: Adm2 \u003c\u003d (HalfAdm1 \u0026\u0026 HalfAdm2)", + "comment": "", + "isPeriodic": false, + "ignoredInputs": {}, + "ignoredOutputs": {}, + "backend": 1 + } +] \ No newline at end of file diff --git a/samples/json/PopulateClocks/SystemDeclarations.json b/samples/json/PopulateClocks/SystemDeclarations.json new file mode 100644 index 00000000..cc638f6b --- /dev/null +++ b/samples/json/PopulateClocks/SystemDeclarations.json @@ -0,0 +1,4 @@ +{ + "name": "System Declarations", + "declarations": "system Spec, Machine, Machine2, Machine3, Machine4, Administration, HalfAdm1, HalfAdm2, Researcher, Adm2;\nIO Spec { grant?, patent! }\nIO Machine { coin?, tea!, cof! }\nIO Machine2 { coin?, tea!, cof! }\nIO Machine3 { coin?, tea!, cof! }\nIO Administration { grant?, pub?, coin!, patent! }\nIO HalfAdm1 { grant?, pub?, coin!, patent! }\nIO HalfAdm2 { grant?, pub?, coin!, patent! }\nIO Researcher { cof?, tea?, pub! }\nIO Adm2 {grant?, pub?, coin!, patent!}" +} \ No newline at end of file diff --git a/samples/json/PopulateClocks/Systems/UniversityExample.json b/samples/json/PopulateClocks/Systems/UniversityExample.json new file mode 100644 index 00000000..24fa73f8 --- /dev/null +++ b/samples/json/PopulateClocks/Systems/UniversityExample.json @@ -0,0 +1,76 @@ +{ + "name": "UniversityExample", + "description": "", + "x": 5.0, + "y": 5.0, + "width": 540.0, + "height": 410.0, + "color": "5", + "systemRootX": 240.0, + "componentInstances": [ + { + "id": 1, + "componentName": "Machine", + "x": 10.0, + "y": 110.0 + }, + { + "id": 3, + "componentName": "Researcher", + "x": 310.0, + "y": 110.0 + }, + { + "id": 5, + "componentName": "HalfAdm1", + "x": 10.0, + "y": 280.0 + }, + { + "id": 6, + "componentName": "HalfAdm2", + "x": 310.0, + "y": 280.0 + } + ], + "operators": [ + { + "id": 2, + "type": "composition", + "x": 250.0, + "y": 60.0 + }, + { + "id": 4, + "type": "conjunction", + "x": 250.0, + "y": 230.0 + } + ], + "edges": [ + { + "child": 2, + "parent": 0 + }, + { + "child": 1, + "parent": 2 + }, + { + "child": 3, + "parent": 2 + }, + { + "child": 4, + "parent": 2 + }, + { + "child": 5, + "parent": 4 + }, + { + "child": 6, + "parent": 4 + } + ] +} \ No newline at end of file diff --git a/samples/json/SyntaxTest/Components/syntaxFailure.json b/samples/json/SyntaxTest/Components/syntaxFailure.json new file mode 100644 index 00000000..47ab3975 --- /dev/null +++ b/samples/json/SyntaxTest/Components/syntaxFailure.json @@ -0,0 +1,67 @@ +{ + "name": "syntaxFailure", + "declarations": "clock u;", + "locations": [ + { + "urgency": "NORMAL", + "x": 120.0, + "y": 120.0, + "color": "6", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + }, + { + "id": "L17", + "nickname": "", + "invariant": "u\u003c1", + "type": "NORMAL", + "urgency": "NORMAL", + "x": 320.00001, + "y": 120.0, + "color": "6", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + } + ], + "edges": [ + { + "id": "E0", + "group": "", + "sourceLocation": "L16", + "targetLocation": "L17", + "status": "INPUT", + "select": "", + "guard": "u \u003c1", + "update": "", + "sync": "coffee", + "isLocked": false, + "nails": [ + { + "x": 180.0, + "y": 120.0, + "propertyType": "GUARD", + "propertyX": 10.0, + "propertyY": 0.0 + }, + { + "x": 240.46740467404675, + "y": 118.65928659286593, + "propertyType": "SYNCHRONIZATION", + "propertyX": 10.0, + "propertyY": 0.0 + } + ] + } + ], + "description": "", + "x": 88.8, + "y": 152.0, + "width": 450.0, + "height": 240.0, + "color": "6", + "includeInPeriodicCheck": false +} \ No newline at end of file diff --git a/samples/json/SyntaxTest/Queries.json b/samples/json/SyntaxTest/Queries.json new file mode 100644 index 00000000..32960f8c --- /dev/null +++ b/samples/json/SyntaxTest/Queries.json @@ -0,0 +1,2 @@ +[ +] \ No newline at end of file diff --git a/samples/json/SyntaxTest/SystemDeclarations.json b/samples/json/SyntaxTest/SystemDeclarations.json new file mode 100644 index 00000000..bb953841 --- /dev/null +++ b/samples/json/SyntaxTest/SystemDeclarations.json @@ -0,0 +1,4 @@ +{ + "name": "System Declarations", + "declarations": "system syntaxFailure;\n" +} \ No newline at end of file diff --git a/samples/json/specTest1/SystemDeclarations.json b/samples/json/specTest1/SystemDeclarations.json index 69f25d26..4419b952 100644 --- a/samples/json/specTest1/SystemDeclarations.json +++ b/samples/json/specTest1/SystemDeclarations.json @@ -1,4 +1,4 @@ { "name": "System Declarations", - "declarations": "system comp, comp1;\n\nIO comp{input?, output!}\nIO comp1{input?, output!}" + "declarations": "system comp, comp1;\n\nIO comp { input?, output!}\nIO comp1 { input?, output!}" } \ No newline at end of file diff --git a/src/DataTypes/mod.rs b/src/DataTypes/mod.rs deleted file mode 100644 index 661b8749..00000000 --- a/src/DataTypes/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod statepair_list; - -pub use statepair_list::{PassedStateList, PassedStateListExt, WaitingStateList}; diff --git a/src/EdgeEval/mod.rs b/src/EdgeEval/mod.rs deleted file mode 100644 index 82edd550..00000000 --- a/src/EdgeEval/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod constraint_applyer; -pub mod updater; diff --git a/src/ModelObjects/component.rs b/src/ModelObjects/component.rs deleted file mode 100644 index 2b8759a7..00000000 --- a/src/ModelObjects/component.rs +++ /dev/null @@ -1,221 +0,0 @@ -use crate::DataReader::serialization::{decode_declarations, DummyComponent}; - -use edbm::util::bounds::Bounds; -use edbm::util::constraints::ClockIndex; - -use crate::ModelObjects::Expressions::BoolExpression; -use crate::ModelObjects::{Edge, Location, SyncType}; -use itertools::Itertools; -use log::info; -use serde::{Deserialize, Serialize}; -use std::collections::{HashMap, HashSet}; -use std::iter::FromIterator; - -/// The basic struct used to represent components read from either Json or xml -#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)] -#[serde(into = "DummyComponent")] -pub struct Component { - pub name: String, - - #[serde( - deserialize_with = "decode_declarations", - serialize_with = "encode_declarations" - )] - pub declarations: Declarations, - pub locations: Vec, - pub edges: Vec, - pub special_id: Option, -} - -impl DeclarationProvider for Component { - fn get_declarations(&self) -> &Declarations { - &self.declarations - } -} - -impl Component { - pub fn set_clock_indices(&mut self, indices: &mut ClockIndex) { - self.declarations.set_clock_indices(*indices); - *indices += self.declarations.get_clock_count(); - } - - pub fn get_location_by_name(&self, name: &str) -> &Location { - let loc_vec = self - .locations - .iter() - .filter(|l| l.id == name) - .collect::>(); - - if loc_vec.len() == 1 { - loc_vec[0] - } else { - panic!("Unable to retrieve location based on id: {}", name) - } - } - - pub fn get_input_actions(&self) -> Vec { - self.get_specific_actions(SyncType::Input) - } - - pub fn get_output_actions(&self) -> Vec { - self.get_specific_actions(SyncType::Output) - } - - fn get_specific_actions(&self, sync_type: SyncType) -> Vec { - Vec::from_iter( - self.edges - .iter() - .filter(|e| e.sync_type == sync_type && e.sync != "*") - .map(|e| e.sync.clone()) - .unique(), - ) - } - - // End of basic methods - - pub fn get_max_bounds(&self, dimensions: ClockIndex) -> Bounds { - let mut max_bounds = Bounds::new(dimensions); - for (clock_name, clock_id) in &self.declarations.clocks { - let max_bound = i32::max( - self.edges - .iter() - .filter_map(|e| e.guard.clone()) - .map(|g| g.get_max_constant(*clock_id, clock_name)) - .max() - .unwrap_or_default(), - self.locations - .iter() - .filter_map(|l| l.invariant.clone()) - .map(|i| i.get_max_constant(*clock_id, clock_name)) - .max() - .unwrap_or_default(), - ); - - // TODO: find more precise upper and lower bounds for clocks - max_bounds.add_lower(*clock_id, max_bound); - max_bounds.add_upper(*clock_id, max_bound); - } - - max_bounds - } - - /// Redoes the components Edge IDs by giving them new unique IDs based on their index. - pub fn remake_edge_ids(&mut self) { - // Give all edges a name - for (index, edge) in self.edges.iter_mut().enumerate() { - edge.id = format!("E{}", index); - } - } - - /// Removes unused clock - /// # Arguments - /// `index`: The index to be removed - pub(crate) fn remove_clock(&mut self, index: ClockIndex) { - // Removes from declarations, and updates the other - let name = self - .declarations - .get_clock_name_by_index(index) - .expect("Couldn't find clock with index") - .to_owned(); - self.declarations.clocks.remove(&name); - - // Removes from from updates and guards - self.edges - .iter_mut() - .filter(|e| e.update.is_some() || e.guard.is_some()) - .for_each(|e| { - // The guard is overwritten to `false`. This can be done since we assume - // that all edges with guards involving the given clock is not reachable - // in some composite system. - if let Some(guard) = e.guard.as_mut().filter(|g| g.has_varname(&name)) { - *guard = BoolExpression::Bool(false); - } - if let Some(inv) = e.update.as_mut() { - inv.retain(|u| u.variable != name); - } - }); - - // Removes from from location invariants - // The invariants containing the clock are overwritten to `false`. - // This can be done since we assume that all locations with invariants involving - // the given clock is not reachable in some composite system. - self.locations - .iter_mut() - .filter_map(|l| l.invariant.as_mut()) - .filter(|i| i.has_varname(&name)) - .for_each(|i| *i = BoolExpression::Bool(false)); - - info!( - "Removed Clock '{name}' (index {index}) has been removed from component {}", - self.name - ); // Should be changed in the future to be the information logger - } - - /// Replaces duplicate clock with a new - /// # Arguments - /// `global_index`: The index of the global clock\n - /// `indices` are the duplicate clocks that should be set to `global_index` - pub(crate) fn replace_clock( - &mut self, - global_index: ClockIndex, - indices: &HashSet, - ) { - for (name, index) in self - .declarations - .clocks - .iter_mut() - .filter(|(_, c)| indices.contains(c)) - { - let old = *index; - *index = global_index; - // TODO: Maybe log the global clock name instead of index - info!( - "Replaced Clock '{name}' (index {old}) with {global_index} in component {}", - self.name - ); // Should be changed in the future to be the information logger - } - } -} - -pub trait DeclarationProvider { - fn get_declarations(&self) -> &Declarations; -} - -/// The declaration struct is used to hold the indices for each clock, and is meant to be the owner of int variables once implemented -#[derive(Debug, Deserialize, Clone, PartialEq, Eq, Serialize)] -pub struct Declarations { - pub ints: HashMap, - pub clocks: HashMap, -} - -impl Declarations { - pub fn empty() -> Declarations { - Declarations { - ints: HashMap::new(), - clocks: HashMap::new(), - } - } - - pub fn get_clock_count(&self) -> usize { - self.clocks.len() - } - - pub fn set_clock_indices(&mut self, start_index: ClockIndex) { - for (_, v) in self.clocks.iter_mut() { - *v += start_index - } - } - - pub fn get_clock_index_by_name(&self, name: &str) -> Option<&ClockIndex> { - self.clocks.get(name) - } - - /// Gets the name of a given `ClockIndex`. - /// Returns `None` if it does not exist in the declarations - pub fn get_clock_name_by_index(&self, index: ClockIndex) -> Option<&String> { - self.clocks - .iter() - .find(|(_, v)| **v == index) - .map(|(k, _)| k) - } -} diff --git a/src/ModelObjects/mod.rs b/src/ModelObjects/mod.rs deleted file mode 100644 index 2b70e5e1..00000000 --- a/src/ModelObjects/mod.rs +++ /dev/null @@ -1,14 +0,0 @@ -pub mod Expressions; -mod component; -mod edge; -mod location; -mod queries; -mod state; -mod statepair; -mod system_declarations; -mod transition; - -pub use self::{ - component::*, edge::*, location::*, queries::*, state::*, statepair::*, system_declarations::*, - transition::*, -}; diff --git a/src/ModelObjects/statepair.rs b/src/ModelObjects/statepair.rs deleted file mode 100644 index 86ce712d..00000000 --- a/src/ModelObjects/statepair.rs +++ /dev/null @@ -1,101 +0,0 @@ -use edbm::zones::OwnedFederation; - -use crate::TransitionSystems::{LocationTree, TransitionSystemPtr}; -use std::fmt::{Display, Formatter}; - -#[derive(Clone, Debug)] -pub struct StatePair { - pub locations1: LocationTree, - pub locations2: LocationTree, - /// The sentinel (Option) allows us to take ownership of the internal fed from a mutable reference - zone_sentinel: Option, -} - -impl StatePair { - pub fn from_locations( - dimensions: usize, - locations1: LocationTree, - locations2: LocationTree, - ) -> StatePair { - let zone = OwnedFederation::init(dimensions); - - StatePair { - locations1, - locations2, - zone_sentinel: Some(zone), - } - } - - pub fn get_locations1(&self) -> &LocationTree { - &self.locations1 - } - - pub fn get_locations2(&self) -> &LocationTree { - &self.locations2 - } - - //Used to allow borrowing both states as mutable - pub fn get_mut_states(&mut self, is_states1: bool) -> (&mut LocationTree, &mut LocationTree) { - if is_states1 { - (&mut self.locations1, &mut self.locations2) - } else { - (&mut self.locations2, &mut self.locations1) - } - } - - pub fn get_locations(&self, is_states1: bool) -> (&LocationTree, &LocationTree) { - if is_states1 { - (&self.locations1, &self.locations2) - } else { - (&self.locations2, &self.locations1) - } - } - - pub fn clone_zone(&self) -> OwnedFederation { - self.ref_zone().clone() - } - - pub fn ref_zone(&self) -> &OwnedFederation { - self.zone_sentinel.as_ref().unwrap() - } - - pub fn take_zone(&mut self) -> OwnedFederation { - self.zone_sentinel.take().unwrap() - } - - pub fn set_zone(&mut self, zone: OwnedFederation) { - self.zone_sentinel = Some(zone); - } - - pub fn extrapolate_max_bounds( - &mut self, - sys1: &TransitionSystemPtr, - sys2: &TransitionSystemPtr, - ) { - let mut bounds = sys1.get_local_max_bounds(&self.locations1); - bounds.add_bounds(&sys2.get_local_max_bounds(&self.locations2)); - let zone = self.take_zone().extrapolate_max_bounds(&bounds); - self.set_zone(zone); - } -} - -impl Display for StatePair { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - f.write_fmt(format_args!( - "Pair: 1:{} where {}, 2:{} where {}, zone: {}", - self.locations1.id, - self.locations1 - .get_invariants() - .map(|f| f.to_string()) - .unwrap_or_else(|| "no invariant".to_string()), - self.locations2.id, - self.locations2 - .get_invariants() - .map(|f| f.to_string()) - .unwrap_or_else(|| "no invariant".to_string()), - self.ref_zone() - ))?; - - Ok(()) - } -} diff --git a/src/System/extract_system_rep.rs b/src/System/extract_system_rep.rs deleted file mode 100644 index 65619dfd..00000000 --- a/src/System/extract_system_rep.rs +++ /dev/null @@ -1,495 +0,0 @@ -use crate::DataReader::component_loader::ComponentLoader; -use crate::ModelObjects::Expressions::{QueryExpression, SaveExpression, SystemExpression}; -use crate::ModelObjects::{Component, Query, State}; -use crate::System::executable_query::{ - ConsistencyExecutor, DeterminismExecutor, ExecutableQuery, GetComponentExecutor, - ReachabilityExecutor, RefinementExecutor, -}; -use crate::System::extract_state::get_state; -use std::collections::HashMap; - -use crate::TransitionSystems::{ - CompiledComponent, Composition, Conjunction, Quotient, TransitionSystemPtr, -}; - -use super::query_failures::SystemRecipeFailure; -use crate::System::pruning; -use crate::TransitionSystems::transition_system::ClockReductionInstruction; -use edbm::util::constraints::ClockIndex; -use log::debug; -use simple_error::bail; - -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum ExecutableQueryError { - SystemRecipeFailure(SystemRecipeFailure), - Custom(String), -} - -impl From> for ExecutableQueryError { - fn from(failure: Box) -> Self { - ExecutableQueryError::SystemRecipeFailure(*failure) - } -} - -impl> From for ExecutableQueryError { - fn from(failure: T) -> Self { - ExecutableQueryError::Custom(failure.into()) - } -} - -/// This function fetches the appropriate components based on the structure of the query and makes the enum structure match the query -/// this function also handles setting up the correct indices for clocks based on the amount of components in each system representation -pub fn create_executable_query<'a>( - full_query: &Query, - component_loader: &'a mut (dyn ComponentLoader + 'static), -) -> Result, ExecutableQueryError> { - let mut dim: ClockIndex = 0; - - if let Some(query) = full_query.get_query() { - match query { - QueryExpression::Refinement(left_side, right_side) => { - let mut quotient_index = None; - - let mut left = - get_system_recipe(left_side, component_loader, &mut dim, &mut quotient_index); - let mut right = - get_system_recipe(right_side, component_loader, &mut dim, &mut quotient_index); - - if !component_loader.get_settings().disable_clock_reduction { - clock_reduction::clock_reduce( - &mut left, - Some(&mut right), - &mut dim, - quotient_index, - )?; - } - - let mut component_index = 0; - - Ok(Box::new(RefinementExecutor { - sys1: left.compile_with_index(dim, &mut component_index)?, - sys2: right.compile_with_index(dim, &mut component_index)?, - })) - } - QueryExpression::Reachability { system, from, to } => { - let machine = get_system_recipe(system, component_loader, &mut dim, &mut None); - let transition_system = machine.clone().compile(dim)?; - - // Assign the start state to the initial state of the transition system if no start state is given by the query - let start_state: State = if let Some(state) = from.as_ref() { - let state = get_state(state, &machine, &transition_system) - .map_err(|err| format!("Invalid Start state: {}", err))?; - if state.decorated_locations.id.is_partial_location() { - return Err("Start state is a partial state, which it must not be".into()); - } - state - } else { - match transition_system.get_initial_state() { - Some(state) => state, - None => return Err("No start state in the transition system".into()), - } - }; - - let end_state: State = get_state(to, &machine, &transition_system) - .map_err(|err| format!("Invalid End state: {}", err))?; - - Ok(Box::new(ReachabilityExecutor { - transition_system, - start_state, - end_state, - })) - } - QueryExpression::Consistency(query_expression) => { - let mut quotient_index = None; - let mut recipe = get_system_recipe( - query_expression, - component_loader, - &mut dim, - &mut quotient_index, - ); - - if !component_loader.get_settings().disable_clock_reduction { - clock_reduction::clock_reduce(&mut recipe, None, &mut dim, quotient_index)?; - } - - Ok(Box::new(ConsistencyExecutor { - system: recipe.compile(dim)?, - })) - } - QueryExpression::Determinism(query_expression) => { - let mut quotient_index = None; - let mut recipe = get_system_recipe( - query_expression, - component_loader, - &mut dim, - &mut quotient_index, - ); - - if !component_loader.get_settings().disable_clock_reduction { - clock_reduction::clock_reduce(&mut recipe, None, &mut dim, quotient_index)?; - } - - Ok(Box::new(DeterminismExecutor { - system: recipe.compile(dim)?, - })) - } - QueryExpression::GetComponent(SaveExpression { system, name }) => { - let mut quotient_index = None; - let mut recipe = - get_system_recipe(system, component_loader, &mut dim, &mut quotient_index); - - if !component_loader.get_settings().disable_clock_reduction { - clock_reduction::clock_reduce(&mut recipe, None, &mut dim, quotient_index)?; - } - - Ok(Box::new(GetComponentExecutor { - system: recipe.compile(dim)?, - comp_name: name.clone().unwrap_or("Unnamed".to_string()), - component_loader, - })) - } - QueryExpression::Prune(SaveExpression { system, name }) => { - let mut quotient_index = None; - let mut recipe = - get_system_recipe(system, component_loader, &mut dim, &mut quotient_index); - - if !component_loader.get_settings().disable_clock_reduction { - clock_reduction::clock_reduce(&mut recipe, None, &mut dim, quotient_index)?; - } - - Ok(Box::new(GetComponentExecutor { - system: pruning::prune_system(recipe.compile(dim)?, dim), - comp_name: name.clone().unwrap_or("Unnamed".to_string()), - component_loader, - })) - } - - // Should handle consistency, Implementation, determinism and specification here, but we cant deal with it atm anyway - _ => bail!("Not yet setup to handle query"), - } - } else { - bail!("No query was supplied for extraction") - } -} - -#[derive(Clone)] -pub enum SystemRecipe { - Composition(Box, Box), - Conjunction(Box, Box), - Quotient(Box, Box, ClockIndex), - Component(Box), -} - -impl SystemRecipe { - pub fn compile(self, dim: ClockIndex) -> Result> { - let mut component_index = 0; - self._compile(dim + 1, &mut component_index) - } - - pub fn compile_with_index( - self, - dim: ClockIndex, - component_index: &mut u32, - ) -> Result> { - self._compile(dim + 1, component_index) - } - - fn _compile( - self, - dim: ClockIndex, - component_index: &mut u32, - ) -> Result> { - match self { - SystemRecipe::Composition(left, right) => Composition::new_ts( - left._compile(dim, component_index)?, - right._compile(dim, component_index)?, - dim, - ), - SystemRecipe::Conjunction(left, right) => Conjunction::new_ts( - left._compile(dim, component_index)?, - right._compile(dim, component_index)?, - dim, - ), - SystemRecipe::Quotient(left, right, clock_index) => Quotient::new_ts( - left._compile(dim, component_index)?, - right._compile(dim, component_index)?, - clock_index, - dim, - ), - SystemRecipe::Component(comp) => { - CompiledComponent::compile(*comp, dim, component_index) - .map(|comp| comp as TransitionSystemPtr) - } - } - } - - /// Gets the number of `Components`s in the `SystemRecipe` - pub fn get_component_count(&self) -> usize { - match self { - SystemRecipe::Composition(left, right) - | SystemRecipe::Conjunction(left, right) - | SystemRecipe::Quotient(left, right, _) => { - left.get_component_count() + right.get_component_count() - } - SystemRecipe::Component(_) => 1, - } - } - - ///Applies the clock-reduction - fn reduce_clocks(&mut self, clock_instruction: Vec) { - let mut comps = self.get_components_mut(); - for redundant in clock_instruction { - match redundant { - ClockReductionInstruction::RemoveClock { clock_index } => comps - .iter_mut() - .find(|c| c.declarations.clocks.values().any(|ci| *ci == clock_index)) - .unwrap_or_else(|| { - panic!( - "A component could not be found for clock index {}", - clock_index - ) - }) - .remove_clock(clock_index), - ClockReductionInstruction::ReplaceClocks { - clock_indices, - clock_index, - } => comps - .iter_mut() - .for_each(|c| c.replace_clock(clock_index, &clock_indices)), - } - } - } - - /// Gets all components in `SystemRecipe` - fn get_components_mut(&mut self) -> Vec<&mut Component> { - match self { - SystemRecipe::Composition(left, right) - | SystemRecipe::Conjunction(left, right) - | SystemRecipe::Quotient(left, right, _) => { - let mut o = left.get_components_mut(); - o.extend(right.get_components_mut()); - o - } - SystemRecipe::Component(c) => vec![c], - } - } - - pub fn get_components(&self) -> Vec<&Component> { - match self { - SystemRecipe::Composition(left, right) - | SystemRecipe::Conjunction(left, right) - | SystemRecipe::Quotient(left, right, _) => { - let mut o = left.get_components(); - o.extend(right.get_components()); - o - } - SystemRecipe::Component(c) => vec![c], - } - } - - fn change_quotient(&mut self, index: ClockIndex) { - match self { - SystemRecipe::Composition(l, r) | SystemRecipe::Conjunction(l, r) => { - l.change_quotient(index); - r.change_quotient(index); - } - SystemRecipe::Quotient(l, r, q) => { - *q = index; - l.change_quotient(index); - r.change_quotient(index); - } - SystemRecipe::Component(_) => (), - } - } -} - -pub fn get_system_recipe( - side: &SystemExpression, - component_loader: &mut dyn ComponentLoader, - clock_index: &mut ClockIndex, - quotient_index: &mut Option, -) -> Box { - match side { - SystemExpression::Composition(left, right) => Box::new(SystemRecipe::Composition( - get_system_recipe(left, component_loader, clock_index, quotient_index), - get_system_recipe(right, component_loader, clock_index, quotient_index), - )), - SystemExpression::Conjunction(left, right) => Box::new(SystemRecipe::Conjunction( - get_system_recipe(left, component_loader, clock_index, quotient_index), - get_system_recipe(right, component_loader, clock_index, quotient_index), - )), - SystemExpression::Quotient(left, right) => { - let left = get_system_recipe(left, component_loader, clock_index, quotient_index); - let right = get_system_recipe(right, component_loader, clock_index, quotient_index); - - let q_index = match quotient_index { - Some(q_i) => *q_i, - None => { - *clock_index += 1; - debug!("Quotient clock index: {}", *clock_index); - - quotient_index.replace(*clock_index); - quotient_index.unwrap() - } - }; - - Box::new(SystemRecipe::Quotient(left, right, q_index)) - } - SystemExpression::Component(name, id) => { - let mut component = component_loader.get_component(name).clone(); - component.set_clock_indices(clock_index); - component.special_id = id.clone(); - debug!("{} Clocks: {:?}", name, component.declarations.clocks); - - Box::new(SystemRecipe::Component(Box::new(component))) - } - } -} - -/// Module containing a "safer" function for clock reduction, along with some helper functions -pub(crate) mod clock_reduction { - use super::*; - - /// Function for a "safer" clock reduction that handles both the dimension of the DBM and the quotient index if needed be - /// # Arguments - /// `lhs`: The (main) [`SystemRecipe`] to clock reduce\n - /// `rhs`: An optional [`SystemRecipe`] used for multiple operands (Refinement)\n - /// `dim`: A mutable reference to the DBMs dimension for updating\n - /// `quotient_clock`: The clock for the quotient (This is not reduced) - /// # Returns - /// A `Result` used if the [`SystemRecipe`](s) fail during compilation - pub fn clock_reduce( - lhs: &mut Box, - rhs: Option<&mut Box>, - dim: &mut usize, - quotient_clock: Option, - ) -> Result<(), Box> { - if *dim == 0 { - return Ok(()); - } else if rhs.is_none() { - return clock_reduce_single(lhs, dim, quotient_clock); - } - let rhs = rhs.unwrap(); - - let (l_clocks, r_clocks) = filter_redundant_clocks( - lhs.clone().compile(*dim)?.find_redundant_clocks(), - rhs.clone().compile(*dim)?.find_redundant_clocks(), - quotient_clock, - lhs.get_components_mut() - .iter() - .flat_map(|c| c.declarations.clocks.values().cloned()) - .max() - .unwrap_or_default(), - ); - - debug!("Clocks to be reduced: {l_clocks:?} + {l_clocks:?}"); - *dim -= l_clocks - .iter() - .chain(r_clocks.iter()) - .fold(0, |acc, c| acc + c.clocks_removed_count()); - debug!("New dimension: {dim}"); - - rhs.reduce_clocks(r_clocks); - lhs.reduce_clocks(l_clocks); - compress_component_decls(lhs.get_components_mut(), Some(rhs.get_components_mut())); - if quotient_clock.is_some() { - lhs.change_quotient(*dim); - rhs.change_quotient(*dim); - } - - Ok(()) - } - - /// Clock reduces a "single_expression", such as consistency - /// # Arguments - /// - /// * `sys`: The [`SystemRecipe`] to clock reduce - /// * `dim`: the dimension of the system - /// * `quotient_clock`: The clock for the quotient (This is not reduced) - /// - /// returns: Result<(), SystemRecipeFailure> - fn clock_reduce_single( - sys: &mut Box, - dim: &mut usize, - quotient_clock: Option, - ) -> Result<(), Box> { - let mut clocks = sys.clone().compile(*dim)?.find_redundant_clocks(); - clocks.retain(|ins| ins.get_clock_index() != quotient_clock.unwrap_or_default()); - debug!("Clocks to be reduced: {clocks:?}"); - *dim -= clocks - .iter() - .fold(0, |acc, c| acc + c.clocks_removed_count()); - debug!("New dimension: {dim}"); - sys.reduce_clocks(clocks); - compress_component_decls(sys.get_components_mut(), None); - if quotient_clock.is_some() { - sys.change_quotient(*dim); - } - Ok(()) - } - - fn filter_redundant_clocks( - lhs: Vec, - rhs: Vec, - quotient_clock: Option, - split_index: ClockIndex, - ) -> ( - Vec, - Vec, - ) { - fn get_unique_redundant_clocks bool>( - l: Vec, - r: Vec, - quotient: ClockIndex, - bound_predicate: P, - ) -> Vec { - l.into_iter() - // Takes clock instructions that also occur in the rhs system - // This is done because the lhs also finds the redundant clocks from the rhs, - // so to ensure that it should be removed, we check if it occurs on both sides - // which would mean it can be removed - // e.g "A <= B", we can find clocks from B that are not used in A, so they are marked as remove - .filter(|ins| r.contains(ins)) - // Takes all the clocks within the bounds of the given system - // This is done to ensure that we don't try to remove a clock from the rhs system - .filter(|ins| bound_predicate(ins.get_clock_index())) - // Removes the quotient clock - .filter(|ins| ins.get_clock_index() != quotient) - .collect() - } - let quotient_clock = quotient_clock.unwrap_or_default(); - ( - get_unique_redundant_clocks(lhs.clone(), rhs.clone(), quotient_clock, |c| { - c <= split_index - }), - get_unique_redundant_clocks(rhs, lhs, quotient_clock, |c| c > split_index), - ) - } - - fn compress_component_decls( - mut comps: Vec<&mut Component>, - other: Option>, - ) { - let mut seen: HashMap = HashMap::new(); - let mut l: Vec<&mut ClockIndex> = comps - .iter_mut() - .flat_map(|c| c.declarations.clocks.values_mut()) - .collect(); - let mut temp = other.unwrap_or_default(); - l.extend( - temp.iter_mut() - .flat_map(|c| c.declarations.clocks.values_mut()), - ); - l.sort(); - let mut index = 1; - for clock in l { - if let Some(val) = seen.get(clock) { - *clock = *val; - } else { - seen.insert(*clock, index); - *clock = index; - index += 1; - } - } - } -} diff --git a/src/cli.rs b/src/cli.rs index 45ad90a1..bf62a26d 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -35,7 +35,7 @@ pub enum Args { /// Reveaal query "determinism: Researcher" -i samples/json/EcdarUniversity Query { /// The query to execute - #[clap(value_name = "QUERY_TYPE: refinement|consistency|reachability|save-component", value_parser = query_check)] + #[clap(value_name = "QUERY_TYPE: refinement|consistency|reachability|save-component|syntax", value_parser = query_check)] query: String, /// File (XML) or folder (JSON) with component definitions diff --git a/src/DataReader/component_loader.rs b/src/data_reader/component_loader.rs similarity index 84% rename from src/DataReader/component_loader.rs rename to src/data_reader/component_loader.rs index 10952e03..e1ed57f1 100644 --- a/src/DataReader/component_loader.rs +++ b/src/data_reader/component_loader.rs @@ -1,14 +1,15 @@ use log::warn; use lru::LruCache; +use crate::data_reader::json_reader; +use crate::data_reader::json_writer::component_to_json_file; +use crate::data_reader::xml_parser::parse_xml_from_file; +use crate::model_objects::{Component, Query, SystemDeclarations}; +use crate::protobuf_server::services; +use crate::protobuf_server::services::query_request::Settings; +use crate::system::input_enabler; +use crate::system::query_failures::SyntaxResult; use crate::xml_parser; -use crate::DataReader::json_reader; -use crate::DataReader::json_writer::component_to_json_file; -use crate::DataReader::xml_parser::parse_xml_from_file; -use crate::ModelObjects::{Component, Query, SystemDeclarations}; -use crate::ProtobufServer::services; -use crate::ProtobufServer::services::query_request::Settings; -use crate::System::input_enabler; use std::collections::HashMap; use std::num::NonZeroUsize; use std::path::{Path, PathBuf}; @@ -108,7 +109,7 @@ impl ModelCache { } pub trait ComponentLoader { - fn get_component(&mut self, component_name: &str) -> &Component; + fn get_component(&mut self, component_name: &str) -> Result<&Component, SyntaxResult>; fn save_component(&mut self, component: Component); fn get_settings(&self) -> &Settings; fn get_settings_mut(&mut self) -> &mut Settings; @@ -121,10 +122,10 @@ pub struct ComponentContainer { } impl ComponentLoader for ComponentContainer { - fn get_component(&mut self, component_name: &str) -> &Component { + fn get_component(&mut self, component_name: &str) -> Result<&Component, SyntaxResult> { if let Some(component) = self.loaded_components.get(component_name) { assert_eq!(component_name, component.name); - component + Ok(component) } else { panic!("The component '{}' could not be retrieved", component_name); } @@ -212,14 +213,14 @@ pub struct JsonProjectLoader { } impl ComponentLoader for JsonProjectLoader { - fn get_component(&mut self, component_name: &str) -> &Component { + fn get_component(&mut self, component_name: &str) -> Result<&Component, SyntaxResult> { if !self.is_component_loaded(component_name) { - self.load_component(component_name); + self.load_component(component_name)?; } if let Some(component) = self.loaded_components.get(component_name) { assert_eq!(component_name, component.name); - component + Ok(component) } else { panic!("The component '{}' could not be retrieved", component_name); } @@ -275,8 +276,8 @@ impl JsonProjectLoader { }) } - fn load_component(&mut self, component_name: &str) { - let mut component = json_reader::read_json_component(&self.project_path, component_name); + fn load_component(&mut self, component_name: &str) -> Result<(), SyntaxResult> { + let mut component = json_reader::read_json_component(&self.project_path, component_name)?; let opt_inputs = self .get_declarations() @@ -285,8 +286,30 @@ impl JsonProjectLoader { input_enabler::make_input_enabled(&mut component, inputs); } + // Will reduce clocks on the component if not disabled + if !self.get_settings().disable_clock_reduction { + // Set up and populate clock usages + component.initialise_clock_usages(); + component.populate_usages_with_guards(); + component.populate_usages_with_updates(); + component.populate_usages_with_invariants(); + + // Remove the redundant clocks from component using the clock_usages + // TODO: Maybe log removed clocks + match component.remove_redundant_clocks() { + Ok(()) => {} + Err(err) => { + //eprintln!("Error removing redundant clocks: {}", err); + } + } + // Compress the declarations after removing + component.compress_dcls(); + } + self.loaded_components .insert(String::from(component_name), component); + + Ok(()) } fn is_component_loaded(&self, component_name: &str) -> bool { @@ -303,10 +326,10 @@ pub struct XmlProjectLoader { } impl ComponentLoader for XmlProjectLoader { - fn get_component(&mut self, component_name: &str) -> &Component { + fn get_component(&mut self, component_name: &str) -> Result<&Component, SyntaxResult> { if let Some(component) = self.loaded_components.get(component_name) { assert_eq!(component_name, component.name); - component + Ok(component) } else { panic!("The component '{}' could not be retrieved", component_name); } diff --git a/src/DataReader/grammars/edge_grammar.pest b/src/data_reader/grammars/edge_grammar.pest similarity index 100% rename from src/DataReader/grammars/edge_grammar.pest rename to src/data_reader/grammars/edge_grammar.pest diff --git a/src/DataReader/grammars/query_grammar.pest b/src/data_reader/grammars/query_grammar.pest similarity index 95% rename from src/DataReader/grammars/query_grammar.pest rename to src/data_reader/grammars/query_grammar.pest index 25718917..edfd1351 100644 --- a/src/DataReader/grammars/query_grammar.pest +++ b/src/data_reader/grammars/query_grammar.pest @@ -2,11 +2,13 @@ queries = _{SOI ~ queryList ~ EOI} queryList = { query ~ (";" ~ query)*} -query = {refinement | consistency | reachability | implementation | determinism | specification | getComponent | prune | bisim /*| logicFormulas*/} +query = {refinement | consistency | reachability | implementation | determinism | specification | getComponent | prune | bisim | syntax /*| logicFormulas*/} refinement = {"refinement:" ~ expr ~ "<=" ~ expr} +syntax = {"syntax:" ~ component} + consistency = {"consistency:" ~ expr} reachability = { "reachability:" ~ expr ~ "@" ~ (state | "init") ~ "->" ~ state } diff --git a/src/DataReader/json_reader.rs b/src/data_reader/json_reader.rs similarity index 64% rename from src/DataReader/json_reader.rs rename to src/data_reader/json_reader.rs index ba968ad8..acc05da7 100644 --- a/src/DataReader/json_reader.rs +++ b/src/data_reader/json_reader.rs @@ -1,4 +1,5 @@ -use crate::ModelObjects::{Component, Query, SystemDeclarations}; +use crate::model_objects::{Component, Query, SystemDeclarations}; +use crate::system::query_failures::{SyntaxFailure, SyntaxResult}; use serde::de::DeserializeOwned; use std::fs::File; use std::io::Read; @@ -21,50 +22,52 @@ pub fn read_system_declarations>(project_path: P) -> Option>(project_path: P, component_name: &str) -> Component { +pub fn read_json_component>( + project_path: P, + component_name: &str, +) -> Result { let component_path = project_path .as_ref() .join("Components") .join(format!("{}.json", component_name)); - let component: Component = match read_json(&component_path) { - Ok(json) => json, - Err(error) => panic!( - "We got error {}, and could not parse json file {} to component", - error, - component_path.display() - ), + let component: Result = match read_json(&component_path) { + Ok(json) => Ok(json), + Err(error) => Err(SyntaxFailure::unparsable( + error.to_string(), + component_path.display().to_string(), + )), }; component } -//Input:File name -//Description:uses the filename to open the file and then reads the file. -//Output: Result type, if more info about this type is need please go to: https://doc.rust-lang.org/std/result/ +/// Opens a file and reads it. +/// If the file is read successfully, +/// a Result object which contains a DeserializeOwned JSON object is returned. +/// More information: https://doc.rust-lang.org/std/result/ +/// +/// # Arguments +/// +/// * `filename` - A path to the json file pub fn read_json>(filename: P) -> serde_json::Result { let mut file = File::open(&filename) .unwrap_or_else(|_| panic!("Could not find file {}", filename.as_ref().display())); let mut data = String::new(); file.read_to_string(&mut data).unwrap(); - let json_file = serde_json::from_str(&data).unwrap_or_else(|_| { - panic!( - "{}: Json format is not as expected", - filename.as_ref().display() - ) - }); - - Ok(json_file) + serde_json::from_str(&data) } pub fn json_to_component(json_str: &str) -> Result { serde_json::from_str(json_str) } -//Input:Filename -//Description: transforms json into query type -//Output:Result +/// Transforms JSON into a Query type +/// +/// # Arguments +/// +/// * `project_path` - A path to the project pub fn read_queries>(project_path: P) -> Option> { let queries_path = project_path.as_ref().join("Queries.json"); diff --git a/src/DataReader/json_writer.rs b/src/data_reader/json_writer.rs similarity index 93% rename from src/DataReader/json_writer.rs rename to src/data_reader/json_writer.rs index a1bef706..68550020 100644 --- a/src/DataReader/json_writer.rs +++ b/src/data_reader/json_writer.rs @@ -1,4 +1,4 @@ -use crate::ModelObjects::Component; +use crate::model_objects::Component; use std::{fs::File, path::Path}; pub fn component_to_json_file>(project_path: P, component: &Component) { diff --git a/src/DataReader/mod.rs b/src/data_reader/mod.rs similarity index 100% rename from src/DataReader/mod.rs rename to src/data_reader/mod.rs diff --git a/src/DataReader/parse_edge.rs b/src/data_reader/parse_edge.rs similarity index 93% rename from src/DataReader/parse_edge.rs rename to src/data_reader/parse_edge.rs index 168da372..81645b01 100644 --- a/src/DataReader/parse_edge.rs +++ b/src/data_reader/parse_edge.rs @@ -1,20 +1,20 @@ extern crate pest; -use crate::EdgeEval::updater::CompiledUpdate; +use crate::edge_eval::updater::CompiledUpdate; -use crate::ModelObjects::Expressions::{ArithExpression, BoolExpression}; +use crate::model_objects::expressions::{ArithExpression, BoolExpression}; -use crate::{DataReader::serialization::encode_arithexpr, ModelObjects::Declarations}; +use crate::{data_reader::serialization::encode_arithexpr, model_objects::Declarations}; use edbm::util::constraints::ClockIndex; use pest::pratt_parser::{Assoc, Op, PrattParser}; use pest::Parser; use serde::{Deserialize, Serialize}; use std::collections::HashMap; -///This file handles parsing the edges based on the abstract syntax described in the .pest files in the grammar folder -///For clarification see documentation on pest crate +//This file handles parsing the edges based on the abstract syntax described in the .pest files in the grammar folder +//For clarification see documentation on pest crate #[derive(Parser)] -#[grammar = "DataReader/grammars/edge_grammar.pest"] +#[grammar = "data_reader/grammars/edge_grammar.pest"] pub struct EdgeParser; lazy_static! { diff --git a/src/DataReader/parse_queries.rs b/src/data_reader/parse_queries.rs similarity index 93% rename from src/DataReader/parse_queries.rs rename to src/data_reader/parse_queries.rs index 1a1f8891..842f1b1a 100644 --- a/src/DataReader/parse_queries.rs +++ b/src/data_reader/parse_queries.rs @@ -1,16 +1,16 @@ extern crate pest; -use crate::ModelObjects::Expressions::{ +use crate::model_objects::expressions::{ ComponentVariable, OperandExpression, QueryExpression, SaveExpression, StateExpression, SystemExpression, }; -use crate::ModelObjects::Query; +use crate::model_objects::Query; use pest::pratt_parser::{Assoc, Op, PrattParser}; use pest::Parser; #[derive(Parser)] -#[grammar = "DataReader/grammars/query_grammar.pest"] +#[grammar = "data_reader/grammars/query_grammar.pest"] pub struct QueryParser; lazy_static! { @@ -20,8 +20,8 @@ lazy_static! { .op(Op::infix(Rule::conjunction_op, Assoc::Left)); } -///This file handles parsing the queries based on the abstract syntax described in the .pest files in the grammar folder -///For clarification see documentation on pest crate +//This file handles parsing the queries based on the abstract syntax described in the .pest files in the grammar folder +//For clarification see documentation on pest crate pub fn parse_system(pair: pest::iterators::Pair) -> SystemExpression { PRATT @@ -34,6 +34,10 @@ pub fn parse_system(pair: pest::iterators::Pair) -> SystemExpression { SystemExpression::Component(comp_name, special_id) } + Rule::variable_name => { + let comp_name = pair.as_str().to_string(); + SystemExpression::Component(comp_name, None) + } _ => unreachable!("Unexpected rule: {:?}", pair.as_rule()), }) .map_infix(|left, op, right| { @@ -196,6 +200,11 @@ fn parse_query(pair: pest::iterators::Pair) -> QueryExpression { let name = pairs.next().map(|it| it.as_str().to_string()); QueryExpression::BisimMinim(SaveExpression { system, name }) } + Rule::syntax => { + let mut pairs = pair.into_inner(); + let system = parse_system(pairs.next().unwrap()); + QueryExpression::Syntax(system) + } _ => unreachable!("Unexpected rule: {:?}", pair.as_rule()), }; query diff --git a/src/DataReader/proto_reader.rs b/src/data_reader/proto_reader.rs similarity index 94% rename from src/DataReader/proto_reader.rs rename to src/data_reader/proto_reader.rs index 5a2a397c..2b3dc92c 100644 --- a/src/DataReader/proto_reader.rs +++ b/src/data_reader/proto_reader.rs @@ -1,18 +1,18 @@ use std::collections::HashMap; use std::convert::TryInto; +use std::rc::Rc; use edbm::util::constraints::{Conjunction, Constraint, Disjunction, Inequality, RawInequality}; use edbm::zones::OwnedFederation; -use crate::ModelObjects::{Component, Declarations, State}; -use crate::ProtobufServer::services::{ +use crate::model_objects::{Component, Decision, Declarations, State}; +use crate::protobuf_server::services::{ clock::Clock as ClockEnum, Clock as ProtoClock, ComponentsInfo, Constraint as ProtoConstraint, Decision as ProtoDecision, Disjunction as ProtoDisjunction, LocationTree as ProtoLocationTree, State as ProtoState, }; -use crate::Simulation::decision::Decision; -use crate::System::specifics::SpecificLocation; -use crate::TransitionSystems::{LocationTree, TransitionSystemPtr}; +use crate::system::specifics::SpecificLocation; +use crate::transition_systems::{LocationTree, TransitionSystemPtr}; use super::component_loader::parse_components_if_some; @@ -82,7 +82,7 @@ pub fn proto_state_to_state(state: ProtoState, system: &TransitionSystemPtr) -> fn proto_location_tree_to_location_tree( location_tree: ProtoLocationTree, system: &TransitionSystemPtr, -) -> LocationTree { +) -> Rc { let target: SpecificLocation = location_tree.into(); system.construct_location_tree(target).unwrap() @@ -155,7 +155,7 @@ fn proto_zone_to_owned_federation( #[cfg(test)] mod tests { - use crate::{tests::refinement::Helper::json_get_system, System::specifics::SpecificState}; + use crate::{system::specifics::SpecificState, tests::refinement::helper::json_get_system}; use super::*; @@ -165,7 +165,7 @@ mod tests { fn assert_state_equals(state1: &State, state2: &State) { assert!( - state1.zone_ref().equals(state2.zone_ref()), + state1.ref_zone().equals(state2.ref_zone()), "Zones are not equal" ); assert_eq!( @@ -217,7 +217,7 @@ mod tests { return; } for action in system.get_actions() { - for t in system.next_transitions(&state.decorated_locations, &action) { + for t in system.next_transitions(Rc::clone(&state.decorated_locations), &action) { let state = t.use_transition_alt(state); if let Some(state) = state { let next_state = convert_to_proto_and_back(&state, system); diff --git a/src/DataReader/serialization.rs b/src/data_reader/serialization.rs similarity index 90% rename from src/DataReader/serialization.rs rename to src/data_reader/serialization.rs index 9e2d3e0a..780dff29 100644 --- a/src/DataReader/serialization.rs +++ b/src/data_reader/serialization.rs @@ -1,7 +1,7 @@ -use crate::DataReader::parse_edge; -use crate::ModelObjects::Expressions; -use crate::ModelObjects::{Component, Declarations, Edge, Location, LocationType, SyncType}; -use crate::Simulation::graph_layout::layout_dummy_component; +use crate::data_reader::parse_edge; +use crate::model_objects::expressions; +use crate::model_objects::{Component, Declarations, Edge, Location, LocationType, SyncType}; +use crate::simulation::graph_layout::layout_dummy_component; use edbm::util::constraints::ClockIndex; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::collections::HashMap; @@ -11,9 +11,9 @@ use std::ops::Add; pub struct DummyNail { pub x: f32, pub y: f32, - pub propertyType: String, - pub propertyX: f32, - pub propertyY: f32, + pub property_type: String, + pub property_x: f32, + pub property_y: f32, } impl DummyNail { @@ -21,9 +21,9 @@ impl DummyNail { Self { x: 0.0, y: 0.0, - propertyType: p_type.to_string(), - propertyX: 10.0, - propertyY: -10.0, + property_type: p_type.to_string(), + property_x: 10.0, + property_y: -10.0, } } } @@ -45,7 +45,7 @@ pub struct DummyEdge { deserialize_with = "decode_guard", serialize_with = "encode_opt_boolexpr" )] - pub guard: Option, + pub guard: Option, #[serde( deserialize_with = "decode_update", serialize_with = "encode_opt_updates" @@ -101,7 +101,7 @@ pub struct DummyComponent { pub edges: Vec, pub description: String, - pub includeInPeriodicCheck: bool, + pub include_in_periodic_check: bool, pub color: String, pub x: f32, pub y: f32, @@ -117,7 +117,7 @@ impl From for DummyComponent { locations: item.locations.into_iter().map(|l| l.into()).collect(), edges: item.edges.into_iter().map(|l| l.into()).collect(), description: "".to_string(), - includeInPeriodicCheck: false, + include_in_periodic_check: false, color: 6.to_string(), x: 0.0, y: 0.0, @@ -138,7 +138,7 @@ pub struct DummyLocation { //deserialize_with = "decode_invariant", serialize_with = "encode_opt_boolexpr" )] - pub invariant: Option, + pub invariant: Option, #[serde( //deserialize_with = "decode_location_type", serialize_with = "encode_location_type", @@ -150,10 +150,10 @@ pub struct DummyLocation { pub x: f32, pub y: f32, pub color: u32, - pub nicknameX: f32, - pub nicknameY: f32, - pub invariantX: f32, - pub invariantY: f32, + pub nickname_x: f32, + pub nickname_y: f32, + pub invariant_x: f32, + pub invariant_y: f32, } impl From for DummyLocation { @@ -167,10 +167,10 @@ impl From for DummyLocation { x: 100.0, y: 100.0, color: 6, - nicknameX: 30.0, - nicknameY: -10.0, - invariantX: 30.0, - invariantY: 10.0, + nickname_x: 30.0, + nickname_y: -10.0, + invariant_x: 30.0, + invariant_y: 10.0, } } } @@ -230,7 +230,7 @@ where /// Function used for deserializing guards pub fn decode_guard<'de, D>( deserializer: D, -) -> Result, D::Error> +) -> Result, D::Error> where D: Deserializer<'de>, { @@ -261,7 +261,7 @@ where //Function used for deserializing invariants pub fn decode_invariant<'de, D>( deserializer: D, -) -> Result, D::Error> +) -> Result, D::Error> where D: Deserializer<'de>, { @@ -270,7 +270,7 @@ where return Ok(None); } match parse_edge::parse_guard(&s) { - Ok(edgeAttribute) => Ok(Some(edgeAttribute)), + Ok(edge_attribute) => Ok(Some(edge_attribute)), Err(e) => panic!("Could not parse invariant {} got error: {:?}", s, e), } } @@ -366,7 +366,7 @@ where } pub fn encode_opt_boolexpr( - opt_expr: &Option, + opt_expr: &Option, serializer: S, ) -> Result where @@ -380,7 +380,7 @@ where } pub fn encode_boolexpr( - expr: &Expressions::BoolExpression, + expr: &expressions::BoolExpression, serializer: S, ) -> Result where @@ -390,7 +390,7 @@ where } pub fn encode_arithexpr( - expr: &Expressions::ArithExpression, + expr: &expressions::ArithExpression, serializer: S, ) -> Result where diff --git a/src/DataReader/xml_parser.rs b/src/data_reader/xml_parser.rs similarity index 91% rename from src/DataReader/xml_parser.rs rename to src/data_reader/xml_parser.rs index a6689347..320e57ee 100644 --- a/src/DataReader/xml_parser.rs +++ b/src/data_reader/xml_parser.rs @@ -1,6 +1,6 @@ -use crate::DataReader::parse_edge; -use crate::DataReader::parse_edge::Update; -use crate::ModelObjects::{ +use crate::data_reader::parse_edge; +use crate::data_reader::parse_edge::Update; +use crate::model_objects::{ Component, Declarations, Edge, Location, LocationType, Query, SyncType, SystemDeclarations, SystemSpecification, }; @@ -13,15 +13,18 @@ use std::io::Read; use std::path::Path; pub fn is_xml_project>(project_path: P) -> bool { - project_path.as_ref().ends_with(".xml") + project_path + .as_ref() + .extension() + .is_some_and(|ext| ext == "xml") } ///Used to parse systems described in xml pub(crate) fn parse_xml_from_file>( - fileName: P, + file_name: P, ) -> (Vec, SystemDeclarations, Vec) { //Open file and read xml - let file = File::open(fileName).unwrap(); + let file = File::open(file_name).unwrap(); let reader = BufReader::new(file); parse_xml(reader) @@ -58,6 +61,7 @@ fn parse_xml(xml_data: R) -> (Vec, SystemDeclarations, Vec Vec match parse_edge::parse_guard(x.text()) { - Ok(edgeAttribute) => Some(edgeAttribute), + Ok(edge_attribute) => Some(edge_attribute), Err(e) => panic!("Could not parse invariant {} got error: {:?}", x.text(), e), }, _ => None, @@ -97,7 +101,7 @@ fn collect_locations(xml_locations: FindChildren, initial_id: &str) -> Vec Vec { let mut edges: Vec = vec![]; for e in xml_edges { - let mut guard: Option = None; + let mut guard: Option = None; let mut updates: Option> = None; let mut sync: String = "".to_string(); for label in e.find_all("label") { @@ -250,19 +254,19 @@ fn decode_sync_type(global_decl: &str) -> SystemSpecification { } if action.ends_with('?') { let r = action.replace('?', ""); - if let Some(Channel_vec) = input_actions.get_mut(&component_name) { - Channel_vec.push(r) + if let Some(channel_vec) = input_actions.get_mut(&component_name) { + channel_vec.push(r) } else { - let Channel_vec = vec![r]; - input_actions.insert(component_name.clone(), Channel_vec); + let channel_vec = vec![r]; + input_actions.insert(component_name.clone(), channel_vec); } } else if action.ends_with('!') { let r = action.replace('!', ""); - if let Some(Channel_vec) = output_actions.get_mut(&component_name) { - Channel_vec.push(r.clone()) + if let Some(channel_vec) = output_actions.get_mut(&component_name) { + channel_vec.push(r.clone()) } else { - let Channel_vec = vec![r.clone()]; - output_actions.insert(component_name.clone(), Channel_vec); + let channel_vec = vec![r.clone()]; + output_actions.insert(component_name.clone(), channel_vec); } } else { panic!("Channel type not defined for Channel {:?}", action) diff --git a/src/EdgeEval/constraint_applyer.rs b/src/edge_eval/constraint_applier.rs similarity index 89% rename from src/EdgeEval/constraint_applyer.rs rename to src/edge_eval/constraint_applier.rs index c7a294e1..927303dd 100644 --- a/src/EdgeEval/constraint_applyer.rs +++ b/src/edge_eval/constraint_applier.rs @@ -1,8 +1,8 @@ use edbm::util::constraints::{ClockIndex, Inequality}; use edbm::zones::OwnedFederation; -use crate::ModelObjects::Declarations; -use crate::ModelObjects::Expressions::{ArithExpression, BoolExpression, Clock}; +use crate::model_objects::expressions::{ArithExpression, BoolExpression, Clock}; +use crate::model_objects::Declarations; pub fn apply_constraints_to_state( guard: &BoolExpression, @@ -80,7 +80,7 @@ fn get_indices( if clocks_left + clocks_right == 0 { return Err(String::from( - "Expressions must use clocks to get indices, this should be unreachable", + "expressions must use clocks to get indices, this should be unreachable", )); } else if clocks_left + clocks_right > 2 { return Err(String::from("Too many clocks")); @@ -132,23 +132,23 @@ fn get_indices( fn replace_vars(expr: &ArithExpression, decls: &Declarations) -> Result { //let mut out = expr.clone(); match expr { - ArithExpression::Difference(l, r) => Ok(ArithExpression::ADif( + ArithExpression::Difference(l, r) => Ok(ArithExpression::a_dif( replace_vars(l, decls)?, replace_vars(r, decls)?, )), - ArithExpression::Addition(l, r) => Ok(ArithExpression::AAdd( + ArithExpression::Addition(l, r) => Ok(ArithExpression::a_add( replace_vars(l, decls)?, replace_vars(r, decls)?, )), - ArithExpression::Multiplication(l, r) => Ok(ArithExpression::AMul( + ArithExpression::Multiplication(l, r) => Ok(ArithExpression::a_mul( replace_vars(l, decls)?, replace_vars(r, decls)?, )), - ArithExpression::Division(l, r) => Ok(ArithExpression::ADiv( + ArithExpression::Division(l, r) => Ok(ArithExpression::a_div( replace_vars(l, decls)?, replace_vars(r, decls)?, )), - ArithExpression::Modulo(l, r) => Ok(ArithExpression::AMod( + ArithExpression::Modulo(l, r) => Ok(ArithExpression::a_mod( replace_vars(l, decls)?, replace_vars(r, decls)?, )), @@ -247,8 +247,8 @@ fn get_clock_val( #[cfg(test)] mod test { use super::get_indices; - use crate::ModelObjects::Declarations; - use crate::ModelObjects::Expressions::ArithExpression; + use crate::model_objects::expressions::ArithExpression; + use crate::model_objects::Declarations; use std::collections::HashMap; #[test] @@ -301,17 +301,17 @@ mod test { ints: HashMap::new(), }; // i-j < c -> c1-c2 < 3 - let left = ArithExpression::ADif(ArithExpression::Clock(1), ArithExpression::Clock(2)); + let left = ArithExpression::a_dif(ArithExpression::Clock(1), ArithExpression::Clock(2)); let right = ArithExpression::Int(3); //Testing: left < right assert_eq!(get_indices(&left, &right, &decl).ok(), Some((1, 2, 3))); - let left = ArithExpression::ADif(ArithExpression::Clock(1), ArithExpression::Int(2)); + let left = ArithExpression::a_dif(ArithExpression::Clock(1), ArithExpression::Int(2)); let right = ArithExpression::Int(3); //Testing: left < right assert_eq!(get_indices(&left, &right, &decl).ok(), Some((1, 0, 5))); - let left = ArithExpression::ADif(ArithExpression::Int(1), ArithExpression::Clock(2)); + let left = ArithExpression::a_dif(ArithExpression::Int(1), ArithExpression::Clock(2)); let right = ArithExpression::Int(3); //Testing: left < right assert_eq!(get_indices(&left, &right, &decl), Ok((0, 2, 2))); @@ -325,7 +325,7 @@ mod test { }; // i-j < c -> c1-c2 > 3 -> c2-c1 < -3 let left = ArithExpression::Int(3); - let right = ArithExpression::ADif(ArithExpression::Clock(1), ArithExpression::Clock(2)); + let right = ArithExpression::a_dif(ArithExpression::Clock(1), ArithExpression::Clock(2)); //Testing: left < right assert_eq!(get_indices(&left, &right, &decl), Ok((2, 1, -3))); @@ -354,14 +354,14 @@ mod test { ints: HashMap::new(), }; let left = ArithExpression::Clock(1); - let right = ArithExpression::ADif(ArithExpression::Clock(2), ArithExpression::Int(3)); + let right = ArithExpression::a_dif(ArithExpression::Clock(2), ArithExpression::Int(3)); assert_eq!(get_indices(&left, &right, &decl), Ok((1, 2, -3))); - let left = ArithExpression::ADif(ArithExpression::Clock(2), ArithExpression::Int(3)); + let left = ArithExpression::a_dif(ArithExpression::Clock(2), ArithExpression::Int(3)); let right = ArithExpression::Clock(1); assert_eq!(get_indices(&left, &right, &decl), Ok((2, 1, 3))); - let left = ArithExpression::ADif(ArithExpression::Int(2), ArithExpression::Clock(3)); + let left = ArithExpression::a_dif(ArithExpression::Int(2), ArithExpression::Clock(3)); let right = ArithExpression::Clock(1); assert_eq!(get_indices(&left, &right, &decl).ok(), None); } @@ -421,13 +421,13 @@ mod test { ints: HashMap::new(), }; // i-j < c -> c1-c2 > 3 -> c2-c1 < -3 - let left = ArithExpression::ADif(ArithExpression::Clock(1), ArithExpression::Int(2)); - let right = ArithExpression::ADif(ArithExpression::Clock(3), ArithExpression::Int(4)); + let left = ArithExpression::a_dif(ArithExpression::Clock(1), ArithExpression::Int(2)); + let right = ArithExpression::a_dif(ArithExpression::Clock(3), ArithExpression::Int(4)); //Testing: left < right assert_eq!(get_indices(&left, &right, &decl), Ok((1, 3, -2))); - let left = ArithExpression::ADif(ArithExpression::Int(1), ArithExpression::Clock(2)); - let right = ArithExpression::ADif(ArithExpression::Int(3), ArithExpression::Clock(4)); + let left = ArithExpression::a_dif(ArithExpression::Int(1), ArithExpression::Clock(2)); + let right = ArithExpression::a_dif(ArithExpression::Int(3), ArithExpression::Clock(4)); //Testing: left < right assert_eq!(get_indices(&left, &right, &decl), Ok((4, 2, 2))); } @@ -538,7 +538,7 @@ mod test { clocks: HashMap::new(), ints: HashMap::new(), }; - let left = ArithExpression::ADif(ArithExpression::Clock(1), ArithExpression::Clock(2)); + let left = ArithExpression::a_dif(ArithExpression::Clock(1), ArithExpression::Clock(2)); let right = Box::new(ArithExpression::Clock(3)); //Testing: left < right @@ -557,7 +557,7 @@ mod test { assert_eq!( get_indices(&left, &right, &decl), Err( - "Expressions must use clocks to get indices, this should be unreachable" + "expressions must use clocks to get indices, this should be unreachable" .to_string() ) ); @@ -571,7 +571,7 @@ mod test { assert_eq!( get_indices(&left, &right, &decl), Err( - "Expressions must use clocks to get indices, this should be unreachable" + "expressions must use clocks to get indices, this should be unreachable" .to_string() ) ); @@ -583,22 +583,22 @@ mod test { clocks: HashMap::new(), ints: HashMap::new(), }; - let left = ArithExpression::ADif( + let left = ArithExpression::a_dif( // = 4 ArithExpression::Int(10), - ArithExpression::ADif( + ArithExpression::a_dif( ArithExpression::Int(9), - ArithExpression::ADif( + ArithExpression::a_dif( ArithExpression::Int(8), - ArithExpression::ADif( + ArithExpression::a_dif( ArithExpression::Int(7), - ArithExpression::ADif( + ArithExpression::a_dif( ArithExpression::Clock(6), - ArithExpression::ADif( + ArithExpression::a_dif( ArithExpression::Int(5), - ArithExpression::ADif( + ArithExpression::a_dif( ArithExpression::Int(4), - ArithExpression::ADif( + ArithExpression::a_dif( ArithExpression::Int(3), ArithExpression::Int(2), ), @@ -620,7 +620,7 @@ mod test { clocks: HashMap::new(), ints: HashMap::new(), }; - let left = ArithExpression::ADif( + let left = ArithExpression::a_dif( ArithExpression::Multiplication( Box::new(ArithExpression::Clock(3)), Box::new(ArithExpression::Int(3)), @@ -631,14 +631,14 @@ mod test { //Testing: left < right assert_eq!(get_indices(&left, &right, &decl).ok(), None); - let left = ArithExpression::ADif( + let left = ArithExpression::a_dif( ArithExpression::Multiplication( Box::new(ArithExpression::Int(3)), Box::new(ArithExpression::Int(3)), ), ArithExpression::Clock(10), ); - let right = ArithExpression::ADif(ArithExpression::Int(10), ArithExpression::Clock(10)); + let right = ArithExpression::a_dif(ArithExpression::Int(10), ArithExpression::Clock(10)); //Testing: left < right assert_eq!(get_indices(&left, &right, &decl), Ok((10, 10, 1))); } diff --git a/src/edge_eval/mod.rs b/src/edge_eval/mod.rs new file mode 100644 index 00000000..60eb9a9e --- /dev/null +++ b/src/edge_eval/mod.rs @@ -0,0 +1,2 @@ +pub mod constraint_applier; +pub mod updater; diff --git a/src/EdgeEval/updater.rs b/src/edge_eval/updater.rs similarity index 94% rename from src/EdgeEval/updater.rs rename to src/edge_eval/updater.rs index 059fdc96..a375cd9d 100644 --- a/src/EdgeEval/updater.rs +++ b/src/edge_eval/updater.rs @@ -1,9 +1,9 @@ use std::collections::HashMap; use std::fmt; -use crate::DataReader::parse_edge; -use crate::ModelObjects::Declarations; -use crate::ModelObjects::Expressions::ArithExpression; +use crate::data_reader::parse_edge; +use crate::model_objects::expressions::ArithExpression; +use crate::model_objects::Declarations; use colored::Colorize; use edbm::util::constraints::ClockIndex; use edbm::zones::OwnedFederation; diff --git a/src/lib.rs b/src/lib.rs index 4a421870..04ec87c1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,23 +1,21 @@ -#![allow(non_snake_case)] -pub mod DataReader; -pub mod DataTypes; -pub mod EdgeEval; -pub mod ModelObjects; -pub mod ProtobufServer; -pub mod Simulation; -pub mod System; -pub mod TransitionSystems; pub mod cli; +pub mod data_reader; +pub mod edge_eval; pub mod logging; +pub mod model_objects; +pub mod protobuf_server; +pub mod simulation; +pub mod system; pub mod tests; +pub mod transition_systems; -pub use crate::DataReader::component_loader::{ +pub use crate::data_reader::component_loader::{ ComponentLoader, JsonProjectLoader, ProjectLoader, XmlProjectLoader, }; -pub use crate::DataReader::{parse_queries, xml_parser}; -use crate::ProtobufServer::services::query_request::Settings; -pub use crate::System::extract_system_rep; -pub use ProtobufServer::start_grpc_server_with_tokio; +pub use crate::data_reader::{parse_queries, xml_parser}; +use crate::protobuf_server::services::query_request::Settings; +pub use crate::system::extract_system_rep; +pub use protobuf_server::start_grpc_server_with_tokio; /// The default settings pub const DEFAULT_SETTINGS: Settings = Settings { diff --git a/src/logging.rs b/src/logging.rs index c3eb6739..0c0894db 100644 --- a/src/logging.rs +++ b/src/logging.rs @@ -1,4 +1,4 @@ -use crate::ProtobufServer::services::query_response::Information; +use crate::protobuf_server::services::query_response::Information; use chrono::Local; use colored::{ColoredString, Colorize}; use log::SetLoggerError; diff --git a/src/main.rs b/src/main.rs index 9d062dfe..8b1beeaf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,10 @@ -#![allow(non_snake_case)] use reveaal::cli::Args; use reveaal::logging::setup_logger; -use reveaal::ModelObjects::Query; -use reveaal::System::query_failures::QueryResult; +use reveaal::model_objects::Query; +use reveaal::system::query_failures::QueryResult; use clap::Parser; -use reveaal::ProtobufServer::services::query_request::Settings; +use reveaal::protobuf_server::services::query_request::Settings; use reveaal::{ extract_system_rep, parse_queries, start_grpc_server_with_tokio, xml_parser, ComponentLoader, JsonProjectLoader, ProjectLoader, XmlProjectLoader, diff --git a/src/model_objects/component.rs b/src/model_objects/component.rs new file mode 100644 index 00000000..62ca9a1d --- /dev/null +++ b/src/model_objects/component.rs @@ -0,0 +1,805 @@ +use crate::data_reader::serialization::{decode_declarations, DummyComponent}; + +use edbm::util::bounds::Bounds; +use edbm::util::constraints::ClockIndex; + +use crate::model_objects::{Edge, Location, SyncType}; +use itertools::Itertools; +use log::info; +use serde::{Deserialize, Serialize}; +use std::collections::hash_map::Entry; +use std::collections::{HashMap, HashSet}; +use std::hash::Hash; +use std::iter::FromIterator; + +/// Errors related to reducing clocks +#[derive(Debug)] +pub enum ClockReduceError { + /// Takes a clock name + ClockIndexNotFound(String), + /// Missing clockIndices without a specific clock in mind + NoClockIndices, + /// Used for evaluating the expressions in clock_usages + EvaluationError(String), + /// For all errors relating to clockReduction that do not fit in the others + Other(String), +} +impl std::fmt::Display for ClockReduceError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ClockReduceError::ClockIndexNotFound(clock) => { + write!(f, "Clock index not found for clock: {}", clock) + } + ClockReduceError::NoClockIndices => write!(f, "No clock indices found"), + ClockReduceError::EvaluationError(msg) => write!(f, "Evaluation error: {}", msg), + ClockReduceError::Other(msg) => write!(f, "Other error: {}", msg), + } + } +} +impl std::error::Error for ClockReduceError {} +impl From for ClockReduceError { + fn from(err: String) -> Self { + ClockReduceError::Other(err) + } +} + +/// The basic struct used to represent components read from either Json or xml +#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)] +#[serde(into = "DummyComponent")] +pub struct Component { + pub name: String, + + #[serde( + deserialize_with = "decode_declarations", + serialize_with = "encode_declarations" + )] + pub declarations: Declarations, + pub locations: Vec, + pub edges: Vec, + pub special_id: Option, + #[serde(skip_deserializing)] + pub clock_usages: HashMap, +} + +/// Details to what edges and locations, clocks are used and where there are updates +#[derive(Debug, Default, Deserialize, Clone, Eq, PartialEq)] +pub struct ClockUsage { + pub edges: HashSet, + pub locations: HashSet, + pub updates: HashSet, +} + +impl ClockUsage { + // edge_id is generated in function remake_edge_ids + pub fn is_in_edge(&self, edge_id: &str) -> bool { + self.edges.contains(edge_id) || self.updates.contains(edge_id) + } + pub fn add_edge(&mut self, edge_id: String) { + self.edges.insert(edge_id); + } + pub fn is_updated_in_edge(&self, edge_id: &str) -> bool { + self.updates.contains(edge_id) + } + pub fn add_update(&mut self, edge_id: String) { + self.updates.insert(edge_id); + } + pub fn is_in_location(&self, location_id: &str) -> bool { + self.locations.contains(location_id) + } + pub fn add_location(&mut self, location_id: String) { + self.locations.insert(location_id); + } +} + +impl DeclarationProvider for Component { + fn get_declarations(&self) -> &Declarations { + &self.declarations + } +} + +impl Component { + pub fn set_clock_indices(&mut self, indices: &mut ClockIndex) { + self.declarations.set_clock_indices(*indices); + *indices += self.declarations.get_clock_count(); + } + + pub fn initialise_clock_usages(&mut self) { + self.clock_usages = HashMap::default(); + for clock in self.declarations.clocks.keys() { + self.clock_usages + .insert(clock.clone(), ClockUsage::default()); + } + } + + pub fn populate_usages_with_guards(&mut self) { + let edges = self.edges.clone(); + let clock_usages = &mut self.clock_usages; + for edge in edges { + match edge.guard { + None => (), + Some(ref exp) => { + for clock_name in exp.get_var_names() { + if let Some(clock_struct) = clock_usages.get_mut(&clock_name) { + clock_struct.add_edge(edge.id.clone()) + } + } + } + } + } + } + + pub fn populate_usages_with_updates(&mut self) { + let edges = self.edges.clone(); + let clock_usages = &mut self.clock_usages; + for edge in edges { + match edge.update { + None => (), + Some(ref updates) => { + for update in updates.clone() { + // Save left side of update clock + let update_name: String = update.get_variable_name().to_string(); + if let Some(clock_struct) = clock_usages.get_mut(&update_name) { + clock_struct.add_update(edge.id.clone()); + } + // Save right side of update clocks + for clock_name in update.expression.get_var_names() { + if let Some(clock_struct) = clock_usages.get_mut(&clock_name) { + clock_struct.add_edge(edge.id.clone()) + } + } + } + } + } + } + } + + pub fn populate_usages_with_invariants(&mut self) { + let locations = self.locations.clone(); + let clock_usages = &mut self.clock_usages; + for location in locations { + match location.invariant { + None => (), + Some(ref exp) => { + for clock_name in exp.get_var_names() { + if let Some(clock_struct) = clock_usages.get_mut(&clock_name) { + clock_struct.add_location(location.id.clone()) + } + } + } + } + } + } + + pub fn remove_redundant_clocks(&mut self) -> Result<(), ClockReduceError> { + let mut used_clocks: HashSet = self.clock_usages.keys().cloned().collect(); + let unused_clocks: HashSet = self.get_unused_clocks(&self.clock_usages); + + // Remove the clocks(and their updates) which never gets read from + for unused_clocks in &unused_clocks { + used_clocks.remove(unused_clocks); + self.declarations.remove_clock_from_dcls(unused_clocks); + self.remove_update(unused_clocks); + } + + // Remap the clocks equivalent to each other + let mut equivalent_clock_groups = self.find_equivalent_clock_groups(&used_clocks)?; + for clock_group in &mut equivalent_clock_groups { + let mut clock_group_indices: HashSet = HashSet::new(); + for clock in clock_group.iter() { + let index = self + .declarations + .get_clock_index_by_name(clock) + .ok_or_else(|| format!("Clock index not found for clock: {}", clock))?; + clock_group_indices.insert(*index); + } + let lowest_clock = *clock_group_indices + .iter() + .min() + .ok_or(ClockReduceError::NoClockIndices)?; + clock_group_indices.remove(&lowest_clock); + self.replace_clock(lowest_clock, &clock_group_indices); + } + Ok(()) + } + + pub fn remove_update(&mut self, clock: &String) { + self.edges + .iter_mut() + .filter_map(|edge| edge.update.as_mut()) + .for_each(|var| var.retain(|u| u.variable != *clock)); + } + + pub fn get_unused_clocks(&self, clock_usages: &HashMap) -> HashSet { + // If the clock in question never appears in these it is never used as a Guard/Invariant and it can therefore be removed + let unused_clocks: HashSet = clock_usages + .iter() + .filter(|(_, clock_info)| { + clock_info.edges.is_empty() && clock_info.locations.is_empty() + }) + .map(|(clock_name, _)| clock_name.clone()) + .collect(); + unused_clocks + } + + // Function which should return a vector with all the finished equivalent clock groups + pub fn find_equivalent_clock_groups( + &self, + used_clocks: &HashSet, + ) -> Result>, ClockReduceError> { + if used_clocks.len() < 2 || self.edges.is_empty() { + return Ok(vec![HashSet::new()]); + } + // Start with all clocks in the same clock group with the global clock + let mut equivalent_clock_groups: Vec> = vec![used_clocks.clone()]; + for edge in &self.edges { + // Find the clocks affected by this edge + let local_equivalences = self.find_local_equivalences(edge)?; + // Update the global clocks variable with the new information and split the groups + self.update_equivalent_clock_groups(&mut equivalent_clock_groups, &local_equivalences); + } + Ok(equivalent_clock_groups) + } + + // Find the clocks that diverge from their respective clock groups on a edge/transition + fn find_local_equivalences( + &self, + edge: &Edge, + ) -> Result, ClockReduceError> { + let mut local_equivalence_map = HashMap::new(); + if let Some(updates) = &edge.update { + for update in updates { + local_equivalence_map.insert( + update.variable.clone(), + update.expression.get_evaluated_int()? as u32, + ); + } + } + Ok(local_equivalence_map) + } + // Updates the current version of the equivalent clock groups based on the new local equivalences + pub fn update_equivalent_clock_groups( + &self, + equivalent_clock_groups: &mut Vec>, + local_equivalences: &HashMap, + ) { + let mut new_groups: HashMap> = HashMap::new(); + let mut group_offset: usize = u32::MAX as usize; + + for (old_group_index, equivalent_clock_group) in + equivalent_clock_groups.iter_mut().enumerate() + { + for clock in equivalent_clock_group.iter() { + if let Some(group_id) = local_equivalences.get(clock) { + Component::get_or_insert( + &mut new_groups, + group_offset + ((*group_id) as usize), + ) + .insert(clock.clone()); + } else { + Component::get_or_insert(&mut new_groups, old_group_index) + .insert(clock.clone()); + } + } + group_offset += (u32::MAX as usize) * 2; + } + *equivalent_clock_groups = new_groups + .into_iter() + .map(|pair| pair.1) + .filter(|group| group.len() > 1) + .collect(); + } + fn get_or_insert(map: &'_ mut HashMap, key: K) -> &'_ mut V { + match map.entry(key) { + Entry::Occupied(o) => o.into_mut(), + Entry::Vacant(v) => v.insert(V::default()), + } + } + + // Compresses index of the declaration to move clock_indexes to fill gaps + pub fn compress_dcls(&mut self) { + let mut seen: HashMap = HashMap::new(); + let mut clocks: Vec<&mut ClockIndex> = self.declarations.clocks.values_mut().collect(); + clocks.sort(); + let mut index = 1; + for clock in clocks { + if let Some(val) = seen.get(clock) { + *clock = *val; + } else { + seen.insert(*clock, index); + *clock = index; + index += 1; + } + } + } + + pub fn get_location_by_name(&self, name: &str) -> &Location { + let loc_vec = self + .locations + .iter() + .filter(|l| l.id == name) + .collect::>(); + + if loc_vec.len() == 1 { + loc_vec[0] + } else { + panic!("Unable to retrieve location based on id: {}", name) + } + } + + pub fn get_input_actions(&self) -> Vec { + self.get_specific_actions(SyncType::Input) + } + + pub fn get_output_actions(&self) -> Vec { + self.get_specific_actions(SyncType::Output) + } + + fn get_specific_actions(&self, sync_type: SyncType) -> Vec { + Vec::from_iter( + self.edges + .iter() + .filter(|e| e.sync_type == sync_type && e.sync != "*") + .map(|e| e.sync.clone()) + .unique(), + ) + } + + // End of basic methods + + pub fn get_max_bounds(&self, dimensions: ClockIndex) -> Bounds { + let mut max_bounds = Bounds::new(dimensions); + for (clock_name, clock_id) in &self.declarations.clocks { + let max_bound = i32::max( + self.edges + .iter() + .filter_map(|e| e.guard.clone()) + .map(|g| g.get_max_constant(*clock_id, clock_name)) + .max() + .unwrap_or_default(), + self.locations + .iter() + .filter_map(|l| l.invariant.clone()) + .map(|i| i.get_max_constant(*clock_id, clock_name)) + .max() + .unwrap_or_default(), + ); + + // TODO: find more precise upper and lower bounds for clocks + max_bounds.add_lower(*clock_id, max_bound); + max_bounds.add_upper(*clock_id, max_bound); + } + + max_bounds + } + + /// Redoes the components Edge IDs by giving them new unique IDs based on their index. + pub fn remake_edge_ids(&mut self) { + // Give all edges a name + for (index, edge) in self.edges.iter_mut().enumerate() { + edge.id = format!("E{}", index); + } + } + + /// Replaces duplicate clock with a new + /// # Arguments + /// `global_index`: The index of the global clock\n + /// `indices` are the duplicate clocks that should be set to `global_index` + pub(crate) fn replace_clock( + &mut self, + global_index: ClockIndex, + indices: &HashSet, + ) { + for (name, index) in self + .declarations + .clocks + .iter_mut() + .filter(|(_, c)| indices.contains(c)) + { + let old = *index; + *index = global_index; + // TODO: Maybe log the global clock name instead of index + info!( + "Replaced Clock '{name}' (index {old}) with {global_index} in component {}", + self.name + ); // Should be changed in the future to be the information logger + } + } +} + +pub trait DeclarationProvider { + fn get_declarations(&self) -> &Declarations; +} + +/// The declaration struct is used to hold the indices for each clock, and is meant to be the owner of int variables once implemented +#[derive(Debug, Deserialize, Clone, PartialEq, Eq, Serialize)] +pub struct Declarations { + pub ints: HashMap, + pub clocks: HashMap, +} + +impl Declarations { + pub fn empty() -> Declarations { + Declarations { + ints: HashMap::new(), + clocks: HashMap::new(), + } + } + + pub fn remove_clock_from_dcls(&mut self, clock: &str) { + self.clocks.remove(clock); + } + + pub fn get_clock_count(&self) -> usize { + self.clocks.values().collect::>().len() + } + + pub fn set_clock_indices(&mut self, start_index: ClockIndex) { + for (_, v) in self.clocks.iter_mut() { + *v += start_index + } + } + + pub fn get_clock_index_by_name(&self, name: &str) -> Option<&ClockIndex> { + self.clocks.get(name) + } + + /// Gets the name of a given `ClockIndex`. + /// Returns `None` if it does not exist in the declarations + pub fn get_clock_name_by_index(&self, index: ClockIndex) -> Option<&String> { + self.clocks + .iter() + .find(|(_, v)| **v == index) + .map(|(k, _)| k) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::JsonProjectLoader; + use std::collections::HashSet; + use test_case::test_case; + struct SetupContext { + test_comp: Component, + expected: HashSet, + } + + /// Simplifying the test process by loading a component in a separate function, instead of in each test + fn setup(comp_name: &str, expected: Vec) -> SetupContext { + let mut project_loader = JsonProjectLoader::new_loader(PATH, crate::tests::TEST_SETTINGS); + project_loader.get_settings_mut().disable_clock_reduction = true; + let mut test_comp = project_loader.get_component(comp_name).unwrap().clone(); + let expected: HashSet = expected.into_iter().collect(); + // Initialise clock usage structs for each clock in component. + test_comp.initialise_clock_usages(); + + SetupContext { + test_comp, + expected, + } + } + + // File path to project for project_loader + // PopulateClocks is designed to test for additional edge cases + const PATH: &str = "samples/json/PopulateClocks"; + + #[test] + fn initialise_clock_usages() { + let context = setup("Update", vec![]); + + assert!( + context.test_comp.clock_usages.contains_key("x") + && context.test_comp.clock_usages.contains_key("y") + ); + } + + // TODO: maybe update component names to reflect tests? + #[test_case("Machine", vec!["E25".to_string(),"E29".to_string()], true; "Clock with usage in two guards")] + #[test_case("Machine", vec!["E36".to_string(),"E45".to_string()], false; "Clock with usage in two fake guards")] + #[test_case("Machine4", vec!["E1".to_string(),"E5".to_string()], true; "Clock with usage in two guards avoiding cherrypicking")] + #[test_case("Machine4", vec!["E36".to_string(),"E45".to_string()], false; "Clock with usage in two fake guards avoiding cherrypicking")] + fn populate_usages_with_guards(comp_name: &str, expected_edges: Vec, verdict: bool) { + // Instantiating variables used in all tests using the "setup" function above. + let mut context = setup(comp_name, expected_edges); + + context.test_comp.populate_usages_with_guards(); + + // Confirming edges where clock "y" exists. + assert_eq!( + (context.test_comp.clock_usages.get("y").unwrap().edges == context.expected), + verdict + ); + } + + #[test_case("Machine", vec!["E27".to_string()], true; "Clock with usage in one update")] + #[test_case("Machine", vec!["E25".to_string(),"E26".to_string()], false; "Clock with usage in two non-updates")] + fn populate_usages_with_updates_lhs( + comp_name: &str, + expected_edges: Vec, + verdict: bool, + ) { + let mut context = setup(comp_name, expected_edges); + + context.test_comp.populate_usages_with_updates(); + + assert_eq!( + (context.test_comp.clock_usages.get("y").unwrap().updates == context.expected), + verdict + ); + } + + // A new sample was created for this test to accommodate the edge-case y=x. + #[test_case("Update", vec!["E27".to_string()], true; "Clock on both rhs and lhs of update")] + #[test_case("Update", vec!["E26".to_string()], false; "Clock on both rhs and lhs of fake update")] + fn populate_usages_with_updates_rhs( + comp_name: &str, + expected_edges: Vec, + verdict: bool, + ) { + let mut context = setup(comp_name, expected_edges); + + context.test_comp.populate_usages_with_updates(); + + // The rhs of an update is handled like a guard on an edge, therefore we check if the edge has been added correctly. + assert_eq!( + (context.test_comp.clock_usages.get("x").unwrap().edges == context.expected), + verdict + ); + } + + #[test_case("Machine", vec!["L4".to_string()], true; "Clock with usage in one invariant")] + #[test_case("Machine", vec!["L6".to_string()], false; "Clock with usage in one fake invariant")] + fn populate_usages_with_invariants( + comp_name: &str, + expected_locations: Vec, + verdict: bool, + ) { + let mut context = setup(comp_name, expected_locations); + + context.test_comp.populate_usages_with_invariants(); + + assert_eq!( + (context.test_comp.clock_usages.get("y").unwrap().locations == context.expected), + verdict + ); + } + // Clock Reduction tests + + /// Test for testing complete clock reduction, by removing redundant clocks and compressing the declarations + #[test] + fn clock_reduction() { + let mut project_loader = JsonProjectLoader::new_loader(PATH, crate::tests::TEST_SETTINGS); + project_loader.get_settings_mut().disable_clock_reduction = true; + let mut test_comp = project_loader.get_component("Component1").unwrap().clone(); + + let expected: HashMap = HashMap::from([ + ("x".to_string(), 1), + ("y".to_string(), 1), + ("z".to_string(), 1), + ("i".to_string(), 2), + ]); + + // Initializing component clock scopes. + test_comp.initialise_clock_usages(); + test_comp.populate_usages_with_guards(); + test_comp.populate_usages_with_updates(); + test_comp.populate_usages_with_invariants(); + + // Clock reduction. + test_comp + .remove_redundant_clocks() + .expect("Could not remove redundant clocks."); + test_comp.compress_dcls(); + + assert_eq!(test_comp.declarations.clocks, expected); + } + + #[test] + fn find_and_remove_unused_clocks() { + let mut project_loader = JsonProjectLoader::new_loader(PATH, crate::tests::TEST_SETTINGS); + project_loader.get_settings_mut().disable_clock_reduction = true; + let mut test_comp = project_loader.get_component("Researcher2").unwrap().clone(); + + test_comp.initialise_clock_usages(); + test_comp.populate_usages_with_guards(); + test_comp.populate_usages_with_updates(); + test_comp.populate_usages_with_invariants(); + + let mut used_clocks: HashSet = test_comp.clock_usages.keys().cloned().collect(); + let unused_clocks: HashSet = test_comp.get_unused_clocks(&test_comp.clock_usages); + + // Remove the clocks(and their updates) which never get read from + for unused_clocks in &unused_clocks { + used_clocks.remove(unused_clocks); + test_comp.declarations.remove_clock_from_dcls(unused_clocks); + test_comp.remove_update(unused_clocks); + } + + assert!(!test_comp.declarations.clocks.contains_key("y")); + assert!(!used_clocks.contains("y")); + + assert!(!test_comp.declarations.clocks.contains_key("z")); + assert!(!used_clocks.contains("z")); + + assert!(!test_comp.declarations.clocks.contains_key("k")); + assert!(!used_clocks.contains("k")); + } + + #[test] + fn remove_redundant_clocks() { + let mut project_loader = JsonProjectLoader::new_loader(PATH, crate::tests::TEST_SETTINGS); + project_loader.get_settings_mut().disable_clock_reduction = true; + let mut test_comp = project_loader.get_component("Component1").unwrap().clone(); + + let expected: HashMap = HashMap::from([ + ("x".to_string(), 1), + ("y".to_string(), 1), + ("z".to_string(), 1), + ("i".to_string(), 4), + ]); + + test_comp.initialise_clock_usages(); + test_comp.populate_usages_with_guards(); + test_comp.populate_usages_with_updates(); + test_comp.populate_usages_with_invariants(); + + test_comp + .remove_redundant_clocks() + .expect("Could not remove redundant clocks."); + + // TODO: Test for remapped clocks instead of just if they exist in component + assert_eq!(test_comp.declarations.clocks, expected); + } + + #[test_case("Machine4", "y".to_string())] + fn remove_update(comp_name: &str, clock: String) { + let mut project_loader = JsonProjectLoader::new_loader(PATH, crate::tests::TEST_SETTINGS); + project_loader.get_settings_mut().disable_clock_reduction = true; + let mut test_comp = project_loader.get_component(comp_name).unwrap().clone(); + + test_comp.remove_update(&clock); + + for edge in test_comp.edges.iter() { + if let Some(updates) = &edge.update { + for update in updates { + assert!( + !clock.contains(&update.variable), + "Update for {} was not removed", + update.variable + ); + } + } + } + } + + #[test] + fn get_unused_clocks() { + let mut project_loader = JsonProjectLoader::new_loader(PATH, crate::tests::TEST_SETTINGS); + project_loader.get_settings_mut().disable_clock_reduction = true; + let mut test_comp = project_loader.get_component("Update").unwrap().clone(); + + // TODO: create component that reflects the below clock scopes to make test more compact. + test_comp.clock_usages = HashMap::from([ + ( + "y".to_string(), + ClockUsage { + edges: HashSet::from(["E3".to_string(), "E4".to_string()]), + locations: HashSet::from([ + "L1".to_string(), + "L2".to_string(), + "L3".to_string(), + ]), + updates: HashSet::from([]), + }, + ), + ( + "x".to_string(), + ClockUsage { + edges: HashSet::new(), + locations: HashSet::new(), + updates: HashSet::new(), + }, + ), + ]); + + let unused_clocks = test_comp.get_unused_clocks(&test_comp.clock_usages); + + assert!(unused_clocks.contains("x")); + assert!(!unused_clocks.contains("y")); + } + + #[test_case("Component1", vec![HashSet::from(["x".to_string(),"y".to_string(),"z".to_string()])])] + #[test_case("Component3", vec![])] + fn find_equivalent_clock_groups(comp_name: &str, result: Vec>) { + let mut project_loader = JsonProjectLoader::new_loader(PATH, crate::tests::TEST_SETTINGS); + project_loader.get_settings_mut().disable_clock_reduction = true; + let test_comp = project_loader.get_component(comp_name).unwrap().clone(); + + let mut clocks: HashSet = HashSet::new(); + let all_clocks = &test_comp.declarations.clocks; + for clock_name in all_clocks.keys() { + clocks.insert(clock_name.clone()); + } + + let equivalent_clock_groups = test_comp.find_equivalent_clock_groups(&clocks).unwrap(); + + assert_eq!(equivalent_clock_groups, result); + } + #[test_case("Updates3", "E12", HashMap::from([("y".to_string(), 5), ("z".to_string(), 7)]))] + fn find_local_equivalences(comp_name: &str, edge_id: &str, result: HashMap) { + let mut project_loader = JsonProjectLoader::new_loader(PATH, crate::tests::TEST_SETTINGS); + project_loader.get_settings_mut().disable_clock_reduction = true; + let test_comp = project_loader.get_component(comp_name).unwrap().clone(); + + let edge = test_comp.edges.iter().find(|&e| e.id == edge_id).unwrap(); + let local_equivalence_map = test_comp.find_local_equivalences(edge).unwrap(); + + assert_eq!(local_equivalence_map, result); + } + + #[test] + fn update_equivalent_clock_groups() { + let mut project_loader = JsonProjectLoader::new_loader(PATH, crate::tests::TEST_SETTINGS); + project_loader.get_settings_mut().disable_clock_reduction = true; + let mut test_comp = project_loader + .get_component("Component7_global_groups") + .unwrap() + .clone(); + + let expected: Vec> = + vec![vec!["y", "z"].into_iter().map(String::from).collect()]; + + let used_clocks: HashSet = vec!["x".to_string(), "y".to_string(), "z".to_string()] + .into_iter() + .collect(); + + let mut equivalent_clock_groups: Vec> = vec![used_clocks.clone()]; + + let local_equivalences: HashMap = + HashMap::from([("y".to_string(), 0), ("z".to_string(), 0)]); + + test_comp.initialise_clock_usages(); + test_comp.populate_usages_with_guards(); + test_comp.populate_usages_with_updates(); + test_comp.populate_usages_with_invariants(); + + test_comp.update_equivalent_clock_groups(&mut equivalent_clock_groups, &local_equivalences); + + assert_eq!(equivalent_clock_groups, expected); + } + + #[test_case("Machine", "y", "y", 5, true; "Compressing after one removed clock ")] + #[test_case("Machine", "x", "y", 4, true; "Two keys for same value removed and clocks compressed")] + #[test_case("Machine", "z", "v", 3, true; "Compressing after two removed clocks")] + fn compress_dcls(comp_name: &str, key1: &str, key2: &str, expected: ClockIndex, verdict: bool) { + let mut project_loader = JsonProjectLoader::new_loader(PATH, crate::tests::TEST_SETTINGS); + project_loader.get_settings_mut().disable_clock_reduction = true; + let mut test_comp = project_loader.get_component(comp_name).unwrap().clone(); + + test_comp.declarations.ints = HashMap::from([ + ("x".to_string(), 5), + ("y".to_string(), 5), + ("z".to_string(), 10), + ("w".to_string(), 6), + ("v".to_string(), 6), + ("q".to_string(), 6), + ]); + test_comp.declarations.clocks = HashMap::from([ + ("x".to_string(), 1), + ("y".to_string(), 1), + ("z".to_string(), 2), + ("w".to_string(), 3), + ("v".to_string(), 4), + ("q".to_string(), 5), + ]); + + test_comp.declarations.clocks.remove(key1); + test_comp.declarations.clocks.remove(key2); + test_comp.compress_dcls(); + + assert_eq!( + (test_comp.declarations.clocks.get("q") == Some(&expected)), + verdict + ); + } +} diff --git a/src/Simulation/decision.rs b/src/model_objects/decision.rs similarity index 87% rename from src/Simulation/decision.rs rename to src/model_objects/decision.rs index 2b18f4c5..c097c369 100644 --- a/src/Simulation/decision.rs +++ b/src/model_objects/decision.rs @@ -1,5 +1,7 @@ -use crate::ModelObjects::{State, Transition}; -use crate::TransitionSystems::TransitionSystemPtr; +use std::rc::Rc; + +use crate::model_objects::{State, Transition}; +use crate::transition_systems::TransitionSystemPtr; /// Represent a decision in a any composition of components: In the current `state` [`State`] we have decided to take this `action` [`String`]. #[derive(Debug, Clone)] @@ -16,7 +18,8 @@ impl Decision { /// # Panics /// Panics if the [`Decision`] leads to no new states or is ambiguous (leads to multiple new states) pub fn resolve(&self, system: &TransitionSystemPtr) -> Vec { - let transitions = system.next_transitions(&self.state.decorated_locations, &self.action); + let transitions = + system.next_transitions(Rc::clone(&self.state.decorated_locations), &self.action); let mut next_states: Vec<_> = transitions .into_iter() .filter_map(|transition| transition.use_transition_alt(&self.state)) @@ -44,7 +47,7 @@ impl Decision { // Intersect the state zone with the allowed zone state.update_zone(|zone| zone.intersection(&allowed)); // Check if the new state is empty - if !state.zone_ref().is_empty() { + if !state.ref_zone().is_empty() { let next_state = transition.use_transition_alt(&state).expect( "If the allowed zone is non-empty, the transition should lead to a non-empty state", ); @@ -64,7 +67,8 @@ impl Decision { let mut next_decisions = vec![]; for action in system.get_actions() { - let possible_transitions = system.next_transitions(&state.decorated_locations, &action); + let possible_transitions = + system.next_transitions(Rc::clone(&state.decorated_locations), &action); for t in possible_transitions { if let Some(decision) = Decision::from_state_transition(state.clone(), &t, &action) { diff --git a/src/ModelObjects/edge.rs b/src/model_objects/edge.rs similarity index 92% rename from src/ModelObjects/edge.rs rename to src/model_objects/edge.rs index acf64c70..11441911 100644 --- a/src/ModelObjects/edge.rs +++ b/src/model_objects/edge.rs @@ -1,10 +1,10 @@ -use crate::DataReader::parse_edge; -use crate::DataReader::serialization::{ +use crate::data_reader::parse_edge; +use crate::data_reader::serialization::{ decode_guard, decode_sync, decode_sync_type, decode_update, DummyEdge, }; -use crate::EdgeEval::constraint_applyer::apply_constraints_to_state; -use crate::ModelObjects::Declarations; -use crate::ModelObjects::Expressions::BoolExpression; +use crate::edge_eval::constraint_applier::apply_constraints_to_state; +use crate::model_objects::expressions::BoolExpression; +use crate::model_objects::Declarations; use edbm::zones::OwnedFederation; use serde::{Deserialize, Serialize}; use std::fmt; diff --git a/src/ModelObjects/Expressions/arith_expression.rs b/src/model_objects/expressions/arith_expression.rs similarity index 74% rename from src/ModelObjects/Expressions/arith_expression.rs rename to src/model_objects/expressions/arith_expression.rs index 242849c7..467d8b17 100644 --- a/src/ModelObjects/Expressions/arith_expression.rs +++ b/src/model_objects/expressions/arith_expression.rs @@ -3,6 +3,7 @@ use edbm::util::constraints::ClockIndex; use serde::Deserialize; +use crate::model_objects::ClockReduceError; use std::collections::HashMap; use std::fmt::{Display, Formatter}; @@ -19,6 +20,47 @@ pub enum ArithExpression { } impl ArithExpression { + pub fn get_evaluated_int(&self) -> Result { + match self { + ArithExpression::Difference(left, right) => { + Ok(left.get_evaluated_int()? - right.get_evaluated_int()?) + } + ArithExpression::Addition(left, right) => { + Ok(left.get_evaluated_int()? + right.get_evaluated_int()?) + } + ArithExpression::Multiplication(left, right) => { + Ok(left.get_evaluated_int()? * right.get_evaluated_int()?) + } + ArithExpression::Division(left, right) => { + let divide_with = right.get_evaluated_int()?; + if divide_with == 0 { + Err(ClockReduceError::EvaluationError( + "Division with zero".to_string(), + )) + } else { + Ok(left.get_evaluated_int()? / divide_with) + } + } + ArithExpression::Modulo(left, right) => { + let modulo_with = right.get_evaluated_int()?; + if modulo_with == 0 { + Err(ClockReduceError::EvaluationError( + "Modulo with zero".to_string(), + )) + } else { + Ok(left.get_evaluated_int()? % modulo_with) + } + } + ArithExpression::Clock(_) => Err(ClockReduceError::EvaluationError( + "This function cant work with clock_index".to_string(), + )), + ArithExpression::VarName(_) => Err(ClockReduceError::EvaluationError( + "This function cant work with clock_names".to_string(), + )), + ArithExpression::Int(value) => Ok(*value), + } + } + pub fn swap_clock_names( &self, from_vars: &HashMap, @@ -190,32 +232,32 @@ impl ArithExpression { match op { Operation::Dif(right) => { out = match right { - true => ArithExpression::ADif(out, val), - false => ArithExpression::ADif(val, out), + true => ArithExpression::a_dif(out, val), + false => ArithExpression::a_dif(val, out), } } Operation::Add(right) => { out = match right { - true => ArithExpression::AAdd(out, val), - false => ArithExpression::AAdd(val, out), + true => ArithExpression::a_add(out, val), + false => ArithExpression::a_add(val, out), } } Operation::Mul(right) => { out = match right { - true => ArithExpression::AMul(out, val), - false => ArithExpression::AMul(val, out), + true => ArithExpression::a_mul(out, val), + false => ArithExpression::a_mul(val, out), } } Operation::Div(right) => { out = match right { - true => ArithExpression::ADiv(out, val), - false => ArithExpression::ADiv(val, out), + true => ArithExpression::a_div(out, val), + false => ArithExpression::a_div(val, out), } } Operation::Mod(right) => { out = match right { - true => ArithExpression::AMod(out, val), - false => ArithExpression::AMod(val, out), + true => ArithExpression::a_mod(out, val), + false => ArithExpression::a_mod(val, out), } } Operation::None => out = val, @@ -391,34 +433,57 @@ impl ArithExpression { } } - /// Finds the clock names used in the expression - pub fn has_varname(&self, name: &String) -> bool { + /// Checks if the clock name is used in the expression. + pub fn has_var_name(&self, name: &String) -> bool { match self { ArithExpression::Difference(a1, a2) | ArithExpression::Addition(a1, a2) | ArithExpression::Multiplication(a1, a2) | ArithExpression::Division(a1, a2) - | ArithExpression::Modulo(a1, a2) => a1.has_varname(name) || a2.has_varname(name), + | ArithExpression::Modulo(a1, a2) => a1.has_var_name(name) || a2.has_var_name(name), ArithExpression::Clock(_) | ArithExpression::Int(_) => false, ArithExpression::VarName(n) => name == n, } } + pub fn get_var_names(&self) -> Vec { + let mut vec = vec![]; + self.get_var_names_rec(&mut vec); + vec + } + + /// Finds the clocks used in the expression and puts them into result_clocks. + pub fn get_var_names_rec(&self, result_clocks: &mut Vec) { + match self { + ArithExpression::Difference(ref left, ref right) + | ArithExpression::Addition(ref left, ref right) + | ArithExpression::Multiplication(ref left, ref right) + | ArithExpression::Division(ref left, ref right) + | ArithExpression::Modulo(ref left, ref right) => { + left.get_var_names_rec(result_clocks); + right.get_var_names_rec(result_clocks); + } + ArithExpression::Clock(_) => (), + ArithExpression::VarName(ref name) => result_clocks.push(name.clone()), + ArithExpression::Int(_) => (), + } + } + /// Replaces all occurrences of `ArithExpression::VarName(old)` with `new` /// # Arguments - /// `old`: The `varname` to be replaced + /// `old`: The `var name` to be replaced - /// `new`: The new varname - pub fn replace_varname(&mut self, old: &String, new: &String) { + /// `new`: The new var name + pub fn replace_var_name(&mut self, old: &String, new: &String) { match self { ArithExpression::Difference(a1, a2) | ArithExpression::Addition(a1, a2) | ArithExpression::Multiplication(a1, a2) | ArithExpression::Division(a1, a2) | ArithExpression::Modulo(a1, a2) => { - a1.replace_varname(old, new); - a2.replace_varname(old, new); + a1.replace_var_name(old, new); + a2.replace_var_name(old, new); } ArithExpression::Clock(_) | ArithExpression::Int(_) => (), ArithExpression::VarName(name) => { @@ -442,11 +507,11 @@ impl ArithExpression { } } - pub fn APar(inner: ArithExpression) -> ArithExpression { + pub fn a_par(inner: ArithExpression) -> ArithExpression { inner } - pub fn ADif(left: ArithExpression, right: ArithExpression) -> ArithExpression { + pub fn a_dif(left: ArithExpression, right: ArithExpression) -> ArithExpression { if let ArithExpression::Int(0) = right { return left; } @@ -460,7 +525,7 @@ impl ArithExpression { ArithExpression::Difference(Box::new(left), Box::new(right)) } - pub fn AAdd(left: ArithExpression, right: ArithExpression) -> ArithExpression { + pub fn a_add(left: ArithExpression, right: ArithExpression) -> ArithExpression { if let ArithExpression::Int(0) = right { return left; } else if let ArithExpression::Int(0) = left { @@ -476,7 +541,7 @@ impl ArithExpression { ArithExpression::Addition(Box::new(left), Box::new(right)) } - pub fn AMul(left: ArithExpression, right: ArithExpression) -> ArithExpression { + pub fn a_mul(left: ArithExpression, right: ArithExpression) -> ArithExpression { if right == ArithExpression::Int(0) || left == ArithExpression::Int(0) { return ArithExpression::Int(0); } @@ -490,7 +555,7 @@ impl ArithExpression { ArithExpression::Multiplication(Box::new(left), Box::new(right)) } - pub fn ADiv(left: ArithExpression, right: ArithExpression) -> ArithExpression { + pub fn a_div(left: ArithExpression, right: ArithExpression) -> ArithExpression { if right == ArithExpression::Int(0) || left == ArithExpression::Int(0) { return ArithExpression::Int(0); } @@ -504,7 +569,7 @@ impl ArithExpression { ArithExpression::Division(Box::new(left), Box::new(right)) } - pub fn AMod(left: ArithExpression, right: ArithExpression) -> ArithExpression { + pub fn a_mod(left: ArithExpression, right: ArithExpression) -> ArithExpression { if let ArithExpression::Int(i) = left { if let ArithExpression::Int(j) = right { return ArithExpression::Int(i % j); @@ -589,3 +654,60 @@ impl Clock { self.negated = !self.negated; } } + +#[cfg(test)] +mod tests { + use crate::data_reader::parse_edge::parse_guard; + use crate::JsonProjectLoader; + use test_case::test_case; + const PATH: &str = "samples/json/PopulateClocks"; + + #[test_case("5", vec![], true ; "No clocks")] + #[test_case("5+x", vec!["x".to_string()], true ; "A single clock with addition")] + #[test_case("y-9", vec!["y".to_string()], true ; "A single clock with difference")] + #[test_case("zz*6/z", vec!["zz".to_string(), "z".to_string()], true ; "2 clocks with similar names")] + #[test_case("5%alpha", vec!["alpha".to_string()], true ; "Longer clock names")] + #[test_case("5%alpha", vec!["x".to_string()], false ; "One clock, should fail")] + fn test_get_clocks_arith(expression: &str, expected: Vec, verdict: bool) { + // Arrange + // We test arith expressions by converting them into boolean expressions and then running the bool test below. + let mut expression = expression.to_owned(); + expression.push_str("<0"); + // parse_guard is used to parse a boolean expression, as guards are just boolean expressions. + match parse_guard(&expression) { + Ok(input_expr) => { + // Act + let results: Vec = input_expr.get_var_names(); + // Assert + assert_eq!((expected == results), verdict); + } + Err(err) => { + panic!("Test failed: {}", err); + } + }; + } + + #[test_case("Updates1", vec![0,0] ; "Two updates set to 0")] + #[test_case("Updates2", vec![3,4] ; "Two updates set to none-zero")] + #[test_case("Updates3", vec![5,7] ; "Updates with arithmetic expressions")] + fn test_get_evaluated_int(comp_name: &str, expected: Vec) { + let mut project_loader = JsonProjectLoader::new_loader(PATH, crate::tests::TEST_SETTINGS); + project_loader.get_settings_mut().disable_clock_reduction = true; + let test_comp = project_loader.get_component(comp_name).unwrap().clone(); + + let mut clock_values: Vec = Vec::new(); + + if let Some(edge) = test_comp.edges.iter().find(|edge| edge.id == "E12") { + if let Some(updates) = &edge.update { + for update in updates { + match update.expression.get_evaluated_int() { + Err(_) => panic!("no value evaluated on update"), + Ok(value) => clock_values.push(value), + }; + } + } + } + + assert_eq!(clock_values, expected); + } +} diff --git a/src/ModelObjects/Expressions/bool_expression.rs b/src/model_objects/expressions/bool_expression.rs similarity index 83% rename from src/ModelObjects/Expressions/bool_expression.rs rename to src/model_objects/expressions/bool_expression.rs index d02e9ea4..6b9458b8 100644 --- a/src/ModelObjects/Expressions/bool_expression.rs +++ b/src/model_objects/expressions/bool_expression.rs @@ -395,61 +395,86 @@ impl BoolExpression { } } - /// Finds the clock names used in the expression - pub fn has_varname(&self, name: &String) -> bool { + /// Checks if the clock name is used in the expression. + pub fn has_var_name(&self, name: &String) -> bool { match self { BoolExpression::AndOp(p1, p2) | BoolExpression::OrOp(p1, p2) => { - p1.has_varname(name) || p2.has_varname(name) + p1.has_var_name(name) || p2.has_var_name(name) } BoolExpression::LessEQ(a1, a2) | BoolExpression::GreatEQ(a1, a2) | BoolExpression::LessT(a1, a2) | BoolExpression::GreatT(a1, a2) - | BoolExpression::EQ(a1, a2) => a1.has_varname(name) || a2.has_varname(name), + | BoolExpression::EQ(a1, a2) => a1.has_var_name(name) || a2.has_var_name(name), BoolExpression::Bool(_) => false, } } + /// Finds the clocks used in the expression and puts them into result_clocks. + pub fn get_var_names(&self) -> Vec { + let mut vec = vec![]; + self.get_var_names_rec(&mut vec); + vec + } + fn get_var_names_rec(&self, result_clocks: &mut Vec) { + match self { + BoolExpression::AndOp(ref left, ref right) + | BoolExpression::OrOp(ref left, ref right) => { + left.get_var_names_rec(result_clocks); + right.get_var_names_rec(result_clocks); + } + BoolExpression::LessEQ(ref left, ref right) + | BoolExpression::GreatEQ(ref left, ref right) + | BoolExpression::LessT(ref left, ref right) + | BoolExpression::GreatT(ref left, ref right) + | BoolExpression::EQ(ref left, ref right) => { + left.get_var_names_rec(result_clocks); + right.get_var_names_rec(result_clocks); + } + BoolExpression::Bool(_) => (), + } + } + /// Replaces all occurrences of `ArithExpression::VarName(old)` with `new` /// # Arguments - /// `old`: The `varname` to be replaced + /// `old`: The `var name` to be replaced - /// `new`: The new varname - pub fn replace_varname(&mut self, old: &String, new: &String) { + /// `new`: The new var name + pub fn replace_var_name(&mut self, old: &String, new: &String) { match self { BoolExpression::AndOp(e1, e2) | BoolExpression::OrOp(e1, e2) => { - e1.replace_varname(old, new); - e2.replace_varname(old, new); + e1.replace_var_name(old, new); + e2.replace_var_name(old, new); } BoolExpression::LessEQ(e1, e2) | BoolExpression::GreatEQ(e1, e2) | BoolExpression::LessT(e1, e2) | BoolExpression::GreatT(e1, e2) | BoolExpression::EQ(e1, e2) => { - e1.replace_varname(old, new); - e2.replace_varname(old, new); + e1.replace_var_name(old, new); + e2.replace_var_name(old, new); } BoolExpression::Bool(_) => (), } } - pub fn BLessEQ(left: ArithExpression, right: ArithExpression) -> BoolExpression { + pub fn b_less_eq(left: ArithExpression, right: ArithExpression) -> BoolExpression { BoolExpression::LessEQ(Box::new(left), Box::new(right)) } - pub fn BLessT(left: ArithExpression, right: ArithExpression) -> BoolExpression { + pub fn b_less_t(left: ArithExpression, right: ArithExpression) -> BoolExpression { BoolExpression::LessT(Box::new(left), Box::new(right)) } - pub fn BGreatEQ(left: ArithExpression, right: ArithExpression) -> BoolExpression { + pub fn b_great_eq(left: ArithExpression, right: ArithExpression) -> BoolExpression { BoolExpression::GreatEQ(Box::new(left), Box::new(right)) } - pub fn BGreatT(left: ArithExpression, right: ArithExpression) -> BoolExpression { + pub fn b_great_t(left: ArithExpression, right: ArithExpression) -> BoolExpression { BoolExpression::GreatT(Box::new(left), Box::new(right)) } - pub fn BEQ(left: ArithExpression, right: ArithExpression) -> BoolExpression { + pub fn b_eq(left: ArithExpression, right: ArithExpression) -> BoolExpression { BoolExpression::EQ(Box::new(left), Box::new(right)) } - pub fn BPar(inner: BoolExpression) -> BoolExpression { + pub fn b_par(inner: BoolExpression) -> BoolExpression { inner } } @@ -589,3 +614,38 @@ fn get_op(exp: &BoolExpression) -> Option { _ => None, } } + +#[cfg(test)] +mod tests { + use crate::data_reader::parse_edge::parse_guard; + use test_case::test_case; + + #[test_case("0>4", vec ! [], true; "No clocks")] + #[test_case("x<=5", vec ! ["x".to_string()], true; "A single clock using leq")] + #[test_case("x <= 5", vec ! ["x".to_string()], true; "A single clock with spaces")] + #[test_case("x==5", vec ! ["x".to_string()], true; "A single clock using eq")] + #[test_case("x>=5", vec ! ["x".to_string()], true; "A single clock using geq")] + #[test_case("x>=xx", vec ! ["x".to_string(), "xx".to_string()], true; "Two clocks with similar names")] + #[test_case("x<5&&x>0", vec ! ["x".to_string(), "x".to_string()], true; "Two occurrences of the same clock")] + #[test_case("x2&&y+1<=6", vec ! ["x".to_string(), "y".to_string()], true; "Two different clocks in two different expressions")] + #[test_case("x<5&&b>1", vec ! ["x".to_string(), "y".to_string()], false; "Two clocks, should fail")] + #[test_case("x<5+4", vec ! ["x".to_string()], true; "A single clock with arithmetic expressions")] + #[test_case("x<5+4||y==6*4", vec ! ["x".to_string(), "y".to_string()], true; "Two clocks with arithmetic expressions")] + pub fn test_get_clocks_bool(expression: &str, expected: Vec, verdict: bool) { + // Arrange + // parse_guard is used to parse a boolean expression, as guards are just boolean expressions. + match parse_guard(expression) { + Ok(input_expr) => { + // Act + let results = input_expr.get_var_names(); + // Assert + assert_eq!((expected == results), verdict); + } + Err(err) => { + panic!("Test failed: {}", err); + } + }; + } +} diff --git a/src/ModelObjects/Expressions/mod.rs b/src/model_objects/expressions/mod.rs similarity index 100% rename from src/ModelObjects/Expressions/mod.rs rename to src/model_objects/expressions/mod.rs diff --git a/src/ModelObjects/Expressions/query_expression.rs b/src/model_objects/expressions/query_expression.rs similarity index 96% rename from src/ModelObjects/Expressions/query_expression.rs rename to src/model_objects/expressions/query_expression.rs index 78d78f21..f887b85f 100644 --- a/src/ModelObjects/Expressions/query_expression.rs +++ b/src/model_objects/expressions/query_expression.rs @@ -17,6 +17,7 @@ pub enum QueryExpression { GetComponent(SaveExpression), Prune(SaveExpression), BisimMinim(SaveExpression), + Syntax(SystemExpression), } #[derive(Debug, Clone)] @@ -106,6 +107,9 @@ impl Display for QueryExpression { QueryExpression::Specification(system) => { write!(f, "specification: {}", system) } + QueryExpression::Syntax(system) => { + write!(f, "syntax: {}", system) + } } } } diff --git a/src/ModelObjects/Expressions/state_expression.rs b/src/model_objects/expressions/state_expression.rs similarity index 100% rename from src/ModelObjects/Expressions/state_expression.rs rename to src/model_objects/expressions/state_expression.rs diff --git a/src/ModelObjects/location.rs b/src/model_objects/location.rs similarity index 89% rename from src/ModelObjects/location.rs rename to src/model_objects/location.rs index 27484dbc..f20c2746 100644 --- a/src/ModelObjects/location.rs +++ b/src/model_objects/location.rs @@ -1,5 +1,5 @@ -use crate::DataReader::serialization::{decode_invariant, decode_location_type, DummyLocation}; -use crate::ModelObjects::Expressions::BoolExpression; +use crate::data_reader::serialization::{decode_invariant, decode_location_type, DummyLocation}; +use crate::model_objects::expressions::BoolExpression; use serde::{Deserialize, Serialize}; #[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Copy)] diff --git a/src/model_objects/mod.rs b/src/model_objects/mod.rs new file mode 100644 index 00000000..c4dd4a9a --- /dev/null +++ b/src/model_objects/mod.rs @@ -0,0 +1,16 @@ +mod component; +mod decision; +mod edge; +pub mod expressions; +mod location; +mod queries; +mod state; +mod statepair; +mod statepair_list; +mod system_declarations; +mod transition; + +pub use self::{ + component::*, decision::*, edge::*, location::*, queries::*, state::*, statepair::*, + statepair_list::*, system_declarations::*, transition::*, +}; diff --git a/src/ModelObjects/queries.rs b/src/model_objects/queries.rs similarity index 76% rename from src/ModelObjects/queries.rs rename to src/model_objects/queries.rs index 411fe757..74e7cd87 100644 --- a/src/ModelObjects/queries.rs +++ b/src/model_objects/queries.rs @@ -1,17 +1,17 @@ -use crate::DataReader::parse_queries; -use crate::ModelObjects::Expressions; +use crate::data_reader::parse_queries; +use crate::model_objects::expressions; use serde::{Deserialize, Deserializer}; /// The struct containing a single query #[derive(Debug, Deserialize, Clone)] pub struct Query { #[serde(deserialize_with = "decode_query")] - pub query: Option, + pub query: Option, pub comment: String, } impl Query { - pub fn get_query(&self) -> &Option { + pub fn get_query(&self) -> &Option { &self.query } } @@ -19,7 +19,7 @@ impl Query { /// Function used for deserializing queries pub fn decode_query<'de, D>( deserializer: D, -) -> Result, D::Error> +) -> Result, D::Error> where D: Deserializer<'de>, { diff --git a/src/ModelObjects/state.rs b/src/model_objects/state.rs similarity index 58% rename from src/ModelObjects/state.rs rename to src/model_objects/state.rs index 9a6d8316..93841bd1 100644 --- a/src/ModelObjects/state.rs +++ b/src/model_objects/state.rs @@ -1,22 +1,27 @@ -use crate::TransitionSystems::{LocationTree, TransitionSystem}; +use std::rc::Rc; + +use crate::transition_systems::{LocationTree, TransitionSystem}; use edbm::util::bounds::Bounds; use edbm::util::constraints::ClockIndex; use edbm::zones::OwnedFederation; -/// FullState is a struct used for initial verification of consistency, and determinism as a state that also hols a dbm -/// This is done as the type used in refinement state pair assumes to sides of an operation -/// this should probably be refactored as it causes unnecessary confusion +/// State is a struct used for initial verification of consistency, and determinism as a state that also holds a dbm +/// This is done as the type used in refinement state pair assumes two sides of an operation +// This should probably be refactored as it causes unnecessary confusion #[derive(Clone, Debug)] pub struct State { - pub decorated_locations: LocationTree, - zone_sentinel: Option, + pub decorated_locations: Rc, + zone: Rc, } impl State { - pub fn new(decorated_locations: LocationTree, zone: OwnedFederation) -> Self { + pub fn new>>( + decorated_locations: Rc, + zone: Z, + ) -> Self { State { decorated_locations, - zone_sentinel: Some(zone), + zone: zone.into(), } } @@ -25,7 +30,7 @@ impl State { } pub fn from_location( - decorated_locations: LocationTree, + decorated_locations: Rc, dimensions: ClockIndex, ) -> Option { let mut fed = OwnedFederation::init(dimensions); @@ -37,30 +42,35 @@ impl State { Some(State { decorated_locations, - zone_sentinel: Some(fed), + zone: Rc::new(fed), }) } pub fn apply_invariants(&mut self) { - let fed = self.take_zone(); + let fed = self.clone_zone(); let new_fed = self.decorated_locations.apply_invariants(fed); + self.set_zone(new_fed); } - pub fn zone_ref(&self) -> &OwnedFederation { - self.zone_sentinel.as_ref().unwrap() + pub fn clone_zone(&self) -> OwnedFederation { + self.zone.as_ref().clone() + } + + pub fn ref_zone(&self) -> &OwnedFederation { + self.zone.as_ref() } - pub(crate) fn take_zone(&mut self) -> OwnedFederation { - self.zone_sentinel.take().unwrap() + pub fn get_zone(&self) -> Rc { + Rc::clone(&self.zone) } - pub(crate) fn set_zone(&mut self, zone: OwnedFederation) { - self.zone_sentinel = Some(zone); + pub(crate) fn set_zone>>(&mut self, zone: Z) { + self.zone = zone.into(); } pub fn update_zone(&mut self, update: impl FnOnce(OwnedFederation) -> OwnedFederation) { - let fed = self.take_zone(); + let fed = self.clone_zone(); let new_fed = update(fed); self.set_zone(new_fed); } @@ -70,7 +80,7 @@ impl State { return false; } - self.zone_ref().subset_eq(other.zone_ref()) + self.ref_zone().subset_eq(other.ref_zone()) } pub fn get_location(&self) -> &LocationTree { @@ -78,7 +88,7 @@ impl State { } pub fn extrapolate_max_bounds(&mut self, system: &dyn TransitionSystem) { - let bounds = system.get_local_max_bounds(&self.decorated_locations); + let bounds = system.get_local_max_bounds(self.decorated_locations.as_ref()); self.update_zone(|zone| zone.extrapolate_max_bounds(&bounds)) } @@ -87,7 +97,7 @@ impl State { system: &dyn TransitionSystem, extra_bounds: &Bounds, ) { - let mut bounds = system.get_local_max_bounds(&self.decorated_locations); + let mut bounds = system.get_local_max_bounds(self.decorated_locations.as_ref()); bounds.add_bounds(extra_bounds); self.update_zone(|zone| zone.extrapolate_max_bounds(&bounds)) } diff --git a/src/model_objects/statepair.rs b/src/model_objects/statepair.rs new file mode 100644 index 00000000..d56ff3aa --- /dev/null +++ b/src/model_objects/statepair.rs @@ -0,0 +1,105 @@ +use edbm::zones::OwnedFederation; + +use crate::transition_systems::{LocationTree, TransitionSystemPtr}; +use std::{ + fmt::{Display, Formatter}, + rc::Rc, +}; + +#[derive(Clone, Debug)] +pub struct StatePair { + pub locations1: Rc, + pub locations2: Rc, + zone: Rc, +} + +impl StatePair { + pub fn from_locations( + dimensions: usize, + locations1: Rc, + locations2: Rc, + ) -> StatePair { + let mut zone = OwnedFederation::init(dimensions); + + zone = locations1.apply_invariants(zone); + zone = locations2.apply_invariants(zone); + + StatePair { + locations1, + locations2, + zone: Rc::new(zone), + } + } + + pub fn new( + locations1: Rc, + locations2: Rc, + zone: Rc, + ) -> Self { + StatePair { + locations1, + locations2, + zone, + } + } + + pub fn get_locations1(&self) -> Rc { + self.locations1.clone() + } + + pub fn get_locations2(&self) -> Rc { + self.locations2.clone() + } + + pub fn get_locations(&self, is_states1: bool) -> (&LocationTree, &LocationTree) { + if is_states1 { + (&self.locations1, &self.locations2) + } else { + (&self.locations2, &self.locations1) + } + } + + pub fn clone_zone(&self) -> OwnedFederation { + self.zone.as_ref().clone() + } + + pub fn ref_zone(&self) -> &OwnedFederation { + self.zone.as_ref() + } + + pub fn get_zone(&self) -> Rc { + Rc::clone(&self.zone) + } + + pub fn extrapolate_max_bounds( + &mut self, + sys1: &TransitionSystemPtr, + sys2: &TransitionSystemPtr, + ) { + let mut bounds = sys1.get_local_max_bounds(self.locations1.as_ref()); + bounds.add_bounds(&sys2.get_local_max_bounds(self.locations2.as_ref())); + + self.zone = Rc::new(self.clone_zone().extrapolate_max_bounds(&bounds)); + } +} + +impl Display for StatePair { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.write_fmt(format_args!( + "Pair: 1:{} where {}, 2:{} where {}, zone: {}", + self.locations1.id, + self.locations1 + .get_invariants() + .map(|f| f.to_string()) + .unwrap_or_else(|| "no invariant".to_string()), + self.locations2.id, + self.locations2 + .get_invariants() + .map(|f| f.to_string()) + .unwrap_or_else(|| "no invariant".to_string()), + self.ref_zone() + ))?; + + Ok(()) + } +} diff --git a/src/DataTypes/statepair_list.rs b/src/model_objects/statepair_list.rs similarity index 77% rename from src/DataTypes/statepair_list.rs rename to src/model_objects/statepair_list.rs index ed651220..c41fb024 100644 --- a/src/DataTypes/statepair_list.rs +++ b/src/model_objects/statepair_list.rs @@ -1,17 +1,20 @@ -use std::collections::{HashMap, VecDeque}; +use std::{ + collections::{HashMap, VecDeque}, + rc::Rc, +}; use edbm::zones::OwnedFederation; -use crate::{ModelObjects::StatePair, TransitionSystems::LocationID}; +use crate::{model_objects::StatePair, transition_systems::LocationID}; pub type PassedStateList = PassedStateListFed; -type PassedStateListFed = HashMap<(LocationID, LocationID), OwnedFederation>; -type PassedStateListVec = HashMap<(LocationID, LocationID), Vec>; +type PassedStateListFed = HashMap<(LocationID, LocationID), Rc>; +type PassedStateListVec = HashMap<(LocationID, LocationID), Vec>>; pub type WaitingStateList = DepthFirstWaitingStateList; pub struct DepthFirstWaitingStateList { queue: VecDeque, - map: HashMap<(LocationID, LocationID), VecDeque>, + map: HashMap<(LocationID, LocationID), VecDeque>>, } pub trait PassedStateListExt { @@ -21,9 +24,9 @@ pub trait PassedStateListExt { } impl PassedStateListExt for PassedStateListVec { - fn put(&mut self, mut pair: StatePair) { - let fed = pair.take_zone(); - let (loc1, loc2) = (pair.locations1.id, pair.locations2.id); + fn put(&mut self, pair: StatePair) { + let fed = pair.get_zone(); + let (loc1, loc2) = (pair.locations1.id.clone(), pair.locations2.id.clone()); let key = (loc1, loc2); if let Some(vec) = self.get_mut(&key) { vec.push(fed); @@ -47,17 +50,17 @@ impl PassedStateListExt for PassedStateListVec { fn zones(&self, key: &(LocationID, LocationID)) -> Vec<&OwnedFederation> { match self.get(key) { - Some(vec) => vec.iter().collect(), + Some(vec) => vec.iter().map(AsRef::as_ref).collect(), None => panic!("No zones for key: {:?}", key), } } } impl PassedStateListExt for DepthFirstWaitingStateList { - fn put(&mut self, mut pair: StatePair) { + fn put(&mut self, pair: StatePair) { self.queue.push_front(pair.clone()); - let fed = pair.take_zone(); - let (loc1, loc2) = (pair.locations1.id, pair.locations2.id); + let fed = pair.get_zone(); + let (loc1, loc2) = (pair.locations1.id.clone(), pair.locations2.id.clone()); let key = (loc1, loc2); if let Some(vec) = self.map.get_mut(&key) { vec.push_front(fed); @@ -79,7 +82,7 @@ impl PassedStateListExt for DepthFirstWaitingStateList { } fn zones(&self, key: &(LocationID, LocationID)) -> Vec<&OwnedFederation> { match self.map.get(key) { - Some(vec) => vec.iter().collect(), + Some(vec) => vec.iter().map(|e| e.as_ref()).collect(), None => panic!("No zones for key: {:?}", key), } } @@ -115,22 +118,22 @@ impl DepthFirstWaitingStateList { } } impl PassedStateListExt for PassedStateListFed { - fn put(&mut self, mut pair: StatePair) { - let mut fed = pair.take_zone(); - let (loc1, loc2) = (pair.locations1.id, pair.locations2.id); + fn put(&mut self, pair: StatePair) { + let mut fed = pair.clone_zone(); + let (loc1, loc2) = (pair.locations1.id.clone(), pair.locations2.id.clone()); let key = (loc1, loc2); if let Some(f) = self.get(&key) { fed = fed.union(f).expensive_reduce(); } - self.insert(key, fed); + self.insert(key, Rc::new(fed)); } fn has(&self, pair: &StatePair) -> bool { let (loc1, loc2, fed) = ( pair.locations1.id.clone(), pair.locations2.id.clone(), - pair.ref_zone(), + pair.get_zone(), ); let key = (loc1, loc2); match self.get(&key) { diff --git a/src/ModelObjects/system_declarations.rs b/src/model_objects/system_declarations.rs similarity index 91% rename from src/ModelObjects/system_declarations.rs rename to src/model_objects/system_declarations.rs index ff71f908..3c38c92e 100644 --- a/src/ModelObjects/system_declarations.rs +++ b/src/model_objects/system_declarations.rs @@ -1,4 +1,4 @@ -use crate::ModelObjects::Component; +use crate::model_objects::Component; use log::debug; use serde::{Deserialize, Deserializer}; use std::collections::HashMap; @@ -115,19 +115,19 @@ where } if action.ends_with('?') { let r = action.replace('?', ""); - if let Some(Channel_vec) = input_actions.get_mut(&component_name) { - Channel_vec.push(r) + if let Some(channel_vec) = input_actions.get_mut(&component_name) { + channel_vec.push(r) } else { - let Channel_vec = vec![r]; - input_actions.insert(component_name.clone(), Channel_vec); + let channel_vec = vec![r]; + input_actions.insert(component_name.clone(), channel_vec); } } else if action.ends_with('!') { let r = action.replace('!', ""); - if let Some(Channel_vec) = output_actions.get_mut(&component_name) { - Channel_vec.push(r.clone()) + if let Some(channel_vec) = output_actions.get_mut(&component_name) { + channel_vec.push(r.clone()) } else { - let Channel_vec = vec![r.clone()]; - output_actions.insert(component_name.clone(), Channel_vec); + let channel_vec = vec![r.clone()]; + output_actions.insert(component_name.clone(), channel_vec); } } else { panic!("Channel type not defined for Channel {:?}", action) diff --git a/src/ModelObjects/transition.rs b/src/model_objects/transition.rs similarity index 85% rename from src/ModelObjects/transition.rs rename to src/model_objects/transition.rs index ddd14b0f..d5574f2a 100644 --- a/src/ModelObjects/transition.rs +++ b/src/model_objects/transition.rs @@ -1,12 +1,13 @@ -use crate::DataReader::parse_edge; -use crate::EdgeEval::updater::CompiledUpdate; -use crate::ModelObjects::Expressions::BoolExpression; -use crate::ModelObjects::{Component, DeclarationProvider, Edge, State}; -use crate::TransitionSystems::{CompositionType, LocationTree, TransitionID}; +use crate::data_reader::parse_edge; +use crate::edge_eval::updater::CompiledUpdate; +use crate::model_objects::expressions::BoolExpression; +use crate::model_objects::{Component, DeclarationProvider, Edge, State}; +use crate::transition_systems::{CompositionType, LocationTree, TransitionID}; use edbm::util::constraints::ClockIndex; use edbm::zones::OwnedFederation; use std::collections::HashMap; use std::fmt; +use std::rc::Rc; /// Represents a single transition from taking edges in multiple components #[derive(Debug, Clone)] @@ -14,24 +15,22 @@ pub struct Transition { /// The ID of the transition, based on the edges it is created from. pub id: TransitionID, pub guard_zone: OwnedFederation, - pub target_locations: LocationTree, + pub target_locations: Rc, pub updates: Vec, } impl Transition { /// Create a new transition not based on an edge with no identifier - pub fn without_id(target_locations: &LocationTree, dim: ClockIndex) -> Transition { + pub fn without_id(target_locations: Rc, dim: ClockIndex) -> Transition { Transition { id: TransitionID::None, guard_zone: OwnedFederation::universe(dim), - target_locations: target_locations.clone(), + target_locations, updates: vec![], } } pub fn from_component_and_edge(comp: &Component, edge: &Edge, dim: ClockIndex) -> Transition { - //let (comp, edge) = edges; - let target_loc_name = &edge.target_location; let target_loc = comp.get_location_by_name(target_loc_name); let target_locations = LocationTree::simple(target_loc, comp.get_declarations(), dim); @@ -54,19 +53,17 @@ impl Transition { } pub fn use_transition(&self, state: &mut State) -> bool { - let mut zone = state.take_zone(); + let mut zone = state.clone_zone(); zone = self.apply_guards(zone); if !zone.is_empty() { zone = self.apply_updates(zone).up(); - self.move_locations(&mut state.decorated_locations); + state.decorated_locations = Rc::clone(&self.target_locations); zone = state.decorated_locations.apply_invariants(zone); - if !zone.is_empty() { - state.set_zone(zone); - return true; - } } + let empty = !zone.is_empty(); state.set_zone(zone); - false + + empty } /// Returns the resulting [`State`] when using a transition in the given [`State`] @@ -86,8 +83,11 @@ impl Transition { let mut out: Vec = vec![]; for l in left { for r in right { - let target_locations = - LocationTree::compose(&l.target_locations, &r.target_locations, comp); + let target_locations = LocationTree::compose( + Rc::clone(&l.target_locations), + Rc::clone(&r.target_locations), + comp, + ); let guard_zone = l.guard_zone.clone().intersection(&r.guard_zone); @@ -148,10 +148,6 @@ impl Transition { zone.intersection(&self.guard_zone) } - pub fn move_locations(&self, locations: &mut LocationTree) { - *locations = self.target_locations.clone(); - } - pub fn combine_edge_guards( edges: &Vec<(&Component, &Edge)>, dim: ClockIndex, diff --git a/src/ProtobufServer/ecdar_backend.rs b/src/protobuf_server/ecdar_backend.rs similarity index 96% rename from src/ProtobufServer/ecdar_backend.rs rename to src/protobuf_server/ecdar_backend.rs index a45d2fa2..855508f9 100644 --- a/src/ProtobufServer/ecdar_backend.rs +++ b/src/protobuf_server/ecdar_backend.rs @@ -1,7 +1,7 @@ -use crate::ProtobufServer::services::ecdar_backend_server::EcdarBackend; +use crate::protobuf_server::services::ecdar_backend_server::EcdarBackend; -use crate::DataReader::component_loader::ModelCache; -use crate::ProtobufServer::services::{ +use crate::data_reader::component_loader::ModelCache; +use crate::protobuf_server::services::{ QueryRequest, QueryResponse, SimulationStartRequest, SimulationStepRequest, SimulationStepResponse, UserTokenResponse, }; diff --git a/src/ProtobufServer/ecdar_requests/mod.rs b/src/protobuf_server/ecdar_requests/mod.rs similarity index 100% rename from src/ProtobufServer/ecdar_requests/mod.rs rename to src/protobuf_server/ecdar_requests/mod.rs diff --git a/src/ProtobufServer/ecdar_requests/request_util.rs b/src/protobuf_server/ecdar_requests/request_util.rs similarity index 71% rename from src/ProtobufServer/ecdar_requests/request_util.rs rename to src/protobuf_server/ecdar_requests/request_util.rs index 80e6c378..61f4147a 100644 --- a/src/ProtobufServer/ecdar_requests/request_util.rs +++ b/src/protobuf_server/ecdar_requests/request_util.rs @@ -3,11 +3,11 @@ use std::{collections::HashMap, sync::Arc}; use log::trace; use crate::{ - DataReader::component_loader::{parse_components_if_some, ComponentContainer, ModelCache}, - ModelObjects::Component, - ProtobufServer::services::{Component as ProtoComponent, SimulationInfo}, - System::input_enabler, - TransitionSystems::{ + data_reader::component_loader::{parse_components_if_some, ComponentContainer, ModelCache}, + model_objects::Component, + protobuf_server::services::{Component as ProtoComponent, SimulationInfo}, + system::input_enabler, + transition_systems::{ transition_system::component_loader_to_transition_system, TransitionSystemPtr, }, }; @@ -32,9 +32,24 @@ pub fn get_or_insert_model( } } +pub fn insert_model( + model_cache: &mut ModelCache, + user_id: i32, + components_hash: u32, + proto_components: &[ProtoComponent], +) -> ComponentContainer { + let parsed_components: Vec = proto_components + .iter() + .flat_map(parse_components_if_some) + .flatten() + .collect::>(); + let components = constrtuct_componentsmap(parsed_components); + model_cache.insert_model(user_id, components_hash, Arc::new(components)) +} + fn constrtuct_componentsmap( components: Vec, -) -> crate::DataReader::component_loader::ComponentsMap { +) -> crate::data_reader::component_loader::ComponentsMap { let mut comp_hashmap = HashMap::::new(); for mut component in components { trace!("Adding comp {} to container", component.name); diff --git a/src/ProtobufServer/ecdar_requests/send_query.rs b/src/protobuf_server/ecdar_requests/send_query.rs similarity index 50% rename from src/ProtobufServer/ecdar_requests/send_query.rs rename to src/protobuf_server/ecdar_requests/send_query.rs index ccf52a01..58f4dca1 100644 --- a/src/ProtobufServer/ecdar_requests/send_query.rs +++ b/src/protobuf_server/ecdar_requests/send_query.rs @@ -1,23 +1,23 @@ +use crate::data_reader::component_loader::{ComponentContainer, ModelCache}; +use crate::data_reader::json_writer::component_to_json; +use crate::data_reader::parse_queries; use crate::extract_system_rep::ExecutableQueryError; -use crate::DataReader::component_loader::ModelCache; -use crate::DataReader::json_writer::component_to_json; -use crate::DataReader::parse_queries; -use crate::ModelObjects::Query; -use crate::ProtobufServer::ecdar_requests::request_util::get_or_insert_model; -use crate::ProtobufServer::services::component::Rep; -use crate::ProtobufServer::services::query_response::{ +use crate::model_objects::Query; +use crate::protobuf_server::ecdar_requests::request_util::insert_model; +use crate::protobuf_server::services::component::Rep; +use crate::protobuf_server::services::query_response::{ Error as InnerError, Result as ProtobufResult, Success, }; -use crate::ProtobufServer::services::{ - Component as ProtobufComponent, QueryRequest, QueryResponse, +use crate::protobuf_server::services::{ + query_response, Component as ProtobufComponent, QueryRequest, QueryResponse, }; -use crate::ProtobufServer::ConcreteEcdarBackend; -use crate::System::query_failures::{ +use crate::protobuf_server::ConcreteEcdarBackend; +use crate::system::query_failures::{ ConsistencyFailure, DeterminismFailure, PathFailure, QueryResult, RefinementFailure, - SystemRecipeFailure, + SyntaxFailure, SystemRecipeFailure, }; -use crate::System::extract_system_rep; +use crate::system::extract_system_rep; use log::trace; use tonic::Status; @@ -36,40 +36,64 @@ impl ConcreteEcdarBackend { trace!("Received query: {:?}", query_request); let components_info = query_request.components_info.as_ref().unwrap(); let proto_components = &components_info.components; - let query = parse_query(&query_request)?; - let user_id = query_request.user_id; - - let mut component_container = get_or_insert_model( - &mut model_cache, - user_id, - components_info.components_hash, - proto_components, - ); - component_container.set_settings(query_request.settings.unwrap_or(crate::DEFAULT_SETTINGS)); - - let out = - match extract_system_rep::create_executable_query(&query, &mut component_container) { - Ok(query) => { - let result = query.execute(); - Ok(QueryResponse { - query_id: query_request.query_id, - info: vec![], // TODO: Should be logs - result: Some(result.into()), - }) - } - Err(ExecutableQueryError::Custom(e)) => Err(Status::invalid_argument(format!( - "Creation of query failed: {}", - e - ))), - Err(ExecutableQueryError::SystemRecipeFailure(failure)) => { - Ok(QueryResponse { - query_id: query_request.query_id, - info: vec![], // TODO: Should be logs - result: Some(failure.into()), - }) - } - }; - out + + // Model already in cache + if let Some(model) = + model_cache.get_model(query_request.user_id, components_info.components_hash) + { + send_query(model, query_request) + } + // Model not in cache but included in request + else if !proto_components.is_empty() { + let model = insert_model( + &mut model_cache, + query_request.user_id, + components_info.components_hash, + proto_components, + ); + send_query(model, query_request) + } + // Model not in cache nor included in request + else { + Ok(QueryResponse { + query_id: query_request.query_id, + info: vec![], + result: Some(query_response::Result::ComponentsNotInCache( + Default::default(), + )), + }) + } + } +} + +fn send_query( + mut model: ComponentContainer, + query_request: QueryRequest, +) -> Result { + let query = parse_query(&query_request)?; + + model.set_settings(query_request.settings.unwrap_or(crate::DEFAULT_SETTINGS)); + + match extract_system_rep::create_executable_query(&query, &mut model) { + Ok(query) => { + let result = query.execute(); + Ok(QueryResponse { + query_id: query_request.query_id, + info: vec![], // TODO: Should be logs + result: Some(result.into()), + }) + } + Err(ExecutableQueryError::Custom(e)) => Err(Status::invalid_argument(format!( + "Creation of query failed: {}", + e + ))), + Err(ExecutableQueryError::SystemRecipeFailure(failure)) => { + Ok(QueryResponse { + query_id: query_request.query_id, + info: vec![], // TODO: Should be logs + result: Some(failure.into()), + }) + } } } @@ -91,11 +115,13 @@ impl From for ProtobufResult { QueryResult::Reachability(Ok(path)) => ProtobufResult::ReachabilityPath(path.into()), QueryResult::Refinement(Ok(_)) | QueryResult::Consistency(Ok(_)) + | QueryResult::Syntax(Ok(_)) | QueryResult::Determinism(Ok(_)) => ProtobufResult::Success(Success {}), QueryResult::Refinement(Err(fail)) => fail.into(), QueryResult::Consistency(Err(fail)) => fail.into(), QueryResult::Determinism(Err(fail)) => fail.into(), QueryResult::Reachability(Err(fail)) => fail.into(), + QueryResult::Syntax(Err(fail)) => fail.into(), QueryResult::GetComponent(comp) => ProtobufResult::Component(ProtobufComponent { rep: Some(Rep::Json(component_to_json(&comp))), @@ -125,6 +151,12 @@ impl From for ProtobufResult { } } +impl From for ProtobufResult { + fn from(fail: SyntaxFailure) -> ProtobufResult { + ProtobufResult::Syntax(fail.into()) + } +} + impl From for ProtobufResult { fn from(fail: RefinementFailure) -> ProtobufResult { ProtobufResult::Refinement(fail.into()) diff --git a/src/ProtobufServer/ecdar_requests/simulation_requests.rs b/src/protobuf_server/ecdar_requests/simulation_requests.rs similarity index 91% rename from src/ProtobufServer/ecdar_requests/simulation_requests.rs rename to src/protobuf_server/ecdar_requests/simulation_requests.rs index 2de30170..aae61209 100644 --- a/src/ProtobufServer/ecdar_requests/simulation_requests.rs +++ b/src/protobuf_server/ecdar_requests/simulation_requests.rs @@ -1,16 +1,16 @@ use tonic::Status; +use crate::model_objects::Decision; use crate::{ - DataReader::{component_loader::ModelCache, proto_reader::proto_decision_to_decision}, - ProtobufServer::{ + data_reader::{component_loader::ModelCache, proto_reader::proto_decision_to_decision}, + protobuf_server::{ services::{SimulationStartRequest, SimulationStepRequest, SimulationStepResponse}, ConcreteEcdarBackend, }, - System::specifics::{SpecificDecision, SpecificState}, + system::specifics::{SpecificDecision, SpecificState}, }; use super::request_util::simulation_info_to_transition_system; -use crate::Simulation::decision::Decision; impl ConcreteEcdarBackend { /// Handles a start simulation request: Responding with the initial decision point in the transition system given in the `request`. diff --git a/src/ProtobufServer/mod.rs b/src/protobuf_server/mod.rs similarity index 100% rename from src/ProtobufServer/mod.rs rename to src/protobuf_server/mod.rs diff --git a/src/ProtobufServer/proto_conversions.rs b/src/protobuf_server/proto_conversions.rs similarity index 96% rename from src/ProtobufServer/proto_conversions.rs rename to src/protobuf_server/proto_conversions.rs index 7aafb720..e16e2e9c 100644 --- a/src/ProtobufServer/proto_conversions.rs +++ b/src/protobuf_server/proto_conversions.rs @@ -1,17 +1,18 @@ -use crate::ProtobufServer::services::query_response::{ +use crate::protobuf_server::services::query_response::{ ConsistencyFailure as ProtobufConsistencyFailure, DeterminismFailure as ProtobufDeterminismFailure, ModelFailure, ReachabilityFailure, ReachabilityPath, RefinementFailure as ProtobufRefinementFailure, + SyntaxFailure as ProtobufSyntaxFailure, }; -use crate::ProtobufServer::services::{ +use crate::protobuf_server::services::{ self, clock::Clock as ProtoClockEnum, clock::ComponentClock as ProtoComponentClock, clock::SystemClock as ProtoSystemClock, ActionFailure as ProtobufActionFailure, BinaryLocationOperator, Clock as ProtoClock, ComponentInstance as ProtoSpecificComponent, Conjunction as ProtoConjunction, Constraint as ProtoConstraint, Disjunction as ProtoDisjunction, LeafLocation, LocationTree, State as ProtoState, }; -use crate::System::query_failures::*; -use crate::System::specifics::{ +use crate::system::query_failures::*; +use crate::system::specifics::{ SpecialLocation, SpecificClock, SpecificClockVar, SpecificComp, SpecificConjunction, SpecificConstraint, SpecificDecision, SpecificDisjunction, SpecificEdge, SpecificLocation, SpecificPath, SpecificState, @@ -214,6 +215,14 @@ impl From for ProtobufDeterminismFailure { } } +impl From for ProtobufSyntaxFailure { + fn from(sf: SyntaxFailure) -> Self { + match sf { + SyntaxFailure::Unparsable { msg, path } => ProtobufSyntaxFailure { msg, path }, + } + } +} + impl From for ProtobufConsistencyFailure { fn from(cf: ConsistencyFailure) -> Self { use services::query_response::consistency_failure::Failure; @@ -271,7 +280,7 @@ impl From for ProtobufRefinementFailure { }, RefinementFailure::Precondition(precond) => { - use crate::System::query_failures::RefinementPrecondition::*; + use crate::system::query_failures::RefinementPrecondition::*; match precond { EmptyChild { child, system } => ProtobufRefinementFailure { system: system.name, diff --git a/src/ProtobufServer/server.rs b/src/protobuf_server/server.rs similarity index 77% rename from src/ProtobufServer/server.rs rename to src/protobuf_server/server.rs index cb659459..601ea91f 100644 --- a/src/ProtobufServer/server.rs +++ b/src/protobuf_server/server.rs @@ -1,7 +1,6 @@ -use crate::ProtobufServer::services::ecdar_backend_server::EcdarBackendServer; -use crate::ProtobufServer::ConcreteEcdarBackend; +use crate::protobuf_server::services::ecdar_backend_server::EcdarBackendServer; +use crate::protobuf_server::ConcreteEcdarBackend; use core::time::Duration; -use log::info; use tokio::runtime; use tonic::transport::Server; @@ -26,16 +25,15 @@ async fn start_grpc_server( cache_size: usize, thread_number: usize, ) -> Result<(), Box> { - info!("Starting grpc server on '{}'", ip_endpoint.trim()); - - Server::builder() + let server = Server::builder() .http2_keepalive_interval(Some(Duration::from_secs(120))) .add_service(EcdarBackendServer::new(ConcreteEcdarBackend::new( thread_number, cache_size, ))) - .serve(ip_endpoint.trim().parse()?) - .await?; + .serve(ip_endpoint.trim().parse()?); + println!("Started grpc server on '{}'\r", ip_endpoint.trim()); + server.await?; Ok(()) } diff --git a/src/Simulation/graph_layout.rs b/src/simulation/graph_layout.rs similarity index 99% rename from src/Simulation/graph_layout.rs rename to src/simulation/graph_layout.rs index ce3c38ba..36a5cdb0 100644 --- a/src/Simulation/graph_layout.rs +++ b/src/simulation/graph_layout.rs @@ -1,4 +1,4 @@ -use crate::DataReader::serialization::DummyComponent; +use crate::data_reader::serialization::DummyComponent; use force_graph::{DefaultNodeIdx, ForceGraph, NodeData}; use log::info; use rand::Rng; diff --git a/src/Simulation/mod.rs b/src/simulation/mod.rs similarity index 55% rename from src/Simulation/mod.rs rename to src/simulation/mod.rs index 939ef543..a6f56767 100644 --- a/src/Simulation/mod.rs +++ b/src/simulation/mod.rs @@ -1,2 +1 @@ -pub mod decision; pub mod graph_layout; diff --git a/src/System/executable_query.rs b/src/system/executable_query.rs similarity index 82% rename from src/System/executable_query.rs rename to src/system/executable_query.rs index b9946507..c049bcf2 100644 --- a/src/System/executable_query.rs +++ b/src/system/executable_query.rs @@ -1,14 +1,16 @@ -use crate::DataReader::component_loader::ComponentLoader; -use crate::ModelObjects::State; -use crate::System::reachability; -use crate::System::refine; -use crate::System::save_component::combine_components; -use crate::TransitionSystems::TransitionSystemPtr; -use edbm::util::constraints::ClockIndex; use std::cmp; +use edbm::util::constraints::ClockIndex; +use crate::data_reader::component_loader::ComponentLoader; +use crate::extract_system_rep::SystemRecipe; +use crate::model_objects::State; +use crate::system::reachability; +use crate::system::refine; +use crate::system::save_component::combine_components; +use crate::transition_systems::TransitionSystemPtr; use super::query_failures::PathFailure; use super::query_failures::QueryResult; +use super::query_failures::SyntaxResult; use super::save_component::PruningStrategy; use super::specifics::SpecificDecision; @@ -34,6 +36,9 @@ impl QueryResult { QueryResult::Consistency(Ok(_)) => satisfied(query_str), QueryResult::Consistency(Err(_)) => not_satisfied(query_str), + QueryResult::Syntax(Ok(_)) => println!("{} -- Success!", query_str), + QueryResult::Syntax(Err(err)) => println!("{} -- Failed!\n{}", query_str, err), + QueryResult::Determinism(Ok(_)) => satisfied(query_str), QueryResult::Determinism(Err(_)) => not_satisfied(query_str), @@ -147,6 +152,23 @@ impl ExecutableQuery for ConsistencyExecutor { } } +pub struct SyntaxExecutor { + pub result: Result, SyntaxResult>, +} + +impl ExecutableQuery for SyntaxExecutor { + fn execute(self: Box) -> QueryResult { + match self.result { + Ok(_) => QueryResult::Syntax(Ok(())), + Err(err) => QueryResult::Syntax(Err(err.unwrap_err())), + } + } + + fn get_dim(&self) -> ClockIndex { + 0 + } +} + pub struct DeterminismExecutor { pub system: TransitionSystemPtr, } diff --git a/src/System/extract_state.rs b/src/system/extract_state.rs similarity index 86% rename from src/System/extract_state.rs rename to src/system/extract_state.rs index 3de219fd..c8146b4e 100644 --- a/src/System/extract_state.rs +++ b/src/system/extract_state.rs @@ -1,11 +1,13 @@ +use std::rc::Rc; + use edbm::zones::OwnedFederation; use itertools::Itertools; +use crate::edge_eval::constraint_applier::apply_constraints_to_state; use crate::extract_system_rep::SystemRecipe; -use crate::EdgeEval::constraint_applyer::apply_constraints_to_state; -use crate::ModelObjects::Expressions::{BoolExpression, ComponentVariable, StateExpression}; -use crate::ModelObjects::{Declarations, State}; -use crate::TransitionSystems::{CompositionType, LocationID, LocationTree, TransitionSystemPtr}; +use crate::model_objects::expressions::{BoolExpression, ComponentVariable, StateExpression}; +use crate::model_objects::{Declarations, State}; +use crate::transition_systems::{CompositionType, LocationID, LocationTree, TransitionSystemPtr}; /// This function takes a [`StateExpression`], the system recipe, and the transitionsystem - /// to define a state from the [`StateExpression`] which has clocks and locations. @@ -110,29 +112,29 @@ fn construct_location_tree( locations: &Vec, machine: &SystemRecipe, system: &TransitionSystemPtr, -) -> Result { +) -> Result, String> { match machine { SystemRecipe::Composition(left, right) => { let (left_system, right_system) = system.get_children(); Ok(LocationTree::compose( - &construct_location_tree(locations, left, left_system)?, - &construct_location_tree(locations, right, right_system)?, + construct_location_tree(locations, left, left_system)?, + construct_location_tree(locations, right, right_system)?, CompositionType::Composition, )) } SystemRecipe::Conjunction(left, right) => { let (left_system, right_system) = system.get_children(); Ok(LocationTree::compose( - &construct_location_tree(locations, left, left_system)?, - &construct_location_tree(locations, right, right_system)?, + construct_location_tree(locations, left, left_system)?, + construct_location_tree(locations, right, right_system)?, CompositionType::Conjunction, )) } SystemRecipe::Quotient(left, right, ..) => { let (left_system, right_system) = system.get_children(); Ok(LocationTree::merge_as_quotient( - &construct_location_tree(locations, left, left_system)?, - &construct_location_tree(locations, right, right_system)?, + construct_location_tree(locations, left, left_system)?, + construct_location_tree(locations, right, right_system)?, )) } SystemRecipe::Component(component) => { diff --git a/src/system/extract_system_rep.rs b/src/system/extract_system_rep.rs new file mode 100644 index 00000000..36da99df --- /dev/null +++ b/src/system/extract_system_rep.rs @@ -0,0 +1,286 @@ +use crate::data_reader::component_loader::ComponentLoader; +use crate::model_objects::expressions::{QueryExpression, SaveExpression, SystemExpression}; +use crate::model_objects::{Component, Query, State}; +use crate::system::executable_query::{ + ConsistencyExecutor, DeterminismExecutor, ExecutableQuery, GetComponentExecutor, + ReachabilityExecutor, RefinementExecutor, +}; +use crate::system::extract_state::get_state; + +use crate::transition_systems::{ + CompiledComponent, Composition, Conjunction, Quotient, TransitionSystemPtr, +}; + +use super::executable_query::SyntaxExecutor; +use super::query_failures::{SyntaxResult, SystemRecipeFailure}; +use crate::system::pruning; +use edbm::util::constraints::ClockIndex; +use log::debug; +use simple_error::bail; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum ExecutableQueryError { + SystemRecipeFailure(SystemRecipeFailure), + Custom(String), +} + +impl From> for ExecutableQueryError { + fn from(failure: Box) -> Self { + ExecutableQueryError::SystemRecipeFailure(*failure) + } +} + +impl> From for ExecutableQueryError { + fn from(failure: T) -> Self { + ExecutableQueryError::Custom(failure.into()) + } +} + +/// This function fetches the appropriate components based on the structure of the query and makes the enum structure match the query +/// this function also handles setting up the correct indices for clocks based on the amount of components in each system representation +pub fn create_executable_query<'a>( + full_query: &Query, + component_loader: &'a mut (dyn ComponentLoader + 'static), +) -> Result, ExecutableQueryError> { + let mut dim: ClockIndex = 0; + + if let Some(query) = full_query.get_query() { + match query { + QueryExpression::Refinement(left_side, right_side) => { + let mut quotient_index = None; + + let left = + get_system_recipe(left_side, component_loader, &mut dim, &mut quotient_index) + .unwrap(); + let right = + get_system_recipe(right_side, component_loader, &mut dim, &mut quotient_index) + .unwrap(); + + let mut component_index = 0; + + Ok(Box::new(RefinementExecutor { + sys1: left.compile_with_index(dim, &mut component_index)?, + sys2: right.compile_with_index(dim, &mut component_index)?, + })) + } + QueryExpression::Reachability { system, from, to } => { + let machine = + get_system_recipe(system, component_loader, &mut dim, &mut None).unwrap(); + let transition_system = machine.clone().compile(dim)?; + + // Assign the start state to the initial state of the transition system if no start state is given by the query + let start_state: State = if let Some(state) = from.as_ref() { + let state = get_state(state, &machine, &transition_system) + .map_err(|err| format!("Invalid Start state: {}", err))?; + if state.decorated_locations.id.is_partial_location() { + return Err("Start state is a partial state, which it must not be".into()); + } + state + } else { + match transition_system.get_initial_state() { + Some(state) => state, + None => return Err("No start state in the transition system".into()), + } + }; + + let end_state: State = get_state(to, &machine, &transition_system) + .map_err(|err| format!("Invalid End state: {}", err))?; + + Ok(Box::new(ReachabilityExecutor { + transition_system, + start_state, + end_state, + })) + } + QueryExpression::Consistency(query_expression) => { + let mut quotient_index = None; + let recipe = get_system_recipe( + query_expression, + component_loader, + &mut dim, + &mut quotient_index, + ) + .unwrap(); + + Ok(Box::new(ConsistencyExecutor { + system: recipe.compile(dim)?, + })) + } + QueryExpression::Syntax(query_expression) => { + let mut quotient_index = None; + let recipe = get_system_recipe( + query_expression, + component_loader, + &mut dim, + &mut quotient_index, + ); + + Ok(Box::new(SyntaxExecutor { result: recipe })) + } + QueryExpression::Determinism(query_expression) => { + let mut quotient_index = None; + let recipe = get_system_recipe( + query_expression, + component_loader, + &mut dim, + &mut quotient_index, + ) + .unwrap(); + + Ok(Box::new(DeterminismExecutor { + system: recipe.compile(dim)?, + })) + } + QueryExpression::GetComponent(SaveExpression { system, name }) => { + let mut quotient_index = None; + let recipe = + get_system_recipe(system, component_loader, &mut dim, &mut quotient_index) + .unwrap(); + + Ok(Box::new(GetComponentExecutor { + system: recipe.compile(dim)?, + comp_name: name.clone().unwrap_or("Unnamed".to_string()), + component_loader, + })) + } + QueryExpression::Prune(SaveExpression { system, name }) => { + let mut quotient_index = None; + let recipe = + get_system_recipe(system, component_loader, &mut dim, &mut quotient_index) + .unwrap(); + + Ok(Box::new(GetComponentExecutor { + system: pruning::prune_system(recipe.compile(dim)?, dim), + comp_name: name.clone().unwrap_or("Unnamed".to_string()), + component_loader, + })) + } + + // Should handle consistency, Implementation, determinism and specification here, but we cant deal with it atm anyway + _ => bail!("Not yet setup to handle query"), + } + } else { + bail!("No query was supplied for extraction") + } +} + +#[derive(Clone, Debug)] +pub enum SystemRecipe { + Composition(Box, Box), + Conjunction(Box, Box), + Quotient(Box, Box, ClockIndex), + Component(Box), +} + +impl SystemRecipe { + pub fn compile(self, dim: ClockIndex) -> Result> { + let mut component_index = 0; + self._compile(dim + 1, &mut component_index) + } + + pub fn compile_with_index( + self, + dim: ClockIndex, + component_index: &mut u32, + ) -> Result> { + self._compile(dim + 1, component_index) + } + + fn _compile( + self, + dim: ClockIndex, + component_index: &mut u32, + ) -> Result> { + match self { + SystemRecipe::Composition(left, right) => Composition::new_ts( + left._compile(dim, component_index)?, + right._compile(dim, component_index)?, + dim, + ), + SystemRecipe::Conjunction(left, right) => Conjunction::new_ts( + left._compile(dim, component_index)?, + right._compile(dim, component_index)?, + dim, + ), + SystemRecipe::Quotient(left, right, clock_index) => Quotient::new_ts( + left._compile(dim, component_index)?, + right._compile(dim, component_index)?, + clock_index, + dim, + ), + SystemRecipe::Component(comp) => { + CompiledComponent::compile(*comp, dim, component_index) + .map(|comp| comp as TransitionSystemPtr) + } + } + } + + /// Gets the number of `Components`s in the `SystemRecipe` + pub fn get_component_count(&self) -> usize { + match self { + SystemRecipe::Composition(left, right) + | SystemRecipe::Conjunction(left, right) + | SystemRecipe::Quotient(left, right, _) => { + left.get_component_count() + right.get_component_count() + } + SystemRecipe::Component(_) => 1, + } + } + + pub fn get_components(&self) -> Vec<&Component> { + match self { + SystemRecipe::Composition(left, right) + | SystemRecipe::Conjunction(left, right) + | SystemRecipe::Quotient(left, right, _) => { + let mut o = left.get_components(); + o.extend(right.get_components()); + o + } + SystemRecipe::Component(c) => vec![c], + } + } +} + +pub fn get_system_recipe( + side: &SystemExpression, + component_loader: &mut dyn ComponentLoader, + clock_index: &mut ClockIndex, + quotient_index: &mut Option, +) -> Result, SyntaxResult> { + match side { + SystemExpression::Composition(left, right) => Ok(Box::new(SystemRecipe::Composition( + get_system_recipe(left, component_loader, clock_index, quotient_index)?, + get_system_recipe(right, component_loader, clock_index, quotient_index)?, + ))), + SystemExpression::Conjunction(left, right) => Ok(Box::new(SystemRecipe::Conjunction( + get_system_recipe(left, component_loader, clock_index, quotient_index)?, + get_system_recipe(right, component_loader, clock_index, quotient_index)?, + ))), + SystemExpression::Quotient(left, right) => { + let left = get_system_recipe(left, component_loader, clock_index, quotient_index)?; + let right = get_system_recipe(right, component_loader, clock_index, quotient_index)?; + + let q_index = match quotient_index { + Some(q_i) => *q_i, + None => { + *clock_index += 1; + debug!("Quotient clock index: {}", *clock_index); + + quotient_index.replace(*clock_index); + quotient_index.unwrap() + } + }; + + Ok(Box::new(SystemRecipe::Quotient(left, right, q_index))) + } + SystemExpression::Component(name, id) => { + let mut component = component_loader.get_component(name)?.clone(); + component.set_clock_indices(clock_index); + component.special_id = id.clone(); + // Logic for locations + debug!("{} Clocks: {:?}", name, component.declarations.clocks); + + Ok(Box::new(SystemRecipe::Component(Box::new(component)))) + } + } +} diff --git a/src/System/input_enabler.rs b/src/system/input_enabler.rs similarity index 89% rename from src/System/input_enabler.rs rename to src/system/input_enabler.rs index c5ddd44b..520ffec8 100644 --- a/src/System/input_enabler.rs +++ b/src/system/input_enabler.rs @@ -1,8 +1,8 @@ use edbm::zones::OwnedFederation; -use crate::EdgeEval::constraint_applyer; -use crate::ModelObjects::Expressions::BoolExpression; -use crate::ModelObjects::{Component, DeclarationProvider, Edge, SyncType}; +use crate::edge_eval::constraint_applier; +use crate::model_objects::expressions::BoolExpression; +use crate::model_objects::{Component, DeclarationProvider, Edge, SyncType}; pub fn make_input_enabled(component: &mut Component, inputs: &[String]) { let dimension = component.declarations.get_clock_count() + 1; @@ -15,7 +15,7 @@ pub fn make_input_enabled(component: &mut Component, inputs: &[String]) { let mut location_inv_zone = OwnedFederation::universe(dimension); if let Some(invariant) = &location.invariant { - location_inv_zone = constraint_applyer::apply_constraints_to_state( + location_inv_zone = constraint_applier::apply_constraints_to_state( invariant, component.get_declarations(), location_inv_zone, @@ -41,7 +41,7 @@ pub fn make_input_enabled(component: &mut Component, inputs: &[String]) { .get_location_by_name(edge.target_location.as_str()) .invariant { - guard_zone = constraint_applyer::apply_constraints_to_state( + guard_zone = constraint_applier::apply_constraints_to_state( target_invariant, component.get_declarations(), guard_zone, @@ -58,7 +58,7 @@ pub fn make_input_enabled(component: &mut Component, inputs: &[String]) { } if let Some(guard) = &edge.guard { - guard_zone = constraint_applyer::apply_constraints_to_state( + guard_zone = constraint_applier::apply_constraints_to_state( guard, component.get_declarations(), guard_zone, diff --git a/src/System/local_consistency.rs b/src/system/local_consistency.rs similarity index 87% rename from src/System/local_consistency.rs rename to src/system/local_consistency.rs index 0cb42d78..33781d0d 100644 --- a/src/System/local_consistency.rs +++ b/src/system/local_consistency.rs @@ -1,9 +1,11 @@ +use std::rc::Rc; + use edbm::zones::OwnedFederation; use log::warn; -use crate::ModelObjects::State; -use crate::System::query_failures::{ConsistencyFailure, DeterminismFailure}; -use crate::TransitionSystems::TransitionSystem; +use crate::model_objects::State; +use crate::system::query_failures::{ConsistencyFailure, DeterminismFailure}; +use crate::transition_systems::TransitionSystem; use super::query_failures::{ConsistencyResult, DeterminismResult}; @@ -44,7 +46,7 @@ fn is_deterministic_helper( for action in system.get_actions() { let mut location_fed = OwnedFederation::empty(system.get_dim()); - for transition in &system.next_transitions(&state.decorated_locations, &action) { + for transition in &system.next_transitions(Rc::clone(&state.decorated_locations), &action) { let mut new_state = state.clone(); if transition.use_transition(&mut new_state) { let mut allowed_fed = transition.get_allowed_federation(); @@ -95,7 +97,7 @@ pub fn consistency_least_helper( passed_list.push(state.clone()); for input in system.get_input_actions() { - for transition in &system.next_inputs(&state.decorated_locations, &input) { + for transition in &system.next_inputs(Rc::clone(&state.decorated_locations), &input) { let mut new_state = state.clone(); if transition.use_transition(&mut new_state) { new_state.extrapolate_max_bounds(system); @@ -105,12 +107,12 @@ pub fn consistency_least_helper( } } - if state.zone_ref().can_delay_indefinitely() { + if state.ref_zone().can_delay_indefinitely() { return Ok(()); } for output in system.get_output_actions() { - for transition in system.next_outputs(&state.decorated_locations, &output) { + for transition in system.next_outputs(Rc::clone(&state.decorated_locations), &output) { let mut new_state = state.clone(); if transition.use_transition(&mut new_state) { new_state.extrapolate_max_bounds(system); @@ -135,7 +137,7 @@ fn consistency_fully_helper( passed_list.push(state.clone()); for input in system.get_input_actions() { - for transition in system.next_inputs(&state.decorated_locations, &input) { + for transition in system.next_inputs(Rc::clone(&state.decorated_locations), &input) { let mut new_state = state.clone(); if transition.use_transition(&mut new_state) { new_state.extrapolate_max_bounds(system); @@ -149,7 +151,7 @@ fn consistency_fully_helper( let mut output_existed = false; for output in system.get_output_actions() { - for transition in system.next_outputs(&state.decorated_locations, &output) { + for transition in system.next_outputs(Rc::clone(&state.decorated_locations), &output) { let mut new_state = state.clone(); if transition.use_transition(&mut new_state) { new_state.extrapolate_max_bounds(system); @@ -167,7 +169,7 @@ fn consistency_fully_helper( Ok(()) } else { let last_state = passed_list.last().unwrap(); - match last_state.zone_ref().can_delay_indefinitely() { + match last_state.ref_zone().can_delay_indefinitely() { false => ConsistencyFailure::inconsistent_from(system, &state), true => Ok(()), } diff --git a/src/System/mod.rs b/src/system/mod.rs similarity index 100% rename from src/System/mod.rs rename to src/system/mod.rs diff --git a/src/System/pruning.rs b/src/system/pruning.rs similarity index 97% rename from src/System/pruning.rs rename to src/system/pruning.rs index a2340602..7a3f560f 100644 --- a/src/System/pruning.rs +++ b/src/system/pruning.rs @@ -2,12 +2,14 @@ use edbm::util::constraints::ClockIndex; use edbm::zones::OwnedFederation; use log::{debug, trace}; -use crate::EdgeEval::constraint_applyer::apply_constraints_to_state; -use crate::ModelObjects::Expressions::BoolExpression; -use crate::ModelObjects::{Component, DeclarationProvider, Declarations, Edge, Location, SyncType}; -use crate::System::save_component::combine_components; -use crate::TransitionSystems::TransitionSystemPtr; -use crate::TransitionSystems::{CompiledComponent, LocationTree}; +use crate::edge_eval::constraint_applier::apply_constraints_to_state; +use crate::model_objects::expressions::BoolExpression; +use crate::model_objects::{ + Component, DeclarationProvider, Declarations, Edge, Location, SyncType, +}; +use crate::system::save_component::combine_components; +use crate::transition_systems::TransitionSystemPtr; +use crate::transition_systems::{CompiledComponent, LocationTree}; use std::collections::{HashMap, HashSet}; use super::save_component::PruningStrategy; diff --git a/src/System/query_failures.rs b/src/system/query_failures.rs similarity index 92% rename from src/System/query_failures.rs rename to src/system/query_failures.rs index 965d1381..f08c1ffa 100644 --- a/src/System/query_failures.rs +++ b/src/system/query_failures.rs @@ -1,7 +1,7 @@ use std::{collections::HashSet, fmt}; -use crate::ModelObjects::{Component, State, StatePair}; -use crate::TransitionSystems::{CompositionType, TransitionSystem, TransitionSystemPtr}; +use crate::model_objects::{Component, State, StatePair}; +use crate::transition_systems::{CompositionType, TransitionSystem, TransitionSystemPtr}; use super::specifics::{SpecificPath, SpecificState}; @@ -146,6 +146,8 @@ pub enum QueryResult { Refinement(RefinementResult), /// A consistency query returned a success or failure, see [ConsistencyResult]. Consistency(ConsistencyResult), + /// A syntax query returned a success or failure, see [SyntaxResult]. + Syntax(SyntaxResult), /// A determinism query returned a success or failure, see [DeterminismResult]. Determinism(DeterminismResult), /// A get components query returned a new component. @@ -161,6 +163,8 @@ pub type RefinementResult = Result<(), RefinementFailure>; pub type ConsistencyResult = Result<(), ConsistencyFailure>; +pub type SyntaxResult = Result<(), SyntaxFailure>; + pub type DeterminismResult = Result<(), DeterminismFailure>; /// Represents the different ways that a reachability query can fail @@ -196,9 +200,9 @@ pub enum RefinementPrecondition { EmptyChild { child: String, system: System }, /// The refinement `system` failed because the initial state was empty. EmptyInitialState { system: System }, - /// The refinement `System` failed because of a `ConsistencyFailure`, see [ConsistencyFailure]. + /// The refinement `system` failed because of a `ConsistencyFailure`, see [ConsistencyFailure]. InconsistentChild(ConsistencyFailure, System), - /// The refinement `System` failed because of an `ActionFailure`, see [ActionFailure]. + /// The refinement `system` failed because of an `ActionFailure`, see [ActionFailure]. ActionMismatch(ActionFailure, System), } @@ -300,7 +304,7 @@ impl ActionFailure { } /// Creates a new [Result] that failed because the actions in `inputs` are not a disjoint from the actions in `outputs`. - pub fn not_disjoint_IO( + pub fn not_disjoint_io( name: impl Into, inputs: HashSet, outputs: HashSet, @@ -373,15 +377,15 @@ impl ActionFailure { ) } - /// Converts this [ActionFailure] that occured during the construction of a [Quotient](crate::TransitionSystems::Quotient) into a [SystemRecipeFailure] given the two [TransitionSystem]s that failed. - pub fn to_rfq(self, T: &TransitionSystemPtr, S: &TransitionSystemPtr) -> SystemRecipeFailure { + /// Converts this [ActionFailure] that occured during the construction of a [Quotient](crate::transition_systems::Quotient) into a [SystemRecipeFailure] given the two [TransitionSystem]s that failed. + pub fn to_rfq(self, t: &TransitionSystemPtr, s: &TransitionSystemPtr) -> SystemRecipeFailure { SystemRecipeFailure::Action( self, - System::from_composite_system(T.as_ref(), S.as_ref(), SystemType::Quotient), + System::from_composite_system(t.as_ref(), s.as_ref(), SystemType::Quotient), ) } - /// Converts this [ActionFailure] that occured during the construction of a [Composition](crate::TransitionSystems::Composition) into a [SystemRecipeFailure] given the two [TransitionSystem]s that failed. + /// Converts this [ActionFailure] that occured during the construction of a [Composition](crate::transition_systems::Composition) into a [SystemRecipeFailure] given the two [TransitionSystem]s that failed. pub fn to_rfcomp( self, left: TransitionSystemPtr, @@ -393,7 +397,7 @@ impl ActionFailure { )) } - /// Converts this [ActionFailure] that occured during the construction of a [Conjunction](crate::TransitionSystems::Conjunction) into a [SystemRecipeFailure] given the two [TransitionSystem]s that failed. + /// Converts this [ActionFailure] that occured during the construction of a [Conjunction](crate::transition_systems::Conjunction) into a [SystemRecipeFailure] given the two [TransitionSystem]s that failed. pub fn to_rfconj( self, left: TransitionSystemPtr, @@ -483,11 +487,11 @@ impl ConsistencyFailure { SystemRecipeFailure::Inconsistent(self, System::from(sys)) } - /// Converts this [ConsistencyFailure] that occured during the construction of a [Quotient](crate::TransitionSystems::Quotient) into a [SystemRecipeFailure] given the two [TransitionSystem]s that failed. - pub fn to_rfq(self, T: &TransitionSystemPtr, S: &TransitionSystemPtr) -> SystemRecipeFailure { + /// Converts this [ConsistencyFailure] that occured during the construction of a [Quotient](crate::transition_systems::Quotient) into a [SystemRecipeFailure] given the two [TransitionSystem]s that failed. + pub fn to_rfq(self, t: &TransitionSystemPtr, s: &TransitionSystemPtr) -> SystemRecipeFailure { SystemRecipeFailure::Inconsistent( self, - System::from_composite_system(T.as_ref(), S.as_ref(), SystemType::Quotient), + System::from_composite_system(t.as_ref(), s.as_ref(), SystemType::Quotient), ) } } @@ -517,6 +521,20 @@ impl DeterminismFailure { } } +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum SyntaxFailure { + Unparsable { msg: String, path: String }, +} + +impl SyntaxFailure { + pub fn unparsable(msg: impl Into, path: impl Into) -> SyntaxResult { + Err(SyntaxFailure::Unparsable { + msg: msg.into(), + path: path.into(), + }) + } +} + // ---------------------------- // // --- Format Display Impl --- // // ---------------------------- // @@ -643,6 +661,16 @@ impl std::fmt::Display for RefinementPrecondition { } } +impl std::fmt::Display for SyntaxFailure { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + SyntaxFailure::Unparsable { msg, path } => { + write!(f, "The file '{}' could not be parsed: {}", path, msg) + } + } + } +} + // ------------------------------- // // - Ugly conversions begin here - // // ----- You have been warned ---- // @@ -655,6 +683,7 @@ mod conversions { impl Error for RefinementFailure {} impl Error for ConsistencyFailure {} impl Error for DeterminismFailure {} + impl Error for SyntaxFailure {} impl From for RefinementFailure { fn from(failure: RefinementPrecondition) -> Self { @@ -703,6 +732,12 @@ mod conversions { } } + impl From for QueryResult { + fn from(res: SyntaxResult) -> Self { + QueryResult::Syntax(res) + } + } + impl From for QueryResult { fn from(res: DeterminismResult) -> Self { QueryResult::Determinism(res) diff --git a/src/System/reachability.rs b/src/system/reachability.rs similarity index 90% rename from src/System/reachability.rs rename to src/system/reachability.rs index 7497f9b3..afef26d6 100644 --- a/src/System/reachability.rs +++ b/src/system/reachability.rs @@ -3,9 +3,8 @@ use edbm::zones::OwnedFederation; use super::query_failures::PathFailure; use super::specifics::SpecificPath; -use crate::ModelObjects::{State, Transition}; -use crate::Simulation::decision::Decision; -use crate::TransitionSystems::{LocationID, TransitionSystemPtr}; +use crate::model_objects::{Decision, State, Transition}; +use crate::transition_systems::{LocationID, TransitionSystemPtr}; use std::collections::{HashMap, VecDeque}; use std::rc::Rc; @@ -26,13 +25,13 @@ struct SubPath { fn is_trivially_unreachable(start_state: &State, end_state: &State) -> bool { // If any of the zones are empty - if start_state.zone_ref().is_empty() || end_state.zone_ref().is_empty() { + if start_state.ref_zone().is_empty() || end_state.ref_zone().is_empty() { return true; } // If the end location has invariants and these do not have an intersection (overlap) with the zone of the end state of the query if let Some(invariants) = end_state.decorated_locations.get_invariants() { - if !end_state.zone_ref().has_intersection(invariants) { + if !end_state.ref_zone().has_intersection(invariants) { return true; } } @@ -116,7 +115,7 @@ fn reachability_search( // Push start state to visited state visited_states.insert( start_state.decorated_locations.id.clone(), - vec![start_state.zone_ref().clone()], + vec![start_state.ref_zone().clone()], ); // Push initial state to frontier @@ -126,7 +125,7 @@ fn reachability_search( transition: None, })); - let target_bounds = end_state.zone_ref().get_bounds(); + let target_bounds = end_state.ref_zone().get_bounds(); // Take the first state from the frontier and explore it while let Some(sub_path) = frontier_states.pop_front() { @@ -135,9 +134,10 @@ fn reachability_search( } for action in &actions { - for transition in - &system.next_transitions(&sub_path.destination_state.decorated_locations, action) - { + for transition in &system.next_transitions( + Rc::clone(&sub_path.destination_state.decorated_locations), + action, + ) { take_transition( &sub_path, transition, @@ -157,8 +157,8 @@ fn reachability_search( fn reached_end_state(cur_state: &State, end_state: &State) -> bool { cur_state .decorated_locations - .compare_partial_locations(&end_state.decorated_locations) - && cur_state.zone_ref().has_intersection(end_state.zone_ref()) + .compare_partial_locations(Rc::clone(&end_state.decorated_locations)) + && cur_state.ref_zone().has_intersection(end_state.ref_zone()) } fn take_transition( @@ -178,14 +178,14 @@ fn take_transition( let new_location_id = &new_state.decorated_locations.id; let existing_zones = visited_states.entry(new_location_id.clone()).or_default(); // If this location has not already been reached (explored) with a larger zone - if !zone_subset_of_existing_zones(new_state.zone_ref(), existing_zones) { + if !zone_subset_of_existing_zones(new_state.ref_zone(), existing_zones) { // Remove the smaller zones for this location in visited_states - remove_existing_subsets_of_zone(new_state.zone_ref(), existing_zones); + remove_existing_subsets_of_zone(new_state.ref_zone(), existing_zones); // Add the new zone to the list of zones for this location in visited_states visited_states .get_mut(new_location_id) .unwrap() - .push(new_state.zone_ref().clone()); + .push(new_state.ref_zone().clone()); // Add the new state to the frontier frontier_states.push_back(Rc::new(SubPath { previous_sub_path: Some(Rc::clone(sub_path)), diff --git a/src/System/refine.rs b/src/system/refine.rs similarity index 91% rename from src/System/refine.rs rename to src/system/refine.rs index 5258000a..c8152631 100644 --- a/src/System/refine.rs +++ b/src/system/refine.rs @@ -1,11 +1,13 @@ use edbm::zones::OwnedFederation; use log::{debug, info, log_enabled, trace, Level}; -use crate::DataTypes::{PassedStateList, PassedStateListExt, WaitingStateList}; -use crate::ModelObjects::{StatePair, Transition}; -use crate::System::query_failures::RefinementFailure; -use crate::TransitionSystems::{LocationTree, TransitionSystemPtr}; +use crate::model_objects::{ + PassedStateList, PassedStateListExt, StatePair, Transition, WaitingStateList, +}; +use crate::system::query_failures::RefinementFailure; +use crate::transition_systems::TransitionSystemPtr; use std::collections::HashSet; +use std::rc::Rc; use super::query_failures::{ActionFailure, RefinementPrecondition, RefinementResult}; @@ -139,11 +141,11 @@ pub fn check_refinement(sys1: TransitionSystemPtr, sys2: TransitionSystemPtr) -> let mut initial_pair = StatePair::from_locations( dimensions, - initial_locations_1.clone(), - initial_locations_2.clone(), + Rc::clone(&initial_locations_1), + Rc::clone(&initial_locations_2), ); - if !prepare_init_state(&mut initial_pair, initial_locations_1, initial_locations_2) { + if initial_pair.ref_zone().is_empty() { return RefinementFailure::empty_initial(sys1.as_ref(), sys2.as_ref()); } initial_pair.extrapolate_max_bounds(context.sys1, context.sys2); @@ -335,12 +337,10 @@ fn build_state_pair( context: &mut RefinementContext, is_state1: bool, ) -> BuildResult { - //Creates new state pair - let mut new_sp: StatePair = curr_pair.clone(); //Creates DBM for that state pair - let mut new_sp_zone = new_sp.take_zone(); + let mut new_sp_zone = curr_pair.clone_zone(); + //Apply guards on both sides - let (locations1, locations2) = new_sp.get_mut_states(is_state1); //Applies the left side guards and checks if zone is valid new_sp_zone = transition1.apply_guards(new_sp_zone); @@ -360,16 +360,15 @@ fn build_state_pair( new_sp_zone = new_sp_zone.up(); //Update locations in states - - transition1.move_locations(locations1); - transition2.move_locations(locations2); + let (locations1, locations2) = ( + Rc::clone(&transition1.target_locations), + Rc::clone(&transition2.target_locations), + ); // Apply invariants on the left side of relation let (left_loc, right_loc) = if is_state1 { - //(locations2, locations1) (locations1, locations2) } else { - //(locations1, locations2) (locations2, locations1) }; @@ -394,8 +393,7 @@ fn build_state_pair( return BuildResult::Failure; } - new_sp.set_zone(new_sp_zone); - + let mut new_sp = StatePair::new(left_loc, right_loc, Rc::new(new_sp_zone)); new_sp.extrapolate_max_bounds(context.sys1, context.sys2); if !context.passed_list.has(&new_sp) && !context.waiting_list.has(&new_sp) { @@ -407,20 +405,6 @@ fn build_state_pair( BuildResult::Success } -fn prepare_init_state( - initial_pair: &mut StatePair, - initial_locations_1: LocationTree, - initial_locations_2: LocationTree, -) -> bool { - let mut sp_zone = initial_pair.take_zone(); - sp_zone = initial_locations_1.apply_invariants(sp_zone); - sp_zone = initial_locations_2.apply_invariants(sp_zone); - - initial_pair.set_zone(sp_zone); - - !initial_pair.ref_zone().is_empty() -} - fn check_preconditions( sys1: &TransitionSystemPtr, sys2: &TransitionSystemPtr, diff --git a/src/System/save_component.rs b/src/system/save_component.rs similarity index 71% rename from src/System/save_component.rs rename to src/system/save_component.rs index 2817ac08..a5a59e11 100644 --- a/src/System/save_component.rs +++ b/src/system/save_component.rs @@ -1,14 +1,15 @@ -use crate::ModelObjects::Expressions::BoolExpression; -use crate::ModelObjects::{Component, Declarations, Location, LocationType, SyncType}; -use crate::TransitionSystems::{LocationTree, TransitionSystemPtr}; +use crate::model_objects::expressions::BoolExpression; +use crate::model_objects::{Component, Declarations, Location, LocationType, SyncType}; +use crate::transition_systems::{LocationTree, TransitionSystemPtr}; use std::collections::HashMap; +use std::rc::Rc; pub enum PruningStrategy { Reachable, NoPruning, } -use crate::ModelObjects::Edge; +use crate::model_objects::Edge; use edbm::util::constraints::ClockIndex; use PruningStrategy::*; @@ -28,7 +29,7 @@ pub fn combine_components( } }; - let locations = get_locations_from_trees(&location_trees, &clocks); + let locations = get_locations_from_trees(location_trees.as_slice(), &clocks); Component { name: "".to_string(), @@ -39,11 +40,12 @@ pub fn combine_components( locations, edges, special_id: None, + clock_usages: Default::default(), } } pub fn get_locations_from_trees( - location_trees: &[LocationTree], + location_trees: &[Rc], clock_map: &HashMap, ) -> Vec { location_trees @@ -92,20 +94,20 @@ pub fn get_clock_map(sysrep: &TransitionSystemPtr) -> HashMap, + locations: &mut Vec>, edges: &mut Vec, clock_map: &HashMap, ) { let l = representation.get_all_locations(); locations.extend(l); for location in locations { - collect_edges_from_location(location, representation, edges, clock_map); + collect_edges_from_location(Rc::clone(location), representation, edges, clock_map); } } fn collect_reachable_edges_and_locations( representation: &TransitionSystemPtr, - locations: &mut Vec, + locations: &mut Vec>, edges: &mut Vec, clock_map: &HashMap, ) { @@ -118,17 +120,17 @@ fn collect_reachable_edges_and_locations( locations.push(l.clone()); - collect_reachable_locations(&l, representation, locations); + collect_reachable_locations(l, representation, locations); for loc in locations { - collect_edges_from_location(loc, representation, edges, clock_map); + collect_edges_from_location(Rc::clone(loc), representation, edges, clock_map); } } fn collect_reachable_locations( - location: &LocationTree, + location: Rc, representation: &TransitionSystemPtr, - locations: &mut Vec, + locations: &mut Vec>, ) { for input in [true, false].iter() { for sync in if *input { @@ -136,15 +138,14 @@ fn collect_reachable_locations( } else { representation.get_output_actions() } { - let transitions = representation.next_transitions(location, &sync); + let transitions = representation.next_transitions(Rc::clone(&location), &sync); for transition in transitions { - let mut target_location = location.clone(); - transition.move_locations(&mut target_location); + let target_location = transition.target_locations; if !locations.contains(&target_location) { - locations.push(target_location.clone()); - collect_reachable_locations(&target_location, representation, locations); + locations.push(Rc::clone(&target_location)); + collect_reachable_locations(target_location, representation, locations); } } } @@ -152,17 +153,29 @@ fn collect_reachable_locations( } fn collect_edges_from_location( - location: &LocationTree, + location: Rc, representation: &TransitionSystemPtr, edges: &mut Vec, clock_map: &HashMap, ) { - collect_specific_edges_from_location(location, representation, edges, true, clock_map); - collect_specific_edges_from_location(location, representation, edges, false, clock_map); + collect_specific_edges_from_location( + Rc::clone(&location), + representation, + edges, + true, + clock_map, + ); + collect_specific_edges_from_location( + Rc::clone(&location), + representation, + edges, + false, + clock_map, + ); } fn collect_specific_edges_from_location( - location: &LocationTree, + location: Rc, representation: &TransitionSystemPtr, edges: &mut Vec, input: bool, @@ -173,10 +186,9 @@ fn collect_specific_edges_from_location( } else { representation.get_output_actions() } { - let transitions = representation.next_transitions(location, &sync); + let transitions = representation.next_transitions(Rc::clone(&location), &sync); for transition in transitions { - let mut target_location = location.clone(); - transition.move_locations(&mut target_location); + let target_location_id = transition.target_locations.id.to_string(); let guard = transition.get_renamed_guard_expression(clock_map); if let Some(BoolExpression::Bool(false)) = guard { @@ -186,7 +198,7 @@ fn collect_specific_edges_from_location( let edge = Edge { id: transition.id.to_string(), source_location: location.id.to_string(), - target_location: target_location.id.to_string(), + target_location: target_location_id, sync_type: if input { SyncType::Input } else { diff --git a/src/System/specifics.rs b/src/system/specifics.rs similarity index 95% rename from src/System/specifics.rs rename to src/system/specifics.rs index bc158db0..378348b9 100644 --- a/src/System/specifics.rs +++ b/src/system/specifics.rs @@ -2,13 +2,10 @@ use std::{collections::HashMap, fmt}; use edbm::util::constraints::{ClockIndex, Conjunction, Constraint, Disjunction}; -use crate::ModelObjects::{State, StatePair}; -use crate::{ - Simulation::decision::Decision, - TransitionSystems::{ - transition_system::ComponentInfoTree, CompositionType, LocationID, TransitionID, - TransitionSystem, - }, +use crate::model_objects::{Decision, State, StatePair}; +use crate::transition_systems::{ + transition_system::ComponentInfoTree, CompositionType, LocationID, TransitionID, + TransitionSystem, }; use super::{query_failures::SystemType, reachability::Path}; @@ -110,7 +107,7 @@ impl SpecificComp { } } -/// Intermediate representation of an [edge](crate::ModelObjects::component::Edge) in a component instance. +/// Intermediate representation of an [edge](crate::model_objects::component::Edge) in a component instance. #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct SpecificEdge { pub comp: SpecificComp, @@ -220,7 +217,7 @@ pub struct SpecificState { pub constraints: SpecificDisjunction, } -/// Intermediate representation of a [LocationID](crate::TransitionSystems::location_id::LocationID) in a system. +/// Intermediate representation of a [LocationID](crate::transition_systems::location_id::LocationID) in a system. /// It is a binary tree with either [component](SpecificComp) locations or [special](SpecialLocation) locations at the leaves. #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum SpecificLocation { @@ -272,7 +269,7 @@ impl fmt::Display for SpecificLocation { } } -/// Intermediate representation of a [special](crate::TransitionSystems::location_id::LocationID::Special) location. E.g. `Error` or `Universal` from a quotient. +/// Intermediate representation of a [special](crate::transition_systems::location_id::LocationID::Special) location. E.g. `Error` or `Universal` from a quotient. #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum SpecialLocation { Universal, @@ -294,7 +291,7 @@ impl SpecificState { let locations = state_specific_location(state, sys); let clock_map = specific_clock_comp_map(sys); - let constraints = state.zone_ref().minimal_constraints(); + let constraints = state.ref_zone().minimal_constraints(); let constraints = SpecificDisjunction::from_disjunction(constraints, &clock_map); Self { locations, diff --git a/src/tests/ClockReduction/advanced_clock_detection_test.rs b/src/tests/ClockReduction/advanced_clock_detection_test.rs deleted file mode 100644 index 4e250d1f..00000000 --- a/src/tests/ClockReduction/advanced_clock_detection_test.rs +++ /dev/null @@ -1,169 +0,0 @@ -#[cfg(test)] -pub mod test { - use crate::tests::ClockReduction::helper::test::{ - create_clock_name_to_index, get_composition_transition_system, - get_conjunction_transition_system, - }; - use crate::TransitionSystems::transition_system::ClockReductionInstruction; - use std::path::Path; - - const ADVANCED_CLOCK_REDUCTION_PATH: &str = - "samples/json/ClockReductionTest/AdvancedClockReduction"; - - #[test] - fn test_advanced_clock_detection() { - let transition_system = get_conjunction_transition_system( - &Path::new(ADVANCED_CLOCK_REDUCTION_PATH).join("Conjunction/Example1"), - "Component1", - "Component2", - ); - - let clock_name_to_index = create_clock_name_to_index(&transition_system); - - let clock_reduction_instruction = transition_system.find_redundant_clocks(); - - assert_eq!( - clock_reduction_instruction.len(), - 1, - "Only one instruction needed" - ); - assert!( - match &clock_reduction_instruction[0] { - ClockReductionInstruction::RemoveClock { .. } => false, - ClockReductionInstruction::ReplaceClocks { - clock_index, - clock_indices, - } => { - assert_eq!( - clock_index, - clock_name_to_index.get("component0:x").unwrap(), - "Clocks get replaced by x" - ); - assert_eq!(clock_indices.len(), 1, "Only one clock should be replaced"); - assert!( - clock_indices.contains(clock_name_to_index.get("component1:y").unwrap()), - "Clock y can be replaced by x" - ); - true - } - }, - "Clock reduction instruction is replace clocks" - ); - } - - #[test] - fn test_advanced_same_component_clock_detection() { - let transition_system = get_conjunction_transition_system( - &Path::new(ADVANCED_CLOCK_REDUCTION_PATH).join("Conjunction/SameComponent"), - "Component1", - "Component1", - ); - - let clock_name_to_index = create_clock_name_to_index(&transition_system); - - let clock_reduction_instruction = transition_system.find_redundant_clocks(); - - assert_eq!( - clock_reduction_instruction.len(), - 1, - "Only one instruction needed" - ); - assert!( - match &clock_reduction_instruction[0] { - ClockReductionInstruction::RemoveClock { .. } => false, - ClockReductionInstruction::ReplaceClocks { - clock_index, - clock_indices, - } => { - assert_eq!( - clock_index, - clock_name_to_index.get("component0:x").unwrap(), - "Clocks get replaced by component1:x" - ); - assert_eq!(clock_indices.len(), 1, "Only one clock should be replaced"); - assert!( - clock_indices.contains(clock_name_to_index.get("component1:x").unwrap()), - "Clock component2:x can be replaced by component1:x" - ); - true - } - }, - "Clock reduction instruction is replace clocks" - ); - } - - #[test] - fn test_conjunction_of_cyclical_component() { - let transition_system = get_conjunction_transition_system( - &Path::new(ADVANCED_CLOCK_REDUCTION_PATH).join("Conjunction/ConjunctionCyclic"), - "Component1", - "Component2", - ); - - let clock_name_to_index = create_clock_name_to_index(&transition_system); - - let clock_reduction_instruction = transition_system.find_redundant_clocks(); - - assert_eq!( - clock_reduction_instruction.len(), - 1, - "Only one instruction needed" - ); - assert!( - match &clock_reduction_instruction[0] { - ClockReductionInstruction::RemoveClock { .. } => false, - ClockReductionInstruction::ReplaceClocks { - clock_index, - clock_indices, - } => { - assert_eq!( - clock_index, - clock_name_to_index.get("component0:x").unwrap(), - "Clocks get replaced by x" - ); - assert_eq!(clock_indices.len(), 1, "Only one clock should be replaced"); - assert!( - clock_indices.contains(clock_name_to_index.get("component1:y").unwrap()), - "Clock y can be replaced by x" - ); - true - } - }, - "Clock reduction instruction is replace clocks" - ); - } - - #[test] - fn test_composition_of_cyclical_component() { - let transition_system = get_composition_transition_system( - &Path::new(ADVANCED_CLOCK_REDUCTION_PATH).join("Composition/CyclicOnlyOutput"), - "Component1", - "Component2", - ); - - let clock_reduction_instruction = transition_system.find_redundant_clocks(); - - assert_eq!( - clock_reduction_instruction.len(), - 0, - "No reduction is possible" - ); - } - - #[test] - fn test_composition_of_component() { - let transition_system = get_composition_transition_system( - &Path::new(ADVANCED_CLOCK_REDUCTION_PATH).join("Composition/CyclicOnlyOutput"), - "Component1", - "Component2", - ); - - let clock_reduction_instruction = transition_system.find_redundant_clocks(); - - assert_eq!( - clock_reduction_instruction.len(), - 0, - "No reduction is possible" - ); - } -} diff --git a/src/tests/ClockReduction/advanced_clock_removal_test.rs b/src/tests/ClockReduction/advanced_clock_removal_test.rs deleted file mode 100644 index 3203e096..00000000 --- a/src/tests/ClockReduction/advanced_clock_removal_test.rs +++ /dev/null @@ -1,77 +0,0 @@ -#[cfg(test)] -pub mod test { - const ADVANCED_CLOCK_REDUCTION_PATH: &str = - "samples/json/ClockReductionTest/AdvancedClockReduction"; - - use crate::extract_system_rep::clock_reduction; - use crate::tests::ClockReduction::helper::test::get_conjunction_system_recipe; - use std::collections::HashSet; - use std::path::Path; - - #[test] - fn test_advanced_clock_removal() { - let (mut dimensions, system_recipe) = get_conjunction_system_recipe( - &Path::new(ADVANCED_CLOCK_REDUCTION_PATH).join("Conjunction/Example1"), - "Component1", - "Component2", - ); - - let mut system_recipe_copy = Box::new(system_recipe); - - clock_reduction::clock_reduce(&mut system_recipe_copy, None, &mut dimensions, None) - .unwrap(); - - //We let it use the unreduced amount of dimensions so we can catch the error - //If a clock is not reduced - let compiled = system_recipe_copy.compile(dimensions).unwrap(); - - for location in compiled.get_all_locations() { - assert!(location.invariant.is_none(), "Should contain no invariants") - } - - let graph = compiled.get_analysis_graph(); - for edge in &graph.edges { - match format!("{}->{}", edge.from, edge.to).as_str() { - "(L0&&L4)->(L1&&L5)" => { - assert_eq!( - edge.guard_dependencies.len(), - 2, - "edge (L0&&L4)->(L1&&L5) should only have 1 guard dependency" - ); - assert!(edge.guard_dependencies.is_subset(&HashSet::from([0, 1]))); - assert_eq!( - edge.updates.len(), - 0, - "(L0&&L4)->(L1&&L5) should have no updates" - ); - } - "(L1&&L5)->(L2&&L6)" => { - assert_eq!( - edge.guard_dependencies.len(), - 0, - "edge (L0&&L4)->(L1&&L5) should only have 2 guard dependency" - ); - for update in &edge.updates { - assert_eq!( - update.clock_index, 1, - "edge (L0&&L4)->(L1&&L5) should only update clock 1" - ); - } - } - "(L2&&L6)->(L3&&L7)" => { - assert_eq!( - edge.guard_dependencies.len(), - 0, - "edge (L0&&L4)->(L1&&L5) should only have 1 guard dependency" - ); - assert_eq!( - edge.updates.len(), - 0, - "(L2&&L6)->(L3&&L7) should have no updates" - ); - } - e => panic!("unknown edge {}", e), - } - } - } -} diff --git a/src/tests/ClockReduction/clock_removal_test.rs b/src/tests/ClockReduction/clock_removal_test.rs deleted file mode 100644 index 3d937737..00000000 --- a/src/tests/ClockReduction/clock_removal_test.rs +++ /dev/null @@ -1,134 +0,0 @@ -#[cfg(test)] -pub mod clock_removal_tests { - use crate::extract_system_rep::{clock_reduction, SystemRecipe}; - use crate::tests::refinement::Helper::json_run_query; - use crate::DataReader::json_reader::read_json_component; - use crate::ModelObjects::Component; - use crate::TransitionSystems::{CompiledComponent, TransitionSystem}; - use std::collections::HashSet; - - #[test] - fn test_check_declarations_unused_clocks_are_removed() { - check_declarations_unused_clocks_are_removed("Component1", "x"); - check_declarations_unused_clocks_are_removed("Component2", "i"); - check_declarations_unused_clocks_are_removed("Component3", "c"); - } - - impl Component { - fn fit_decls(&mut self, index: edbm::util::constraints::ClockIndex) { - self.declarations - .clocks - .values_mut() - .filter(|val| **val > index) - .for_each(|val| *val -= 1); - } - } - - fn check_declarations_unused_clocks_are_removed(component_name: &str, clock: &str) { - let mut component = read_json_component( - "samples/json/ClockReductionTest/UnusedClock", - component_name, - ); - - let clock_index = *component - .declarations - .get_clock_index_by_name(clock) - .unwrap(); - - component.remove_clock(clock_index); - component.fit_decls(clock_index); - - let clock_reduced_compiled_component = CompiledComponent::compile( - component.clone(), - component.declarations.clocks.len() + 1, - &mut 0, - ) - .unwrap(); - - let decls = clock_reduced_compiled_component.get_decls(); - - assert!(!decls[0].clocks.contains_key(clock)); - } - - #[test] - fn test_check_declarations_duplicated_clocks_are_removed() { - let mut component = read_json_component( - "samples/json/ClockReductionTest/RedundantClocks", - "Component1", - ); - - let clock_1_index = component.declarations.get_clock_index_by_name("x").unwrap(); - let mut duplicate_clocks_index = HashSet::new(); - duplicate_clocks_index - .insert(*component.declarations.get_clock_index_by_name("y").unwrap()); - duplicate_clocks_index - .insert(*component.declarations.get_clock_index_by_name("z").unwrap()); - - component.replace_clock(*clock_1_index, &duplicate_clocks_index); - - let clock_reduced_compiled_component = CompiledComponent::compile( - component.clone(), - component.declarations.clocks.len() + 1, - &mut 0, - ) - .unwrap(); - - let decls = clock_reduced_compiled_component.get_decls(); - - assert_eq!(*decls[0].clocks.get_key_value("x").unwrap().1, 1); - assert_eq!(*decls[0].clocks.get_key_value("y").unwrap().1, 1); - assert_eq!(*decls[0].clocks.get_key_value("z").unwrap().1, 1); - } - - #[test] - fn test_no_used_clock() { - const PATH: &str = "samples/json/AG"; - - let comp = read_json_component(PATH, "A"); - - let mut dim = comp.declarations.clocks.len(); - assert_eq!( - dim, 4, - "As of writing these tests, this component has 4 unused clocks" - ); - - let recipe = SystemRecipe::Component(Box::from(comp)); - clock_reduction::clock_reduce(&mut Box::from(recipe), None, &mut dim, None).unwrap(); - assert_eq!(dim, 0, "After removing the clocks, the dim should be 0"); - - assert!( - json_run_query(PATH, "consistency: A").is_ok(), - "A should be consistent" - ); - } - - #[test] - fn test_no_used_clock_multi() { - const PATH: &str = "samples/json/AG"; - let mut dim = 0; - let mut lhs = read_json_component(PATH, "A"); - lhs.set_clock_indices(&mut dim); - let mut rhs = read_json_component(PATH, "A"); - rhs.set_clock_indices(&mut dim); - - assert_eq!( - dim, 8, - "As of writing these tests, these component has 8 unused clocks" - ); - assert_eq!( - lhs.declarations.clocks.len() + rhs.declarations.clocks.len(), - 8 - ); - - let l = SystemRecipe::Component(Box::from(lhs)); - let r = SystemRecipe::Component(Box::from(rhs)); - clock_reduction::clock_reduce(&mut Box::from(l), Some(&mut Box::from(r)), &mut dim, None) - .unwrap(); - assert_eq!(dim, 0, "After removing the clocks, the dim should be 0"); - - assert!( - json_run_query(PATH, "refinement: A <= A").is_ok(), - "A should refine itself" - ); - } -} diff --git a/src/tests/ClockReduction/helper.rs b/src/tests/ClockReduction/helper.rs deleted file mode 100644 index 2dc123b4..00000000 --- a/src/tests/ClockReduction/helper.rs +++ /dev/null @@ -1,136 +0,0 @@ -#[cfg(test)] -pub mod test { - use crate::extract_system_rep::SystemRecipe; - use crate::DataReader::json_reader::read_json_component; - use crate::ModelObjects::Component; - use crate::System::input_enabler; - use crate::TransitionSystems::transition_system::ClockReductionInstruction; - use crate::TransitionSystems::TransitionSystemPtr; - use crate::{JsonProjectLoader, DEFAULT_SETTINGS}; - use edbm::util::constraints::ClockIndex; - use std::collections::{HashMap, HashSet}; - use std::path::Path; - - /// Reads and processes a component. - pub fn read_json_component_and_process(project_path: &str, component_name: &str) -> Component { - let mut component = read_json_component(project_path, component_name); - let inputs = component.get_input_actions(); - input_enabler::make_input_enabled(&mut component, &inputs); - component - } - - /// Assert that a [`vec<&ClockReductionInstruction>`] contains an instruction that `clock` should - /// be removed. - pub(crate) fn assert_unused_clock_in_clock_reduction_instruction_vec( - redundant_clocks: Vec, - clock: ClockIndex, - ) { - assert!(redundant_clocks - .iter() - .any(|instruction| match instruction { - ClockReductionInstruction::RemoveClock { clock_index } => { - println!("Found {}, searching for {}", clock_index, clock); - *clock_index == clock - } - _ => false, - })); - } - /// Assert that a [`vec<&ClockReductionInstruction>`] contains an instruction that `clock` is a - /// duplicate of the clocks in `clocks`. - pub(crate) fn assert_duplicate_clock_in_clock_reduction_instruction_vec( - redundant_clocks: Vec, - clock: ClockIndex, - clocks: &HashSet, - ) { - assert!(redundant_clocks - .iter() - .any(|instruction| match instruction { - ClockReductionInstruction::RemoveClock { .. } => { - false - } - ClockReductionInstruction::ReplaceClocks { - clock_index, - clock_indices, - } => { - *clock_index == clock && clock_indices == clocks - } - })); - } - - pub(crate) fn get_conjunction_transition_system( - path: &Path, - comp1: &str, - comp2: &str, - ) -> TransitionSystemPtr { - let (dim, system_recipe) = get_conjunction_system_recipe(path, comp1, comp2); - system_recipe.compile(dim).unwrap() - } - - pub(crate) fn get_conjunction_system_recipe( - path: &Path, - comp1: &str, - comp2: &str, - ) -> (ClockIndex, SystemRecipe) { - let project_loader = - JsonProjectLoader::new_loader(path.to_string_lossy().to_string(), DEFAULT_SETTINGS); - - let mut component_loader = project_loader.to_comp_loader(); - - let mut next_clock_index: usize = 0; - let mut component1 = component_loader.get_component(comp1).clone(); - let mut component2 = component_loader.get_component(comp2).clone(); - - component1.set_clock_indices(&mut next_clock_index); - component2.set_clock_indices(&mut next_clock_index); - - let dimensions = - component1.declarations.clocks.len() + component2.declarations.clocks.len(); - - let sr_component1 = Box::new(SystemRecipe::Component(Box::new(component1))); - let sr_component2 = Box::new(SystemRecipe::Component(Box::new(component2))); - - let conjunction = SystemRecipe::Conjunction(sr_component1, sr_component2); - (dimensions, conjunction) - } - - pub(crate) fn get_composition_transition_system( - path: &Path, - comp1: &str, - comp2: &str, - ) -> TransitionSystemPtr { - let project_loader = - JsonProjectLoader::new_loader(path.to_string_lossy().to_string(), DEFAULT_SETTINGS); - - let mut component_loader = project_loader.to_comp_loader(); - - let mut next_clock_index: usize = 0; - let mut component1 = component_loader.get_component(comp1).clone(); - let mut component2 = component_loader.get_component(comp2).clone(); - - component1.set_clock_indices(&mut next_clock_index); - component2.set_clock_indices(&mut next_clock_index); - - let dimensions = - component1.declarations.clocks.len() + component2.declarations.clocks.len(); - - let sr_component1 = Box::new(SystemRecipe::Component(Box::new(component1))); - let sr_component2 = Box::new(SystemRecipe::Component(Box::new(component2))); - - let conjunction = SystemRecipe::Composition(sr_component1, sr_component2); - - conjunction.compile(dimensions).unwrap() - } - - pub(crate) fn create_clock_name_to_index( - transition_system: &TransitionSystemPtr, - ) -> HashMap { - let mut clock_name_to_index: HashMap = HashMap::new(); - - for (i, declaration) in transition_system.get_decls().iter().enumerate() { - for (clock_name, clock_index) in &declaration.clocks { - clock_name_to_index.insert(format!("component{}:{}", i, clock_name), *clock_index); - } - } - clock_name_to_index - } -} diff --git a/src/tests/ClockReduction/mod.rs b/src/tests/ClockReduction/mod.rs deleted file mode 100644 index bffb377c..00000000 --- a/src/tests/ClockReduction/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -mod advanced_clock_detection_test; -mod advanced_clock_removal_test; -mod clock_removal_test; -mod helper; -pub mod redundant_clock_detection_test; -pub mod unused_clock_detection_test; diff --git a/src/tests/ClockReduction/redundant_clock_detection_test.rs b/src/tests/ClockReduction/redundant_clock_detection_test.rs deleted file mode 100644 index 61a7c9c5..00000000 --- a/src/tests/ClockReduction/redundant_clock_detection_test.rs +++ /dev/null @@ -1,41 +0,0 @@ -#[cfg(test)] -pub mod test { - use crate::tests::ClockReduction::helper::test::{ - assert_duplicate_clock_in_clock_reduction_instruction_vec, read_json_component_and_process, - }; - use crate::TransitionSystems::{CompiledComponent, TransitionSystem}; - use edbm::util::constraints::ClockIndex; - use std::collections::HashSet; - - const REDUNDANT_CLOCKS_TEST_PROJECT: &str = "samples/json/ClockReductionTest/RedundantClocks"; - const DIM: ClockIndex = 5; // TODO: Dim - - #[test] - fn test_three_synced_clocks() { - let expected_clocks = ["x".to_string(), "y".to_string(), "z".to_string()]; - let component = - read_json_component_and_process(REDUNDANT_CLOCKS_TEST_PROJECT, "Component1"); - let compiled_component = - CompiledComponent::compile(component.clone(), DIM, &mut 0).unwrap(); - let clock_index_x = component - .declarations - .get_clock_index_by_name(&expected_clocks[0]) - .unwrap(); - let clock_index_y = component - .declarations - .get_clock_index_by_name(&expected_clocks[1]) - .unwrap(); - let clock_index_z = component - .declarations - .get_clock_index_by_name(&expected_clocks[2]) - .unwrap(); - - let instructions = compiled_component.find_redundant_clocks(); - - assert_duplicate_clock_in_clock_reduction_instruction_vec( - instructions, - *clock_index_x, - &HashSet::from([*clock_index_y, *clock_index_z]), - ); - } -} diff --git a/src/tests/ClockReduction/unused_clock_detection_test.rs b/src/tests/ClockReduction/unused_clock_detection_test.rs deleted file mode 100644 index 405a966c..00000000 --- a/src/tests/ClockReduction/unused_clock_detection_test.rs +++ /dev/null @@ -1,66 +0,0 @@ -#[cfg(test)] -mod unused_clocks_tests { - use crate::tests::ClockReduction::helper::test::assert_unused_clock_in_clock_reduction_instruction_vec; - use crate::DataReader::json_reader::read_json_component; - use crate::TransitionSystems::{CompiledComponent, TransitionSystem}; - - /// Loads the sample in `samples/json/ClockReductionTest/UnusedClockWithCycle` which contains - /// unused clocks. It then tests that these clocks are located correctly. - fn unused_clocks_with_cycles(component_name: &str, unused_clock: &str) { - let component = read_json_component( - "samples/json/ClockReductionTest/UnusedClockWithCycle", - component_name, - ); - - let compiled_component = CompiledComponent::compile( - component.clone(), - component.declarations.clocks.len() + 1, - &mut 0, - ) - .unwrap(); - - let clock_index = component - .declarations - .get_clock_index_by_name(unused_clock) - .unwrap(); - - let instructions = compiled_component.find_redundant_clocks(); - - assert_unused_clock_in_clock_reduction_instruction_vec(instructions, *clock_index) - } - - /// Loads the sample in `samples/json/ClockReductionTest/UnusedClock` which contains - /// unused clocks. It then tests that these clocks are located correctly. - fn unused_clock(component_name: &str, unused_clock: &str) { - let component = read_json_component( - "samples/json/ClockReductionTest/UnusedClock", - component_name, - ); - - let compiled_component = CompiledComponent::compile( - component.clone(), - component.declarations.clocks.len() + 1, - &mut 0, - ) - .unwrap(); - - let clock_index = component - .declarations - .get_clock_index_by_name(unused_clock) - .unwrap(); - - let instructions = compiled_component.find_redundant_clocks(); - - assert_unused_clock_in_clock_reduction_instruction_vec(instructions, *clock_index) - } - - #[test] - fn test_unused_clock_test() { - unused_clocks_with_cycles("Component1", "x"); - unused_clocks_with_cycles("Component2", "z"); - unused_clocks_with_cycles("Component3", "j"); - unused_clock("Component1", "x"); - unused_clock("Component2", "i"); - unused_clock("Component3", "c"); - } -} diff --git a/src/tests/ModelObjects/arith_expression.rs b/src/tests/ModelObjects/arith_expression.rs deleted file mode 100644 index e8e4c98a..00000000 --- a/src/tests/ModelObjects/arith_expression.rs +++ /dev/null @@ -1,128 +0,0 @@ -#[cfg(test)] -mod test { - use crate::ModelObjects::Expressions::ArithExpression as AE; - use AE::*; - #[test] - fn simplify_test1() { - let expr = AE::ADif(Int(10), Int(5)); //10 - 5 - assert_eq!(Ok(Int(5)), expr.simplify()); - - let expr = AE::AAdd(Int(10), Int(5)); //10 + 5 - assert_eq!(Ok(Int(15)), expr.simplify()); - } - - #[test] - fn simplify_test2() { - let expr = Multiplication( - //(10 - 5) * (5 + 3) - Box::new(AE::ADif(Int(10), Int(5))), - Box::new(AE::AAdd(Int(5), Int(3))), - ); - assert_eq!(Ok(Int(40)), expr.simplify()); - - let expr = Multiplication( - //(10 + 5) * (5 - 3) - Box::new(AE::AAdd(Int(10), Int(5))), - Box::new(AE::ADif(Int(5), Int(3))), - ); - assert_eq!(Ok(Int(30)), expr.simplify()); - } - #[test] - fn simplify_test3() { - let expr = AE::ADif( - Clock(1), - AE::ADif(Int(5), AE::ADif(Int(4), AE::ADif(Int(3), Int(2)))), //5-(4-(3-2)) - ); - assert_eq!(Ok(AE::ADif(Clock(1), Int(2))), expr.simplify()); - - let expr = AE::AAdd( - Clock(1), - AE::AAdd(Int(5), AE::AAdd(Int(4), AE::AAdd(Int(3), Int(2)))), - ); - assert_eq!(Ok(AE::AAdd(Clock(1), Int(14))), expr.simplify()); - } - #[test] - fn simplify_test4() { - //((5-4)-3)-2 - let expr = AE::ADif( - Clock(1), - AE::ADif(AE::ADif(AE::ADif(Int(5), Int(4)), Int(3)), Int(2)), - ); - assert_eq!(Ok(AE::ADif(Clock(1), Int(-4))), expr.simplify()); - - let expr = AE::AAdd( - Clock(1), - AE::AAdd(AE::AAdd(AE::AAdd(Int(5), Int(4)), Int(3)), Int(2)), - ); - assert_eq!(Ok(AE::AAdd(Clock(1), Int(14))), expr.simplify()); - } - - #[test] - fn simplify_test5() { - //((5-4)-3)-2 - let expr = AE::ADif(AE::ADif(AE::ADif(Int(5), Clock(4)), Int(3)), Int(2)); - assert_eq!(Ok(AE::ADif(Int(0), Clock(4))), expr.simplify()); - - let expr = AE::AAdd(AE::AAdd(AE::AAdd(Int(5), Clock(4)), Int(3)), Int(2)); - assert_eq!(Ok(AE::AAdd(Int(10), Clock(4))), expr.simplify()); - } - - #[test] - fn simplify_test6() { - //5-(4-(3-2)) - let expr = AE::ADif(Int(5), AE::ADif(Int(4), AE::ADif(Int(3), Clock(2)))); - assert_eq!(Ok(AE::ADif(Int(4), Clock(2))), expr.simplify()); - - let expr = AE::AAdd(Int(5), AE::AAdd(Int(4), AE::AAdd(Int(3), Clock(2)))); - assert_eq!(Ok(AE::AAdd(Int(12), Clock(2))), expr.simplify()); - } - - #[test] - fn simplify_test7() { - //5-(4-(3-2)) - let expr = AE::ADif( - Int(5), - AE::ADif(Clock(4), AE::ADif(Int(3), AE::ADif(Int(2), Int(1)))), - ); - assert_eq!(Ok(AE::ADif(Clock(4), Int(3))), expr.simplify()); - - let expr = AE::AAdd( - Int(5), - AE::AAdd(Clock(4), AE::AAdd(Int(3), AE::AAdd(Int(2), Int(1)))), - ); - assert_eq!(Ok(AE::AAdd(Clock(4), Int(11))), expr.simplify()); - } - - #[test] - fn simplify_test_highoperators_ints() { - let expr = AE::AMul(Int(10), Int(5)); - assert_eq!(Ok(Int(50)), expr.simplify()); - - let expr = AE::ADiv(Int(10), Int(5)); - assert_eq!(Ok(Int(2)), expr.simplify()); - - let expr = AE::AMod(Int(10), Int(5)); - assert_eq!(Ok(Int(0)), expr.simplify()); - } - - #[test] - fn simplify_test_highoperators_clocks() { - let expr = AE::AMul(Clock(10), Int(5)); - assert_eq!(expr.simplify().ok(), None); - - let expr = AE::AMul(Int(10), Clock(5)); - assert_eq!(expr.simplify().ok(), None); - - let expr = AE::ADiv(Clock(10), Int(5)); - assert_eq!(expr.simplify().ok(), None); - - let expr = AE::ADiv(Int(10), Clock(5)); - assert_eq!(expr.simplify().ok(), None); - - let expr = AE::AMod(Clock(10), Int(5)); - assert_eq!(expr.simplify().ok(), None); - - let expr = AE::AMod(Int(10), Clock(5)); - assert_eq!(expr.simplify().ok(), None); - } -} diff --git a/src/tests/ModelObjects/bool_expression.rs b/src/tests/ModelObjects/bool_expression.rs deleted file mode 100644 index 8d7781e0..00000000 --- a/src/tests/ModelObjects/bool_expression.rs +++ /dev/null @@ -1,20 +0,0 @@ -#[cfg(test)] -mod test { - use crate::ModelObjects::Expressions::ArithExpression as AE; - use crate::ModelObjects::Expressions::BoolExpression as BE; - use AE::Int; - use BE::Bool; - #[test] - fn simplify_test1() { - let mut expr = (Bool(false) & BE::BLessEQ(Int(3), Int(2))) | Bool(true); - expr.simplify(); - assert_eq!(Bool(true), expr); - } - - #[test] - fn simplify_test2() { - let mut expr = BE::BLessEQ(Int(2), Int(3)); - expr.simplify(); - assert_eq!(Bool(true), expr); - } -} diff --git a/src/tests/edge_ids/edge_tests.rs b/src/tests/edge_ids/edge_tests.rs index 9eb2c910..5f0479ca 100644 --- a/src/tests/edge_ids/edge_tests.rs +++ b/src/tests/edge_ids/edge_tests.rs @@ -1,13 +1,13 @@ #[cfg(test)] mod reachability_edge_test { - use crate::DataReader::json_reader::read_json_component; + use crate::data_reader::json_reader::read_json_component; use test_case::test_case; const FOLDER_PATH: &str = "samples/json/EcdarUniversity"; #[test_case("Machine", vec!["E25".to_string(), "E26".to_string(), "E27".to_string(), "E28".to_string(), "E29".to_string()]; "Edge ID test on Machine from the ECDAR University")] fn edge_id_checking(component_name: &str, edge_ids: Vec) { - let component = read_json_component(FOLDER_PATH, component_name); + let component = read_json_component(FOLDER_PATH, component_name).unwrap(); for (i, edge) in component.edges.iter().enumerate() { assert_eq!(edge.id, edge_ids[i]); } diff --git a/src/tests/edge_ids/saving_transitionid.rs b/src/tests/edge_ids/saving_transitionid.rs index 215b86c1..281645b2 100644 --- a/src/tests/edge_ids/saving_transitionid.rs +++ b/src/tests/edge_ids/saving_transitionid.rs @@ -1,8 +1,8 @@ #[cfg(test)] -mod saving_transitionid_test { +mod saving_transition_id_test { + use crate::model_objects::expressions::SystemExpression; + use crate::system::save_component::{combine_components, PruningStrategy}; use crate::tests::reachability::helper_functions::reachability_test_helper_functions; - use crate::ModelObjects::Expressions::SystemExpression; - use crate::System::save_component::{combine_components, PruningStrategy}; use std::collections::HashSet; use std::iter::FromIterator; use test_case::test_case; @@ -33,10 +33,10 @@ mod saving_transitionid_test { "E11".to_string() ]; "Conjunction save HalfAdm1 and HalfAdm2")] fn transition_save_id_checker( - machineExpression: SystemExpression, + machine_expression: SystemExpression, transition_ids: Vec, ) { - let mock_model = Box::new(machineExpression); + let mock_model = Box::new(machine_expression); let mut expected_ids: HashSet<&String> = HashSet::from_iter(transition_ids.iter()); let (_, system) = reachability_test_helper_functions::create_system_recipe_and_machine( *mock_model, diff --git a/src/tests/edge_ids/transition_id_tests.rs b/src/tests/edge_ids/transition_id_tests.rs index 4c4a1b6d..ee43af78 100644 --- a/src/tests/edge_ids/transition_id_tests.rs +++ b/src/tests/edge_ids/transition_id_tests.rs @@ -2,10 +2,11 @@ mod reachability_transition_id_test { use std::collections::HashSet; use std::iter::FromIterator; + use std::rc::Rc; + use crate::model_objects::expressions::SystemExpression; use crate::tests::reachability::helper_functions::reachability_test_helper_functions; - use crate::ModelObjects::Expressions::SystemExpression; - use crate::TransitionSystems::TransitionID; + use crate::transition_systems::TransitionID; use test_case::test_case; const FOLDER_PATH: &str = "samples/json/EcdarUniversity"; @@ -70,10 +71,10 @@ mod reachability_transition_id_test { ) ]; "Conjunction HalfAdm1 and HalfAdm2")] fn transition_id_checker( - machineExpression: SystemExpression, + machine_expression: SystemExpression, transition_ids: Vec, ) { - let mock_model = Box::new(machineExpression); + let mock_model = Box::new(machine_expression); let mut expected_ids: HashSet<&TransitionID> = HashSet::from_iter(transition_ids.iter()); let (_, system) = reachability_test_helper_functions::create_system_recipe_and_machine( *mock_model, @@ -81,7 +82,7 @@ mod reachability_transition_id_test { ); for loc in system.get_all_locations() { for ac in system.get_actions() { - for tran in system.next_transitions(&loc, &ac) { + for tran in system.next_transitions(Rc::clone(&loc), &ac) { if expected_ids.contains(&tran.id) { expected_ids.remove(&tran.id); } else { diff --git a/src/tests/failure_message/actions_test.rs b/src/tests/failure_message/actions_test.rs index a0fe566d..cc854433 100644 --- a/src/tests/failure_message/actions_test.rs +++ b/src/tests/failure_message/actions_test.rs @@ -2,12 +2,12 @@ mod test { - use crate::tests::refinement::Helper::json_run_query; - use crate::System::query_failures::{ + use crate::system::query_failures::{ ConsistencyFailure, DeterminismFailure, DeterminismResult, QueryResult, RefinementFailure, RefinementPrecondition, }; - use crate::System::specifics::SpecificLocation; + use crate::system::specifics::SpecificLocation; + use crate::tests::refinement::helper::json_run_query; const PATH: &str = "samples/json/Actions"; #[test] diff --git a/src/tests/failure_message/consistency_test.rs b/src/tests/failure_message/consistency_test.rs index d5bb578a..a5bdc6c7 100644 --- a/src/tests/failure_message/consistency_test.rs +++ b/src/tests/failure_message/consistency_test.rs @@ -2,8 +2,8 @@ mod test { use crate::{ - tests::refinement::Helper::json_run_query, - System::query_failures::{ConsistencyFailure, ConsistencyResult, QueryResult}, + system::query_failures::{ConsistencyFailure, ConsistencyResult, QueryResult}, + tests::refinement::helper::json_run_query, }; const PATH: &str = "samples/json/ConsistencyTest"; diff --git a/src/tests/failure_message/determinism_test.rs b/src/tests/failure_message/determinism_test.rs index c90130be..422b4800 100644 --- a/src/tests/failure_message/determinism_test.rs +++ b/src/tests/failure_message/determinism_test.rs @@ -2,10 +2,10 @@ mod test { use crate::{ - tests::refinement::Helper::json_run_query, - System::query_failures::{ + system::query_failures::{ ConsistencyFailure, QueryResult, RefinementFailure, RefinementPrecondition, }, + tests::refinement::helper::json_run_query, }; const PATH: &str = "samples/json/Determinism"; diff --git a/src/tests/failure_message/mod.rs b/src/tests/failure_message/mod.rs index 7dae42e4..f0da28ac 100644 --- a/src/tests/failure_message/mod.rs +++ b/src/tests/failure_message/mod.rs @@ -2,3 +2,4 @@ pub mod actions_test; pub mod consistency_test; pub mod determinism_test; pub mod refinement_test; +pub mod syntax_test; diff --git a/src/tests/failure_message/refinement_test.rs b/src/tests/failure_message/refinement_test.rs index 46e31bb1..789f3e91 100644 --- a/src/tests/failure_message/refinement_test.rs +++ b/src/tests/failure_message/refinement_test.rs @@ -2,10 +2,10 @@ mod test { use crate::{ - tests::refinement::Helper::json_run_query, - System::query_failures::{ + system::query_failures::{ ActionFailure, QueryResult, RefinementFailure, RefinementPrecondition, }, + tests::refinement::helper::json_run_query, }; const PATH: &str = "samples/json/RefinementTests"; diff --git a/src/tests/failure_message/syntax_test.rs b/src/tests/failure_message/syntax_test.rs new file mode 100644 index 00000000..c30bb8f2 --- /dev/null +++ b/src/tests/failure_message/syntax_test.rs @@ -0,0 +1,19 @@ +#[cfg(test)] + +mod test { + use crate::{ + system::query_failures::{QueryResult, SyntaxFailure, SyntaxResult}, + tests::refinement::helper::json_run_query, + }; + + const PATH: &str = "samples/json/SyntaxTest"; + + #[test] + fn syntax_failure_test() { + let actual = json_run_query(PATH, "syntax: syntaxFailure").unwrap(); + assert!(matches!( + actual, + QueryResult::Syntax(SyntaxResult::Err(SyntaxFailure::Unparsable { .. })) + )); + } +} diff --git a/src/tests/grpc/send_query.rs b/src/tests/grpc/send_query.rs index 19563cc8..9f5ba783 100644 --- a/src/tests/grpc/send_query.rs +++ b/src/tests/grpc/send_query.rs @@ -1,12 +1,12 @@ #[cfg(test)] mod refinements { - use crate::ProtobufServer::services::component::Rep; - use crate::ProtobufServer::services::ecdar_backend_server::EcdarBackend; - use crate::ProtobufServer::services::query_response; - use crate::ProtobufServer::services::Component; - use crate::ProtobufServer::services::ComponentsInfo; - use crate::ProtobufServer::services::QueryRequest; - use crate::ProtobufServer::ConcreteEcdarBackend; + use crate::protobuf_server::services::component::Rep; + use crate::protobuf_server::services::ecdar_backend_server::EcdarBackend; + use crate::protobuf_server::services::query_response; + use crate::protobuf_server::services::Component; + use crate::protobuf_server::services::ComponentsInfo; + use crate::protobuf_server::services::QueryRequest; + use crate::protobuf_server::ConcreteEcdarBackend; use tonic::Request; //const CONJUN: &str = "samples/xml/conjun.xml"; @@ -43,6 +43,21 @@ mod refinements { } } + #[tokio::test] + async fn send_syntax_query() { + let backend = ConcreteEcdarBackend::default(); + let query_request = construct_query_request("syntax: Machine"); + + let query_response = backend.send_query(query_request).await; + + let query_result = query_response.unwrap().into_inner(); + let result = query_result.result.unwrap(); + match result { + query_response::Result::Success(_) => {} + _ => panic!("Expected success, got {:?}", result), + } + } + #[tokio::test] async fn send_determinism_query() { let backend = ConcreteEcdarBackend::default(); @@ -58,6 +73,101 @@ mod refinements { } } + #[tokio::test] + async fn send_query_using_cache() { + let backend = ConcreteEcdarBackend::default(); + let query_request = construct_query_request_for_cache("refinement: Machine <= Machine"); + + // Normal query request, including component. + let query_response = backend.send_query(query_request.0).await; + + let query_result = query_response.unwrap().into_inner(); + let normal_result = query_result.result.unwrap(); + + // Component should be cached now. + // Query without component utilizing cache + let query_response = backend.send_query(query_request.1).await; + + let query_result = query_response.unwrap().into_inner(); + let cache_result = query_result.result.unwrap(); + + // Compare normal and cache response. + assert_eq!(normal_result, cache_result); + } + + #[tokio::test] + async fn send_query_not_in_cache() { + let backend = ConcreteEcdarBackend::default(); + let query_request = construct_query_request_for_cache("refinement: Machine <= Machine"); + + // Cache request + let query_response = backend.send_query(query_request.1).await; + + let query_result = query_response.unwrap().into_inner(); + let result = query_result.result.unwrap(); + + match result { + query_response::Result::ComponentsNotInCache(_) => {} + _ => panic!("Expected failure, got {:?}", result), + } + } + + #[tokio::test] + async fn send_query_different_users_cache() { + let backend = ConcreteEcdarBackend::default(); + let query_request = construct_query_request_for_cache("refinement: Machine <= Machine"); + + let _ = backend.send_query(query_request.0).await; + + let user_1_request = Request::new(QueryRequest { + user_id: 1, + ..query_request.1.into_inner() + }); + + let query_response = backend.send_query(user_1_request).await; + + let query_result = query_response.unwrap().into_inner(); + let result = query_result.result.unwrap(); + + match result { + query_response::Result::ComponentsNotInCache(_) => {} + _ => panic!("Expected failure, got {:?}", result), + } + } + + fn construct_query_request_for_cache( + query: &str, + ) -> (Request, Request) { + let json = + std::fs::read_to_string(format!("{}/Components/Machine.json", ECDAR_UNI)).unwrap(); + + let normal_request = Request::new(QueryRequest { + user_id: 0, + query_id: 0, + query: String::from(query), + components_info: Some(ComponentsInfo { + components: vec![Component { + rep: Some(Rep::Json(json)), + }], + components_hash: 1, + }), + settings: Some(crate::tests::TEST_SETTINGS), + }); + + //TODO There is some fancy rust syntax to make a clone of the above with minor alterations. + let empty_component_request = Request::new(QueryRequest { + user_id: 0, + query_id: 0, + query: String::from(query), + components_info: Some(ComponentsInfo { + components: vec![], + components_hash: 1, + }), + settings: Some(crate::tests::TEST_SETTINGS), + }); + (normal_request, empty_component_request) + } + fn construct_query_request(query: &str) -> Request { let json = std::fs::read_to_string(format!("{}/Components/Machine.json", ECDAR_UNI)).unwrap(); diff --git a/src/tests/grpc/simulation.rs b/src/tests/grpc/simulation.rs index cb8ae302..ff534945 100644 --- a/src/tests/grpc/simulation.rs +++ b/src/tests/grpc/simulation.rs @@ -1,9 +1,9 @@ #[cfg(test)] mod tests { - use crate::ProtobufServer::services::SimulationStartRequest; + use crate::protobuf_server::services::SimulationStartRequest; use crate::{ - tests::Simulation::helper::construct_step_requests, - ProtobufServer::{self, services::ecdar_backend_server::EcdarBackend}, + protobuf_server::{self, services::ecdar_backend_server::EcdarBackend}, + tests::simulation::helper::construct_step_requests, }; use test_case::test_case; use tonic::Request; @@ -45,7 +45,7 @@ mod tests { composition: &str, ) { // Arrange - let backend = ProtobufServer::ConcreteEcdarBackend::default(); + let backend = protobuf_server::ConcreteEcdarBackend::default(); let request = Request::new(SimulationStartRequest::new( component_names, components_path, diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 980f0732..ea8b95a2 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -1,15 +1,14 @@ -use crate::ProtobufServer::services::query_request::Settings; +use crate::protobuf_server::services::query_request::Settings; -pub mod ClockReduction; -pub mod ModelObjects; -pub mod Simulation; pub mod edge_ids; pub mod failure_message; pub mod grpc; +pub mod model_objects; pub mod reachability; pub mod refinement; pub mod sample; pub mod save_component; +pub mod simulation; pub mod system_recipe; /// The default settings for Testing diff --git a/src/tests/model_objects/arith_expression.rs b/src/tests/model_objects/arith_expression.rs new file mode 100644 index 00000000..ada32a68 --- /dev/null +++ b/src/tests/model_objects/arith_expression.rs @@ -0,0 +1,128 @@ +#[cfg(test)] +mod test { + use crate::model_objects::expressions::ArithExpression as AE; + use AE::*; + #[test] + fn simplify_test_1() { + let expr = AE::a_dif(Int(10), Int(5)); //10 - 5 + assert_eq!(Ok(Int(5)), expr.simplify()); + + let expr = AE::a_add(Int(10), Int(5)); //10 + 5 + assert_eq!(Ok(Int(15)), expr.simplify()); + } + + #[test] + fn simplify_test_2() { + let expr = Multiplication( + //(10 - 5) * (5 + 3) + Box::new(AE::a_dif(Int(10), Int(5))), + Box::new(AE::a_add(Int(5), Int(3))), + ); + assert_eq!(Ok(Int(40)), expr.simplify()); + + let expr = Multiplication( + //(10 + 5) * (5 - 3) + Box::new(AE::a_add(Int(10), Int(5))), + Box::new(AE::a_dif(Int(5), Int(3))), + ); + assert_eq!(Ok(Int(30)), expr.simplify()); + } + #[test] + fn simplify_test_3() { + let expr = AE::a_dif( + Clock(1), + AE::a_dif(Int(5), AE::a_dif(Int(4), AE::a_dif(Int(3), Int(2)))), //5-(4-(3-2)) + ); + assert_eq!(Ok(AE::a_dif(Clock(1), Int(2))), expr.simplify()); + + let expr = AE::a_add( + Clock(1), + AE::a_add(Int(5), AE::a_add(Int(4), AE::a_add(Int(3), Int(2)))), + ); + assert_eq!(Ok(AE::a_add(Clock(1), Int(14))), expr.simplify()); + } + #[test] + fn simplify_test_4() { + //((5-4)-3)-2 + let expr = AE::a_dif( + Clock(1), + AE::a_dif(AE::a_dif(AE::a_dif(Int(5), Int(4)), Int(3)), Int(2)), + ); + assert_eq!(Ok(AE::a_dif(Clock(1), Int(-4))), expr.simplify()); + + let expr = AE::a_add( + Clock(1), + AE::a_add(AE::a_add(AE::a_add(Int(5), Int(4)), Int(3)), Int(2)), + ); + assert_eq!(Ok(AE::a_add(Clock(1), Int(14))), expr.simplify()); + } + + #[test] + fn simplify_test_5() { + //((5-4)-3)-2 + let expr = AE::a_dif(AE::a_dif(AE::a_dif(Int(5), Clock(4)), Int(3)), Int(2)); + assert_eq!(Ok(AE::a_dif(Int(0), Clock(4))), expr.simplify()); + + let expr = AE::a_add(AE::a_add(AE::a_add(Int(5), Clock(4)), Int(3)), Int(2)); + assert_eq!(Ok(AE::a_add(Int(10), Clock(4))), expr.simplify()); + } + + #[test] + fn simplify_test_6() { + //5-(4-(3-2)) + let expr = AE::a_dif(Int(5), AE::a_dif(Int(4), AE::a_dif(Int(3), Clock(2)))); + assert_eq!(Ok(AE::a_dif(Int(4), Clock(2))), expr.simplify()); + + let expr = AE::a_add(Int(5), AE::a_add(Int(4), AE::a_add(Int(3), Clock(2)))); + assert_eq!(Ok(AE::a_add(Int(12), Clock(2))), expr.simplify()); + } + + #[test] + fn simplify_test_7() { + //5-(4-(3-2)) + let expr = AE::a_dif( + Int(5), + AE::a_dif(Clock(4), AE::a_dif(Int(3), AE::a_dif(Int(2), Int(1)))), + ); + assert_eq!(Ok(AE::a_dif(Clock(4), Int(3))), expr.simplify()); + + let expr = AE::a_add( + Int(5), + AE::a_add(Clock(4), AE::a_add(Int(3), AE::a_add(Int(2), Int(1)))), + ); + assert_eq!(Ok(AE::a_add(Clock(4), Int(11))), expr.simplify()); + } + + #[test] + fn simplify_test_highoperators_ints() { + let expr = AE::a_mul(Int(10), Int(5)); + assert_eq!(Ok(Int(50)), expr.simplify()); + + let expr = AE::a_div(Int(10), Int(5)); + assert_eq!(Ok(Int(2)), expr.simplify()); + + let expr = AE::a_mod(Int(10), Int(5)); + assert_eq!(Ok(Int(0)), expr.simplify()); + } + + #[test] + fn simplify_test_highoperators_clocks() { + let expr = AE::a_mul(Clock(10), Int(5)); + assert_eq!(expr.simplify().ok(), None); + + let expr = AE::a_mul(Int(10), Clock(5)); + assert_eq!(expr.simplify().ok(), None); + + let expr = AE::a_div(Clock(10), Int(5)); + assert_eq!(expr.simplify().ok(), None); + + let expr = AE::a_div(Int(10), Clock(5)); + assert_eq!(expr.simplify().ok(), None); + + let expr = AE::a_mod(Clock(10), Int(5)); + assert_eq!(expr.simplify().ok(), None); + + let expr = AE::a_mod(Int(10), Clock(5)); + assert_eq!(expr.simplify().ok(), None); + } +} diff --git a/src/tests/model_objects/bool_expression.rs b/src/tests/model_objects/bool_expression.rs new file mode 100644 index 00000000..a6a522a9 --- /dev/null +++ b/src/tests/model_objects/bool_expression.rs @@ -0,0 +1,20 @@ +#[cfg(test)] +mod test { + use crate::model_objects::expressions::ArithExpression as AE; + use crate::model_objects::expressions::BoolExpression as BE; + use AE::Int; + use BE::Bool; + #[test] + fn simplify_test_1() { + let mut expr = (Bool(false) & BE::b_less_eq(Int(3), Int(2))) | Bool(true); + expr.simplify(); + assert_eq!(Bool(true), expr); + } + + #[test] + fn simplify_test_2() { + let mut expr = BE::b_less_eq(Int(2), Int(3)); + expr.simplify(); + assert_eq!(Bool(true), expr); + } +} diff --git a/src/tests/ModelObjects/mod.rs b/src/tests/model_objects/mod.rs similarity index 100% rename from src/tests/ModelObjects/mod.rs rename to src/tests/model_objects/mod.rs diff --git a/src/tests/reachability/clock_variables.rs b/src/tests/reachability/clock_variables.rs index 907ccb8b..5502bbcc 100644 --- a/src/tests/reachability/clock_variables.rs +++ b/src/tests/reachability/clock_variables.rs @@ -2,8 +2,8 @@ mod reachability_parser_clock_variable_validation { use crate::{ + model_objects::expressions::SystemExpression, system, tests::reachability::helper_functions::reachability_test_helper_functions, - ModelObjects::Expressions::SystemExpression, System, }; use test_case::test_case; const FOLDER_PATH: &str = "samples/json/EcdarUniversity"; @@ -27,10 +27,7 @@ mod reachability_parser_clock_variable_validation { let mock_state = reachability_test_helper_functions::string_to_state_expr(clock_str); - assert!(matches!( - System::extract_state::get_state(&mock_state, &machine, &system), - Err(_) - )); + assert!(system::extract_state::get_state(&mock_state, &machine, &system).is_err()); } #[test_case("Adm2.L20 && Adm2.x>1"; @@ -46,9 +43,7 @@ mod reachability_parser_clock_variable_validation { ); let mock_state = reachability_test_helper_functions::string_to_state_expr(clock_str); - assert!(matches!( - System::extract_state::get_state(&mock_state, &machine, &system), - Ok(_) - )); + + assert!(system::extract_state::get_state(&mock_state, &machine, &system).is_ok()); } } diff --git a/src/tests/reachability/get_leaves_tests.rs b/src/tests/reachability/get_leaves_tests.rs index adc2db92..a8ca6acf 100644 --- a/src/tests/reachability/get_leaves_tests.rs +++ b/src/tests/reachability/get_leaves_tests.rs @@ -1,6 +1,6 @@ #[cfg(test)] mod reachability_search_algorithm_test { - use crate::TransitionSystems::TransitionID; + use crate::transition_systems::TransitionID; use test_case::test_case; diff --git a/src/tests/reachability/grammar.rs b/src/tests/reachability/grammar.rs index badbd7aa..b020dbe3 100644 --- a/src/tests/reachability/grammar.rs +++ b/src/tests/reachability/grammar.rs @@ -9,19 +9,13 @@ mod reachability_grammar_test { #[test_case("reachability: Hi[1] && Hi[2] @ Hi[1].L1 && Hi[2].L1 && Hi[1].y<3 -> Hi[1].L2 && Hi[1].y<2"; "2 machine, start/end location and clock restriction")] fn query_grammar_test_valid_queries(parser_input: &str) { // This tests that the grammar accepts this string, and does not panic: - assert!(matches!( - parse_queries::parse_to_expression_tree(parser_input), - Ok(_) - )); + assert!(parse_queries::parse_to_expression_tree(parser_input).is_ok()); } #[test_case("reachability: Hi @ L1 && Hi.y<3 -> L2 && Hi.y<2"; "No component prefix on location")] #[test_case("reachability: Hi @ Hi.L1 && y<3 -> Hi.L2 && y<2"; "No component prefix on clock")] fn query_grammar_test_invalid_queries(parser_input: &str) { // This tests that the grammar does NOT accept this string and panics: - assert!(matches!( - parse_queries::parse_to_expression_tree(parser_input), - Err(_) - )); + assert!(parse_queries::parse_to_expression_tree(parser_input).is_err()); } } diff --git a/src/tests/reachability/helper_functions.rs b/src/tests/reachability/helper_functions.rs index c0aa0f22..ac65e964 100644 --- a/src/tests/reachability/helper_functions.rs +++ b/src/tests/reachability/helper_functions.rs @@ -3,12 +3,12 @@ pub mod reachability_test_helper_functions { use crate::extract_system_rep::get_system_recipe; use crate::extract_system_rep::SystemRecipe; + use crate::model_objects::expressions::StateExpression; + use crate::model_objects::expressions::SystemExpression; use crate::parse_queries::parse_to_state_expr; + use crate::transition_systems::TransitionSystem; use crate::xml_parser; use crate::JsonProjectLoader; - use crate::ModelObjects::Expressions::StateExpression; - use crate::ModelObjects::Expressions::SystemExpression; - use crate::TransitionSystems::TransitionSystem; use crate::XmlProjectLoader; /// Helper function which converts a string to an option> by replacing ',' with "&&" and using the invariant parser. @@ -29,7 +29,8 @@ pub mod reachability_test_helper_functions { .to_comp_loader(); let mut dim: ClockIndex = 0; let mut quotient_index = None; - let machine = get_system_recipe(&model, &mut (*comp_loader), &mut dim, &mut quotient_index); + let machine = + get_system_recipe(&model, &mut (*comp_loader), &mut dim, &mut quotient_index).unwrap(); //TODO:: - unwrap might not be the best way to handle this let system = machine.clone().compile(dim).unwrap(); (machine, system) diff --git a/src/tests/reachability/location_validation.rs b/src/tests/reachability/location_validation.rs index 62975aa8..1196d2e4 100644 --- a/src/tests/reachability/location_validation.rs +++ b/src/tests/reachability/location_validation.rs @@ -1,8 +1,8 @@ #[cfg(test)] mod reachability_parser_location_validation { use crate::{ + model_objects::expressions::SystemExpression, system, tests::reachability::helper_functions::reachability_test_helper_functions, - ModelObjects::Expressions::SystemExpression, System, }; use test_case::test_case; const FOLDER_PATH: &str = "samples/json/EcdarUniversity"; @@ -24,10 +24,7 @@ mod reachability_parser_location_validation { let mock_state = reachability_test_helper_functions::string_to_state_expr(location_str); - assert!(matches!( - System::extract_state::get_state(&mock_state, &machine, &system), - Err(_) - )); + assert!(system::extract_state::get_state(&mock_state, &machine, &system).is_err()); } #[test_case("Adm2.L20"; @@ -43,9 +40,7 @@ mod reachability_parser_location_validation { ); let mock_state = reachability_test_helper_functions::string_to_state_expr(location_str); - assert!(matches!( - System::extract_state::get_state(&mock_state, &machine, &system), - Ok(_) - )); + + assert!(system::extract_state::get_state(&mock_state, &machine, &system).is_ok()); } } diff --git a/src/tests/reachability/parse_partial_state.rs b/src/tests/reachability/parse_partial_state.rs index 2f22d4e0..5bd17bc5 100644 --- a/src/tests/reachability/parse_partial_state.rs +++ b/src/tests/reachability/parse_partial_state.rs @@ -2,11 +2,10 @@ mod reachability_parse_partial_state { use crate::{ extract_system_rep::{self, ExecutableQueryError}, - parse_queries, + model_objects::expressions::SystemExpression, + parse_queries, system, tests::reachability::helper_functions::reachability_test_helper_functions, JsonProjectLoader, - ModelObjects::Expressions::SystemExpression, - System, }; use test_case::test_case; @@ -27,7 +26,7 @@ mod reachability_parse_partial_state { let mock_state = reachability_test_helper_functions::string_to_state_expr(location_str); - let result = System::extract_state::get_state(&mock_state, &machine, &system); + let result = system::extract_state::get_state(&mock_state, &machine, &system); if let Ok(end_state) = result { assert_eq!( diff --git a/src/tests/reachability/partial_state.rs b/src/tests/reachability/partial_state.rs index 6d3cbf7f..a18496dc 100644 --- a/src/tests/reachability/partial_state.rs +++ b/src/tests/reachability/partial_state.rs @@ -1,11 +1,13 @@ #[cfg(test)] mod reachability_partial_states_test { - use crate::ModelObjects::{Declarations, Location, LocationType}; - use crate::TransitionSystems::CompositionType; - use crate::TransitionSystems::LocationTree; + use std::rc::Rc; + + use crate::model_objects::{Declarations, Location, LocationType}; + use crate::transition_systems::CompositionType; + use crate::transition_systems::LocationTree; use test_case::test_case; - fn build_location_tree_helper(id: &str, location_type: LocationType) -> LocationTree { + fn build_location_tree_helper(id: &str, location_type: LocationType) -> Rc { LocationTree::simple( &Location { id: id.to_string(), @@ -26,60 +28,60 @@ mod reachability_partial_states_test { #[test_case(build_location_tree_helper("L5", LocationType::Normal), build_location_tree_helper("L5", LocationType::Normal); "L5 == L5")] - #[test_case(LocationTree::merge_as_quotient(&build_location_tree_helper("L5", LocationType::Normal), &LocationTree::build_any_location_tree()), - LocationTree::merge_as_quotient(&build_location_tree_helper("L5", LocationType::Normal), &build_location_tree_helper("L1", LocationType::Normal)); + #[test_case(LocationTree::merge_as_quotient(build_location_tree_helper("L5", LocationType::Normal), LocationTree::build_any_location_tree()), + LocationTree::merge_as_quotient(build_location_tree_helper("L5", LocationType::Normal), build_location_tree_helper("L1", LocationType::Normal)); "L5//_ == L5//L1")] - #[test_case(LocationTree::compose(&build_location_tree_helper("L5", LocationType::Normal), &LocationTree::build_any_location_tree(), CompositionType::Conjunction), - LocationTree::compose(&LocationTree::build_any_location_tree(), &build_location_tree_helper("L1", LocationType::Normal), CompositionType::Conjunction); + #[test_case(LocationTree::compose(build_location_tree_helper("L5", LocationType::Normal), LocationTree::build_any_location_tree(), CompositionType::Conjunction), + LocationTree::compose(LocationTree::build_any_location_tree(), build_location_tree_helper("L1", LocationType::Normal), CompositionType::Conjunction); "L5&&_ == _&&L1")] - #[test_case(LocationTree::compose(&build_location_tree_helper("L7", LocationType::Normal), &LocationTree::build_any_location_tree(), CompositionType::Composition), - LocationTree::compose(&build_location_tree_helper("L7", LocationType::Normal), &build_location_tree_helper("L1", LocationType::Normal), CompositionType::Composition); + #[test_case(LocationTree::compose(build_location_tree_helper("L7", LocationType::Normal), LocationTree::build_any_location_tree(), CompositionType::Composition), + LocationTree::compose(build_location_tree_helper("L7", LocationType::Normal), build_location_tree_helper("L1", LocationType::Normal), CompositionType::Composition); "L7||_ == L7||L1")] - #[test_case(LocationTree::compose(&LocationTree::build_any_location_tree(), &LocationTree::build_any_location_tree(), CompositionType::Composition), - LocationTree::compose(&build_location_tree_helper("L2", LocationType::Normal), &build_location_tree_helper("L1", LocationType::Normal), CompositionType::Composition); + #[test_case(LocationTree::compose(LocationTree::build_any_location_tree(), LocationTree::build_any_location_tree(), CompositionType::Composition), + LocationTree::compose(build_location_tree_helper("L2", LocationType::Normal), build_location_tree_helper("L1", LocationType::Normal), CompositionType::Composition); "_||_ == L2||L1")] - #[test_case(LocationTree::compose(&LocationTree::compose(&LocationTree::build_any_location_tree(), &LocationTree::build_any_location_tree(), CompositionType::Composition),&build_location_tree_helper("L2", LocationType::Normal), CompositionType::Composition), - LocationTree::compose(&LocationTree::compose(&build_location_tree_helper("L2", LocationType::Normal), &build_location_tree_helper("L1", LocationType::Normal), CompositionType::Composition),&build_location_tree_helper("L2", LocationType::Normal), CompositionType::Composition); + #[test_case(LocationTree::compose(LocationTree::compose(LocationTree::build_any_location_tree(), LocationTree::build_any_location_tree(), CompositionType::Composition),build_location_tree_helper("L2", LocationType::Normal), CompositionType::Composition), + LocationTree::compose(LocationTree::compose(build_location_tree_helper("L2", LocationType::Normal), build_location_tree_helper("L1", LocationType::Normal), CompositionType::Composition),build_location_tree_helper("L2", LocationType::Normal), CompositionType::Composition); "_||_||L2 == L2||L1||L2")] #[test_case(build_location_tree_helper("L_35", LocationType::Normal), build_location_tree_helper("L_35", LocationType::Normal); "L_35 == L_35")] - fn checks_cmp_locations_returns_true(loc1: LocationTree, loc2: LocationTree) { - assert!(loc1.compare_partial_locations(&loc2)); + fn checks_cmp_locations_returns_true(loc1: Rc, loc2: Rc) { + assert!(loc1.compare_partial_locations(loc2)); } - #[test_case(LocationTree::compose(&build_location_tree_helper("L2", LocationType::Normal), &build_location_tree_helper("L5", LocationType::Normal), CompositionType::Composition), - LocationTree::compose(&build_location_tree_helper("L2", LocationType::Normal), &build_location_tree_helper("L1", LocationType::Normal), CompositionType::Composition); + #[test_case(LocationTree::compose(build_location_tree_helper("L2", LocationType::Normal), build_location_tree_helper("L5", LocationType::Normal), CompositionType::Composition), + LocationTree::compose(build_location_tree_helper("L2", LocationType::Normal), build_location_tree_helper("L1", LocationType::Normal), CompositionType::Composition); "L2||L5 != L2||L1")] - #[test_case(LocationTree::merge_as_quotient(&build_location_tree_helper("L2", LocationType::Normal), &build_location_tree_helper("L6", LocationType::Normal)), - LocationTree::compose(&build_location_tree_helper("L2", LocationType::Normal), &build_location_tree_helper("L1", LocationType::Normal), CompositionType::Composition); + #[test_case(LocationTree::merge_as_quotient(build_location_tree_helper("L2", LocationType::Normal), build_location_tree_helper("L6", LocationType::Normal)), + LocationTree::compose(build_location_tree_helper("L2", LocationType::Normal), build_location_tree_helper("L1", LocationType::Normal), CompositionType::Composition); "L2//L6 != L2||L1")] - #[test_case(LocationTree::merge_as_quotient(&build_location_tree_helper("L7", LocationType::Normal), &build_location_tree_helper("L6", LocationType::Normal)), - LocationTree::compose(&build_location_tree_helper("L2", LocationType::Normal), &build_location_tree_helper("L1", LocationType::Normal), CompositionType::Conjunction); + #[test_case(LocationTree::merge_as_quotient(build_location_tree_helper("L7", LocationType::Normal), build_location_tree_helper("L6", LocationType::Normal)), + LocationTree::compose(build_location_tree_helper("L2", LocationType::Normal), build_location_tree_helper("L1", LocationType::Normal), CompositionType::Conjunction); "L7//L6 != L2&&L1")] - #[test_case(LocationTree::merge_as_quotient(&build_location_tree_helper("L8", LocationType::Normal), &LocationTree::build_any_location_tree()), - LocationTree::compose(&build_location_tree_helper("L2", LocationType::Normal), &build_location_tree_helper("L1", LocationType::Normal), CompositionType::Conjunction); + #[test_case(LocationTree::merge_as_quotient(build_location_tree_helper("L8", LocationType::Normal), LocationTree::build_any_location_tree()), + LocationTree::compose(build_location_tree_helper("L2", LocationType::Normal), build_location_tree_helper("L1", LocationType::Normal), CompositionType::Conjunction); "L8//_ != L2&&L1")] #[test_case(LocationTree::build_any_location_tree(), - LocationTree::compose(&build_location_tree_helper("L6", LocationType::Normal), &build_location_tree_helper("L1", LocationType::Normal), CompositionType::Conjunction); + LocationTree::compose(build_location_tree_helper("L6", LocationType::Normal), build_location_tree_helper("L1", LocationType::Normal), CompositionType::Conjunction); "_ != L6&&L1")] #[test_case(LocationTree::build_any_location_tree(), - LocationTree::compose(&LocationTree::build_any_location_tree(), &LocationTree::build_any_location_tree(), CompositionType::Conjunction); + LocationTree::compose(LocationTree::build_any_location_tree(), LocationTree::build_any_location_tree(), CompositionType::Conjunction); "anylocation _ != _&&_")] - #[test_case(LocationTree::compose(&build_location_tree_helper("L2", LocationType::Normal), &build_location_tree_helper("L4", LocationType::Normal), CompositionType::Conjunction), - LocationTree::merge_as_quotient(&build_location_tree_helper("L2", LocationType::Normal), &build_location_tree_helper("L4", LocationType::Normal)); + #[test_case(LocationTree::compose(build_location_tree_helper("L2", LocationType::Normal), build_location_tree_helper("L4", LocationType::Normal), CompositionType::Conjunction), + LocationTree::merge_as_quotient(build_location_tree_helper("L2", LocationType::Normal), build_location_tree_helper("L4", LocationType::Normal)); "L2&&L4 != L2\\L4")] - #[test_case(LocationTree::compose(&LocationTree::compose(&LocationTree::build_any_location_tree(), &LocationTree::build_any_location_tree(), CompositionType::Composition),&build_location_tree_helper("L2", LocationType::Normal), CompositionType::Conjunction), - LocationTree::compose(&LocationTree::compose(&build_location_tree_helper("L2", LocationType::Normal), &build_location_tree_helper("L1", LocationType::Normal), CompositionType::Composition),&build_location_tree_helper("L2", LocationType::Normal), CompositionType::Composition); + #[test_case(LocationTree::compose(LocationTree::compose(LocationTree::build_any_location_tree(), LocationTree::build_any_location_tree(), CompositionType::Composition),build_location_tree_helper("L2", LocationType::Normal), CompositionType::Conjunction), + LocationTree::compose(LocationTree::compose(build_location_tree_helper("L2", LocationType::Normal), build_location_tree_helper("L1", LocationType::Normal), CompositionType::Composition),build_location_tree_helper("L2", LocationType::Normal), CompositionType::Composition); "_||_&&L2 == L2||L1||L2")] - #[test_case(LocationTree::compose(&LocationTree::compose(&build_location_tree_helper("L2", LocationType::Normal), &LocationTree::build_any_location_tree(), CompositionType::Composition),&build_location_tree_helper("L2", LocationType::Normal), CompositionType::Conjunction), - LocationTree::compose(&LocationTree::build_any_location_tree(), &LocationTree::build_any_location_tree(), CompositionType::Conjunction); + #[test_case(LocationTree::compose(LocationTree::compose(build_location_tree_helper("L2", LocationType::Normal), LocationTree::build_any_location_tree(), CompositionType::Composition),build_location_tree_helper("L2", LocationType::Normal), CompositionType::Conjunction), + LocationTree::compose(LocationTree::build_any_location_tree(), LocationTree::build_any_location_tree(), CompositionType::Conjunction); "L2||_&&L2 == _&&_")] #[test_case(build_location_tree_helper("L7", LocationType::Normal), build_location_tree_helper("L5", LocationType::Normal); "L7 != L5")] - #[test_case(LocationTree::merge_as_quotient(&LocationTree::build_any_location_tree(), &LocationTree::build_any_location_tree()), - LocationTree::compose(&build_location_tree_helper("L6", LocationType::Normal), &build_location_tree_helper("L25", LocationType::Normal), CompositionType::Conjunction); + #[test_case(LocationTree::merge_as_quotient(LocationTree::build_any_location_tree(), LocationTree::build_any_location_tree()), + LocationTree::compose(build_location_tree_helper("L6", LocationType::Normal), build_location_tree_helper("L25", LocationType::Normal), CompositionType::Conjunction); "_//_ != L6&&L25")] #[test_case(build_location_tree_helper("_L1", LocationType::Normal), build_location_tree_helper("L1", LocationType::Normal); @@ -87,7 +89,7 @@ mod reachability_partial_states_test { #[test_case(build_location_tree_helper("__", LocationType::Normal), build_location_tree_helper("L7", LocationType::Normal); "__ != L7")] - fn checks_cmp_locations_returns_false(loc1: LocationTree, loc2: LocationTree) { - assert!(!loc1.compare_partial_locations(&loc2)); + fn checks_cmp_locations_returns_false(loc1: Rc, loc2: Rc) { + assert!(!loc1.compare_partial_locations(loc2)); } } diff --git a/src/tests/reachability/search_algorithm_test.rs b/src/tests/reachability/search_algorithm_test.rs index 02f85d0a..5ff71c2e 100644 --- a/src/tests/reachability/search_algorithm_test.rs +++ b/src/tests/reachability/search_algorithm_test.rs @@ -1,8 +1,8 @@ #[cfg(test)] mod reachability_search_algorithm_test { - use crate::tests::refinement::Helper::json_run_query; - use crate::System::query_failures::QueryResult; + use crate::system::query_failures::QueryResult; + use crate::tests::refinement::helper::json_run_query; use test_case::test_case; const PATH: &str = "samples/json/EcdarUniversity"; @@ -51,7 +51,9 @@ mod reachability_search_algorithm_test { #[test_case(PATH2, "reachability: Component3[1] && Component3[2] @ Component3[1].L6 && Component3[2].L6 -> Component3[1].L7 && Component3[2].L7", true; "Simple conjunction")] fn search_algorithm_returns_result(path: &str, query: &str, expected: bool) { match json_run_query(path, query).unwrap() { - QueryResult::Reachability(path) => assert_eq!(path.is_ok(), expected), + QueryResult::Reachability(path) => { + assert_eq!(path.is_ok(), expected, "Final state is not reachable") + } _ => panic!("Inconsistent query result, expected Reachability"), } } diff --git a/src/tests/reachability/split_component_tests.rs b/src/tests/reachability/split_component_tests.rs index 8b92010e..714947b8 100644 --- a/src/tests/reachability/split_component_tests.rs +++ b/src/tests/reachability/split_component_tests.rs @@ -1,6 +1,6 @@ #[cfg(test)] mod reachability_search_algorithm_test { - use crate::TransitionSystems::TransitionID; + use crate::transition_systems::TransitionID; use test_case::test_case; #[test_case( diff --git a/src/tests/refinement/Helper.rs b/src/tests/refinement/Helper.rs deleted file mode 100644 index 6a2bdca1..00000000 --- a/src/tests/refinement/Helper.rs +++ /dev/null @@ -1,76 +0,0 @@ -use crate::extract_system_rep::ExecutableQueryError; -use crate::logging::setup_logger; -use crate::DataReader::component_loader::{JsonProjectLoader, XmlProjectLoader}; -use crate::DataReader::parse_queries; -use crate::ModelObjects::Query; -use crate::System::extract_system_rep::create_executable_query; -use crate::System::query_failures::QueryResult; -use crate::TransitionSystems::transition_system::component_loader_to_transition_system; -use crate::TransitionSystems::TransitionSystemPtr; - -fn try_setup_logging() { - #[cfg(feature = "logging")] - let _ = setup_logger(); -} - -pub fn xml_refinement_check(PATH: &str, QUERY: &str) -> bool { - try_setup_logging(); - match xml_run_query(PATH, QUERY) { - QueryResult::Refinement(Ok(())) => true, - QueryResult::Refinement(Err(_)) => false, - QueryResult::CustomError(err) => panic!("{}", err), - _ => panic!("Not a refinement check"), - } -} - -pub fn json_refinement_check(PATH: &str, QUERY: &str) -> bool { - try_setup_logging(); - - match json_run_query(PATH, QUERY).unwrap() { - QueryResult::Refinement(Ok(())) => true, - QueryResult::Refinement(Err(_)) => false, - QueryResult::CustomError(err) => panic!("{}", err), - _ => panic!("Not a refinement check"), - } -} - -pub fn xml_run_query(PATH: &str, QUERY: &str) -> QueryResult { - let project_path = String::from(PATH); - let project_loader = XmlProjectLoader::new_loader(project_path, crate::tests::TEST_SETTINGS); - let query = parse_queries::parse_to_expression_tree(QUERY) - .unwrap() - .remove(0); - let q = Query { - query: Option::from(query), - comment: "".to_string(), - }; - - let mut comp_loader = project_loader.to_comp_loader(); - let query = create_executable_query(&q, &mut *comp_loader).unwrap(); - - query.execute() -} - -pub fn json_run_query(PATH: &str, QUERY: &str) -> Result { - let project_loader = - JsonProjectLoader::new_loader(String::from(PATH), crate::tests::TEST_SETTINGS); - let query = parse_queries::parse_to_expression_tree(QUERY) - .unwrap() - .remove(0); - let q = Query { - query: Option::from(query), - comment: "".to_string(), - }; - - let mut comp_loader = project_loader.to_comp_loader(); - let query = create_executable_query(&q, &mut *comp_loader)?; - - Ok(query.execute()) -} - -pub fn json_get_system(PATH: &str, COMP: &str) -> TransitionSystemPtr { - let project_loader = - JsonProjectLoader::new_loader(String::from(PATH), crate::tests::TEST_SETTINGS); - let mut loader = project_loader.to_comp_loader(); - component_loader_to_transition_system(&mut *loader, COMP) -} diff --git a/src/tests/refinement/AG_Tests.rs b/src/tests/refinement/ag_tests.rs similarity index 77% rename from src/tests/refinement/AG_Tests.rs rename to src/tests/refinement/ag_tests.rs index d0f640e8..ec8ea637 100644 --- a/src/tests/refinement/AG_Tests.rs +++ b/src/tests/refinement/ag_tests.rs @@ -1,69 +1,69 @@ #[cfg(test)] mod test { - use crate::tests::refinement::Helper::json_refinement_check; + use crate::tests::refinement::helper::json_refinement_check; const PATH: &str = "samples/json/AG"; #[test] - fn ARefinesSelf() { + fn a_refines_self() { assert!(json_refinement_check(PATH, "refinement: A <= A")); } #[test] - fn GRefinesSelf() { + fn g_refines_self() { assert!(json_refinement_check(PATH, "refinement: G <= G")); } #[test] - fn QRefinesSelf() { + fn q_refines_self() { assert!(json_refinement_check(PATH, "refinement: Q <= Q")); } #[test] - fn ImpRefinesSelf() { + fn imp_refines_self() { assert!(json_refinement_check(PATH, "refinement: Imp <= Imp")); } #[test] - fn AaRefinesSelf() { + fn aa_refines_self() { assert!(json_refinement_check(PATH, "refinement: AA <= AA")); } #[test] - fn AGNotRefinesAImp() { + fn a_g_not_refines_a_imp() { assert!(!json_refinement_check(PATH, "refinement: A||G <= A||Imp")); // should fail because left side has more inputs } #[test] - fn GNotRefinesImp() { + fn g_not_refines_imp() { assert!(!json_refinement_check(PATH, "refinement: G <= Imp")); // should fail because right side has more outputs } #[test] - fn ImpRefinesG() { + fn imp_refines_g() { assert!(json_refinement_check(PATH, "refinement: Imp <= G")); } #[test] - fn GRefinesQ() { + fn g_refines_q() { assert!(json_refinement_check(PATH, "refinement: G <= Q")); } #[test] - fn QRefinesG() { + fn q_refines_g() { assert!(json_refinement_check(PATH, "refinement: Q <= G")); } #[test] - fn QNotRefinesImp() { + fn q_not_refines_imp() { // should fail because right side has more outputs assert!(!json_refinement_check(PATH, "refinement: Q <= Imp")); } #[test] - fn ImpRefinesQ() { + fn imp_refines_q() { assert!(json_refinement_check(PATH, "refinement: Imp <= Q")); } } diff --git a/src/tests/refinement/Big_Refinement.rs b/src/tests/refinement/big_refinement.rs similarity index 70% rename from src/tests/refinement/Big_Refinement.rs rename to src/tests/refinement/big_refinement.rs index 41dec67e..0459534a 100644 --- a/src/tests/refinement/Big_Refinement.rs +++ b/src/tests/refinement/big_refinement.rs @@ -1,27 +1,27 @@ #[cfg(test)] mod test { - use crate::tests::refinement::Helper::json_refinement_check; + use crate::tests::refinement::helper::json_refinement_check; const PATH: &str = "samples/json/BigRefinement"; #[test] - fn testRef1NotRefinesComp1() { + fn test_ref_1_not_refines_comp_1() { // should fail because left side has more inputs assert!(!json_refinement_check(PATH, "refinement: Ref1 <= Comp1")); } #[test] - fn testComp1NotRefinesRef1() { + fn test_comp_1_not_refines_ref_1() { assert!(!json_refinement_check(PATH, "refinement: Comp1 <= Ref1")); } #[test] - fn testRef1RefinesSelf() { + fn test_ref_1_refines_self() { assert!(json_refinement_check(PATH, "refinement: Ref1 <= Ref1")); } #[test] - fn testComp1RefinesSelf() { + fn test_comp_1_refines_self() { assert!(json_refinement_check(PATH, "refinement: Comp1 <= Comp1")); } } diff --git a/src/tests/refinement/Conjunction_refinement.rs b/src/tests/refinement/conjunction_refinement.rs similarity index 77% rename from src/tests/refinement/Conjunction_refinement.rs rename to src/tests/refinement/conjunction_refinement.rs index 051b68bd..1bb4cab4 100644 --- a/src/tests/refinement/Conjunction_refinement.rs +++ b/src/tests/refinement/conjunction_refinement.rs @@ -1,36 +1,36 @@ #[cfg(test)] mod test { - use crate::tests::refinement::Helper::json_refinement_check; + use crate::tests::refinement::helper::json_refinement_check; const PATH: &str = "samples/json/Conjunction"; #[test] - fn T1RefinesSelf() { + fn t1_refines_self() { assert!(json_refinement_check(PATH, "refinement: Test1 <= Test1")); } #[test] - fn T2RefinesSelf() { + fn t2_refines_self() { assert!(json_refinement_check(PATH, "refinement: Test2 <= Test2")); } #[test] - fn T3RefinesSelf() { + fn t3_refines_self() { assert!(json_refinement_check(PATH, "refinement: Test3 <= Test3")); } #[test] - fn T4RefinesSelf() { + fn t4_refines_self() { assert!(json_refinement_check(PATH, "refinement: Test4 <= Test4")); } #[test] - fn T5RefinesSelf() { + fn t5_refines_self() { assert!(json_refinement_check(PATH, "refinement: Test5 <= Test5")); } #[test] - fn T1ConjT2RefinesT3() { + fn t1_conj_t2_refines_t3() { assert!(json_refinement_check( PATH, "refinement: Test1 && Test2 <= Test3" @@ -38,7 +38,7 @@ mod test { } #[test] - fn T2ConjT3RefinesT1() { + fn t2_conj_t3_refines_t1() { assert!(json_refinement_check( PATH, "refinement: Test2 && Test3 <= Test1" @@ -46,7 +46,7 @@ mod test { } #[test] - fn T1ConjT3RefinesT2() { + fn t1_conj_t3_refines_t2() { assert!(json_refinement_check( PATH, "refinement: Test1 && Test3 <= Test2" @@ -54,7 +54,7 @@ mod test { } #[test] - fn T1ConjT2ConjT4RefinesT5() { + fn t1_conj_t2_conj_t4_refines_t5() { assert!(json_refinement_check( PATH, "refinement: Test1 && Test2 && Test4 <= Test5" @@ -62,7 +62,7 @@ mod test { } #[test] - fn T3ConjT4RefinesT5() { + fn t3_conj_t4_refines_t5() { assert!(json_refinement_check( PATH, "refinement: Test3 && Test4 <= Test5" @@ -70,7 +70,7 @@ mod test { } #[test] - fn T6ConjT7RefinesT8() { + fn t6_conj_t7_refines_t8() { assert!(json_refinement_check( PATH, "refinement: Test6 && Test7 <= Test8" @@ -78,7 +78,7 @@ mod test { } #[test] - fn test1NestedConjRefinesT12() { + fn test1_nested_conj_refines_t12() { assert!(json_refinement_check( PATH, "refinement: Test9 && Test10 && Test11 <= Test12" diff --git a/src/tests/refinement/helper.rs b/src/tests/refinement/helper.rs new file mode 100644 index 00000000..3e43effe --- /dev/null +++ b/src/tests/refinement/helper.rs @@ -0,0 +1,96 @@ +use crate::data_reader::component_loader::{JsonProjectLoader, XmlProjectLoader}; +use crate::data_reader::parse_queries; +use crate::extract_system_rep::ExecutableQueryError; +use crate::logging::setup_logger; +use crate::model_objects::expressions::QueryExpression; +use crate::model_objects::Query; +use crate::system::extract_system_rep::create_executable_query; +use crate::system::query_failures::QueryResult; +use crate::transition_systems::transition_system::component_loader_to_transition_system; +use crate::transition_systems::TransitionSystemPtr; + +fn try_setup_logging() { + #[cfg(feature = "logging")] + let _ = setup_logger(); +} + +pub fn xml_refinement_check(path: &str, query: &str) -> bool { + try_setup_logging(); + match xml_run_query(path, query) { + QueryResult::Refinement(Ok(())) => true, + QueryResult::Refinement(Err(_)) => false, + QueryResult::CustomError(err) => panic!("{}", err), + _ => panic!("Not a refinement check"), + } +} + +pub fn json_refinement_check(path: &str, query: &str) -> bool { + try_setup_logging(); + + match json_run_query(path, query).unwrap() { + QueryResult::Refinement(Ok(())) => true, + QueryResult::Refinement(Err(_)) => false, + QueryResult::CustomError(err) => panic!("{}", err), + _ => panic!("Not a refinement check"), + } +} + +pub fn xml_run_query(path: &str, query: &str) -> QueryResult { + let project_path = String::from(path); + let project_loader = XmlProjectLoader::new_loader(project_path, crate::tests::TEST_SETTINGS); + let query = parse_queries::parse_to_expression_tree(query) + .unwrap() + .remove(0); + let q = Query { + query: Option::from(query), + comment: "".to_string(), + }; + + let mut comp_loader = project_loader.to_comp_loader(); + let query = create_executable_query(&q, &mut *comp_loader).unwrap(); + + query.execute() +} + +pub fn json_run_query(path: &str, query: &str) -> Result { + let mut project_loader = + JsonProjectLoader::new_loader(String::from(path), crate::tests::TEST_SETTINGS); + let query = parse_queries::parse_to_expression_tree(query) + .unwrap() + .remove(0); + let q = Query { + query: Option::from(query), + comment: "".to_string(), + }; + // FIXME: After implementing clock reduction on component level, a few tests are failing due to inconsistencies with initial state and global clock. Turn disabled_clock_reduction boolean to true to ignore inconsistencies + if let Some(query_type) = q.get_query() { + match query_type { + QueryExpression::Reachability { .. } => { + project_loader.get_settings_mut().disable_clock_reduction = true; + } + QueryExpression::Refinement(_, _) + | QueryExpression::Consistency(_) + | QueryExpression::Implementation(_) + | QueryExpression::Determinism(_) + | QueryExpression::Specification(_) + | QueryExpression::Syntax(_) + | QueryExpression::BisimMinim(_) + | QueryExpression::GetComponent(_) + | QueryExpression::Prune(_) => { + project_loader.get_settings_mut().disable_clock_reduction = false; + } + } + } + + let mut comp_loader = project_loader.to_comp_loader(); + let query = create_executable_query(&q, &mut *comp_loader)?; + + Ok(query.execute()) +} + +pub fn json_get_system(path: &str, comp: &str) -> TransitionSystemPtr { + let project_loader = + JsonProjectLoader::new_loader(String::from(path), crate::tests::TEST_SETTINGS); + let mut loader = project_loader.to_comp_loader(); + component_loader_to_transition_system(&mut *loader, comp) +} diff --git a/src/tests/refinement/mod.rs b/src/tests/refinement/mod.rs index 275e3f16..87ab33ba 100644 --- a/src/tests/refinement/mod.rs +++ b/src/tests/refinement/mod.rs @@ -1,8 +1,8 @@ -mod AG_Tests; -mod Big_Refinement; -mod Conjunction_refinement; -pub mod Helper; -mod Refinement_delay_add; -mod Refinement_university; -mod Refinement_unspec; +mod ag_tests; +mod big_refinement; +mod conjunction_refinement; +pub mod helper; +mod refinement_delay_add; +mod refinement_university; +mod refinement_unspec; pub mod xml; diff --git a/src/tests/refinement/Refinement_delay_add.rs b/src/tests/refinement/refinement_delay_add.rs similarity index 69% rename from src/tests/refinement/Refinement_delay_add.rs rename to src/tests/refinement/refinement_delay_add.rs index 7d35e1fb..708d4430 100644 --- a/src/tests/refinement/Refinement_delay_add.rs +++ b/src/tests/refinement/refinement_delay_add.rs @@ -1,21 +1,21 @@ #[cfg(test)] mod test { - use crate::tests::refinement::Helper::json_refinement_check; + use crate::tests::refinement::helper::json_refinement_check; const PATH: &str = "samples/json/DelayAdd"; #[test] - fn A1A2NotRefinesB() { + fn a1_a2_not_refines_b() { assert!(!json_refinement_check(PATH, "refinement: A1 || A2 <= B")); } #[test] - fn C1NotRefinesC2() { + fn c1_not_refines_c2() { assert!(!json_refinement_check(PATH, "refinement: C1 <= C2")); } #[test] - fn D1NotRefinesD2() { + fn d1_not_refines_d2() { assert!(!json_refinement_check(PATH, "refinement: D1 <= D2")); } } diff --git a/src/tests/refinement/Refinement_university.rs b/src/tests/refinement/refinement_university.rs similarity index 76% rename from src/tests/refinement/Refinement_university.rs rename to src/tests/refinement/refinement_university.rs index 4a2e3524..5e628b8e 100644 --- a/src/tests/refinement/Refinement_university.rs +++ b/src/tests/refinement/refinement_university.rs @@ -1,16 +1,16 @@ #[cfg(test)] mod test { - use crate::tests::refinement::Helper::json_refinement_check; + use crate::tests::refinement::helper::json_refinement_check; const PATH: &str = "samples/json/EcdarUniversity"; #[test] - fn testAdm2RefinesSelf() { + fn test_adm_2_refines_self() { assert!(json_refinement_check(PATH, "refinement: Adm2 <= Adm2")); } #[test] - fn testHalf1RefinesSelf() { + fn test_half_1_refines_self() { assert!(json_refinement_check( PATH, "refinement: HalfAdm1 <= HalfAdm1" @@ -18,7 +18,7 @@ mod test { } #[test] - fn testHalf2RefinesSelf() { + fn test_half_2_refines_self() { assert!(json_refinement_check( PATH, "refinement: HalfAdm2 <= HalfAdm2" @@ -26,7 +26,7 @@ mod test { } #[test] - fn testAdmRefinesSelf() { + fn test_adm_refines_self() { assert!(json_refinement_check( PATH, "refinement: Administration <= Administration" @@ -34,7 +34,7 @@ mod test { } #[test] - fn testMachineRefinesSelf() { + fn test_machine_refines_self() { assert!(json_refinement_check( PATH, "refinement: Machine <= Machine" @@ -42,7 +42,7 @@ mod test { } #[test] - fn testResRefinesSelf() { + fn test_res_refines_self() { assert!(json_refinement_check( PATH, "refinement: Researcher <= Researcher" @@ -50,12 +50,12 @@ mod test { } #[test] - fn testSpecRefinesSelf() { + fn test_spec_refines_self() { assert!(json_refinement_check(PATH, "refinement: Spec <= Spec")); } #[test] - fn testMachine3RefinesSelf() { + fn test_machine_3_refines_self() { assert!(json_refinement_check( PATH, "refinement: Machine3 <= Machine3" @@ -63,7 +63,7 @@ mod test { } #[test] - fn testAdmNotRefinesMachine() { + fn test_adm_not_refines_machine() { assert!(!json_refinement_check( PATH, "refinement: Administration <= Machine" @@ -71,7 +71,7 @@ mod test { } #[test] - fn testAdmNotRefinesResearcher() { + fn test_adm_not_refines_researcher() { assert!(!json_refinement_check( PATH, "refinement: Administration <= Researcher" @@ -79,7 +79,7 @@ mod test { } #[test] - fn testAdmNotRefinesSpec() { + fn test_adm_not_refines_spec() { assert!(!json_refinement_check( PATH, "refinement: Administration <= Spec" @@ -87,7 +87,7 @@ mod test { } #[test] - fn testAdmNotRefinesMachine3() { + fn test_adm_not_refines_machine_3() { assert!(!json_refinement_check( PATH, "refinement: Administration <= Machine3" @@ -95,7 +95,7 @@ mod test { } #[test] - fn testMachineNotRefinesAdm() { + fn test_machine_not_refines_adm() { assert!(!json_refinement_check( PATH, "refinement: Machine <= Administration" @@ -103,7 +103,7 @@ mod test { } #[test] - fn testMachineNotRefinesResearcher() { + fn test_machine_not_refines_researcher() { assert!(!json_refinement_check( PATH, "refinement: Machine <= Researcher" @@ -111,12 +111,12 @@ mod test { } #[test] - fn testMachineNotRefinesSpec() { + fn test_machine_not_refines_spec() { assert!(!json_refinement_check(PATH, "refinement: Machine <= Spec")); } #[test] - fn testMachineNotRefinesMachine3() { + fn test_machine_not_refines_machine_3() { assert!(!json_refinement_check( PATH, "refinement: Machine <= Machine3" @@ -124,7 +124,7 @@ mod test { } #[test] - fn testResNotRefinesAdm() { + fn test_res_not_refines_adm() { assert!(!json_refinement_check( PATH, "refinement: Researcher <= Administration" @@ -132,7 +132,7 @@ mod test { } #[test] - fn testResNotRefinesMachine() { + fn test_res_not_refines_machine() { assert!(!json_refinement_check( PATH, "refinement: Researcher <= Machine" @@ -140,7 +140,7 @@ mod test { } #[test] - fn testResNotRefinesSpec() { + fn test_res_not_refines_spec() { assert!(!json_refinement_check( PATH, "refinement: Researcher <= Spec" @@ -148,7 +148,7 @@ mod test { } #[test] - fn testResNotRefinesMachine3() { + fn test_res_not_refines_machine_3() { assert!(!json_refinement_check( PATH, "refinement: Researcher <= Machine3" @@ -156,7 +156,7 @@ mod test { } #[test] - fn testSpecNotRefinesAdm() { + fn test_spec_not_refines_adm() { assert!(!json_refinement_check( PATH, "refinement: Spec <= Administration" @@ -164,12 +164,12 @@ mod test { } #[test] - fn testSpecNotRefinesMachine() { + fn test_spec_not_refines_machine() { assert!(!json_refinement_check(PATH, "refinement: Spec <= Machine")); } #[test] - fn testSpecNotRefinesResearcher() { + fn test_spec_not_refines_researcher() { assert!(!json_refinement_check( PATH, "refinement: Spec <= Researcher" @@ -177,12 +177,12 @@ mod test { } #[test] - fn testSpecNotRefinesMachine3() { + fn test_spec_not_refines_machine_3() { assert!(!json_refinement_check(PATH, "refinement: Spec <= Machine3")); } #[test] - fn testMachine3RefinesMachine() { + fn test_machine_3_refines_machine() { assert!(json_refinement_check( PATH, "refinement: Machine3 <= Machine" @@ -190,7 +190,7 @@ mod test { } #[test] - fn testMachine3NotRefinesAdm() { + fn test_machine_3_not_refines_adm() { assert!(!json_refinement_check( PATH, "refinement: Machine3 <= Administration" @@ -198,7 +198,7 @@ mod test { } #[test] - fn testMachine3NotRefinesResearcher() { + fn test_machine_3_not_refines_researcher() { assert!(!json_refinement_check( PATH, "refinement: Machine3 <= Researcher" @@ -206,12 +206,12 @@ mod test { } #[test] - fn testMachine3NotRefinesSpec() { + fn test_machine_3_not_refines_spec() { assert!(!json_refinement_check(PATH, "refinement: Machine3 <= Spec")); } #[test] - fn testCompRefinesSpec() { + fn test_comp_refines_spec() { assert!(json_refinement_check( PATH, "refinement: Administration || Researcher || Machine <= Spec" @@ -219,7 +219,7 @@ mod test { } #[test] - fn testHalfCompNotRefinesSpec() { + fn test_half_comp_not_refines_spec() { assert!(!json_refinement_check( PATH, "refinement: (HalfAdm1 && HalfAdm2) || Researcher || Machine <= Spec" @@ -227,7 +227,7 @@ mod test { } #[test] - fn testAdm2NotRefinesSpec() { + fn test_adm_2_not_refines_spec() { assert!(!json_refinement_check( PATH, "refinement: Adm2 <= Spec // Researcher // Machine" @@ -235,7 +235,7 @@ mod test { } #[test] - fn testResearcherNotRefinesAdm2Spec() { + fn test_researcher_not_refines_adm_2_spec() { assert!(!json_refinement_check( PATH, "refinement: Researcher <= Spec // Adm2 // Machine" @@ -243,7 +243,7 @@ mod test { } #[test] - fn testMachineNotRefinesAdm2Spec() { + fn test_machine_not_refines_adm_2_spec() { assert!(!json_refinement_check( PATH, "refinement: Machine <= Spec // Adm2 // Researcher" @@ -251,7 +251,7 @@ mod test { } #[test] - fn testAdm2ResearcherNotRefinesSpec() { + fn test_adm_2_researcher_not_refines_spec() { assert!(!json_refinement_check( PATH, "refinement: Adm2 || Researcher <= Spec // Machine" @@ -259,7 +259,7 @@ mod test { } #[test] - fn testResearcherMachineNotRefinesAdm2Spec() { + fn test_researcher_machine_not_refines_adm_2_spec() { assert!(!json_refinement_check( PATH, "refinement: Researcher || Machine <= Spec // Adm2" @@ -267,7 +267,7 @@ mod test { } #[test] - fn testMachineAdm2NotRefinesSpec() { + fn test_machine_adm_2_not_refines_spec() { assert!(!json_refinement_check( PATH, "refinement: Machine || Adm2 <= Spec // Researcher" @@ -275,7 +275,7 @@ mod test { } #[test] - fn testAdminRefinesSpec() { + fn test_admin_refines_spec() { assert!(json_refinement_check( PATH, "refinement: Administration <= Spec // Researcher // Machine" @@ -283,7 +283,7 @@ mod test { } #[test] - fn testResearcherRefinesSpec() { + fn test_researcher_refines_spec() { assert!(json_refinement_check( PATH, "refinement: Researcher <= Spec // Administration // Machine" @@ -291,7 +291,7 @@ mod test { } #[test] - fn testMachineRefinesSpec() { + fn test_machine_refines_spec() { assert!(json_refinement_check( PATH, "refinement: Machine <= Spec // Administration // Researcher" @@ -299,7 +299,7 @@ mod test { } #[test] - fn testAdminResearcherRefinesSpec() { + fn test_admin_researcher_refines_spec() { assert!(json_refinement_check( PATH, "refinement: Administration || Researcher <= Spec // Machine" @@ -307,7 +307,7 @@ mod test { } #[test] - fn testResearcherMachineRefinesSpec() { + fn test_researcher_machine_refines_spec() { assert!(json_refinement_check( PATH, "refinement: Researcher || Machine <= Spec // Administration" @@ -315,7 +315,7 @@ mod test { } #[test] - fn testMachineAdminRefinesSpec() { + fn test_machine_admin_refines_spec() { assert!(json_refinement_check( PATH, "refinement: Machine || Administration <= Spec // Researcher" @@ -323,7 +323,7 @@ mod test { } #[test] - fn testCompRefinesSelf() { + fn test_comp_refines_self() { assert!(json_refinement_check( PATH, "refinement: Administration || Researcher || Machine <= Administration || Researcher || Machine" @@ -331,7 +331,7 @@ mod test { } #[test] - fn testHalf1AndHalf2RefinesAdm2() { + fn test_half_1_and_half_2_refines_adm2() { assert!(json_refinement_check( PATH, "refinement: HalfAdm1 && HalfAdm2 <= Adm2" @@ -339,7 +339,7 @@ mod test { } #[test] - fn testAdm2RefinesHalf1AndHalf2() { + fn test_adm_2_refines_half_1_and_half2() { assert!(json_refinement_check( PATH, "refinement: Adm2 <= HalfAdm1 && HalfAdm2" diff --git a/src/tests/refinement/Refinement_unspec.rs b/src/tests/refinement/refinement_unspec.rs similarity index 68% rename from src/tests/refinement/Refinement_unspec.rs rename to src/tests/refinement/refinement_unspec.rs index 54b13aa8..bd30372a 100644 --- a/src/tests/refinement/Refinement_unspec.rs +++ b/src/tests/refinement/refinement_unspec.rs @@ -1,21 +1,21 @@ #[cfg(test)] mod test { - use crate::tests::refinement::Helper::json_refinement_check; + use crate::tests::refinement::helper::json_refinement_check; const PATH: &str = "samples/json/Unspec"; #[test] - fn testARefinesSelf() { + fn test_arefines_self() { assert!(json_refinement_check(PATH, "refinement: A <= A")); } #[test] - fn testAaRefinesSelf() { + fn test_aa_refines_self() { assert!(json_refinement_check(PATH, "refinement: AA <= AA")); } #[test] - fn testBRefinesSelf() { + fn test_brefines_self() { assert!(json_refinement_check(PATH, "refinement: B <= B")); } } diff --git a/src/tests/refinement/xml/conjunction_tests.rs b/src/tests/refinement/xml/conjunction_tests.rs index 7dd1510f..9ff8fcdd 100644 --- a/src/tests/refinement/xml/conjunction_tests.rs +++ b/src/tests/refinement/xml/conjunction_tests.rs @@ -1,16 +1,16 @@ #[cfg(test)] mod test { - use crate::tests::refinement::Helper::xml_refinement_check; + use crate::tests::refinement::helper::xml_refinement_check; const PATH: &str = "samples/xml/conjun.xml"; #[test] - fn P0ConjP1RefP2() { + fn p0_conj_p1_ref_p2() { assert!(!xml_refinement_check(PATH, "refinement: P0 && P1 <= P2")); } #[test] - fn P7ConjP8ConjP9RefP10() { + fn p7_conj_p8_conj_p9_ref_p10() { assert!(!xml_refinement_check( PATH, "refinement: P7 && P8 && P9 <= P10" @@ -18,7 +18,7 @@ mod test { } #[test] - fn P11ConjP12RefP13() { + fn p11_conj_p12_ref_p13() { assert!(!xml_refinement_check(PATH, "refinement: P11 && P12 <= P13")); } } diff --git a/src/tests/refinement/xml/consistency_tests.rs b/src/tests/refinement/xml/consistency_tests.rs index 4a4bb84e..ab99e4a0 100644 --- a/src/tests/refinement/xml/consistency_tests.rs +++ b/src/tests/refinement/xml/consistency_tests.rs @@ -1,6 +1,6 @@ #[cfg(test)] mod test { - use crate::{tests::refinement::Helper::xml_run_query, System::query_failures::QueryResult}; + use crate::{system::query_failures::QueryResult, tests::refinement::helper::xml_run_query}; const PATH: &str = "samples/xml/ConsTests.xml"; @@ -9,7 +9,7 @@ mod test { } #[test] - fn testG1() { + fn test_g1() { let result = xml_run_query(PATH, "consistency: G1"); if let QueryResult::Consistency(_) = &result { @@ -19,7 +19,7 @@ mod test { } } #[test] - fn testG2() { + fn test_g2() { let result = xml_run_query(PATH, "consistency: G2"); if let QueryResult::Consistency(_) = &result { @@ -30,7 +30,7 @@ mod test { } #[test] - fn testG3() { + fn test_g3() { let result = xml_run_query(PATH, "consistency: G3"); if let QueryResult::Consistency(_) = &result { @@ -41,7 +41,7 @@ mod test { } #[test] - fn testG4() { + fn test_g4() { let result = xml_run_query(PATH, "consistency: G4"); if let QueryResult::Consistency(_) = &result { @@ -52,7 +52,7 @@ mod test { } #[test] - fn testG5() { + fn test_g5() { let result = xml_run_query(PATH, "consistency: G5"); if let QueryResult::Consistency(_) = &result { @@ -63,7 +63,7 @@ mod test { } #[test] - fn testG6() { + fn test_g6() { let result = xml_run_query(PATH, "consistency: G6"); if let QueryResult::Consistency(_) = &result { @@ -74,7 +74,7 @@ mod test { } #[test] - fn testG7() { + fn test_g7() { let result = xml_run_query(PATH, "consistency: G7"); if let QueryResult::Consistency(_) = &result { @@ -85,7 +85,7 @@ mod test { } #[test] - fn testG8() { + fn test_g8() { let result = xml_run_query(PATH, "consistency: G8"); if let QueryResult::Consistency(_) = &result { @@ -96,7 +96,7 @@ mod test { } #[test] - fn testG9() { + fn test_g9() { let result = xml_run_query(PATH, "consistency: G9"); if let QueryResult::Consistency(_) = &result { @@ -107,7 +107,7 @@ mod test { } #[test] - fn testG10() { + fn test_g10() { let result = xml_run_query(PATH, "consistency: G10"); if let QueryResult::Consistency(_) = &result { @@ -118,7 +118,7 @@ mod test { } #[test] - fn testG11() { + fn test_g11() { let result = xml_run_query(PATH, "consistency: G11"); if let QueryResult::Consistency(_) = &result { @@ -129,7 +129,7 @@ mod test { } #[test] - fn testG12() { + fn test_g12() { let result = xml_run_query(PATH, "consistency: G12"); if let QueryResult::Consistency(_) = &result { @@ -140,7 +140,7 @@ mod test { } #[test] - fn testG13() { + fn test_g13() { let result = xml_run_query(PATH, "consistency: G13"); if let QueryResult::Consistency(_) = &result { @@ -151,7 +151,7 @@ mod test { } #[test] - fn testG14() { + fn test_g14() { let result = xml_run_query(PATH, "consistency: G14"); if let QueryResult::Consistency(_) = &result { @@ -162,7 +162,7 @@ mod test { } #[test] - fn testG15() { + fn test_g15() { let result = xml_run_query(PATH, "consistency: G15"); if let QueryResult::Consistency(_) = &result { @@ -173,7 +173,7 @@ mod test { } #[test] - fn testG16() { + fn test_g16() { let result = xml_run_query(PATH, "consistency: G16"); if let QueryResult::Consistency(_) = &result { @@ -184,7 +184,7 @@ mod test { } #[test] - fn testG17() { + fn test_g17() { let result = xml_run_query(PATH, "consistency: G17"); if let QueryResult::Consistency(_) = &result { @@ -195,7 +195,7 @@ mod test { } #[test] - fn testG18() { + fn test_g18() { let result = xml_run_query(PATH, "consistency: G18"); if let QueryResult::Consistency(_) = &result { @@ -206,7 +206,7 @@ mod test { } #[test] - fn testG19() { + fn test_g19() { let result = xml_run_query(PATH, "consistency: G19"); if let QueryResult::Consistency(_) = &result { @@ -217,7 +217,7 @@ mod test { } #[test] - fn testG20() { + fn test_g20() { let result = xml_run_query(PATH, "consistency: G20"); if let QueryResult::Consistency(_) = &result { @@ -228,7 +228,7 @@ mod test { } #[test] - fn testG21() { + fn test_g21() { let result = xml_run_query(PATH, "consistency: G21"); if let QueryResult::Consistency(_) = &result { diff --git a/src/tests/refinement/xml/delay_refinement.rs b/src/tests/refinement/xml/delay_refinement.rs index 162c241c..473510c5 100644 --- a/src/tests/refinement/xml/delay_refinement.rs +++ b/src/tests/refinement/xml/delay_refinement.rs @@ -1,13 +1,13 @@ #[cfg(test)] mod test { - use crate::tests::refinement::Helper::xml_refinement_check; + use crate::tests::refinement::helper::xml_refinement_check; const PATH: &str = "samples/xml/delayRefinement.xml"; const PATH_2: &str = "samples/xml/loop.xml"; // Self Refinements #[test] - fn LoopTest() { + fn loop_test() { assert!(xml_refinement_check( PATH_2, "refinement: SelfloopNonZeno <= SelfloopNonZeno" @@ -16,397 +16,397 @@ mod test { // Self Refinements #[test] - fn T1RefinesSelf() { + fn t1_refines_self() { assert!(xml_refinement_check(PATH, "refinement: T1 <= T1")); } #[test] - fn T2RefinesSelf() { + fn t2_refines_self() { assert!(xml_refinement_check(PATH, "refinement: T2 <= T2")); } #[test] - fn T3RefinesSelf() { + fn t3_refines_self() { assert!(xml_refinement_check(PATH, "refinement: T3 <= T3")); } #[test] - fn C1RefinesSelf() { + fn c1_refines_self() { assert!(xml_refinement_check(PATH, "refinement: C1 <= C1")); } #[test] - fn C2RefinesSelf() { + fn c2_refines_self() { assert!(xml_refinement_check(PATH, "refinement: C2 <= C2")); } #[test] - fn F1RefinesSelf() { + fn f1_refines_self() { assert!(xml_refinement_check(PATH, "refinement: F1 <= F1")); } #[test] - fn F2RefinesSelf() { + fn f2_refines_self() { assert!(xml_refinement_check(PATH, "refinement: F2 <= F2")); } #[test] - fn F3RefinesSelf() { + fn f3_refines_self() { assert!(xml_refinement_check(PATH, "refinement: F3 <= F3")); } #[test] - fn T4RefinesSelf() { + fn t4_refines_self() { assert!(xml_refinement_check(PATH, "refinement: T4 <= T4")); } #[test] - fn T0RefinesSelf() { + fn t0_refines_self() { assert!(xml_refinement_check(PATH, "refinement: T0 <= T0")); } #[test] - fn T5RefinesSelf() { + fn t5_refines_self() { assert!(xml_refinement_check(PATH, "refinement: T5 <= T5")); } #[test] - fn T6RefinesSelf() { + fn t6_refines_self() { assert!(xml_refinement_check(PATH, "refinement: T6 <= T6")); } #[test] - fn T7RefinesSelf() { + fn t7_refines_self() { assert!(xml_refinement_check(PATH, "refinement: T7 <= T7")); } #[test] - fn T8RefinesSelf() { + fn t8_refines_self() { assert!(xml_refinement_check(PATH, "refinement: T8 <= T8")); } #[test] - fn T9RefinesSelf() { + fn t9_refines_self() { assert!(xml_refinement_check(PATH, "refinement: T9 <= T9")); } #[test] - fn T10RefinesSelf() { + fn t10_refines_self() { assert!(xml_refinement_check(PATH, "refinement: T10 <= T10")); } #[test] - fn T11RefinesSelf() { + fn t11_refines_self() { assert!(xml_refinement_check(PATH, "refinement: T11 <= T11")); } #[test] - fn N1RefinesSelf() { + fn n1_refines_self() { assert!(xml_refinement_check(PATH, "refinement: N1 <= N1")); } #[test] - fn N2RefinesSelf() { + fn n2_refines_self() { assert!(xml_refinement_check(PATH, "refinement: N2 <= N2")); } #[test] - fn N3RefinesSelf() { + fn n3_refines_self() { assert!(xml_refinement_check(PATH, "refinement: N3 <= N3")); } #[test] - fn N4RefinesSelf() { + fn n4_refines_self() { assert!(xml_refinement_check(PATH, "refinement: N4 <= N4")); } #[test] - fn D1RefinesSelf() { + fn d1_refines_self() { assert!(xml_refinement_check(PATH, "refinement: D1 <= D1")); } #[test] - fn D2RefinesSelf() { + fn d2_refines_self() { assert!(xml_refinement_check(PATH, "refinement: D2 <= D2")); } #[test] - fn K1RefinesSelf() { + fn k1_refines_self() { assert!(xml_refinement_check(PATH, "refinement: K1 <= K1")); } #[test] - fn K2RefinesSelf() { + fn k2_refines_self() { assert!(xml_refinement_check(PATH, "refinement: K2 <= K2")); } #[test] - fn K3RefinesSelf() { + fn k3_refines_self() { assert!(xml_refinement_check(PATH, "refinement: K3 <= K3")); } #[test] - fn K4RefinesSelf() { + fn k4_refines_self() { assert!(xml_refinement_check(PATH, "refinement: K4 <= K4")); } #[test] - fn K5RefinesSelf() { + fn k5_refines_self() { assert!(xml_refinement_check(PATH, "refinement: K5 <= K5")); } #[test] - fn K6RefinesSelf() { + fn k6_refines_self() { assert!(xml_refinement_check(PATH, "refinement: K6 <= K6")); } #[test] - fn P0RefinesSelf() { + fn p0_refines_self() { assert!(xml_refinement_check(PATH, "refinement: P0 <= P0")); } #[test] - fn P1RefinesSelf() { + fn p1_refines_self() { assert!(xml_refinement_check(PATH, "refinement: P1 <= P1")); } #[test] - fn P2RefinesSelf() { + fn p2_refines_self() { assert!(xml_refinement_check(PATH, "refinement: P2 <= P2")); } #[test] - fn P3RefinesSelf() { + fn p3_refines_self() { assert!(xml_refinement_check(PATH, "refinement: P3 <= P3")); } #[test] - fn P4RefinesSelf() { + fn p4_refines_self() { assert!(xml_refinement_check(PATH, "refinement: P4 <= P4")); } #[test] - fn P5RefinesSelf() { + fn p5_refines_self() { assert!(xml_refinement_check(PATH, "refinement: P5 <= P5")); } #[test] - fn P6RefinesSelf() { + fn p6_refines_self() { assert!(xml_refinement_check(PATH, "refinement: P6 <= P6")); } #[test] - fn P7RefinesSelf() { + fn p7_refines_self() { assert!(xml_refinement_check(PATH, "refinement: P7 <= P7")); } #[test] - fn L1RefinesSelf() { + fn l1_refines_self() { assert!(xml_refinement_check(PATH, "refinement: L1 <= L1")); } #[test] - fn L2RefinesSelf() { + fn l2_refines_self() { assert!(xml_refinement_check(PATH, "refinement: L2 <= L2")); } #[test] - fn L3RefinesSelf() { + fn l3_refines_self() { assert!(xml_refinement_check(PATH, "refinement: L3 <= L3")); } #[test] - fn L4RefinesSelf() { + fn l4_refines_self() { assert!(xml_refinement_check(PATH, "refinement: L4 <= L4")); } #[test] - fn L5RefinesSelf() { + fn l5_refines_self() { assert!(xml_refinement_check(PATH, "refinement: L5 <= L5")); } #[test] - fn L6RefinesSelf() { + fn l6_refines_self() { assert!(xml_refinement_check(PATH, "refinement: L6 <= L6")); } #[test] - fn L7RefinesSelf() { + fn l7_refines_self() { assert!(xml_refinement_check(PATH, "refinement: L7 <= L7")); } #[test] - fn Z1RefinesSelf() { + fn z1_refines_self() { assert!(xml_refinement_check(PATH, "refinement: Z1 <= Z1")); } #[test] - fn Z2RefinesSelf() { + fn z2_refines_self() { assert!(xml_refinement_check(PATH, "refinement: Z2 <= Z2")); } #[test] - fn Z3RefinesSelf() { + fn z3_refines_self() { assert!(xml_refinement_check(PATH, "refinement: Z3 <= Z3")); } #[test] - fn Z4RefinesSelf() { + fn z4_refines_self() { assert!(xml_refinement_check(PATH, "refinement: Z4 <= Z4")); } #[test] - fn Z5RefinesSelf() { + fn z5_refines_self() { assert!(xml_refinement_check(PATH, "refinement: Z5 <= Z5")); } #[test] - fn Z6RefinesSelf() { + fn z6_refines_self() { assert!(xml_refinement_check(PATH, "refinement: Z6 <= Z6")); } #[test] - fn Z7RefinesSelf() { + fn z7_refines_self() { assert!(xml_refinement_check(PATH, "refinement: Z7 <= Z7")); } // // Rest of the tests #[test] - fn T1T2RefinesT3() { + fn t1_t2_refines_t3() { assert!(xml_refinement_check(PATH, "refinement: T1||T2 <= T3")); } #[test] - fn C1RefinesC2() { + fn c1_refines_c2() { assert!(xml_refinement_check(PATH, "refinement: C1 <= C2")); } #[test] - fn C2RefinesC1() { + fn c2_refines_c1() { assert!(xml_refinement_check(PATH, "refinement: C2 <= C1")); } #[test] - fn T0T1T2RefinesT3() { + fn t0_t1_t2_refines_t3() { assert!(xml_refinement_check(PATH, "refinement: T0||T1||T2 <= T3")); } #[test] - fn F1F2RefinesF3() { + fn f1_f2_refines_f3() { assert!(xml_refinement_check(PATH, "refinement: F1||F2 <= F3")); } #[test] - fn T4RefinesT3() { + fn t4_refines_t3() { assert!(xml_refinement_check(PATH, "refinement: T4 <= T3")); } #[test] - fn T6RefinesT5() { + fn t6_refines_t5() { assert!(xml_refinement_check(PATH, "refinement: T6 <= T5")); } #[test] - fn T7NotRefinesT8() { + fn t7_not_refines_t8() { //Refinement passes, tho should fail ! same symbols assert!(!xml_refinement_check(PATH, "refinement: T7 <= T8")); } #[test] - fn T9NotRefinesT8() { + fn t9_not_refines_t8() { //Refinement passes, tho should fail ! same symbols assert!(!xml_refinement_check(PATH, "refinement: T9 <= T8")); } #[test] - fn T10NotRefinesT11() { + fn t1_0not_refines_t11() { //Refinement passes, tho should fail ! assert!(!xml_refinement_check(PATH, "refinement: T10 <= T11")); } #[test] - fn N1RefinesN2() { + fn n1_refines_n2() { assert!(xml_refinement_check(PATH, "refinement: N1 <= N2")); } #[test] - fn D2RefinesD1() { + fn d2_refines_d1() { assert!(xml_refinement_check(PATH, "refinement: D2 <= D1")); } #[test] - fn D1NotRefinesD2() { + fn d1_not_refines_d2() { assert!(!xml_refinement_check(PATH, "refinement: D1 <= D2")); } #[test] - fn K1NotRefinesK2() { + fn k1_not_refines_k2() { //Should fail, but passes ? assert!(!xml_refinement_check(PATH, "refinement: K1 <= K2")); } #[test] - fn K3NotRefinesK4() { + fn k3_not_refines_k4() { //should fail, tho passes ?! assert!(!xml_refinement_check(PATH, "refinement: K3 <= K4")); } #[test] - fn K5NotRefinesK6() { + fn k5_not_refines_k6() { //Should fail, tho passes ?!? assert!(!xml_refinement_check(PATH, "refinement: K5 <= K6")); } #[test] - fn P0RefinesP1() { + fn p0_refines_p1() { assert!(xml_refinement_check(PATH, "refinement: P0 <= P1")); } #[test] - fn P2NotRefinesP3() { + fn p2_not_refines_p3() { assert!(!xml_refinement_check(PATH, "refinement: P2 <= P3")); } #[test] - fn P4RefinesP5() { + fn p4_refines_p5() { assert!(xml_refinement_check(PATH, "refinement: P4 <= P5")); } #[test] - fn P6RefinesP7() { + fn p6_refines_p7() { assert!(xml_refinement_check(PATH, "refinement: P6 <= P7")); } #[test] - fn L1L2NotRefinesL3() { + fn l1_l2_not_refines_l3() { assert!(!xml_refinement_check(PATH, "refinement: L1||L2 <= L3")); } #[test] - fn L4RefinesL5() { + fn l4_refines_l5() { //should pass tho fails assert!(xml_refinement_check(PATH, "refinement: L5 <= L5")); } #[test] - fn Z1RefinesZ2() { + fn z1_refines_z2() { assert!(xml_refinement_check(PATH, "refinement: Z1 <= Z2")); } #[test] - fn Z3RefinesZ4() { + fn z3_refines_z4() { assert!(xml_refinement_check(PATH, "refinement: Z3 <= Z4")); } #[test] - fn Q1NotRefinesQ2() { + fn q1_not_refines_q2() { //refinement should not hold tho it holds ? assert!(!xml_refinement_check(PATH, "refinement: Q1 <= Q2")); } #[test] - fn Q2NotRefinesQ1() { + fn q2_not_refines_q1() { assert!(!xml_refinement_check(PATH, "refinement: Q2 <= Q1")); } } diff --git a/src/tests/refinement/xml/determinism_tests.rs b/src/tests/refinement/xml/determinism_tests.rs index a167e313..4bbd1724 100644 --- a/src/tests/refinement/xml/determinism_tests.rs +++ b/src/tests/refinement/xml/determinism_tests.rs @@ -1,8 +1,8 @@ #[cfg(test)] mod test { use crate::{ - tests::refinement::Helper::xml_run_query, - System::query_failures::{DeterminismResult, QueryResult}, + system::query_failures::{DeterminismResult, QueryResult}, + tests::refinement::helper::xml_run_query, }; const PATH: &str = "samples/xml/ConsTests.xml"; @@ -12,7 +12,7 @@ mod test { } #[test] - fn testG1() { + fn test_g1() { let result = xml_run_query(PATH, "determinism: G1"); if let QueryResult::Determinism(is_deterministic) = result { @@ -22,7 +22,7 @@ mod test { } } #[test] - fn testG2() { + fn test_g2() { let result = xml_run_query(PATH, "determinism: G2"); if let QueryResult::Determinism(is_deterministic) = result { @@ -33,7 +33,7 @@ mod test { } #[test] - fn testG3() { + fn test_g3() { let result = xml_run_query(PATH, "determinism: G3"); if let QueryResult::Determinism(is_deterministic) = result { @@ -43,7 +43,7 @@ mod test { } } #[test] - fn testG4() { + fn test_g4() { let result = xml_run_query(PATH, "determinism: G4"); if let QueryResult::Determinism(is_deterministic) = result { @@ -54,7 +54,7 @@ mod test { } #[test] - fn testG5() { + fn test_g5() { let result = xml_run_query(PATH, "determinism: G5"); if let QueryResult::Determinism(is_deterministic) = result { @@ -64,7 +64,7 @@ mod test { } } #[test] - fn testG6() { + fn test_g6() { let result = xml_run_query(PATH, "determinism: G6"); if let QueryResult::Determinism(is_deterministic) = result { @@ -75,7 +75,7 @@ mod test { } #[test] - fn testG7() { + fn test_g7() { let result = xml_run_query(PATH, "determinism: G7"); if let QueryResult::Determinism(is_deterministic) = result { @@ -86,7 +86,7 @@ mod test { } #[test] - fn testG8() { + fn test_g8() { let result = xml_run_query(PATH, "determinism: G8"); if let QueryResult::Determinism(is_deterministic) = result { @@ -97,7 +97,7 @@ mod test { } #[test] - fn testG9() { + fn test_g9() { // shouldn't be deterministic let result = xml_run_query(PATH, "determinism: G9"); @@ -109,7 +109,7 @@ mod test { } #[test] - fn testG10() { + fn test_g10() { let result = xml_run_query(PATH, "determinism: G10"); if let QueryResult::Determinism(is_deterministic) = result { @@ -120,7 +120,7 @@ mod test { } #[test] - fn testG11() { + fn test_g11() { let result = xml_run_query(PATH, "determinism: G11"); if let QueryResult::Determinism(is_deterministic) = result { @@ -131,7 +131,7 @@ mod test { } #[test] - fn testG12() { + fn test_g12() { let result = xml_run_query(PATH, "determinism: G12"); if let QueryResult::Determinism(is_deterministic) = result { @@ -142,7 +142,7 @@ mod test { } #[test] - fn testG13() { + fn test_g13() { let result = xml_run_query(PATH, "determinism: G13"); if let QueryResult::Determinism(is_deterministic) = result { @@ -153,7 +153,7 @@ mod test { } #[test] - fn testG14() { + fn test_g14() { let result = xml_run_query(PATH, "determinism: G14"); if let QueryResult::Determinism(is_deterministic) = result { @@ -164,7 +164,7 @@ mod test { } #[test] - fn testG15() { + fn test_g15() { let result = xml_run_query(PATH, "determinism: G15"); if let QueryResult::Determinism(is_deterministic) = result { @@ -175,7 +175,7 @@ mod test { } #[test] - fn testG16() { + fn test_g16() { let result = xml_run_query(PATH, "determinism: G16"); if let QueryResult::Determinism(is_deterministic) = result { @@ -186,7 +186,7 @@ mod test { } #[test] - fn testG17() { + fn test_g17() { let result = xml_run_query(PATH, "determinism: G17"); if let QueryResult::Determinism(is_deterministic) = result { @@ -197,7 +197,7 @@ mod test { } #[test] - fn testG22() { + fn test_g22() { let result = xml_run_query(PATH, "determinism: G22"); if let QueryResult::Determinism(is_deterministic) = result { @@ -208,7 +208,7 @@ mod test { } #[test] - fn testG23() { + fn test_g23() { // shouldn't be deterministic let result = xml_run_query(PATH, "determinism: G23"); diff --git a/src/tests/refinement/xml/extrapolation_tests.rs b/src/tests/refinement/xml/extrapolation_tests.rs index b2e18255..4770a333 100644 --- a/src/tests/refinement/xml/extrapolation_tests.rs +++ b/src/tests/refinement/xml/extrapolation_tests.rs @@ -6,7 +6,7 @@ mod test { // Self Refinements #[test] - fn InfRefinesInf() { + fn inf_refines_inf() { assert!(xml_refinement_check(PATH, "refinement: Inf <= Inf")); } } diff --git a/src/tests/refinement/xml/misc_tests.rs b/src/tests/refinement/xml/misc_tests.rs index 87a6aa32..dd27830e 100644 --- a/src/tests/refinement/xml/misc_tests.rs +++ b/src/tests/refinement/xml/misc_tests.rs @@ -1,11 +1,11 @@ #[cfg(test)] mod test { - use crate::tests::refinement::Helper::xml_refinement_check; + use crate::tests::refinement::helper::xml_refinement_check; const PATH: &str = "samples/xml/misc_test.xml"; #[test] - fn GuardParanRefinesSelf() { + fn guard_paran_refines_self() { assert!(xml_refinement_check( PATH, "refinement: GuardParan <= GuardParan" diff --git a/src/tests/sample.rs b/src/tests/sample.rs index f6614de3..da837335 100644 --- a/src/tests/sample.rs +++ b/src/tests/sample.rs @@ -1,46 +1,48 @@ #[cfg(test)] mod samples { - use crate::DataReader::component_loader::JsonProjectLoader; + use crate::data_reader::component_loader::JsonProjectLoader; const CONJUNCTION_SAMPLE: &str = "samples/json/Conjunction"; #[test] - fn test_locations_T1() { + fn test_locations_t1() { let mut project_loader = JsonProjectLoader::new_loader(CONJUNCTION_SAMPLE, crate::tests::TEST_SETTINGS); - let t1 = project_loader.get_component("Test1"); + let t1 = project_loader.get_component("Test1").unwrap(); assert_eq!(t1.name, "Test1"); assert_eq!(t1.locations.len(), 2); } #[test] - fn test_locations_T2() { + fn test_locations_t2() { let mut project_loader = JsonProjectLoader::new_loader(CONJUNCTION_SAMPLE, crate::tests::TEST_SETTINGS); - let t2 = project_loader.get_component("Test2"); + let t2 = project_loader.get_component("Test2").unwrap(); assert_eq!(t2.name, "Test2"); assert_eq!(t2.locations.len(), 2); } #[test] - fn test_locations_T3() { + fn test_locations_t3() { let mut project_loader = JsonProjectLoader::new_loader(CONJUNCTION_SAMPLE, crate::tests::TEST_SETTINGS); - let t3 = project_loader.get_component("Test3"); + let t3 = project_loader.get_component("Test3").unwrap(); assert_eq!(t3.name, "Test3"); assert_eq!(t3.locations.len(), 3); } #[test] - fn test_names_T1_through_T12() { + fn test_names_t1_through_t12() { let mut project_loader = JsonProjectLoader::new_loader(CONJUNCTION_SAMPLE, crate::tests::TEST_SETTINGS); for i in 1..12 { - let t = project_loader.get_component(&format!("Test{}", i).to_string()); + let t = project_loader + .get_component(&format!("Test{}", i).to_string()) + .unwrap(); assert_eq!(t.name, format!("Test{}", i)); } diff --git a/src/tests/save_component/composition_tests.rs b/src/tests/save_component/composition_tests.rs index 74b448e3..33fe1528 100644 --- a/src/tests/save_component/composition_tests.rs +++ b/src/tests/save_component/composition_tests.rs @@ -6,117 +6,117 @@ mod test { const ECDAR_UNI: &str = "samples/json/EcdarUniversity"; #[test] - fn Adm2MachineSavedRefinesSelf() { + fn adm_2_machine_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Adm2 || Machine"); } #[test] - fn Adm2Machine2SavedRefinesSelf() { + fn adm_2_machine_2_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Adm2 || Machine2"); } #[test] - fn Adm2Machine3SavedRefinesSelf() { + fn adm_2_machine_3_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Adm2 || Machine3"); } #[test] - fn Adm2ResearcherSavedRefinesSelf() { + fn adm_2_researcher_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Adm2 || Researcher"); } #[test] - fn AdministrationMachineSavedRefinesSelf() { + fn administration_machine_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Administration || Machine"); } #[test] - fn AdministrationMachine2SavedRefinesSelf() { + fn administration_machine_2_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Administration || Machine2"); } #[test] - fn AdministrationMachine3SavedRefinesSelf() { + fn administration_machine_3_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Administration || Machine3"); } #[test] - fn AdministrationResearcherSavedRefinesSelf() { + fn administration_researcher_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Administration || Researcher"); } #[test] - fn HalfAdm1MachineSavedRefinesSelf() { + fn half_adm_1_machine_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "HalfAdm1 || Machine"); } #[test] - fn HalfAdm1Machine2SavedRefinesSelf() { + fn half_adm_1_machine_2_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "HalfAdm1 || Machine2"); } #[test] - fn HalfAdm1Machine3SavedRefinesSelf() { + fn half_adm_1_machine_3_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "HalfAdm1 || Machine3"); } #[test] - fn HalfAdm1ResearcherSavedRefinesSelf() { + fn half_adm_1_researcher_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "HalfAdm1 || Researcher"); } #[test] - fn HalfAdm2MachineSavedRefinesSelf() { + fn half_adm_2_machine_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "HalfAdm2 || Machine"); } #[test] - fn HalfAdm2Machine2SavedRefinesSelf() { + fn half_adm_2_machine_2_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "HalfAdm2 || Machine2"); } #[test] - fn HalfAdm2Machine3SavedRefinesSelf() { + fn half_adm_2_machine_3_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "HalfAdm2 || Machine3"); } #[test] - fn HalfAdm2ResearcherSavedRefinesSelf() { + fn half_adm_2_researcher_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "HalfAdm2 || Researcher"); } #[test] - fn MachineResearcherSavedRefinesSelf() { + fn machine_researcher_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Machine || Researcher"); } #[test] - fn MachineSpecSavedRefinesSelf() { + fn machine_spec_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Machine || Spec"); } #[test] - fn Machine2ResearcherSavedRefinesSelf() { + fn machine_2_researcher_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Machine2 || Researcher"); } #[test] - fn Machine2SpecSavedRefinesSelf() { + fn machine_2_spec_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Machine2 || Spec"); } #[test] - fn Machine3ResearcherSavedRefinesSelf() { + fn machine_3_researcher_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Machine3 || Researcher"); } #[test] - fn Machine3SpecSavedRefinesSelf() { + fn machine_3_spec_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Machine3 || Spec"); } #[test] - fn ResearcherSpecSavedRefinesSelf() { + fn researcher_spec_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Researcher || Spec"); } } diff --git a/src/tests/save_component/conjunction_tests.rs b/src/tests/save_component/conjunction_tests.rs index c74c1f1c..0990f7a4 100644 --- a/src/tests/save_component/conjunction_tests.rs +++ b/src/tests/save_component/conjunction_tests.rs @@ -1,447 +1,447 @@ #[cfg(test)] -mod Conjunction_tests { +mod test { use crate::tests::save_component::save_comp_helper::util::json_reconstructed_component_refines_base_self; const PATH: &str = "samples/json/Conjunction"; const ECDAR_UNI: &str = "samples/json/EcdarUniversity"; #[test] - fn Test1AndTest1SavedRefinesSelf() { + fn test1_and_test1_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test1 && Test1"); } #[test] - fn Test1AndTest2SavedRefinesSelf() { + fn test1_and_test2_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test1 && Test2"); } #[test] - fn Test1AndTest3SavedRefinesSelf() { + fn test1_and_test3_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test1 && Test3"); } #[test] - fn Test1AndTest4SavedRefinesSelf() { + fn test1_and_test4_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test1 && Test4"); } #[test] - fn Test1AndTest5SavedRefinesSelf() { + fn test1_and_test5_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test1 && Test5"); } #[test] - fn Test1AndTest6SavedRefinesSelf() { + fn test1_and_test6_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test1 && Test6"); } #[test] - fn Test1AndTest7SavedRefinesSelf() { + fn test1_and_test7_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test1 && Test7"); } #[test] - fn Test1AndTest8SavedRefinesSelf() { + fn test1_and_test8_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test1 && Test8"); } #[test] - fn Test1AndTest9SavedRefinesSelf() { + fn test1_and_test9_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test1 && Test9"); } #[test] - fn Test1AndTest10SavedRefinesSelf() { + fn test1_and_test10_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test1 && Test10"); } #[test] - fn Test1AndTest11SavedRefinesSelf() { + fn test1_and_test11_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test1 && Test11"); } #[test] - fn Test1AndTest12SavedRefinesSelf() { + fn test1_and_test12_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test1 && Test12"); } #[test] - fn Test2AndTest2SavedRefinesSelf() { + fn test2_and_test2_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test2 && Test2"); } #[test] - fn Test2AndTest3SavedRefinesSelf() { + fn test2_and_test3_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test2 && Test3"); } #[test] - fn Test2AndTest4SavedRefinesSelf() { + fn test2_and_test4_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test2 && Test4"); } #[test] - fn Test2AndTest5SavedRefinesSelf() { + fn test2_and_test5_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test2 && Test5"); } #[test] - fn Test2AndTest6SavedRefinesSelf() { + fn test2_and_test6_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test2 && Test6"); } #[test] - fn Test2AndTest7SavedRefinesSelf() { + fn test2_and_test7_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test2 && Test7"); } #[test] - fn Test2AndTest8SavedRefinesSelf() { + fn test2_and_test8_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test2 && Test8"); } #[test] - fn Test2AndTest9SavedRefinesSelf() { + fn test2_and_test9_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test2 && Test9"); } #[test] - fn Test2AndTest10SavedRefinesSelf() { + fn test2_and_test10_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test2 && Test10"); } #[test] - fn Test2AndTest11SavedRefinesSelf() { + fn test2_and_test11_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test2 && Test11"); } #[test] - fn Test2AndTest12SavedRefinesSelf() { + fn test2_and_test12_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test2 && Test12"); } #[test] - fn Test3AndTest3SavedRefinesSelf() { + fn test3_and_test3_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test3 && Test3"); } #[test] - fn Test3AndTest4SavedRefinesSelf() { + fn test3_and_test4_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test3 && Test4"); } #[test] - fn Test3AndTest5SavedRefinesSelf() { + fn test3_and_test5_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test3 && Test5"); } #[test] - fn Test3AndTest6SavedRefinesSelf() { + fn test3_and_test6_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test3 && Test6"); } #[test] - fn Test3AndTest7SavedRefinesSelf() { + fn test3_and_test7_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test3 && Test7"); } #[test] - fn Test3AndTest8SavedRefinesSelf() { + fn test3_and_test8_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test3 && Test8"); } #[test] - fn Test3AndTest9SavedRefinesSelf() { + fn test3_and_test9_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test3 && Test9"); } #[test] - fn Test3AndTest10SavedRefinesSelf() { + fn test3_and_test10_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test3 && Test10"); } #[test] - fn Test3AndTest11SavedRefinesSelf() { + fn test3_and_test11_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test3 && Test11"); } #[test] - fn Test3AndTest12SavedRefinesSelf() { + fn test3_and_test12_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test3 && Test12"); } #[test] - fn Test4AndTest4SavedRefinesSelf() { + fn test4_and_test4_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test4 && Test4"); } #[test] - fn Test4AndTest5SavedRefinesSelf() { + fn test4_and_test5_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test4 && Test5"); } #[test] - fn Test4AndTest6SavedRefinesSelf() { + fn test4_and_test6_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test4 && Test6"); } #[test] - fn Test4AndTest7SavedRefinesSelf() { + fn test4_and_test7_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test4 && Test7"); } #[test] - fn Test4AndTest8SavedRefinesSelf() { + fn test4_and_test8_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test4 && Test8"); } #[test] - fn Test4AndTest9SavedRefinesSelf() { + fn test4_and_test9_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test4 && Test9"); } #[test] - fn Test4AndTest10SavedRefinesSelf() { + fn test4_and_test10_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test4 && Test10"); } #[test] - fn Test4AndTest11SavedRefinesSelf() { + fn test4_and_test11_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test4 && Test11"); } #[test] - fn Test4AndTest12SavedRefinesSelf() { + fn test4_and_test12_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test4 && Test12"); } #[test] - fn Test5AndTest5SavedRefinesSelf() { + fn test5_and_test5_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test5 && Test5"); } #[test] - fn Test5AndTest6SavedRefinesSelf() { + fn test5_and_test6_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test5 && Test6"); } #[test] - fn Test5AndTest7SavedRefinesSelf() { + fn test5_and_test7_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test5 && Test7"); } #[test] - fn Test5AndTest8SavedRefinesSelf() { + fn test5_and_test8_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test5 && Test8"); } #[test] - fn Test5AndTest9SavedRefinesSelf() { + fn test5_and_test9_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test5 && Test9"); } #[test] - fn Test5AndTest10SavedRefinesSelf() { + fn test5_and_test10_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test5 && Test10"); } #[test] - fn Test5AndTest11SavedRefinesSelf() { + fn test5_and_test11_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test5 && Test11"); } #[test] - fn Test5AndTest12SavedRefinesSelf() { + fn test5_and_test12_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test5 && Test12"); } #[test] - fn Test6AndTest6SavedRefinesSelf() { + fn test6_and_test6_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test6 && Test6"); } #[test] - fn Test6AndTest7SavedRefinesSelf() { + fn test6_and_test7_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test6 && Test7"); } #[test] - fn Test6AndTest8SavedRefinesSelf() { + fn test6_and_test8_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test6 && Test8"); } #[test] - fn Test6AndTest9SavedRefinesSelf() { + fn test6_and_test9_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test6 && Test9"); } #[test] - fn Test6AndTest10SavedRefinesSelf() { + fn test6_and_test10_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test6 && Test10"); } #[test] - fn Test6AndTest11SavedRefinesSelf() { + fn test6_and_test11_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test6 && Test11"); } #[test] - fn Test6AndTest12SavedRefinesSelf() { + fn test6_and_test12_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test6 && Test12"); } #[test] - fn Test7AndTest7SavedRefinesSelf() { + fn test7_and_test7_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test7 && Test7"); } #[test] - fn Test7AndTest8SavedRefinesSelf() { + fn test7_and_test8_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test7 && Test8"); } #[test] - fn Test7AndTest9SavedRefinesSelf() { + fn test7_and_test9_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test7 && Test9"); } #[test] - fn Test7AndTest10SavedRefinesSelf() { + fn test7_and_test10_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test7 && Test10"); } #[test] - fn Test7AndTest11SavedRefinesSelf() { + fn test7_and_test11_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test7 && Test11"); } #[test] - fn Test7AndTest12SavedRefinesSelf() { + fn test7_and_test12_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test7 && Test12"); } #[test] - fn Test8AndTest8SavedRefinesSelf() { + fn test8_and_test8_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test8 && Test8"); } #[test] - fn Test8AndTest9SavedRefinesSelf() { + fn test8_and_test9_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test8 && Test9"); } #[test] - fn Test8AndTest10SavedRefinesSelf() { + fn test8_and_test10_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test8 && Test10"); } #[test] - fn Test8AndTest11SavedRefinesSelf() { + fn test8_and_test11_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test8 && Test11"); } #[test] - fn Test8AndTest12SavedRefinesSelf() { + fn test8_and_test12_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test8 && Test12"); } #[test] - fn Test9AndTest9SavedRefinesSelf() { + fn test9_and_test9_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test9 && Test9"); } #[test] - fn Test9AndTest10SavedRefinesSelf() { + fn test9_and_test10_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test9 && Test10"); } #[test] - fn Test9AndTest11SavedRefinesSelf() { + fn test9_and_test11_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test9 && Test11"); } #[test] - fn Test9AndTest12SavedRefinesSelf() { + fn test9_and_test12_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test9 && Test12"); } #[test] - fn Test10AndTest10SavedRefinesSelf() { + fn test10_and_test10_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test10 && Test10"); } #[test] - fn Test10AndTest11SavedRefinesSelf() { + fn test10_and_test11_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test10 && Test11"); } #[test] - fn Test10AndTest12SavedRefinesSelf() { + fn test10_and_test12_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test10 && Test12"); } #[test] - fn Test11AndTest11SavedRefinesSelf() { + fn test11_and_test11_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test11 && Test11"); } #[test] - fn Test11AndTest12SavedRefinesSelf() { + fn test11_and_test12_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test11 && Test12"); } #[test] - fn Test12AndTest12SavedRefinesSelf() { + fn test12_and_test12_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test12 && Test12"); } #[test] - fn Adm2AndAdm2SavedRefinesSelf() { + fn adm2_and_adm2_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Adm2 && Adm2"); } #[test] - fn Adm2AndAdministrationSavedRefinesSelf() { + fn adm2_and_administration_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Adm2 && Administration"); } #[test] - fn Adm2AndHalfAdm1SavedRefinesSelf() { + fn adm2_and_half_adm1_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Adm2 && HalfAdm1"); } #[test] - fn Adm2AndHalfAdm2SavedRefinesSelf() { + fn adm2_and_half_adm2_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Adm2 && HalfAdm2"); } #[test] - fn Adm2AndMachineSavedRefinesSelf() { + fn adm2_and_machine_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Adm2 && Machine"); } #[test] - fn Adm2AndMachine2SavedRefinesSelf() { + fn adm2_and_machine2_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Adm2 && Machine2"); } #[test] - fn Adm2AndMachine3SavedRefinesSelf() { + fn adm2_and_machine3_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Adm2 && Machine3"); } #[test] - fn Adm2AndResearcherSavedRefinesSelf() { + fn adm2_and_researcher_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Adm2 && Researcher"); } #[test] - fn Adm2AndSpecSavedRefinesSelf() { + fn adm2_and_spec_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Adm2 && Spec"); } #[test] - fn AdministrationAndAdministrationSavedRefinesSelf() { + fn administration_and_administration_saved_refines_self() { json_reconstructed_component_refines_base_self( ECDAR_UNI, "Administration && Administration", @@ -449,177 +449,177 @@ mod Conjunction_tests { } #[test] - fn AdministrationAndHalfAdm1SavedRefinesSelf() { + fn administration_and_half_adm1saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Administration && HalfAdm1"); } #[test] - fn AdministrationAndHalfAdm2SavedRefinesSelf() { + fn administration_and_half_adm2saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Administration && HalfAdm2"); } #[test] - fn AdministrationAndMachineSavedRefinesSelf() { + fn administration_and_machine_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Administration && Machine"); } #[test] - fn AdministrationAndMachine2SavedRefinesSelf() { + fn administration_and_machine2_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Administration && Machine2"); } #[test] - fn AdministrationAndMachine3SavedRefinesSelf() { + fn administration_and_machine3_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Administration && Machine3"); } #[test] - fn AdministrationAndResearcherSavedRefinesSelf() { + fn administration_and_researcher_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Administration && Researcher"); } #[test] - fn AdministrationAndSpecSavedRefinesSelf() { + fn administration_and_spec_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Administration && Spec"); } #[test] - fn HalfAdm1AndHalfAdm1SavedRefinesSelf() { + fn half_adm1and_half_adm1_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "HalfAdm1 && HalfAdm1"); } #[test] - fn HalfAdm1AndHalfAdm2SavedRefinesSelf() { + fn half_adm1and_half_adm2_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "HalfAdm1 && HalfAdm2"); } #[test] - fn HalfAdm1AndMachineSavedRefinesSelf() { + fn half_adm1and_machine_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "HalfAdm1 && Machine"); } #[test] - fn HalfAdm1AndMachine2SavedRefinesSelf() { + fn half_adm1and_machine2_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "HalfAdm1 && Machine2"); } #[test] - fn HalfAdm1AndMachine3SavedRefinesSelf() { + fn half_adm1and_machine3_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "HalfAdm1 && Machine3"); } #[test] - fn HalfAdm1AndResearcherSavedRefinesSelf() { + fn half_adm1and_researcher_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "HalfAdm1 && Researcher"); } #[test] - fn HalfAdm1AndSpecSavedRefinesSelf() { + fn half_adm1and_spec_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "HalfAdm1 && Spec"); } #[test] - fn HalfAdm2AndHalfAdm2SavedRefinesSelf() { + fn half_adm2_and_half_adm2_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "HalfAdm2 && HalfAdm2"); } #[test] - fn HalfAdm2AndMachineSavedRefinesSelf() { + fn half_adm2_and_machine_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "HalfAdm2 && Machine"); } #[test] - fn HalfAdm2AndMachine2SavedRefinesSelf() { + fn half_adm2_and_machine2_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "HalfAdm2 && Machine2"); } #[test] - fn HalfAdm2AndMachine3SavedRefinesSelf() { + fn half_adm2_and_machine3_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "HalfAdm2 && Machine3"); } #[test] - fn HalfAdm2AndResearcherSavedRefinesSelf() { + fn half_adm2_and_researcher_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "HalfAdm2 && Researcher"); } #[test] - fn HalfAdm2AndSpecSavedRefinesSelf() { + fn half_adm2_and_spec_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "HalfAdm2 && Spec"); } #[test] - fn MachineAndMachineSavedRefinesSelf() { + fn machine_and_machine_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Machine && Machine"); } #[test] - fn MachineAndMachine2SavedRefinesSelf() { + fn machine_and_machine2_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Machine && Machine2"); } #[test] - fn MachineAndMachine3SavedRefinesSelf() { + fn machine_and_machine3_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Machine && Machine3"); } #[test] - fn MachineAndResearcherSavedRefinesSelf() { + fn machine_and_researcher_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Machine && Researcher"); } #[test] - fn MachineAndSpecSavedRefinesSelf() { + fn machine_and_spec_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Machine && Spec"); } #[test] - fn Machine2AndMachine2SavedRefinesSelf() { + fn machine2_and_machine2_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Machine2 && Machine2"); } #[test] - fn Machine2AndMachine3SavedRefinesSelf() { + fn machine2_and_machine3_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Machine2 && Machine3"); } #[test] - fn Machine2AndResearcherSavedRefinesSelf() { + fn machine2_and_researcher_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Machine2 && Researcher"); } #[test] - fn Machine2AndSpecSavedRefinesSelf() { + fn machine2_and_spec_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Machine2 && Spec"); } #[test] - fn Machine3AndMachine3SavedRefinesSelf() { + fn machine3_and_machine3_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Machine3 && Machine3"); } #[test] - fn Machine3AndResearcherSavedRefinesSelf() { + fn machine3_and_researcher_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Machine3 && Researcher"); } #[test] - fn Machine3AndSpecSavedRefinesSelf() { + fn machine3_and_spec_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Machine3 && Spec"); } #[test] - fn ResearcherAndResearcherSavedRefinesSelf() { + fn researcher_and_researcher_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Researcher && Researcher"); } #[test] - fn ResearcherAndSpecSavedRefinesSelf() { + fn researcher_and_spec_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Researcher && Spec"); } #[test] - fn SpecAndSpecSavedRefinesSelf() { + fn spec_and_spec_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Spec && Spec"); } } diff --git a/src/tests/save_component/no_operation_tests.rs b/src/tests/save_component/no_operation_tests.rs index d8a61ea9..87c89264 100644 --- a/src/tests/save_component/no_operation_tests.rs +++ b/src/tests/save_component/no_operation_tests.rs @@ -6,96 +6,96 @@ mod test { const ECDAR_UNI: &str = "samples/json/EcdarUniversity"; #[test] - fn T1SavedRefinesSelf() { + fn t1_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test1"); } #[test] - fn T2SavedRefinesSelf() { + fn t2_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test2"); } #[test] - fn T3SavedRefinesSelf() { + fn t3_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test3"); } #[test] - fn T4SavedRefinesSelf() { + fn t4_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test4"); } #[test] - fn T5SavedRefinesSelf() { + fn t5_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test5"); } #[test] - fn T6SavedRefinesSelf() { + fn t6_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test6"); } #[test] - fn T7SavedRefinesSelf() { + fn t7_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test7"); } #[test] - fn T8SavedRefinesSelf() { + fn t8_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test8"); } #[test] - fn T9SavedRefinesSelf() { + fn t9_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test9"); } #[test] - fn T10SavedRefinesSelf() { + fn t10_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test10"); } #[test] - fn T11SavedRefinesSelf() { + fn t11_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test11"); } #[test] - fn T12SavedRefinesSelf() { + fn t12_saved_refines_self() { json_reconstructed_component_refines_base_self(PATH, "Test12"); } #[test] - fn Adm2SavedRefinesSelf() { + fn adm_2_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Adm2"); } #[test] - fn AdministrationSavedRefinesSelf() { + fn administration_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Administration"); } #[test] - fn HalfAdm1SavedRefinesSelf() { + fn half_adm1saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "HalfAdm1"); } #[test] - fn HalfAdm2SavedRefinesSelf() { + fn half_adm_2_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "HalfAdm2"); } #[test] - fn MachineSavedRefinesSelf() { + fn machine_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Machine"); } #[test] - fn Machine2SavedRefinesSelf() { + fn machine_2_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Machine2"); } #[test] - fn Machine3SavedRefinesSelf() { + fn machine_3_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Machine3"); } #[test] - fn ResearcherSavedRefinesSelf() { + fn researcher_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Researcher"); } #[test] - fn SpecSavedRefinesSelf() { + fn spec_saved_refines_self() { json_reconstructed_component_refines_base_self(ECDAR_UNI, "Spec"); } } diff --git a/src/tests/save_component/save_comp_helper.rs b/src/tests/save_component/save_comp_helper.rs index 7d9aa51d..4145a449 100644 --- a/src/tests/save_component/save_comp_helper.rs +++ b/src/tests/save_component/save_comp_helper.rs @@ -1,14 +1,14 @@ #[cfg(test)] pub mod util { - use crate::DataReader::component_loader::JsonProjectLoader; - use crate::DataReader::parse_queries; - use crate::ModelObjects::Expressions::QueryExpression; - use crate::System::extract_system_rep; - use crate::System::extract_system_rep::SystemRecipe; - use crate::System::query_failures::ConsistencyResult; - use crate::System::refine; - use crate::System::save_component::combine_components; - use crate::System::save_component::PruningStrategy; + use crate::data_reader::component_loader::JsonProjectLoader; + use crate::data_reader::parse_queries; + use crate::model_objects::expressions::QueryExpression; + use crate::system::extract_system_rep; + use crate::system::extract_system_rep::SystemRecipe; + use crate::system::query_failures::ConsistencyResult; + use crate::system::refine; + use crate::system::save_component::combine_components; + use crate::system::save_component::PruningStrategy; use edbm::util::constraints::ClockIndex; pub fn json_reconstructed_component_refines_base_self(input_path: &str, system: &str) { @@ -30,13 +30,15 @@ pub mod util { &mut *comp_loader, &mut dim, &mut None, - ), + ) + .unwrap(), extract_system_rep::get_system_recipe( &expr.system, &mut *comp_loader, &mut dim, &mut None, - ), + ) + .unwrap(), ) } else { panic!("Failed to create system") diff --git a/src/tests/Simulation/helper.rs b/src/tests/simulation/helper.rs similarity index 95% rename from src/tests/Simulation/helper.rs rename to src/tests/simulation/helper.rs index e8dc6097..acb59e7b 100644 --- a/src/tests/Simulation/helper.rs +++ b/src/tests/simulation/helper.rs @@ -2,8 +2,8 @@ use std::fs; use tonic::{Response, Status}; -use crate::ProtobufServer::services::component::Rep; -use crate::ProtobufServer::services::{ +use crate::protobuf_server::services::component::Rep; +use crate::protobuf_server::services::{ Component as ProtoComponent, ComponentsInfo as ProtoComponentsInfo, SimulationInfo as ProtoSimulationInfo, SimulationStartRequest, SimulationStepRequest, SimulationStepResponse, diff --git a/src/tests/Simulation/mod.rs b/src/tests/simulation/mod.rs similarity index 100% rename from src/tests/Simulation/mod.rs rename to src/tests/simulation/mod.rs diff --git a/src/tests/system_recipe/compiled_component.rs b/src/tests/system_recipe/compiled_component.rs index fa004a0c..2b4d8c32 100644 --- a/src/tests/system_recipe/compiled_component.rs +++ b/src/tests/system_recipe/compiled_component.rs @@ -5,8 +5,8 @@ mod test { use crate::extract_system_rep::ExecutableQueryError; use crate::{ - tests::refinement::Helper::json_run_query, - System::query_failures::{ActionFailure, SystemRecipeFailure}, + system::query_failures::{ActionFailure, SystemRecipeFailure}, + tests::refinement::helper::json_run_query, }; const PATH: &str = "samples/json/SystemRecipe/CompiledComponent"; diff --git a/src/tests/system_recipe/composition.rs b/src/tests/system_recipe/composition.rs index 8edcea5a..790676a3 100644 --- a/src/tests/system_recipe/composition.rs +++ b/src/tests/system_recipe/composition.rs @@ -5,8 +5,8 @@ mod test { use crate::extract_system_rep::ExecutableQueryError; use crate::{ - tests::refinement::Helper::json_run_query, - System::query_failures::{ActionFailure, SystemRecipeFailure}, + system::query_failures::{ActionFailure, SystemRecipeFailure}, + tests::refinement::helper::json_run_query, }; const PATH: &str = "samples/json/SystemRecipe/Composition"; diff --git a/src/tests/system_recipe/conjunction.rs b/src/tests/system_recipe/conjunction.rs index 04f3fe4e..d7bed503 100644 --- a/src/tests/system_recipe/conjunction.rs +++ b/src/tests/system_recipe/conjunction.rs @@ -4,9 +4,9 @@ mod test { use std::collections::HashSet; use crate::{ - tests::refinement::Helper::json_run_query, - System::extract_system_rep::ExecutableQueryError, - System::query_failures::{ActionFailure, SystemRecipeFailure}, + system::extract_system_rep::ExecutableQueryError, + system::query_failures::{ActionFailure, SystemRecipeFailure}, + tests::refinement::helper::json_run_query, }; const PATH: &str = "samples/json/SystemRecipe/Conjunction"; diff --git a/src/tests/system_recipe/quotient.rs b/src/tests/system_recipe/quotient.rs index 1dd24e3c..146847f4 100644 --- a/src/tests/system_recipe/quotient.rs +++ b/src/tests/system_recipe/quotient.rs @@ -4,11 +4,11 @@ mod test { use std::collections::HashSet; use crate::{ - tests::refinement::Helper::json_run_query, - System::extract_system_rep::ExecutableQueryError, - System::query_failures::{ + system::extract_system_rep::ExecutableQueryError, + system::query_failures::{ ActionFailure, ConsistencyFailure, DeterminismFailure, SystemRecipeFailure, }, + tests::refinement::helper::json_run_query, }; const PATH: &str = "samples/json/SystemRecipe/Quotient"; diff --git a/src/TransitionSystems/common.rs b/src/transition_systems/common.rs similarity index 79% rename from src/TransitionSystems/common.rs rename to src/transition_systems/common.rs index fc6d8ae2..26ff5f6b 100644 --- a/src/TransitionSystems/common.rs +++ b/src/transition_systems/common.rs @@ -1,4 +1,4 @@ -use std::collections::HashSet; +use std::{collections::HashSet, rc::Rc}; use dyn_clone::{clone_trait_object, DynClone}; use edbm::{ @@ -7,17 +7,17 @@ use edbm::{ }; use log::warn; -use crate::ModelObjects::{Declarations, State, Transition}; -use crate::System::{ +use crate::model_objects::{Declarations, State, Transition}; +use crate::system::{ query_failures::{ConsistencyResult, DeterminismResult}, specifics::SpecificLocation, }; -use crate::TransitionSystems::CompositionType; +use crate::transition_systems::CompositionType; use super::{LocationTree, TransitionSystem, TransitionSystemPtr}; pub(super) trait ComposedTransitionSystem: DynClone { - fn next_transitions(&self, location: &LocationTree, action: &str) -> Vec; + fn next_transitions(&self, location: Rc, action: &str) -> Vec; fn check_local_consistency(&self) -> ConsistencyResult; @@ -41,8 +41,8 @@ impl TransitionSystem for T { let (left, right) = self.get_children(); let loc_l = loc.get_left(); let loc_r = loc.get_right(); - let mut bounds_l = left.get_local_max_bounds(loc_l); - let bounds_r = right.get_local_max_bounds(loc_r); + let mut bounds_l = left.get_local_max_bounds(&loc_l); + let bounds_r = right.get_local_max_bounds(&loc_r); bounds_l.add_bounds(&bounds_r); bounds_l } @@ -50,7 +50,7 @@ impl TransitionSystem for T { fn get_dim(&self) -> ClockIndex { self.get_dim() } - fn next_transitions(&self, location: &LocationTree, action: &str) -> Vec { + fn next_transitions(&self, location: Rc, action: &str) -> Vec { self.next_transitions(location, action) } fn get_input_actions(&self) -> HashSet { @@ -68,24 +68,24 @@ impl TransitionSystem for T { .collect() } - fn get_initial_location(&self) -> Option { + fn get_initial_location(&self) -> Option> { let (left, right) = self.get_children(); let l = left.get_initial_location()?; let r = right.get_initial_location()?; - Some(LocationTree::compose(&l, &r, self.get_composition_type())) + Some(LocationTree::compose(l, r, self.get_composition_type())) } - fn get_all_locations(&self) -> Vec { + fn get_all_locations(&self) -> Vec> { let (left, right) = self.get_children(); - let mut location_trees = vec![]; + let mut location_trees: Vec> = vec![]; let left = left.get_all_locations(); let right = right.get_all_locations(); for loc1 in &left { for loc2 in &right { location_trees.push(LocationTree::compose( - loc1, - loc2, + Rc::clone(loc1), + Rc::clone(loc2), self.get_composition_type(), )); } @@ -134,14 +134,17 @@ impl TransitionSystem for T { self.get_composition_type() } - fn construct_location_tree(&self, target: SpecificLocation) -> Result { + fn construct_location_tree( + &self, + target: SpecificLocation, + ) -> Result, String> { let (left, right) = self.get_children(); let (t_left, t_right) = target.split(); let loc_l = left.construct_location_tree(t_left)?; let loc_r = right.construct_location_tree(t_right)?; Ok(LocationTree::compose( - &loc_l, - &loc_r, + loc_l, + loc_r, self.get_composition_type(), )) } diff --git a/src/TransitionSystems/compiled_component.rs b/src/transition_systems/compiled_component.rs similarity index 86% rename from src/TransitionSystems/compiled_component.rs rename to src/transition_systems/compiled_component.rs index 2bad9eef..5952e03a 100644 --- a/src/TransitionSystems/compiled_component.rs +++ b/src/transition_systems/compiled_component.rs @@ -1,15 +1,16 @@ -use crate::ModelObjects::{Component, DeclarationProvider, Declarations, State, Transition}; -use crate::System::local_consistency::{self}; -use crate::System::query_failures::{ +use crate::model_objects::{Component, DeclarationProvider, Declarations, State, Transition}; +use crate::system::local_consistency::{self}; +use crate::system::query_failures::{ ActionFailure, ConsistencyResult, DeterminismResult, SystemRecipeFailure, }; -use crate::System::specifics::SpecificLocation; -use crate::TransitionSystems::{LocationTree, TransitionSystem, TransitionSystemPtr}; +use crate::system::specifics::SpecificLocation; +use crate::transition_systems::{LocationTree, TransitionSystem, TransitionSystemPtr}; use edbm::util::bounds::Bounds; use edbm::util::constraints::ClockIndex; use std::collections::hash_set::HashSet; use std::collections::HashMap; use std::iter::FromIterator; +use std::rc::Rc; use super::transition_system::ComponentInfoTree; use super::{CompositionType, LocationID}; @@ -28,9 +29,9 @@ pub struct ComponentInfo { pub struct CompiledComponent { inputs: HashSet, outputs: HashSet, - locations: HashMap, + locations: HashMap>, location_edges: HashMap>, - initial_location: Option, + initial_location: Option>, comp_info: ComponentInfo, dim: ClockIndex, } @@ -44,11 +45,11 @@ impl CompiledComponent { id: u32, ) -> Result, Box> { if !inputs.is_disjoint(&outputs) { - ActionFailure::not_disjoint_IO(&component.name, inputs.clone(), outputs.clone()) + ActionFailure::not_disjoint_io(&component.name, inputs.clone(), outputs.clone()) .map_err(|e| e.to_simple_failure(&component.name))?; } - let locations: HashMap = component + let locations: HashMap> = component .locations .iter() .map(|loc| { @@ -124,7 +125,7 @@ impl TransitionSystem for CompiledComponent { self.dim } - fn next_transitions(&self, locations: &LocationTree, action: &str) -> Vec { + fn next_transitions(&self, locations: Rc, action: &str) -> Vec { assert!(self.actions_contain(action)); let is_input = self.inputs_contain(action); @@ -160,11 +161,11 @@ impl TransitionSystem for CompiledComponent { self.inputs.union(&self.outputs).cloned().collect() } - fn get_initial_location(&self) -> Option { + fn get_initial_location(&self) -> Option> { self.initial_location.clone() } - fn get_all_locations(&self) -> Vec { + fn get_all_locations(&self) -> Vec> { self.locations.values().cloned().collect() } @@ -194,7 +195,7 @@ impl TransitionSystem for CompiledComponent { CompositionType::Simple } - fn get_location(&self, id: &LocationID) -> Option { + fn get_location(&self, id: &LocationID) -> Option> { self.locations.get(id).cloned() } @@ -210,7 +211,10 @@ impl TransitionSystem for CompiledComponent { self.comp_info.name.clone() } - fn construct_location_tree(&self, target: SpecificLocation) -> Result { + fn construct_location_tree( + &self, + target: SpecificLocation, + ) -> Result, String> { match target { SpecificLocation::ComponentLocation { comp, location_id } => { assert_eq!(comp.name, self.comp_info.name); diff --git a/src/TransitionSystems/composition.rs b/src/transition_systems/composition.rs similarity index 92% rename from src/TransitionSystems/composition.rs rename to src/transition_systems/composition.rs index a3e12c27..22fceeb6 100644 --- a/src/TransitionSystems/composition.rs +++ b/src/transition_systems/composition.rs @@ -1,9 +1,10 @@ use edbm::util::constraints::ClockIndex; -use crate::ModelObjects::Transition; -use crate::System::query_failures::{ActionFailure, SystemRecipeFailure}; -use crate::TransitionSystems::{LocationTree, TransitionSystem, TransitionSystemPtr}; +use crate::model_objects::Transition; +use crate::system::query_failures::{ActionFailure, SystemRecipeFailure}; +use crate::transition_systems::{LocationTree, TransitionSystem, TransitionSystemPtr}; use std::collections::hash_set::HashSet; +use std::rc::Rc; use super::common::ComposedTransitionSystem; use super::CompositionType; @@ -75,7 +76,7 @@ impl Composition { } impl ComposedTransitionSystem for Composition { - fn next_transitions(&self, location: &LocationTree, action: &str) -> Vec { + fn next_transitions(&self, location: Rc, action: &str) -> Vec { assert!(self.actions_contain(action)); let loc_left = location.get_left(); @@ -132,7 +133,7 @@ impl ComposedTransitionSystem for Composition { self.outputs.clone() } - fn check_local_consistency(&self) -> crate::System::query_failures::ConsistencyResult { + fn check_local_consistency(&self) -> crate::system::query_failures::ConsistencyResult { self.left.check_local_consistency()?; self.right.check_local_consistency() } diff --git a/src/TransitionSystems/conjunction.rs b/src/transition_systems/conjunction.rs similarity index 91% rename from src/TransitionSystems/conjunction.rs rename to src/transition_systems/conjunction.rs index 3a32a017..5cfe2d17 100644 --- a/src/TransitionSystems/conjunction.rs +++ b/src/transition_systems/conjunction.rs @@ -1,12 +1,13 @@ use edbm::util::constraints::ClockIndex; -use crate::ModelObjects::Transition; -use crate::System::local_consistency; -use crate::System::query_failures::{ActionFailure, ConsistencyResult, SystemRecipeFailure}; -use crate::TransitionSystems::{ +use crate::model_objects::Transition; +use crate::system::local_consistency; +use crate::system::query_failures::{ActionFailure, ConsistencyResult, SystemRecipeFailure}; +use crate::transition_systems::{ CompositionType, LocationTree, TransitionSystem, TransitionSystemPtr, }; use std::collections::hash_set::HashSet; +use std::rc::Rc; use super::common::ComposedTransitionSystem; @@ -73,7 +74,7 @@ impl Conjunction { } impl ComposedTransitionSystem for Conjunction { - fn next_transitions(&self, location: &LocationTree, action: &str) -> Vec { + fn next_transitions(&self, location: Rc, action: &str) -> Vec { assert!(self.actions_contain(action)); let loc_left = location.get_left(); diff --git a/src/TransitionSystems/location_id.rs b/src/transition_systems/location_id.rs similarity index 96% rename from src/TransitionSystems/location_id.rs rename to src/transition_systems/location_id.rs index 3989c392..43ce3229 100644 --- a/src/TransitionSystems/location_id.rs +++ b/src/transition_systems/location_id.rs @@ -1,6 +1,6 @@ use std::fmt::{Display, Formatter}; -use crate::{ModelObjects::Expressions::SystemExpression, System::specifics::SpecialLocation}; +use crate::{model_objects::expressions::SystemExpression, system::specifics::SpecialLocation}; #[derive(Debug, Clone, Eq, Hash, PartialEq)] pub enum LocationID { @@ -21,7 +21,7 @@ impl LocationID { // A bit of a hack but we use the parser get the a query expression from which we can // determine to composition types needed to construct the location ID // TODO: This is a bit of a hack, but it works for now. - let system = crate::DataReader::parse_queries::parse_to_system_expr(string).unwrap(); + let system = crate::data_reader::parse_queries::parse_to_system_expr(string).unwrap(); system.into() } diff --git a/src/TransitionSystems/location_tree.rs b/src/transition_systems/location_tree.rs similarity index 75% rename from src/TransitionSystems/location_tree.rs rename to src/transition_systems/location_tree.rs index 122eadb9..55259804 100644 --- a/src/TransitionSystems/location_tree.rs +++ b/src/transition_systems/location_tree.rs @@ -1,7 +1,9 @@ +use std::rc::Rc; + use edbm::{util::constraints::ClockIndex, zones::OwnedFederation}; -use crate::EdgeEval::constraint_applyer::apply_constraints_to_state; -use crate::ModelObjects::{Declarations, Location, LocationType}; +use crate::edge_eval::constraint_applier::apply_constraints_to_state; +use crate::model_objects::{Declarations, Location, LocationType}; use super::LocationID; @@ -19,8 +21,8 @@ pub struct LocationTree { /// The invariant for the `Location` pub invariant: Option, loc_type: LocationType, - left: Option>, - right: Option>, + left: Option>, + right: Option>, } impl PartialEq for LocationTree { @@ -30,29 +32,29 @@ impl PartialEq for LocationTree { } impl LocationTree { - pub fn universal() -> Self { - LocationTree { - id: LocationID::Special(crate::System::specifics::SpecialLocation::Universal), + pub fn universal() -> Rc { + Rc::new(LocationTree { + id: LocationID::Special(crate::system::specifics::SpecialLocation::Universal), invariant: None, loc_type: LocationType::Universal, left: None, right: None, - } + }) } - pub fn error(dim: ClockIndex, quotient_clock_index: ClockIndex) -> Self { + pub fn error(dim: ClockIndex, quotient_clock_index: ClockIndex) -> Rc { let inv = OwnedFederation::universe(dim).constrain_eq(quotient_clock_index, 0); - LocationTree { - id: LocationID::Special(crate::System::specifics::SpecialLocation::Error), + Rc::new(LocationTree { + id: LocationID::Special(crate::system::specifics::SpecialLocation::Error), invariant: Some(inv), loc_type: LocationType::Inconsistent, left: None, right: None, - } + }) } - pub fn simple(location: &Location, decls: &Declarations, dim: ClockIndex) -> Self { + pub fn simple(location: &Location, decls: &Declarations, dim: ClockIndex) -> Rc { let invariant = if let Some(inv) = &location.invariant { let mut fed = OwnedFederation::universe(dim); fed = apply_constraints_to_state(inv, decls, fed).unwrap(); @@ -60,45 +62,45 @@ impl LocationTree { } else { None }; - LocationTree { + Rc::new(LocationTree { id: LocationID::Simple(location.id.clone()), invariant, loc_type: location.location_type, left: None, right: None, - } + }) } /// This method is used to a build partial [`LocationTree`]. /// A partial [`LocationTree`] means it has a [`LocationID`] that is [`LocationID::AnyLocation`]. /// A partial [`LocationTree`] has `None` in the field `invariant` since a partial [`LocationTree`] /// covers more than one location, and therefore there is no specific `invariant` - pub fn build_any_location_tree() -> Self { - LocationTree { + pub fn build_any_location_tree() -> Rc { + Rc::new(LocationTree { id: LocationID::AnyLocation, invariant: None, loc_type: LocationType::Any, left: None, right: None, - } + }) } //Merge two locations keeping the invariants seperate - pub fn merge_as_quotient(left: &Self, right: &Self) -> Self { + pub fn merge_as_quotient(left: Rc, right: Rc) -> Rc { let id = LocationID::Quotient(Box::new(left.id.clone()), Box::new(right.id.clone())); let loc_type = left.loc_type.combine(right.loc_type); - LocationTree { + Rc::new(LocationTree { id, invariant: None, loc_type, - left: Some(Box::new(left.clone())), - right: Some(Box::new(right.clone())), - } + left: Some(Rc::clone(&left)), + right: Some(Rc::clone(&right)), + }) } //Compose two locations intersecting the invariants - pub fn compose(left: &Self, right: &Self, comp: CompositionType) -> Self { + pub fn compose(left: Rc, right: Rc, comp: CompositionType) -> Rc { let id = match comp { CompositionType::Conjunction => { LocationID::Conjunction(Box::new(left.id.clone()), Box::new(right.id.clone())) @@ -121,32 +123,33 @@ impl LocationTree { let loc_type = left.loc_type.combine(right.loc_type); - LocationTree { + Rc::new(LocationTree { id, invariant, loc_type, - left: Some(Box::new(left.clone())), - right: Some(Box::new(right.clone())), - } + left: Some(Rc::clone(&left)), + right: Some(Rc::clone(&right)), + }) } pub fn get_invariants(&self) -> Option<&OwnedFederation> { self.invariant.as_ref() } - pub fn apply_invariants(&self, mut fed: OwnedFederation) -> OwnedFederation { + pub fn apply_invariants(&self, fed: OwnedFederation) -> OwnedFederation { if let Some(inv) = &self.invariant { - fed = fed.intersection(inv); + fed.intersection(inv) + } else { + fed } - fed } - pub fn get_left(&self) -> &LocationTree { - self.left.as_ref().unwrap() + pub fn get_left(&self) -> Rc { + Rc::clone(self.left.as_ref().unwrap()) } - pub fn get_right(&self) -> &LocationTree { - self.right.as_ref().unwrap() + pub fn get_right(&self) -> Rc { + Rc::clone(self.right.as_ref().unwrap()) } pub fn is_initial(&self) -> bool { @@ -162,7 +165,7 @@ impl LocationTree { } /// This function is used when you want to compare [`LocationTree`]s that can contain partial locations. - pub fn compare_partial_locations(&self, other: &LocationTree) -> bool { + pub fn compare_partial_locations(&self, other: Rc) -> bool { match (&self.id, &other.id) { (LocationID::Composition(..), LocationID::Composition(..)) | (LocationID::Conjunction(..), LocationID::Conjunction(..)) diff --git a/src/TransitionSystems/mod.rs b/src/transition_systems/mod.rs similarity index 100% rename from src/TransitionSystems/mod.rs rename to src/transition_systems/mod.rs diff --git a/src/TransitionSystems/quotient.rs b/src/transition_systems/quotient.rs similarity index 71% rename from src/TransitionSystems/quotient.rs rename to src/transition_systems/quotient.rs index e80cd494..276ab9db 100644 --- a/src/TransitionSystems/quotient.rs +++ b/src/transition_systems/quotient.rs @@ -2,28 +2,31 @@ use edbm::util::constraints::ClockIndex; use edbm::zones::OwnedFederation; use log::debug; -use crate::EdgeEval::updater::CompiledUpdate; -use crate::ModelObjects::{Declarations, State, Transition}; -use crate::System::query_failures::{ +use crate::edge_eval::updater::CompiledUpdate; +use crate::model_objects::{Declarations, State, Transition}; +use crate::system::query_failures::{ ActionFailure, ConsistencyResult, DeterminismResult, SystemRecipeFailure, }; -use crate::System::specifics::{SpecialLocation, SpecificLocation}; +use crate::system::specifics::{SpecialLocation, SpecificLocation}; use edbm::util::bounds::Bounds; -use crate::TransitionSystems::{LocationTree, TransitionID, TransitionSystem, TransitionSystemPtr}; +use crate::transition_systems::{ + LocationTree, TransitionID, TransitionSystem, TransitionSystemPtr, +}; use std::collections::hash_set::HashSet; +use std::rc::Rc; use std::vec; use super::CompositionType; #[derive(Clone)] pub struct Quotient { - T: TransitionSystemPtr, - S: TransitionSystemPtr, + t: TransitionSystemPtr, + s: TransitionSystemPtr, inputs: HashSet, outputs: HashSet, - universal_location: LocationTree, - inconsistent_location: LocationTree, + universal_location: Rc, + inconsistent_location: Rc, decls: Declarations, quotient_clock_index: ClockIndex, new_input_name: String, @@ -34,25 +37,25 @@ pub struct Quotient { impl Quotient { /// Create a new [TransitionSystem] that is the quotient of `T` and `S`. pub fn new_ts( - T: TransitionSystemPtr, - S: TransitionSystemPtr, + t: TransitionSystemPtr, + s: TransitionSystemPtr, new_clock_index: ClockIndex, dim: ClockIndex, ) -> Result> { - if !S.get_output_actions().is_disjoint(&T.get_input_actions()) { + if !s.get_output_actions().is_disjoint(&t.get_input_actions()) { ActionFailure::not_disjoint( - (S.as_ref(), S.get_output_actions()), - (T.as_ref(), T.get_input_actions()), + (s.as_ref(), s.get_output_actions()), + (t.as_ref(), t.get_input_actions()), ) - .map_err(|e| e.to_rfq(&T, &S))?; + .map_err(|e| e.to_rfq(&t, &s))?; } - T.precheck_sys_rep().map_err(|e| e.to_rfq(&T, &S))?; - S.precheck_sys_rep().map_err(|e| e.to_rfq(&T, &S))?; + t.precheck_sys_rep().map_err(|e| e.to_rfq(&t, &s))?; + s.precheck_sys_rep().map_err(|e| e.to_rfq(&t, &s))?; - let mut inputs: HashSet = T + let mut inputs: HashSet = t .get_input_actions() - .union(&S.get_output_actions()) + .union(&s.get_output_actions()) .cloned() .collect(); let mut i = 0; @@ -66,14 +69,14 @@ impl Quotient { inputs.insert(new_input_name.clone()); - let output_dif: HashSet = T + let output_dif: HashSet = t .get_output_actions() - .difference(&S.get_output_actions()) + .difference(&s.get_output_actions()) .cloned() .collect(); - let input_dif: HashSet = S + let input_dif: HashSet = s .get_input_actions() - .difference(&T.get_input_actions()) + .difference(&t.get_input_actions()) .cloned() .collect(); @@ -87,18 +90,18 @@ impl Quotient { debug!("S//T Inputs: {inputs:?}, Outputs: {outputs:?}"); debug!( "S Inputs: {:?}, Outputs: {:?}", - S.get_input_actions(), - S.get_output_actions() + s.get_input_actions(), + s.get_output_actions() ); debug!( "T Inputs: {:?}, Outputs: {:?}", - T.get_input_actions(), - T.get_output_actions() + t.get_input_actions(), + t.get_output_actions() ); let ts = Box::new(Quotient { - T, - S, + t, + s, inputs, outputs, universal_location: LocationTree::universal(), @@ -122,8 +125,8 @@ impl TransitionSystem for Quotient { let (left, right) = self.get_children(); let loc_l = loc.get_left(); let loc_r = loc.get_right(); - let mut bounds_l = left.get_local_max_bounds(loc_l); - let bounds_r = right.get_local_max_bounds(loc_r); + let mut bounds_l = left.get_local_max_bounds(loc_l.as_ref()); + let bounds_r = right.get_local_max_bounds(loc_r.as_ref()); bounds_l.add_bounds(&bounds_r); bounds_l.add_upper(self.quotient_clock_index, 0); bounds_l @@ -134,7 +137,7 @@ impl TransitionSystem for Quotient { self.dim } - fn next_transitions(&self, location: &LocationTree, action: &str) -> Vec { + fn next_transitions(&self, location: Rc, action: &str) -> Vec { assert!(self.actions_contain(action)); let is_input = self.inputs_contain(action); @@ -161,21 +164,25 @@ impl TransitionSystem for Quotient { // As it is not universal or inconsistent it must be a quotient loc let loc_t = location.get_left(); let loc_s = location.get_right(); - let t = self.T.next_transitions_if_available(loc_t, action); - let s = self.S.next_transitions_if_available(loc_s, action); + let t = self + .t + .next_transitions_if_available(Rc::clone(&loc_t), action); + let s = self + .s + .next_transitions_if_available(Rc::clone(&loc_s), action); //Rule 1 - if self.S.actions_contain(action) && self.T.actions_contain(action) { + if self.s.actions_contain(action) && self.t.actions_contain(action) { for t_transition in &t { for s_transition in &s { // In the following comments we use ϕ to symbolize the guard of the transition // ϕ_T ∧ Inv(l2_t)[r |-> 0] ∧ Inv(l1_t) ∧ ϕ_S ∧ Inv(l2_s)[r |-> 0] ∧ Inv(l1_s) - let guard_zone = get_allowed_fed(loc_t, t_transition) - .intersection(&get_allowed_fed(loc_s, s_transition)); + let guard_zone = get_allowed_fed(loc_t.as_ref(), t_transition) + .intersection(&get_allowed_fed(loc_s.as_ref(), s_transition)); let target_locations = merge( - &t_transition.target_locations, - &s_transition.target_locations, + Rc::clone(&t_transition.target_locations), + Rc::clone(&s_transition.target_locations), ); //Union of left and right updates @@ -196,12 +203,13 @@ impl TransitionSystem for Quotient { } //Rule 2 - if self.S.actions_contain(action) && !self.T.actions_contain(action) { + if self.s.actions_contain(action) && !self.t.actions_contain(action) { //Independent S for s_transition in &s { - let guard_zone = get_allowed_fed(loc_s, s_transition); + let guard_zone = get_allowed_fed(&loc_s, s_transition); - let target_locations = merge(loc_t, &s_transition.target_locations); + let target_locations = + merge(Rc::clone(&loc_t), Rc::clone(&s_transition.target_locations)); let updates = s_transition.updates.clone(); transitions.push(Transition { id: TransitionID::Quotient(Vec::new(), vec![s_transition.id.clone()]), @@ -212,12 +220,12 @@ impl TransitionSystem for Quotient { } } - if self.S.get_output_actions().contains(action) { + if self.s.get_output_actions().contains(action) { // new Rule 3 (includes rule 4 by de-morgan) let mut g_s = OwnedFederation::empty(self.dim); for s_transition in &s { - let allowed_fed = get_allowed_fed(loc_s, s_transition); + let allowed_fed = get_allowed_fed(loc_s.as_ref(), s_transition); g_s += allowed_fed; } @@ -243,20 +251,21 @@ impl TransitionSystem for Quotient { } //Rule 6 - if self.S.get_output_actions().contains(action) - && self.T.get_output_actions().contains(action) + if self.s.get_output_actions().contains(action) + && self.t.get_output_actions().contains(action) { //Calculate inverse G_T let mut g_t = OwnedFederation::empty(self.dim); for t_transition in &t { - g_t = g_t.union(&get_allowed_fed(loc_t, t_transition)); + g_t = g_t.union(&get_allowed_fed(loc_t.as_ref(), t_transition)); } let inverse_g_t = g_t.inverse(); for s_transition in &s { // In the following comments we use ϕ to symbolize the guard of the transition // ϕ_S ∧ Inv(l2_s)[r |-> 0] ∧ Inv(l1_s) ∧ ¬G_T - let guard_zone = get_allowed_fed(loc_s, s_transition).intersection(&inverse_g_t); + let guard_zone = + get_allowed_fed(loc_s.as_ref(), s_transition).intersection(&inverse_g_t); let updates = vec![CompiledUpdate { clock_index: self.quotient_clock_index, @@ -277,8 +286,8 @@ impl TransitionSystem for Quotient { //Rule 7 if action == self.new_input_name { - let inverse_t_invariant = get_invariant(loc_t, self.dim).inverse(); - let s_invariant = get_invariant(loc_s, self.dim); + let inverse_t_invariant = get_invariant(loc_t.as_ref(), self.dim).inverse(); + let s_invariant = get_invariant(loc_s.as_ref(), self.dim); let guard_zone = inverse_t_invariant.intersection(&s_invariant); let updates = vec![CompiledUpdate { @@ -294,13 +303,14 @@ impl TransitionSystem for Quotient { }) } //Rule 8 - if self.T.actions_contain(action) && !self.S.actions_contain(action) { + if self.t.actions_contain(action) && !self.s.actions_contain(action) { for t_transition in &t { - let mut guard_zone = get_allowed_fed(loc_t, t_transition); + let mut guard_zone = get_allowed_fed(loc_t.as_ref(), t_transition); guard_zone = loc_s.apply_invariants(guard_zone); - let target_locations = merge(&t_transition.target_locations, loc_s); + let target_locations = + merge(Rc::clone(&t_transition.target_locations), Rc::clone(&loc_s)); let updates = t_transition.updates.clone(); transitions.push(Transition { @@ -326,22 +336,19 @@ impl TransitionSystem for Quotient { fn get_actions(&self) -> HashSet { self.inputs.union(&self.outputs).cloned().collect() } - fn get_initial_location(&self) -> Option { + fn get_initial_location(&self) -> Option> { let (t, s) = self.get_children(); - Some(merge( - &t.get_initial_location()?, - &s.get_initial_location()?, - )) + Some(merge(t.get_initial_location()?, s.get_initial_location()?)) } - fn get_all_locations(&self) -> Vec { + fn get_all_locations(&self) -> Vec> { let mut location_trees = vec![]; - let left = self.T.get_all_locations(); - let right = self.S.get_all_locations(); + let left = self.t.get_all_locations(); + let right = self.s.get_all_locations(); for loc_t in &left { for loc_s in &right { - let location = merge(loc_t, loc_s); + let location = merge(Rc::clone(loc_t), Rc::clone(loc_s)); location_trees.push(location); } } @@ -353,20 +360,20 @@ impl TransitionSystem for Quotient { } fn get_decls(&self) -> Vec<&Declarations> { - let mut comps = self.T.get_decls(); - comps.extend(self.S.get_decls()); + let mut comps = self.t.get_decls(); + comps.extend(self.s.get_decls()); comps.push(&self.decls); comps } fn check_determinism(&self) -> DeterminismResult { - self.T.check_determinism()?; - self.S.check_determinism() + self.t.check_determinism()?; + self.s.check_determinism() } fn check_local_consistency(&self) -> ConsistencyResult { - self.S.check_local_consistency()?; - self.T.check_local_consistency() + self.s.check_local_consistency()?; + self.t.check_local_consistency() } fn get_initial_state(&self) -> Option { @@ -376,19 +383,22 @@ impl TransitionSystem for Quotient { } fn get_children(&self) -> (&TransitionSystemPtr, &TransitionSystemPtr) { - (&self.T, &self.S) + (&self.t, &self.s) } fn get_composition_type(&self) -> CompositionType { CompositionType::Quotient } - fn construct_location_tree(&self, target: SpecificLocation) -> Result { + fn construct_location_tree( + &self, + target: SpecificLocation, + ) -> Result, String> { match target { SpecificLocation::BranchLocation(left, right, _) => { - let left = self.T.construct_location_tree(*left)?; - let right = self.S.construct_location_tree(*right)?; - Ok(merge(&left, &right)) + let left = self.t.construct_location_tree(*left)?; + let right = self.s.construct_location_tree(*right)?; + Ok(merge(left, right)) } SpecificLocation::SpecialLocation(SpecialLocation::Universal) => { Ok(self.universal_location.clone()) @@ -401,7 +411,7 @@ impl TransitionSystem for Quotient { } } -fn merge(t: &LocationTree, s: &LocationTree) -> LocationTree { +fn merge(t: Rc, s: Rc) -> Rc { LocationTree::merge_as_quotient(t, s) } diff --git a/src/TransitionSystems/transition_id.rs b/src/transition_systems/transition_id.rs similarity index 95% rename from src/TransitionSystems/transition_id.rs rename to src/transition_systems/transition_id.rs index eb8ad89e..f8738227 100644 --- a/src/TransitionSystems/transition_id.rs +++ b/src/transition_systems/transition_id.rs @@ -16,7 +16,7 @@ impl TransitionID { /// Returns a vector of transitionIDs for all components involved in the transition /// For example /// ``` - /// use crate::reveaal::TransitionSystems::TransitionID; + /// use crate::reveaal::transition_systems::TransitionID; /// let id = TransitionID::Conjunction( /// Box::new(TransitionID::Simple("a".to_string())), /// Box::new(TransitionID::Simple("b".to_string()))); @@ -64,7 +64,7 @@ impl TransitionID { /// Takes a path of TransitionIDs, and splits them into seperate paths for each component /// For example /// ``` - /// use crate::reveaal::TransitionSystems::TransitionID; + /// use crate::reveaal::transition_systems::TransitionID; /// let path = /// vec![ /// TransitionID::Conjunction( @@ -95,17 +95,17 @@ impl TransitionID { let amount = leaves.len(); let mut paths: Vec>> = vec![Vec::new(); leaves.len()]; - for transitionID in path { - let leaves = transitionID.get_leaves(); - for (componentIndex, transition) in leaves.iter().enumerate() { + for transition_id in path { + let leaves = transition_id.get_leaves(); + for (component_index, transition) in leaves.iter().enumerate() { if leaves.len() != amount { return Err(format!("Could not split into components because first transition has {} components but {:?} has {} components", amount, leaves, leaves.len())); } - paths[componentIndex].push( + paths[component_index].push( transition .iter() - .cloned() .filter(|id| !matches!(id, TransitionID::None)) + .cloned() .collect(), ); } diff --git a/src/TransitionSystems/transition_system.rs b/src/transition_systems/transition_system.rs similarity index 89% rename from src/TransitionSystems/transition_system.rs rename to src/transition_systems/transition_system.rs index 11b3ae6c..81950a11 100644 --- a/src/TransitionSystems/transition_system.rs +++ b/src/transition_systems/transition_system.rs @@ -1,13 +1,13 @@ use super::ComponentInfo; use super::{CompositionType, LocationID, LocationTree}; +use crate::edge_eval::updater::CompiledUpdate; +use crate::model_objects::{Component, Declarations, State, Transition}; use crate::parse_queries::parse_to_system_expr; -use crate::EdgeEval::updater::CompiledUpdate; -use crate::ModelObjects::{Component, Declarations, State, Transition}; -use crate::System::query_failures::{ConsistencyResult, DeterminismResult}; -use crate::System::specifics::SpecificLocation; +use crate::system::query_failures::{ConsistencyResult, DeterminismResult}; +use crate::system::specifics::SpecificLocation; use crate::{ - extract_system_rep::get_system_recipe, ComponentLoader, - DataReader::component_loader::ComponentContainer, + data_reader::component_loader::ComponentContainer, extract_system_rep::get_system_recipe, + ComponentLoader, }; use dyn_clone::{clone_trait_object, DynClone}; use edbm::util::{bounds::Bounds, constraints::ClockIndex}; @@ -15,6 +15,7 @@ use std::collections::hash_map::Entry; use std::collections::vec_deque::VecDeque; use std::collections::{hash_set::HashSet, HashMap}; use std::hash::Hash; +use std::rc::Rc; pub type TransitionSystemPtr = Box; pub type Action = String; @@ -63,7 +64,7 @@ pub trait TransitionSystem: DynClone { fn next_transitions_if_available( &self, - location: &LocationTree, + location: Rc, action: &str, ) -> Vec { if self.actions_contain(action) { @@ -73,14 +74,14 @@ pub trait TransitionSystem: DynClone { } } - fn next_transitions(&self, location: &LocationTree, action: &str) -> Vec; + fn next_transitions(&self, location: Rc, action: &str) -> Vec; - fn next_outputs(&self, location: &LocationTree, action: &str) -> Vec { + fn next_outputs(&self, location: Rc, action: &str) -> Vec { debug_assert!(self.get_output_actions().contains(action)); self.next_transitions(location, action) } - fn next_inputs(&self, location: &LocationTree, action: &str) -> Vec { + fn next_inputs(&self, location: Rc, action: &str) -> Vec { debug_assert!(self.get_input_actions().contains(action)); self.next_transitions(location, action) } @@ -103,14 +104,14 @@ pub trait TransitionSystem: DynClone { self.get_actions().contains(action) } - fn get_initial_location(&self) -> Option; + fn get_initial_location(&self) -> Option>; /// Function to get all locations from a [`TransitionSystem`] /// #### Warning /// This function utilizes a lot of memory. Use with caution - fn get_all_locations(&self) -> Vec; + fn get_all_locations(&self) -> Vec>; - fn get_location(&self, id: &LocationID) -> Option { + fn get_location(&self, id: &LocationID) -> Option> { self.get_all_locations() .iter() .find(|loc| loc.id == *id) @@ -163,7 +164,7 @@ pub trait TransitionSystem: DynClone { left_child .component_names() .into_iter() - .chain(right_child.component_names().into_iter()) + .chain(right_child.component_names()) .collect() } @@ -179,8 +180,12 @@ pub trait TransitionSystem: DynClone { ///Helper function to recursively traverse all transitions in a transitions system ///in order to find all transitions and location in the transition system, and ///saves these as [ClockAnalysisEdge]s and [ClockAnalysisNode]s in the [ClockAnalysisGraph] - fn find_edges_and_nodes(&self, init_location: LocationTree, graph: &mut ClockAnalysisGraph) { - let mut worklist = VecDeque::from([init_location]); + fn find_edges_and_nodes( + &self, + init_location: Rc, + graph: &mut ClockAnalysisGraph, + ) { + let mut worklist: VecDeque> = VecDeque::from([init_location]); let actions = self.get_actions(); while let Some(location) = worklist.pop_front() { //Constructs a node to represent this location and add it to the graph. @@ -203,7 +208,7 @@ pub trait TransitionSystem: DynClone { //Constructs an edge to represent each transition from this graph and add it to the graph. for action in &actions { - for transition in self.next_transitions_if_available(&location, action) { + for transition in self.next_transitions_if_available(Rc::clone(&location), action) { let mut edge = ClockAnalysisEdge { from: location.id.get_unique_string(), to: transition.target_locations.id.get_unique_string(), @@ -238,7 +243,8 @@ pub trait TransitionSystem: DynClone { self.get_analysis_graph().find_clock_redundancies() } - fn construct_location_tree(&self, target: SpecificLocation) -> Result; + fn construct_location_tree(&self, target: SpecificLocation) + -> Result, String>; } /// Returns a [`TransitionSystemPtr`] equivalent to a `composition` of some `components`. @@ -258,6 +264,7 @@ pub fn component_loader_to_transition_system( let mut dimension = 0; let sys_expr = parse_to_system_expr(composition).unwrap(); get_system_recipe(&sys_expr, loader, &mut dimension, &mut None) + .unwrap() .compile(dimension) .unwrap() } @@ -273,22 +280,6 @@ pub enum ClockReductionInstruction { }, } -impl ClockReductionInstruction { - pub(crate) fn clocks_removed_count(&self) -> usize { - match self { - ClockReductionInstruction::RemoveClock { .. } => 1, - ClockReductionInstruction::ReplaceClocks { clock_indices, .. } => clock_indices.len(), - } - } - - pub(crate) fn get_clock_index(&self) -> ClockIndex { - match self { - ClockReductionInstruction::RemoveClock { clock_index } - | ClockReductionInstruction::ReplaceClocks { clock_index, .. } => *clock_index, - } - } -} - #[derive(Debug)] pub struct ClockAnalysisNode { pub invariant_dependencies: HashSet, @@ -415,10 +406,10 @@ impl ClockAnalysisGraph { equivalent_clock_groups.iter_mut().enumerate() { for clock in equivalent_clock_group.iter() { - if let Some(groupId) = locally_equivalent_clock_groups.get(clock) { + if let Some(group_id) = locally_equivalent_clock_groups.get(clock) { ClockAnalysisGraph::get_or_insert( &mut new_groups, - group_offset + ((*groupId) as usize), + group_offset + *group_id as usize, ) .insert(*clock); } else {