1
use oxidd::BooleanFunction;
2
use oxidd::bdd::BDDFunction;
3
use oxidd::util::OptBool;
4

            
5
use merc_symbolic::CubeIterAll;
6
use merc_utilities::MercError;
7

            
8
use crate::PG;
9
use crate::ParityGame;
10
use crate::VariabilityParityGame;
11

            
12
/// Projects a variability parity game into a standard parity game by removing
13
/// edges that are not enabled by the given feature selection.
14
753
pub fn project_variability_parity_game(
15
753
    vpg: &VariabilityParityGame,
16
753
    feature_selection: &BDDFunction,
17
753
) -> Result<ParityGame, MercError> {
18
753
    let mut edges = Vec::new();
19

            
20
16566
    for v in vpg.iter_vertices() {
21
24322
        for edge in vpg.outgoing_conf_edges(v) {
22
            // Check if the edge is enabled by the feature selection, if so, include it.
23
24322
            if feature_selection.and(edge.configuration())?.satisfiable() {
24
22675
                edges.push((v, edge.to()));
25
22675
            }
26
        }
27
    }
28

            
29
753
    Ok(ParityGame::from_edges(
30
753
        vpg.initial_vertex(),
31
753
        vpg.owners().clone(),
32
753
        vpg.priorities().clone(),
33
        true, // It can be that after removing edges the result is not a total parity game.
34
1506
        || edges.iter().cloned(),
35
    ))
36
753
}
37

            
38
/// Projects all configurations of a variability parity game into standard parity games.
39
100
pub fn project_variability_parity_games_iter(
40
100
    vpg: &VariabilityParityGame,
41
100
) -> impl Iterator<Item = Result<(Vec<OptBool>, BDDFunction, ParityGame), MercError>> {
42
753
    CubeIterAll::new(vpg.variables(), vpg.configuration()).map(|cube| {
43
753
        let (cube, bdd) = cube?;
44
753
        let pg = project_variability_parity_game(vpg, &bdd)?;
45
753
        Ok((cube, bdd, pg))
46
753
    })
47
100
}