Skip to content

Commit 5abd44a

Browse files
committed
feaf: version 2.0.0
2 parents 1dad51d + dc2c725 commit 5abd44a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+6143
-976
lines changed

.github/workflows/main.yaml

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,14 @@ jobs:
1414
- name: Install dependencies
1515
run: |
1616
python -m pip install --upgrade pip
17-
pip install flamapy-fm
18-
pip install prospector[with_everything]==1.7.7
17+
python -m venv venv
18+
source venv/bin/activate
19+
pip install -r requirements.txt
20+
pip install prospector[with_everything]==1.10.3
1921
pip install .
2022
- name: Analysing the code with prospector
2123
run: |
24+
source venv/bin/activate
2225
prospector
2326
mypy:
2427
runs-on: ubuntu-latest
@@ -35,7 +38,7 @@ jobs:
3538
pip install .
3639
- name: Running static types with mypy
3740
run: |
38-
mypy flamapy
41+
mypy flamapy --no-namespace-packages
3942
pytest:
4043
runs-on: ubuntu-latest
4144
steps:
@@ -46,13 +49,14 @@ jobs:
4649
python-version: 3.9
4750
- name: Install dependencies
4851
run: |
52+
python -m pip install --upgrade pip
53+
pip install flamapy-fm
54+
pip install .
55+
pip install pytest==5.4.3
4956
sudo add-apt-repository universe
5057
sudo apt update
5158
sudo apt install graphviz -y
52-
python -m pip install --upgrade pip
53-
pip install pytest==5.4.3
5459
pip install graphviz
55-
pip install .
5660
- name: Running test
5761
run: |
5862
python -m pytest

.prospector.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ doc-warnings: false
55
ignore-paths:
66
- build
77
- env
8-
8+
- tests
9+
910
pycodestyle:
1011
options:
1112
max-line-length: 100

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ lint:
44
prospector
55

66
mypy:
7-
mypy flamapy
7+
mypy flamapy --no-namespace-packages
88

99
test:
1010
python -m pytest -sv

README.md

