flamapy-z3 2.6.0.dev1__tar.gz → 2.6.0.dev2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev2}/PKG-INFO +4 -4
  2. {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev2}/flamapy/metamodels/z3_metamodel/operations/__init__.py +3 -0
  3. flamapy_z3-2.6.0.dev2/flamapy/metamodels/z3_metamodel/operations/z3_backbone.py +70 -0
  4. {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev2}/flamapy/metamodels/z3_metamodel/operations/z3_core_features.py +2 -16
  5. {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev2}/flamapy/metamodels/z3_metamodel/operations/z3_dead_features.py +2 -16
  6. {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev2}/flamapy/metamodels/z3_metamodel/transformations/fm_to_z3.py +6 -6
  7. {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev2}/flamapy_z3.egg-info/PKG-INFO +4 -4
  8. {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev2}/flamapy_z3.egg-info/SOURCES.txt +1 -0
  9. {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev2}/flamapy_z3.egg-info/requires.txt +2 -2
  10. {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev2}/pyproject.toml +5 -5
  11. {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev2}/tests/test_z3_metamodel.py +2 -1
  12. {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev2}/README.md +0 -0
  13. {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev2}/flamapy/metamodels/z3_metamodel/__init__.py +0 -0
  14. {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev2}/flamapy/metamodels/z3_metamodel/models/__init__.py +0 -0
  15. {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev2}/flamapy/metamodels/z3_metamodel/models/z3_model.py +0 -0
  16. {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev2}/flamapy/metamodels/z3_metamodel/operations/interfaces/__init__.py +0 -0
  17. {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev2}/flamapy/metamodels/z3_metamodel/operations/interfaces/attribute_optimization.py +0 -0
  18. {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev2}/flamapy/metamodels/z3_metamodel/operations/z3_all_feature_bounds.py +0 -0
  19. {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev2}/flamapy/metamodels/z3_metamodel/operations/z3_attribute_optimization.py +0 -0
  20. {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev2}/flamapy/metamodels/z3_metamodel/operations/z3_configurations.py +0 -0
  21. {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev2}/flamapy/metamodels/z3_metamodel/operations/z3_configurations_number.py +0 -0
  22. {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev2}/flamapy/metamodels/z3_metamodel/operations/z3_false_optional_features.py +0 -0
  23. {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev2}/flamapy/metamodels/z3_metamodel/operations/z3_feature_bounds.py +0 -0
  24. {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev2}/flamapy/metamodels/z3_metamodel/operations/z3_satisfiable.py +0 -0
  25. {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev2}/flamapy/metamodels/z3_metamodel/operations/z3_satisfiable_configuration.py +0 -0
  26. {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev2}/flamapy/metamodels/z3_metamodel/operations/z3_variable_bounds_complex.py +0 -0
  27. {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev2}/flamapy/metamodels/z3_metamodel/transformations/__init__.py +0 -0
  28. {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev2}/flamapy_z3.egg-info/dependency_links.txt +0 -0
  29. {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev2}/flamapy_z3.egg-info/top_level.txt +0 -0
  30. {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev2}/setup.cfg +0 -0
  31. {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev2}/setup.py +0 -0
@@ -1,14 +1,14 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flamapy-z3
3
- Version: 2.6.0.dev1
3
+ Version: 2.6.0.dev2
4
4
  Summary: z3-plugin for the automated analysis of feature models
5
5
  Author-email: Flamapy <flamapy@us.es>
6
6
  License-Expression: GPL-3.0-or-later
7
7
  Project-URL: Homepage, https://github.com/flamapy/z3_metamodel
8
- Requires-Python: >=3.9
8
+ Requires-Python: >=3.11
9
9
  Description-Content-Type: text/markdown
10
- Requires-Dist: flamapy-fw~=2.6.0.dev1
11
- Requires-Dist: flamapy-fm~=2.6.0.dev1
10
+ Requires-Dist: flamapy-fw~=2.6.0.dev2
11
+ Requires-Dist: flamapy-fm~=2.6.0.dev2
12
12
  Requires-Dist: z3-solver~=4.14.1.0
