-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathacceptance_variants.py
More file actions
128 lines (102 loc) · 4.46 KB
/
acceptance_variants.py
File metadata and controls
128 lines (102 loc) · 4.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
from itertools import permutations
from typing import List, Tuple, Dict, Set
from dependencies import (
TemporalType,
ExistentialType,
TemporalDependency,
ExistentialDependency,
Direction,
)
from adjacency_matrix import AdjacencyMatrix
from constraint_logic import check_temporal_relationship, check_existential_relationship
def satisfies_existential_constraints(
subset: Set[str],
activities: List[str],
existential_dependencies: Dict[Tuple[str, str], ExistentialDependency],
) -> bool:
"""
Checks if a subset of activities satisfies all existential constraints.
"""
for (ai, aj), dependency in existential_dependencies.items():
if dependency.type == ExistentialType.INDEPENDENCE:
continue
in_subset_ai = ai in subset
in_subset_aj = aj in subset
dep_type = dependency.type
if not check_existential_relationship(
in_subset_ai, in_subset_aj, dep_type, dependency.direction
):
return False
return True
def build_permutations(subset: Set[str]) -> List[List[str]]:
"""
Generates all possible orderings (permutations) of activities in a subset.
"""
if not subset:
return [[]]
return [list(p) for p in permutations(subset)]
def satisfies_temporal_constraints(
variant: List[str],
temporal_dependencies: Dict[Tuple[str, str], TemporalDependency],
) -> bool:
"""
Checks if a variant of activities satisfies all temporal constraints.
"""
if not variant: # An empty variant has no temporal constraints to violate
return True
activity_to_pos = {activity: i for i, activity in enumerate(variant)}
for i in range(len(variant)):
for j in range(len(variant)):
if i == j:
continue
ai = variant[i]
aj = variant[j]
dependency = temporal_dependencies.get((ai, aj))
if not dependency or dependency.type == TemporalType.INDEPENDENCE:
continue # No constraint or independence means satisfied
pos_ai = activity_to_pos[ai]
pos_aj = activity_to_pos[aj]
dep_type = dependency.type
if not check_temporal_relationship(
pos_ai, pos_aj, dep_type, dependency.direction
):
return False
return True
def generate_acceptance_variants(adj_matrix: AdjacencyMatrix) -> List[List[str]]:
"""
Generates all valid acceptance variants from an adjacency matrix.
"""
activities = adj_matrix.activities
temporal_deps: Dict[Tuple[str, str], TemporalDependency] = {}
existential_deps: Dict[Tuple[str, str], ExistentialDependency] = {}
for (source, target), (temp_dep, exist_dep) in adj_matrix.dependencies.items():
if temp_dep:
temporal_deps[(source, target)] = temp_dep
if exist_dep:
existential_deps[(source, target)] = exist_dep
acceptance_variants = []
n = len(activities)
for i in range(1, 1 << n): # 2^n subsets, skip empty set
current_subset_indices = []
for j in range(n):
if (i >> j) & 1: # Check if j-th bit is set
current_subset_indices.append(j)
current_subset_activities = {activities[k] for k in current_subset_indices}
if satisfies_existential_constraints(
current_subset_activities, activities, existential_deps
):
permutations_of_subset = build_permutations(current_subset_activities)
for seq in permutations_of_subset:
if satisfies_temporal_constraints(seq, temporal_deps):
acceptance_variants.append(seq)
return acceptance_variants
# if __name__ == "__main__":
# adj_matrix = AdjacencyMatrix(activities=["A", "B", "C", "D", "E"])
# adj_matrix.add_dependency("A", "B", TemporalDependency(TemporalType.DIRECT), ExistentialDependency(ExistentialType.IMPLICATION))
# adj_matrix.add_dependency("B", "C", TemporalDependency(TemporalType.EVENTUAL), ExistentialDependency(ExistentialType.EQUIVALENCE))
# adj_matrix.add_dependency("C", "D", TemporalDependency(TemporalType.INDEPENDENCE), ExistentialDependency(ExistentialType.NAND))
# adj_matrix.add_dependency("D", "E", TemporalDependency(TemporalType.DIRECT), ExistentialDependency(ExistentialType.INDEPENDENCE))
# acceptance_vars = generate_acceptance_variants(adj_matrix)
# print("Generated Acceptance Variants:")
# for var in acceptance_vars:
# print(var)