Lines changed: 74 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
- [Description](#description)
44
- [Requirements and Installation](#requirements-and-installation)
55
- [Functionality and usage](#functionality-and-usage)
6-
- [Load a feature model and create the BDD](#load-a-feature-model-and-create-the-bdd)
6+
- [Load a feature model in UVL and create the BDD](#load-a-feature-model-in-uvl-and-create-the-bdd)
77
- [Save the BDD in a file](#save-the-bdd-in-a-file)
8+
- [Load the BDD from a file](#load-the-bdd-from-a-file)
89
- [Analysis operations](#analysis-operations)
910
- [Contributing to the BDD plugin](#contributing-to-the-bdd-plugin)
1011

@@ -48,128 +49,130 @@ The executable script [test_bdd_metamodel.py](https://github.com/flamapy/bdd_met
4849
The following functionality is provided:
4950

5051

51-
### Load a feature model and create the BDD
52+
### Load a feature model in UVL and create the BDD
5253
```python
53-
from flamapy.metamodels.fm_metamodel.transformations.featureide_reader import FeatureIDEReader
54-
from flamapy.metamodels.bdd_metamodel.transformations.fm_to_bdd import FmToBDD
54+
from flamapy.metamodels.fm_metamodel.transformations import UVLReader
55+
from flamapy.metamodels.bdd_metamodel.transformations import FmToBDD
5556

56-
# Load the feature model from FeatureIDE
57-
feature_model = FeatureIDEReader('input_fms/featureide_models/pizzas.xml').transform()
57+
# Load the feature model from UVL
58+
feature_model = UVLReader('models/uvl_models/pizzas.uvl').transform()
5859
# Create the BDD from the feature model
5960
bdd_model = FmToBDD(feature_model).transform()
6061
```
6162

6263

6364
### Save the BDD in a file
6465
```python
65-
from flamapy.metamodels.bdd_metamodel.transformations.bdd_writer import BDDWriter, BDDDumpFormat
66+
from flamapy.metamodels.bdd_metamodel.transformations import PNGWriter, DDDMPv3Writer
6667
# Save the BDD as an image in PNG
67-
BDDWriter(path='my_bdd.png',
68-
source_model=bdd_model,
69-
roots=[bdd_model.root],
70-
output_format=BDDDumpFormat.PNG).transform()
68+
PNGWriter(path='my_bdd.png', bdd_model).transform()
69+
# Save the BDD in a .dddmp file
70+
DDDMPv3Writer(f'my_bdd.dddmp', bdd_model).transform()
7171
```
72-
Formats supported: DDDMP_V3 ('dddmp'), DDDMP_V2 ('dddmp2'), PDF ('pdf'), PNG ('png'), SVG ('svg').
72+
Writers available: DDDMPv3 ('dddmp'), DDDMPv2 ('dddmp'), JSON ('json'), Pickle ('p'), PDF ('pdf'), PNG ('png'), SVG ('svg').
7373

74+
### Load the BDD from a file
75+
```python
76+
from flamapy.metamodels.bdd_metamodel.transformations import JSONReader
77+
# Load the BDD from a .json file
78+
bdd_model = JSONReader(path='path/to/my_bdd.json').transform()
79+
```
80+
Readers available: JSON ('json'), DDDMP ('dddmp'), Pickle ('p').
81+
82+
*NOTE:* DDDMP and Pickle readers are not fully supported yet.
7483

7584
### Analysis operations
7685

77-
- Products number
86+
- Satisfiable
7887

79-
Return the number of products (configurations):
88+
Return whether the model is satisfiable (valid):
8089
```python
81-
from flamapy.metamodels.bdd_metamodel.operations import BDDProductsNumber
82-
nof_products = BDDProductsNumber().execute(bdd_model).get_result()
83-
print(f'#Products: {nof_products}')
84-
```
85-
or alternatively:
86-
```python
87-
from flamapy.metamodels.bdd_metamodel.operations import products_number
88-
nof_products = products_number(bdd_model)
89-
print(f'#Products: {nof_products}')
90+
from flamapy.metamodels.bdd_metamodel.operations import BDDSatisfiable
91+
satisfiable = BDDSatisfiable().execute(bdd_model).get_result()
92+
print(f'Satisfiable? (valid?): {satisfiable}')
9093
```
9194

92-
- Products
95+
- Configurations number
9396

94-
Return the list of products (configurations):
97+
Return the number of configurations:
9598
```python
96-
from flamapy.metamodels.bdd_metamodel.operations import BDDProducts
97-
list_products = BDDProducts().execute(bdd_model).get_result()
98-
for i, prod in enumerate(list_products):
99-
print(f'Product {i}: {[feat for feat in prod.elements if prod.elements[feat]]}')
99+
from flamapy.metamodels.bdd_metamodel.operations import BDDConfigurationsNumber
100+
n_configs = BDDConfigurationsNumber().execute(bdd_model).get_result()
101+
print(f'#Configurations: {n_configs}')
100102
```
101-
or alternatively:
103+
104+
- Configurations
105+
106+
Enumerate the configurations of the model:
102107
```python
103-
from flamapy.metamodels.bdd_metamodel.operations import products
104-
nof_products = products(bdd_model)
105-
for i, prod in enumerate(list_products):
106-
print(f'Product {i}: {[feat for feat in prod.elements if prod.elements[feat]]}')
108+
from flamapy.metamodels.bdd_metamodel.operations import BDDConfigurations
109+
configurations = BDDConfigurations().execute(bdd_model).get_result()
110+
for i, config in enumerate(configurations, 1):
111+
print(f'Config {i}: {[feat for feat in config.elements if config.elements[feat]]}')
107112
```
108113

109114
- Sampling
110115

111-
Return a sample of the given size of uniform random products (configurations) with or without replacement:
116+
Return a sample of the given size of uniform random configurations with or without replacement:
112117
```python
113118
from flamapy.metamodels.bdd_metamodel.operations import BDDSampling
114-
list_sample = BDDSampling(size=5, with_replacement=False).execute(bdd_model).get_result()
115-
for i, prod in enumerate(list_sample):
116-
print(f'Product {i}: {[feat for feat in prod.elements if prod.elements[feat]]}')
117-
```
118-
or alternatively:
119-
```python
120-
from flamapy.metamodels.bdd_metamodel.operations import sample
121-
list_sample = sample(bdd_model, size=5, with_replacement=False)
122-
for i, prod in enumerate(list_sample):
123-
print(f'Product {i}: {[feat for feat in prod.elements if prod.elements[feat]]}')
119+
sampling_op = BDDSampling()
120+
sampling_op.set_sample_size(5)
121+
sampling_op.set_with_replacement(False) # Default False
122+
sample = sampling_op.execute(bdd_model).get_result()
123+
for i, config in enumerate(sample, 1):
124+
print(f'Config {i}: {[feat for feat in config.elements if config.elements[feat]]}')
124125
```
125126

126127
- Product Distribution
127128

128-
Return the number of products having a given number of features:
129-
```python
130-
from flamapy.metamodels.bdd_metamodel.operations import BDDProductDistributionBF
131-
dist = BDDProductDistributionBF().execute(bdd_model).get_result()
132-
print(f'Product Distribution: {dist}')
133-
```
134-
or alternatively:
129+
Return the number of products (configurations) having a given number of features:
135130
```python
136-
from flamapy.metamodels.bdd_metamodel.operations import product_distribution
137-
dist = product_distribution(bdd_model)
131+
from flamapy.metamodels.bdd_metamodel.operations import BDDProductDistribution
132+
dist = BDDProductDistribution().execute(bdd_model).get_result()
138133
print(f'Product Distribution: {dist}')
139134
```
140135

141136
- Feature Inclusion Probability
142137

143-
Return the probability for a feature to be included in a valid product:
138+
Return the probability for a feature to be included in a valid configuration:
144139
```python
145-
from flamapy.metamodels.bdd_metamodel.operations import BDDFeatureInclusionProbabilityBF
146-
prob = BDDFeatureInclusionProbabilityBF().execute(bdd_model).get_result()
140+
from flamapy.metamodels.bdd_metamodel.operations import BDDFeatureInclusionProbability
141+
prob = BDDFeatureInclusionProbability().execute(bdd_model).get_result()
147142
for feat in prob.keys():
148143
print(f'{feat}: {prob[feat]}')
149144
```
150-
or alternatively:
145+
146+
- Core features
147+
148+
Return the core features (those features that are present in all the configurations):
151149
```python
152-
from flamapy.metamodels.bdd_metamodel.operations import feature_inclusion_probability
153-
prob = feature_inclusion_probability(bdd_model)
154-
for feat in prob.keys():
155-
print(f'{feat}: {prob[feat]}')
150+
from flamapy.metamodels.bdd_metamodel.operations import BDDCoreFeatures
151+
core_features = BDDCoreFeatures().execute(bdd_model).get_result()
152+
print(f'Core features: {core_features}')
156153
```
157154

158-
All analysis operations support also a partial configuration as an additional argument, so the operation will return the result taking into account the given partial configuration. For example:
155+
- Dead features
156+
157+
Return the dead features (those features that are not present in any configuration):
158+
```python
159+
from flamapy.metamodels.bdd_metamodel.operations import BDDDeadFeatures
160+
dead_features = BDDDeadFeatures().execute(bdd_model).get_result()
161+
print(f'Dead features: {dead_features}')
162+
```
163+
164+
Most analysis operations support also a partial configuration as an additional argument, so the operation will return the result taking into account the given partial configuration. For example:
159165

160166
```python
161167
from flamapy.core.models import Configuration
162168
# Create a partial configuration
163169
elements = {'Pizza': True, 'Big': True}
164170
partial_config = Configuration(elements)
165-
# Calculate the number of products from the partial configuration
166-
nof_products = BDDProductsNumber(partial_config).execute(bdd_model).get_result()
167-
print(f'#Products: {nof_products}')
168-
```
169-
or alternatively:
170-
```python
171-
nof_products = products(bdd_model, partial_config)
172-
print(f'#Products: {nof_products}')
171+
# Calculate the number of configuration from the partial configuration
172+
configs_number_op = BDDConfigurationsNumber()
173+
configs_number_op.set_partial_configuration(partial_config)
174+
n_configs = configs_number_op.execute(bdd_model).get_result()
175+
print(f'#Configurations: {n_configs}')
173176
```
174177

175178

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from .bdd_model import BDDModel
1+
from .bdd_model import BDDModel
22

33

4-
__all__ = ['BDDModel']
4+
__all__ = ['BDDModel']

0 commit comments

Comments
 (0)