13
13
  Provides-Extra: dev
14
14
  Requires-Dist: pytest; extra == "dev"
@@ -1,6 +1,7 @@
1
1
  from .z3_satisfiable import Z3Satisfiable
2
2
  from .z3_configurations import Z3Configurations
3
3
  from .z3_configurations_number import Z3ConfigurationsNumber
4
+ from .z3_backbone import Z3Backbone
4
5
  from .z3_core_features import Z3CoreFeatures
5
6
  from .z3_dead_features import Z3DeadFeatures
6
7
  from .z3_false_optional_features import Z3FalseOptionalFeatures
@@ -9,9 +10,11 @@ from .z3_satisfiable_configuration import Z3SatisfiableConfiguration
9
10
  from .z3_feature_bounds import Z3FeatureBounds
10
11
  from .z3_all_feature_bounds import Z3AllFeatureBounds
11
12
 
13
+
12
14
  __all__ = [
13
15
  'Z3AllFeatureBounds',
14
16
  'Z3AttributeOptimization',
17
+ 'Z3Backbone',
15
18
  'Z3Configurations',
16
19
  'Z3ConfigurationsNumber',
17
20
  'Z3CoreFeatures',
@@ -0,0 +1,70 @@
1
+ from typing import Any, cast
2
+
3
+ import z3
4
+
5
+ from flamapy.core.models import VariabilityModel
6
+ from flamapy.core.operations import Operation
7
+ from flamapy.metamodels.z3_metamodel.models import Z3Model
8
+
9
+
10
+ class Z3Backbone(Operation):
11
+
12
+ def __init__(self) -> None:
13
+ self._result: dict[str, list[Any]] = {"core": [], "dead": []}
14
+
15
+ def get_backbone(self) -> dict[str, list[Any]]:
16
+ return self.get_result()
17
+
18
+ def get_result(self) -> dict[str, list[Any]]:
19
+ return self._result
20
+
21
+ def execute(self, model: VariabilityModel) -> 'Z3Backbone':
22
+ z3_model = cast(Z3Model, model)
23
+ self._result = get_backbone(z3_model)
24
+ return self
25
+
26
+
27
+ def get_backbone(model: Z3Model) -> dict[str, list[Any]]:
28
+ solver = z3.Solver(ctx=model.ctx)
29
+ solver.add(model.constraints)
30
+
31
+ vars_to_features = {f_info.sel: name for name, f_info in model.features.items()}
32
+
33
+ # (out, C) <- SAT(phi)
34
+ if solver.check() != z3.sat:
35
+ return {"core": [], "dead": list(model.features.keys())}
36
+
37
+ m = solver.model()
38
+ # C <- filter(C)
39
+ core_candidates = {var for var in vars_to_features.keys() if z3.is_true(m[var])}
40
+ dead_candidates = {var for var in vars_to_features.keys() if z3.is_false(m[var])}
41
+
42
+ backbone_core = []
43
+ backbone_dead = []
44
+
45
+ while core_candidates or dead_candidates:
46
+ if core_candidates:
47
+ literal = next(iter(core_candidates))
48
+ check_lit = z3.Not(literal)
49
+ is_core = True
50
+ else:
51
+ literal = next(iter(dead_candidates))
52
+ check_lit = literal
53
+ is_core = False
54
+
55
+ # (out, S) <- SAT(phi U {not l})
56
+ if solver.check([check_lit]) == z3.unsat:
57
+ if is_core:
58
+ backbone_core.append(vars_to_features[literal])
59
+ solver.add(literal)
60
+ core_candidates.remove(literal)
61
+ else:
62
+ backbone_dead.append(vars_to_features[literal])
63
+ solver.add(z3.Not(literal))
64
+ dead_candidates.remove(literal)
65
+ else:
66
+ new_model = solver.model()
67
+ core_candidates = {var for var in core_candidates if z3.is_true(new_model[var])}
68
+ dead_candidates = {var for var in dead_candidates if z3.is_false(new_model[var])}
69
+
70
+ return {"core": backbone_core, "dead": backbone_dead}
@@ -1,10 +1,9 @@
1
1
  from typing import Any, cast
2
2
 
3
- import z3
4
-
5
3
  from flamapy.core.models import VariabilityModel
6
4
  from flamapy.core.operations import CoreFeatures
7
5
  from flamapy.metamodels.z3_metamodel.models import Z3Model
6
+ from flamapy.metamodels.z3_metamodel.operations import Z3Backbone
8
7
 
9
8
 
10
9
  class Z3CoreFeatures(CoreFeatures):
@@ -20,18 +19,5 @@ class Z3CoreFeatures(CoreFeatures):
20
19
 
21
20
  def execute(self, model: VariabilityModel) -> 'Z3CoreFeatures':
22
21
  z3_model = cast(Z3Model, model)
23
- self._result = get_core_features(z3_model)
22
+ self._result = Z3Backbone().execute(z3_model).get_result()["core"]
24
23
  return self
25
-
26
-
27
- def get_core_features(model: Z3Model) -> list[Any]:
28
- solver = z3.Solver(ctx=model.ctx)
29
- solver.add(model.constraints)
30
-
31
- core_features = []
32
- if solver.check() == z3.sat:
33
- for feature, feature_info in model.features.items():
34
- variable = feature_info.sel
35
- if solver.check([z3.Not(variable)]) == z3.unsat:
36
- core_features.append(feature)
37
- return core_features
@@ -1,10 +1,9 @@
1
1
  from typing import Any, cast
2
2
 
3
- import z3
4
-
5
3
  from flamapy.core.models import VariabilityModel
6
4
  from flamapy.core.operations import DeadFeatures
7
5
  from flamapy.metamodels.z3_metamodel.models import Z3Model
6
+ from flamapy.metamodels.z3_metamodel.operations import Z3Backbone
8
7
 
9
8
 
10
9
  class Z3DeadFeatures(DeadFeatures):
@@ -20,18 +19,5 @@ class Z3DeadFeatures(DeadFeatures):
20
19
 
21
20
  def execute(self, model: VariabilityModel) -> 'Z3DeadFeatures':
22
21
  z3_model = cast(Z3Model, model)
23
- self._result = get_dead_features(z3_model)
22
+ self._result = Z3Backbone().execute(z3_model).get_result()["dead"]
24
23
  return self
25
-
26
-
27
- def get_dead_features(model: Z3Model) -> list[Any]:
28
- solver = z3.Solver(ctx=model.ctx)
29
- solver.add(model.constraints)
30
-
31
- dead_features = []
32
- if solver.check() == z3.sat:
33
- for feature, feature_info in model.features.items():
34
- variable = feature_info.sel
35
- if solver.check([variable]) == z3.unsat:
36
- dead_features.append(feature)
37
- return dead_features
@@ -195,7 +195,6 @@ class FmToZ3(ModelToModel):
195
195
  self.destination_model.add_constraint(formula)
196
196
 
197
197
  def _add_mutex_formula(self, relation: Relation) -> None:
198
- formulas = []
199
198
  parent_variable = self.destination_model.get_variable(relation.parent.name)
200
199
  if parent_variable is None:
201
200
  raise FlamaException(f'Unsupported feature: {relation.parent.name}')
@@ -206,12 +205,13 @@ class FmToZ3(ModelToModel):
206
205
  if child_variable is None:
207
206
  raise FlamaException(f'Unsupported feature: {child.name}')
208
207
  children.add(child_variable.sel)
208
+ one_child_formula = []
209
209
  for child in children:
210
- children_negatives = children - {child}
211
- formula = (child == z3.And([z3.Not(ch) for ch in children_negatives] + [parent]))
212
- formulas.append(formula)
213
- formula = z3.And(*formulas)
214
- formula = z3.Or(parent == z3.Not(z3.Or(*children)), formula)
210
+ other_children_or = z3.Or(*list(children - {child}))
211
+ one_child_formula.append(z3.Not(child) == other_children_or)
212
+ one_child_formula = z3.And(*one_child_formula)
213
+ no_child_formula = z3.And(*[z3.Not(ch) for ch in children])
214
+ formula = z3.Or(no_child_formula, z3.And(one_child_formula, parent))
215
215
  self.destination_model.add_constraint(formula)
216
216
 
217
217
  def _build_literals(self, children: list[Any], combination: tuple[Any, ...]) -> list[Any]:
@@ -1,14 +1,14 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flamapy-z3
3
- Version: 2.6.0.dev1
3
+ Version: 2.6.0.dev2
4
4
  Summary: z3-plugin for the automated analysis of feature models
5
5
  Author-email: Flamapy <flamapy@us.es>
6
6
  License-Expression: GPL-3.0-or-later
7
7
  Project-URL: Homepage, https://github.com/flamapy/z3_metamodel
8
- Requires-Python: >=3.9
8
+ Requires-Python: >=3.11
9
9
  Description-Content-Type: text/markdown
10
- Requires-Dist: flamapy-fw~=2.6.0.dev1
11
- Requires-Dist: flamapy-fm~=2.6.0.dev1
10
+ Requires-Dist: flamapy-fw~=2.6.0.dev2
11
+ Requires-Dist: flamapy-fm~=2.6.0.dev2
12
12
  Requires-Dist: z3-solver~=4.14.1.0
13
13
  Provides-Extra: dev
14
14
  Requires-Dist: pytest; extra == "dev"
@@ -7,6 +7,7 @@ flamapy/metamodels/z3_metamodel/models/z3_model.py
7
7
  flamapy/metamodels/z3_metamodel/operations/__init__.py
8
8
  flamapy/metamodels/z3_metamodel/operations/z3_all_feature_bounds.py
9
9
  flamapy/metamodels/z3_metamodel/operations/z3_attribute_optimization.py
10
+ flamapy/metamodels/z3_metamodel/operations/z3_backbone.py
10
11
  flamapy/metamodels/z3_metamodel/operations/z3_configurations.py
11
12
  flamapy/metamodels/z3_metamodel/operations/z3_configurations_number.py
12
13
  flamapy/metamodels/z3_metamodel/operations/z3_core_features.py
@@ -1,5 +1,5 @@
1
- flamapy-fw~=2.6.0.dev1
2
- flamapy-fm~=2.6.0.dev1
1
+ flamapy-fw~=2.6.0.dev2
2
+ flamapy-fm~=2.6.0.dev2
3
3
  z3-solver~=4.14.1.0
4
4
 
5
5
  [dev]
@@ -4,15 +4,15 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "flamapy-z3"
7
- version = "2.6.0.dev1"
7
+ version = "2.6.0.dev2"
8
8
  description = "z3-plugin for the automated analysis of feature models"
9
9
  readme = "README.md"
10
10
  license = "GPL-3.0-or-later"
11
11
  authors = [{ name = "Flamapy", email = "flamapy@us.es" }]
12
- requires-python = ">=3.9"
12
+ requires-python = ">=3.11"
13
13
  dependencies = [
14
- "flamapy-fw~=2.6.0.dev1",
15
- "flamapy-fm~=2.6.0.dev1",
14
+ "flamapy-fw~=2.6.0.dev2",
15
+ "flamapy-fm~=2.6.0.dev2",
16
16
  "z3-solver~=4.14.1.0",
17
17
  ]
18
18
 
@@ -33,7 +33,7 @@ include = ["flamapy.*"]
33
33
 
34
34
  [tool.ruff]
35
35
  line-length = 100
36
- target-version = "py39"
36
+ target-version = "py311"
37
37
 
38
38
  [tool.ruff.lint]
39
39
  select = ["E", "W", "F", "C", "PL", "RUF"]
@@ -53,7 +53,8 @@ def test_z3_satisfiable(path: str, expected: bool):
53
53
  ('resources/models/uvl_models/fm09_real_bounded.uvl', 6),
54
54
  ('resources/models/uvl_models/fm10_real_conditional_bounded.uvl', 3),
55
55
  ('resources/models/uvl_models/icecream_attributes.uvl', 15),
56
- ('resources/models/uvl_models/group_cardinalities.uvl', 16)
56
+ ('resources/models/uvl_models/group_cardinalities.uvl', 16),
57
+ ('resources/models/uvl_models/mutex.uvl', 6)
57
58
  ])
58
59
  def test_nconfigs(path: str, expected: int):
59
60
  z3_model = _read_model(path)