flamapy-fm 2.6.0.dev5__tar.gz → 2.6.0.dev7__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_fm-2.6.0.dev5/flamapy_fm.egg-info → flamapy_fm-2.6.0.dev7}/PKG-INFO +1 -1
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/operations/__init__.py +2 -0
- flamapy_fm-2.6.0.dev7/flamapy/metamodels/fm_metamodel/operations/fm_generate_random_feature_model.py +100 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7/flamapy_fm.egg-info}/PKG-INFO +1 -1
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy_fm.egg-info/SOURCES.txt +1 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/pyproject.toml +1 -1
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/LICENSE +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/README.md +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/__init__.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/models/__init__.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/models/feature_model.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/operations/fm_atomic_sets.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/operations/fm_average_branching_factor.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/operations/fm_core_features.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/operations/fm_count_leafs.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/operations/fm_estimated_configurations_number.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/operations/fm_feature_ancestors.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/operations/fm_generate_random_attribute.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/operations/fm_language_level.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/operations/fm_leaf_features.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/operations/fm_max_depth_tree.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/operations/fm_metrics.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/operations/fm_variation_points.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/operations/interfaces/__init__.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/operations/interfaces/variation_points.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/__init__.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/afm_reader.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/afm_writer.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/clafer_writer.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/featureide_reader.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/featureide_writer.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/flat_fm.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/fm_secure_features_names.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/glencoe_reader.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/glencoe_writer.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/json_reader.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/json_writer.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/pl_writer.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/pysat_to_fm.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/refactorings/__init__.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/refactorings/cardinality_group_refactoring.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/refactorings/commitment_feature.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/refactorings/deletion_feature.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/refactorings/feature_cardinality_refactoring.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/refactorings/feature_cardinality_refactoring_paper.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/refactorings/multiple_group_decomposition_refactoring.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/refactorings/mutex_group_refactoring.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/refactorings/or_mandatory_refactoring.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/refactorings/pseudocomplex_constraint_refactoring.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/refactorings/refactoring_exception.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/refactorings/refactoring_interface.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/refactorings/strictcomplex_constraint_refactoring.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/refactorings/xor_mandatory_refactoring.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/splot_writer.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/uvl_reader.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/uvl_writer.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/xml_reader.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/transformations/xml_writer.py +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy_fm.egg-info/dependency_links.txt +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy_fm.egg-info/requires.txt +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy_fm.egg-info/top_level.txt +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/setup.cfg +0 -0
- {flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/setup.py +0 -0
|
@@ -8,6 +8,7 @@ from .fm_estimated_configurations_number import FMEstimatedConfigurationsNumber
|
|
|
8
8
|
from .fm_atomic_sets import FMAtomicSets
|
|
9
9
|
from .fm_metrics import FMMetrics
|
|
10
10
|
from .fm_generate_random_attribute import GenerateRandomAttribute
|
|
11
|
+
from .fm_generate_random_feature_model import GenerateRandomFeatureModel
|
|
11
12
|
from .fm_variation_points import FMVariationPoints
|
|
12
13
|
from .fm_language_level import FMLanguageLevel, LanguageLevel, MajorLevel, MinorLevel
|
|
13
14
|
|
|
@@ -25,6 +26,7 @@ __all__ = [
|
|
|
25
26
|
'FMMetrics',
|
|
26
27
|
'FMVariationPoints',
|
|
27
28
|
'GenerateRandomAttribute',
|
|
29
|
+
'GenerateRandomFeatureModel',
|
|
28
30
|
'LanguageLevel',
|
|
29
31
|
'MajorLevel',
|
|
30
32
|
'MinorLevel'
|
flamapy_fm-2.6.0.dev7/flamapy/metamodels/fm_metamodel/operations/fm_generate_random_feature_model.py
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import random
|
|
3
|
+
import tempfile
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
6
|
+
from flamapy.core.models import VariabilityModel
|
|
7
|
+
from flamapy.core.operations import Operation
|
|
8
|
+
from flamapy.metamodels.fm_metamodel.models import FeatureModel
|
|
9
|
+
from flamapy.metamodels.fm_metamodel.transformations import UVLReader
|
|
10
|
+
|
|
11
|
+
# Minimum children an or/alternative group needs (and minimum features for a cross-tree constraint).
|
|
12
|
+
_MIN_GROUP_MEMBERS = 2
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class GenerateRandomFeatureModel(Operation):
|
|
16
|
+
"""Generate a random synthetic feature model.
|
|
17
|
+
|
|
18
|
+
A random feature tree (mandatory/optional/or/alternative groups) plus random cross-tree
|
|
19
|
+
constraints are emitted as UVL and parsed back into a :class:`FeatureModel`. Useful to build
|
|
20
|
+
corpora for benchmarking, testing, or training learning-based operations. When ``void`` is
|
|
21
|
+
set, a contradictory constraint is added so the resulting model is unsatisfiable.
|
|
22
|
+
|
|
23
|
+
The operation produces a model, so ``execute`` ignores its (optional) input model.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def __init__(self) -> None:
|
|
27
|
+
self.result: FeatureModel
|
|
28
|
+
self._num_features: int = 10
|
|
29
|
+
self._max_constraints: int = 3
|
|
30
|
+
self._seed: int = 0
|
|
31
|
+
self._void: bool = False
|
|
32
|
+
|
|
33
|
+
def get_result(self) -> FeatureModel:
|
|
34
|
+
return self.result
|
|
35
|
+
|
|
36
|
+
def set_num_features(self, num_features: int) -> None:
|
|
37
|
+
self._num_features = max(2, num_features)
|
|
38
|
+
|
|
39
|
+
def set_max_constraints(self, max_constraints: int) -> None:
|
|
40
|
+
self._max_constraints = max(0, max_constraints)
|
|
41
|
+
|
|
42
|
+
def set_seed(self, seed: int) -> None:
|
|
43
|
+
self._seed = seed
|
|
44
|
+
|
|
45
|
+
def set_void(self, void: bool) -> None:
|
|
46
|
+
self._void = void
|
|
47
|
+
|
|
48
|
+
def _emit_uvl(self, rng: random.Random) -> str:
|
|
49
|
+
names = [f'F{i}' for i in range(self._num_features)]
|
|
50
|
+
root = names[0]
|
|
51
|
+
lines = ['features', f' {root} {{abstract}}']
|
|
52
|
+
|
|
53
|
+
children: dict[str, list[str]] = {name: [] for name in names}
|
|
54
|
+
for name in names[1:]:
|
|
55
|
+
parent = rng.choice(names[: names.index(name)])
|
|
56
|
+
children[parent].append(name)
|
|
57
|
+
|
|
58
|
+
def emit(parent: str, depth: int) -> None:
|
|
59
|
+
kids = children[parent]
|
|
60
|
+
if not kids:
|
|
61
|
+
return
|
|
62
|
+
indent = ' ' * (depth + 1)
|
|
63
|
+
group = rng.choice(['mandatory', 'optional', 'or', 'alternative'])
|
|
64
|
+
if group in ('or', 'alternative') and len(kids) < _MIN_GROUP_MEMBERS:
|
|
65
|
+
group = 'optional'
|
|
66
|
+
lines.append(f'{indent}{group}')
|
|
67
|
+
lines.extend(f'{indent} {kid}' for kid in kids)
|
|
68
|
+
for kid in kids:
|
|
69
|
+
emit(kid, depth + 2)
|
|
70
|
+
|
|
71
|
+
emit(root, 1)
|
|
72
|
+
|
|
73
|
+
constraints = []
|
|
74
|
+
non_root = names[1:]
|
|
75
|
+
if len(non_root) >= _MIN_GROUP_MEMBERS and self._max_constraints > 0:
|
|
76
|
+
for _ in range(rng.randint(1, self._max_constraints)):
|
|
77
|
+
left, right = rng.sample(non_root, 2)
|
|
78
|
+
constraints.append(
|
|
79
|
+
rng.choice([f'{left} => {right}', f'!{left} | {right}', f'!{left} | !{right}'])
|
|
80
|
+
)
|
|
81
|
+
if self._void and non_root:
|
|
82
|
+
forced = rng.choice(non_root)
|
|
83
|
+
constraints.append(f'{root} => {forced}')
|
|
84
|
+
constraints.append(f'!{forced}')
|
|
85
|
+
if constraints:
|
|
86
|
+
lines.append('constraints')
|
|
87
|
+
lines.extend(f' {constraint}' for constraint in constraints)
|
|
88
|
+
return '\n'.join(lines) + '\n'
|
|
89
|
+
|
|
90
|
+
def execute(self, model: Optional[VariabilityModel] = None) -> 'GenerateRandomFeatureModel':
|
|
91
|
+
rng = random.Random(self._seed)
|
|
92
|
+
uvl = self._emit_uvl(rng)
|
|
93
|
+
handle, path = tempfile.mkstemp(suffix='.uvl')
|
|
94
|
+
try:
|
|
95
|
+
with os.fdopen(handle, 'w') as file:
|
|
96
|
+
file.write(uvl)
|
|
97
|
+
self.result = UVLReader(path).transform()
|
|
98
|
+
finally:
|
|
99
|
+
os.remove(path)
|
|
100
|
+
return self
|
|
@@ -13,6 +13,7 @@ flamapy/metamodels/fm_metamodel/operations/fm_count_leafs.py
|
|
|
13
13
|
flamapy/metamodels/fm_metamodel/operations/fm_estimated_configurations_number.py
|
|
14
14
|
flamapy/metamodels/fm_metamodel/operations/fm_feature_ancestors.py
|
|
15
15
|
flamapy/metamodels/fm_metamodel/operations/fm_generate_random_attribute.py
|
|
16
|
+
flamapy/metamodels/fm_metamodel/operations/fm_generate_random_feature_model.py
|
|
16
17
|
flamapy/metamodels/fm_metamodel/operations/fm_language_level.py
|
|
17
18
|
flamapy/metamodels/fm_metamodel/operations/fm_leaf_features.py
|
|
18
19
|
flamapy/metamodels/fm_metamodel/operations/fm_max_depth_tree.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flamapy_fm-2.6.0.dev5 → flamapy_fm-2.6.0.dev7}/flamapy/metamodels/fm_metamodel/models/__init__.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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|