flamapy-z3 2.6.0.dev1__tar.gz → 2.6.0.dev3__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.
- {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/PKG-INFO +4 -4
- {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/flamapy/metamodels/z3_metamodel/operations/__init__.py +3 -0
- flamapy_z3-2.6.0.dev3/flamapy/metamodels/z3_metamodel/operations/z3_backbone.py +70 -0
- {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/flamapy/metamodels/z3_metamodel/operations/z3_core_features.py +2 -16
- {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/flamapy/metamodels/z3_metamodel/operations/z3_dead_features.py +2 -16
- {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/flamapy/metamodels/z3_metamodel/transformations/fm_to_z3.py +6 -6
- {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/flamapy_z3.egg-info/PKG-INFO +4 -4
- {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/flamapy_z3.egg-info/SOURCES.txt +1 -0
- {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/flamapy_z3.egg-info/requires.txt +2 -2
- {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/pyproject.toml +5 -5
- {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/tests/test_z3_metamodel.py +2 -1
- {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/README.md +0 -0
- {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/flamapy/metamodels/z3_metamodel/__init__.py +0 -0
- {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/flamapy/metamodels/z3_metamodel/models/__init__.py +0 -0
- {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/flamapy/metamodels/z3_metamodel/models/z3_model.py +0 -0
- {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/flamapy/metamodels/z3_metamodel/operations/interfaces/__init__.py +0 -0
- {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/flamapy/metamodels/z3_metamodel/operations/interfaces/attribute_optimization.py +0 -0
- {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/flamapy/metamodels/z3_metamodel/operations/z3_all_feature_bounds.py +0 -0
- {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/flamapy/metamodels/z3_metamodel/operations/z3_attribute_optimization.py +0 -0
- {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/flamapy/metamodels/z3_metamodel/operations/z3_configurations.py +0 -0
- {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/flamapy/metamodels/z3_metamodel/operations/z3_configurations_number.py +0 -0
- {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/flamapy/metamodels/z3_metamodel/operations/z3_false_optional_features.py +0 -0
- {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/flamapy/metamodels/z3_metamodel/operations/z3_feature_bounds.py +0 -0
- {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/flamapy/metamodels/z3_metamodel/operations/z3_satisfiable.py +0 -0
- {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/flamapy/metamodels/z3_metamodel/operations/z3_satisfiable_configuration.py +0 -0
- {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/flamapy/metamodels/z3_metamodel/operations/z3_variable_bounds_complex.py +0 -0
- {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/flamapy/metamodels/z3_metamodel/transformations/__init__.py +0 -0
- {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/flamapy_z3.egg-info/dependency_links.txt +0 -0
- {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/flamapy_z3.egg-info/top_level.txt +0 -0
- {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/setup.cfg +0 -0
- {flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/setup.py +0 -0
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flamapy-z3
|
|
3
|
-
Version: 2.6.0.
|
|
3
|
+
Version: 2.6.0.dev3
|
|
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.
|
|
8
|
+
Requires-Python: >=3.11
|
|
9
9
|
Description-Content-Type: text/markdown
|
|
10
|
-
Requires-Dist: flamapy-fw~=2.6.0.
|
|
11
|
-
Requires-Dist: flamapy-fm~=2.6.0.
|
|
10
|
+
Requires-Dist: flamapy-fw~=2.6.0.dev3
|
|
11
|
+
Requires-Dist: flamapy-fm~=2.6.0.dev3
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
formula = z3.Or(
|
|
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.
|
|
3
|
+
Version: 2.6.0.dev3
|
|
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.
|
|
8
|
+
Requires-Python: >=3.11
|
|
9
9
|
Description-Content-Type: text/markdown
|
|
10
|
-
Requires-Dist: flamapy-fw~=2.6.0.
|
|
11
|
-
Requires-Dist: flamapy-fm~=2.6.0.
|
|
10
|
+
Requires-Dist: flamapy-fw~=2.6.0.dev3
|
|
11
|
+
Requires-Dist: flamapy-fm~=2.6.0.dev3
|
|
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
|
|
@@ -4,15 +4,15 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "flamapy-z3"
|
|
7
|
-
version = "2.6.0.
|
|
7
|
+
version = "2.6.0.dev3"
|
|
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.
|
|
12
|
+
requires-python = ">=3.11"
|
|
13
13
|
dependencies = [
|
|
14
|
-
"flamapy-fw~=2.6.0.
|
|
15
|
-
"flamapy-fm~=2.6.0.
|
|
14
|
+
"flamapy-fw~=2.6.0.dev3",
|
|
15
|
+
"flamapy-fm~=2.6.0.dev3",
|
|
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 = "
|
|
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)
|
|
File without changes
|
|
File without changes
|
{flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/flamapy/metamodels/z3_metamodel/models/__init__.py
RENAMED
|
File without changes
|
{flamapy_z3-2.6.0.dev1 → flamapy_z3-2.6.0.dev3}/flamapy/metamodels/z3_metamodel/models/z3_model.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|