diff --git a/flamapy/metamodels/pysat_metamodel/models/pysat_model.py b/flamapy/metamodels/pysat_metamodel/models/pysat_model.py index c073eb8..5afada4 100644 --- a/flamapy/metamodels/pysat_metamodel/models/pysat_model.py +++ b/flamapy/metamodels/pysat_metamodel/models/pysat_model.py @@ -10,14 +10,12 @@ def get_extension() -> str: return 'pysat' def __init__(self) -> None: - # self.r_cnf = CNF() # ToDo: This should be avoid - # self.ctc_cnf = CNF() # ToDo: This should be avoid self._cnf = CNF() self.variables: dict[str, int] = {} # feature's name -> id self.features: dict[int, str] = {} # id -> feature's name - + self.original_model: VariabilityModel + def add_clause(self, clause: list[int]) -> None: - # self.ctc_cnf.append(clause) self._cnf.append(clause) def get_variable(self, key: str) -> int: @@ -26,8 +24,4 @@ def get_variable(self, key: str) -> int: return self.variables[key] def get_all_clauses(self) -> CNF: - # clauses = CNF() - # clauses.extend(self.r_cnf.clauses) - # clauses.extend(self.ctc_cnf.clauses) - # return clauses return self._cnf diff --git a/flamapy/metamodels/pysat_metamodel/operations/__init__.py b/flamapy/metamodels/pysat_metamodel/operations/__init__.py index 4d84cae..1e5dc3f 100644 --- a/flamapy/metamodels/pysat_metamodel/operations/__init__.py +++ b/flamapy/metamodels/pysat_metamodel/operations/__init__.py @@ -1,26 +1,26 @@ -from .glucose3_valid import Glucose3Valid -from .glucose3_valid_configuration import Glucose3ValidConfiguration -from .glucose3_valid_product import Glucose3ValidProduct -from .glucose3_products import Glucose3Products -from .glucose3_products_number import Glucose3ProductsNumber -from .glucose3_commonality import Glucose3Commonality -from .glucose3_filter import Glucose3Filter -from .glucose3_core_features import Glucose3CoreFeatures -from .glucose3_dead_features import Glucose3DeadFeatures -from .glucose3_false_optional_features import Glucose3FalseOptionalFeatures -from .glucose3_error_detection import Glucose3ErrorDetection - +from .pysat_valid import PySATValid +from .pysat_valid_configuration import PySATValidConfiguration +from .pysat_valid_product import PySATValidProduct +from .pysat_products import PySATProducts +from .pysat_products_number import PySATProductsNumber +from .pysat_commonality import PySATCommonality +from .pysat_filter import PySATFilter +from .pysat_core_features import PySATCoreFeatures +from .pysat_dead_features import PySATDeadFeatures +from .pysat_false_optional_features import PySATFalseOptionalFeatures +from .pysat_error_detection import PySATErrorDetection +from .pysat_metrics import PySATMetrics __all__ = [ - 'Glucose3Valid', - 'Glucose3ValidConfiguration', - 'Glucose3ValidProduct', - 'Glucose3Products', - 'Glucose3ProductsNumber', - 'Glucose3Commonality', - 'Glucose3Filter', - 'Glucose3CoreFeatures', - 'Glucose3DeadFeatures', - 'Glucose3FalseOptionalFeatures', - 'Glucose3ErrorDetection', + 'PySATValid', + 'PySATValidConfiguration', + 'PySATValidProduct', + 'PySATProducts', + 'PySATProductsNumber', + 'PySATCommonality', + 'PySATFilter', + 'PySATCoreFeatures', + 'PySATDeadFeatures', + 'PySATFalseOptionalFeatures', + 'PySATErrorDetection', ] diff --git a/flamapy/metamodels/pysat_metamodel/operations/glucose3_commonality.py b/flamapy/metamodels/pysat_metamodel/operations/pysat_commonality.py similarity index 78% rename from flamapy/metamodels/pysat_metamodel/operations/glucose3_commonality.py rename to flamapy/metamodels/pysat_metamodel/operations/pysat_commonality.py index 86c7a08..0127591 100644 --- a/flamapy/metamodels/pysat_metamodel/operations/glucose3_commonality.py +++ b/flamapy/metamodels/pysat_metamodel/operations/pysat_commonality.py @@ -1,10 +1,10 @@ from flamapy.core.operations import Commonality from flamapy.core.models import VariabilityModel from flamapy.metamodels.configuration_metamodel.models.configuration import Configuration -from flamapy.metamodels.pysat_metamodel.operations.glucose3_products import Glucose3Products +from flamapy.metamodels.pysat_metamodel.operations.pysat_products import PySATProducts -class Glucose3Commonality(Commonality): +class PySATCommonality(Commonality): def __init__(self) -> None: self.commonality: float = 0 self.configuration = Configuration({}) @@ -18,8 +18,8 @@ def get_commonality(self) -> float: def get_result(self) -> float: return self.get_commonality() - def execute(self, model: VariabilityModel) -> 'Glucose3Commonality': - glucose3products = Glucose3Products() + def execute(self, model: VariabilityModel) -> 'PySATCommonality': + glucose3products = PySATProducts() glucose3products.execute(model) products = glucose3products.get_result() diff --git a/flamapy/metamodels/pysat_metamodel/operations/glucose3_core_features.py b/flamapy/metamodels/pysat_metamodel/operations/pysat_core_features.py similarity index 90% rename from flamapy/metamodels/pysat_metamodel/operations/glucose3_core_features.py rename to flamapy/metamodels/pysat_metamodel/operations/pysat_core_features.py index 00fa993..6a28518 100644 --- a/flamapy/metamodels/pysat_metamodel/operations/glucose3_core_features.py +++ b/flamapy/metamodels/pysat_metamodel/operations/pysat_core_features.py @@ -7,7 +7,7 @@ from flamapy.core.models import VariabilityModel -class Glucose3CoreFeatures(CoreFeatures): +class PySATCoreFeatures(CoreFeatures): def __init__(self) -> None: self.core_features: list[list[Any]] = [] @@ -19,7 +19,7 @@ def get_core_features(self) -> list[list[Any]]: def get_result(self) -> list[list[Any]]: return self.get_core_features() - def execute(self, model: VariabilityModel) -> 'Glucose3CoreFeatures': + def execute(self, model: VariabilityModel) -> 'PySATCoreFeatures': model = cast(PySATModel, model) for clause in model.get_all_clauses(): # AC es conjunto de conjuntos self.solver.add_clause(clause) # aƱadimos la constraint diff --git a/flamapy/metamodels/pysat_metamodel/operations/glucose3_dead_features.py b/flamapy/metamodels/pysat_metamodel/operations/pysat_dead_features.py similarity index 89% rename from flamapy/metamodels/pysat_metamodel/operations/glucose3_dead_features.py rename to flamapy/metamodels/pysat_metamodel/operations/pysat_dead_features.py index 4d5b830..7a0467b 100644 --- a/flamapy/metamodels/pysat_metamodel/operations/glucose3_dead_features.py +++ b/flamapy/metamodels/pysat_metamodel/operations/pysat_dead_features.py @@ -7,7 +7,7 @@ from flamapy.core.models import VariabilityModel -class Glucose3DeadFeatures(DeadFeatures): +class PySATDeadFeatures(DeadFeatures): def __init__(self) -> None: self.dead_features: list[list[Any]] = [] @@ -19,7 +19,7 @@ def get_dead_features(self) -> list[list[Any]]: def get_result(self) -> list[list[Any]]: return self.get_dead_features() - def execute(self, model: VariabilityModel) -> 'Glucose3DeadFeatures': + def execute(self, model: VariabilityModel) -> 'PySATDeadFeatures': model = cast(PySATModel, model) for clause in model.get_all_clauses(): # AC es conjunto de conjuntos diff --git a/flamapy/metamodels/pysat_metamodel/operations/glucose3_error_detection.py b/flamapy/metamodels/pysat_metamodel/operations/pysat_error_detection.py similarity index 69% rename from flamapy/metamodels/pysat_metamodel/operations/glucose3_error_detection.py rename to flamapy/metamodels/pysat_metamodel/operations/pysat_error_detection.py index cc74a18..42b2162 100644 --- a/flamapy/metamodels/pysat_metamodel/operations/glucose3_error_detection.py +++ b/flamapy/metamodels/pysat_metamodel/operations/pysat_error_detection.py @@ -2,19 +2,19 @@ from flamapy.core.operations import ErrorDetection from flamapy.metamodels.pysat_metamodel.models.pysat_model import PySATModel -from flamapy.metamodels.pysat_metamodel.operations.glucose3_dead_features import ( - Glucose3DeadFeatures +from flamapy.metamodels.pysat_metamodel.operations.pysat_dead_features import ( + PySATDeadFeatures ) -from flamapy.metamodels.pysat_metamodel.operations.glucose3_false_optional_features import ( - Glucose3FalseOptionalFeatures +from flamapy.metamodels.pysat_metamodel.operations.pysat_false_optional_features import ( + PySATFalseOptionalFeatures ) from flamapy.core.models import VariabilityModel from flamapy.core.exceptions import FlamaException from flamapy.metamodels.fm_metamodel.models.feature_model import FeatureModel -from flamapy.metamodels.pysat_metamodel.operations.glucose3_valid import Glucose3Valid +from flamapy.metamodels.pysat_metamodel.operations.pysat_valid import PySATValid -class Glucose3ErrorDetection(ErrorDetection): +class PySATErrorDetection(ErrorDetection): def __init__(self) -> None: self.feature_model: Optional[FeatureModel] = None @@ -26,25 +26,25 @@ def get_errors_messages(self) -> list[str]: def get_result(self) -> list[str]: return self.errors_messages - def execute(self, model: VariabilityModel) -> 'Glucose3ErrorDetection': + def execute(self, model: VariabilityModel) -> 'PySATErrorDetection': if self.feature_model is None: raise FlamaException('The feature model is not setted') cast_model = cast(PySATModel, model) # Valid feature model check - valid = Glucose3Valid().execute(cast_model).get_result() + valid = PySATValid().execute(cast_model).get_result() if not valid: self.errors_messages.append('The model is not valid (it is void), \ so it has not any product.') # Dead features detection - dead_features = Glucose3DeadFeatures().execute(cast_model).get_result() + dead_features = PySATDeadFeatures().execute(cast_model).get_result() if dead_features: self.errors_messages.append(f'Dead features: {dead_features}') # False optional detection - fof_op = Glucose3FalseOptionalFeatures() + fof_op = PySATFalseOptionalFeatures() fof_op.feature_model = self.feature_model false_optional_features = fof_op.execute(cast_model).get_result() if false_optional_features: diff --git a/flamapy/metamodels/pysat_metamodel/operations/glucose3_false_optional_features.py b/flamapy/metamodels/pysat_metamodel/operations/pysat_false_optional_features.py similarity index 73% rename from flamapy/metamodels/pysat_metamodel/operations/glucose3_false_optional_features.py rename to flamapy/metamodels/pysat_metamodel/operations/pysat_false_optional_features.py index 714fb1c..f09609d 100644 --- a/flamapy/metamodels/pysat_metamodel/operations/glucose3_false_optional_features.py +++ b/flamapy/metamodels/pysat_metamodel/operations/pysat_false_optional_features.py @@ -1,4 +1,5 @@ -from typing import Any, Optional, cast +import logging +from typing import Any, cast from pysat.solvers import Solver @@ -8,21 +9,19 @@ from flamapy.core.models import VariabilityModel from flamapy.core.exceptions import FlamaException +LOGGER = logging.getLogger('PySATFalseOptionalFeatures') -class Glucose3FalseOptionalFeatures(FalseOptionalFeatures): + +class PySATFalseOptionalFeatures(FalseOptionalFeatures): def __init__(self) -> None: self.result: list[Any] = [] - self.feature_model: Optional[FeatureModel] = None self.solver = Solver(name='glucose3') - def execute(self, model: VariabilityModel) -> 'Glucose3FalseOptionalFeatures': - if self.feature_model is None: - raise FlamaException('The feature model is not setted') - + def execute(self, model: VariabilityModel) -> 'PySATFalseOptionalFeatures': model = cast(PySATModel, model) - self.result = self._get_false_optional_features(model, self.feature_model) + self.result = self._get_false_optional_features(model) return self def get_false_optional_features(self) -> list[list[Any]]: @@ -31,8 +30,12 @@ def get_false_optional_features(self) -> list[list[Any]]: def get_result(self) -> list[Any]: return self.result - def _get_false_optional_features(self, sat_model: PySATModel, - feature_model: FeatureModel) -> list[Any]: + def _get_false_optional_features(self, sat_model: PySATModel) -> list[Any]: + try: + feature_model=cast(FeatureModel,sat_model.original_model) + except FlamaException: + LOGGER.exception("The transformation didn't attach the source model, which is required for this operation." ) + real_optional_features = [f for f in feature_model.get_features() if not f.is_root() and not f.is_mandatory()] diff --git a/flamapy/metamodels/pysat_metamodel/operations/glucose3_filter.py b/flamapy/metamodels/pysat_metamodel/operations/pysat_filter.py similarity index 93% rename from flamapy/metamodels/pysat_metamodel/operations/glucose3_filter.py rename to flamapy/metamodels/pysat_metamodel/operations/pysat_filter.py index c7d5157..ee17114 100644 --- a/flamapy/metamodels/pysat_metamodel/operations/glucose3_filter.py +++ b/flamapy/metamodels/pysat_metamodel/operations/pysat_filter.py @@ -8,7 +8,7 @@ from flamapy.core.models import VariabilityModel -class Glucose3Filter(Filter): +class PySATFilter(Filter): def __init__(self) -> None: self.filter_products: list[list[Any]] = [] @@ -24,7 +24,7 @@ def get_result(self) -> list[list[Any]]: def set_configuration(self, configuration: Configuration) -> None: self.configuration = configuration - def execute(self, model: VariabilityModel) -> 'Glucose3Filter': + def execute(self, model: VariabilityModel) -> 'PySATFilter': model = cast(PySATModel, model) for clause in model.get_all_clauses(): # AC es conjunto de conjuntos diff --git a/flamapy/metamodels/pysat_metamodel/operations/pysat_metrics.py b/flamapy/metamodels/pysat_metamodel/operations/pysat_metrics.py new file mode 100644 index 0000000..fd11565 --- /dev/null +++ b/flamapy/metamodels/pysat_metamodel/operations/pysat_metrics.py @@ -0,0 +1,146 @@ +from typing import List, Tuple, Union, cast, Callable, Dict, Any + +from flamapy.core.operations.metrics_operation import Metrics +from flamapy.core.models.variability_model import VariabilityModel + +from flamapy.metamodels.pysat_metamodel.models import PySATModel +from flamapy.metamodels.pysat_metamodel import operations as sat_operations + + + +def metric_method(func: Callable) -> Callable: + """Decorator to mark a method as a metric method. + It has the value of the measure, it can also have a size and a ratio. + Example: + property name: Abstract Features. + description: The description of the property + value (optional): the list of abstract features. + size (optional): the length of the list. + ratio (optional): the percentage of abstract features with regards the total number of features. + """ + if not hasattr(func, '_is_metric_method'): + setattr(func, '_is_metric_method', True) + return func + +class PySATMetrics(Metrics): + + def __init__(self) -> None: + self.model = None + self.result: List[Dict[str, Any]] = [] + self.model_type_extension="pysat" + + def get_result(self) -> Dict[str, Any]: + return self.result + + def calculate_metamodel_metrics(self,model) -> Dict[str, Any]: + self.model = cast(PySATModel, model) + + #Do some basic calculations to speedup the rest + self._features = self.model.features + self._common_features = sat_operations.PySATCoreFeatures().execute(self.model).get_result() + self._dead_features = sat_operations.PySATDeadFeatures().execute(self.model).get_result() + # Get all methods that are marked with the metric_method decorator + metric_methods = [getattr(self, method_name) for method_name in dir(self) + if callable(getattr(self, method_name)) and hasattr(getattr(self, method_name), '_is_metric_method')] + if self.filter is not None: + metric_methods = [method for method in metric_methods if method.__name__ in self.filter] + + return [method() for method in metric_methods] + + @metric_method + def valid(self) -> Dict[str, Any]: + """A feature model is valid if it represents at least one configuration.""" + name = "Valid (not void)" + _valid = sat_operations.PySATValid().execute(self.model).get_result() + result = self.construct_result( name=name, + doc=self.valid.__doc__, + result=_valid) + return result + + @metric_method + def core_features(self) -> Dict[str, Any]: + """Features that are part of all the configurations (aka 'common features').""" + name = "Core features" + _core = self._common_features + result = self.construct_result( name=name, + doc=self.core_features.__doc__, + result=_core, + size=len(_core), + ratio=self.get_ratio(_core, self._features, 2)) + return result + + @metric_method + def variant_features(self) -> Dict[str, Any]: + """Features that do not appear in all the configurations.""" + name = "Variant features" + _variant_features = [f for f in self._features.values() + if f not in self._common_features and + f not in self._dead_features] + result = self.construct_result( name=name, + doc=self.variant_features.__doc__, + result=_variant_features, + size=len(_variant_features), + ratio=self.get_ratio(_variant_features, self._features, 2)) + return result + + @metric_method + def dead_features(self) -> Dict[str, Any]: + """Features that cannot appear in any configuration.""" + name = "Dead features" + _dead_features = sat_operations.PySATDeadFeatures().execute(self.model).get_result() + result = self.construct_result( name=name, + doc=self.dead_features.__doc__, + result=_dead_features, + size=len(_dead_features), + ratio=self.get_ratio(_dead_features, self._features, 2)) + return result + + @metric_method + def unique_features(self) -> Dict[str, Any]: + """Features that appear in exactly one configuration.""" + name = "Unique features" + + seen_once = set() + seen_multiple = set() + + # Step 2: Iterate through each configuration + for config in self.configurations()["result"]: + for feature in config: + if feature in seen_once: + seen_multiple.add(feature) + else: + seen_once.add(feature) + + # Step 3: Find features that are in seen_once but not in seen_multiple + _unique_features = seen_once - seen_multiple + + result = self.construct_result( name=name, + doc=self.unique_features.__doc__, + result=_unique_features, + size=len(_unique_features), + ratio=self.get_ratio(_unique_features, self._features, 2)) + return result + + @metric_method + def false_optional_features(self) -> Dict[str, Any]: + """Features defined as optionals the selection of their parents make the feature itself selected as well.""" + name = "False-optional features" + _false_optional_features=sat_operations.PySATFalseOptionalFeatures().execute(self.model).get_result() + result = self.construct_result( name=name, + doc=self.false_optional_features.__doc__, + result=_false_optional_features, + size=len(_false_optional_features), + ratio=self.get_ratio(_false_optional_features, self._features, 2)) + return result + + @metric_method + def configurations(self) -> Tuple[str, str, Union[int, float]]: + """Number of configurations represented by the feature model. If <= is shown, the number represents an upper estimation bound.""" + name = "Configurations" + _configurations = sat_operations.PySATProducts().execute(self.model).get_result() + result = self.construct_result( name=name, + doc=self.configurations.__doc__, + result=_configurations, + size=len(_configurations)) + return result + \ No newline at end of file diff --git a/flamapy/metamodels/pysat_metamodel/operations/glucose3_products.py b/flamapy/metamodels/pysat_metamodel/operations/pysat_products.py similarity index 90% rename from flamapy/metamodels/pysat_metamodel/operations/glucose3_products.py rename to flamapy/metamodels/pysat_metamodel/operations/pysat_products.py index b1b110d..95f8f90 100644 --- a/flamapy/metamodels/pysat_metamodel/operations/glucose3_products.py +++ b/flamapy/metamodels/pysat_metamodel/operations/pysat_products.py @@ -7,7 +7,7 @@ from flamapy.core.models import VariabilityModel -class Glucose3Products(Products): +class PySATProducts(Products): def __init__(self) -> None: self.products: list[list[Any]] = [] @@ -19,7 +19,7 @@ def get_products(self) -> list[list[Any]]: def get_result(self) -> list[list[Any]]: return self.get_products() - def execute(self, model: VariabilityModel) -> 'Glucose3Products': + def execute(self, model: VariabilityModel) -> 'PySATProducts': model = cast(PySATModel, model) for clause in model.get_all_clauses(): # AC es conjunto de conjuntos diff --git a/flamapy/metamodels/pysat_metamodel/operations/glucose3_products_number.py b/flamapy/metamodels/pysat_metamodel/operations/pysat_products_number.py similarity index 87% rename from flamapy/metamodels/pysat_metamodel/operations/glucose3_products_number.py rename to flamapy/metamodels/pysat_metamodel/operations/pysat_products_number.py index cf99722..8cd6384 100644 --- a/flamapy/metamodels/pysat_metamodel/operations/glucose3_products_number.py +++ b/flamapy/metamodels/pysat_metamodel/operations/pysat_products_number.py @@ -7,7 +7,7 @@ from flamapy.core.models import VariabilityModel -class Glucose3ProductsNumber(ProductsNumber): +class PySATProductsNumber(ProductsNumber): def __init__(self) -> None: self.products_number = 0 @@ -19,7 +19,7 @@ def get_products_number(self) -> int: def get_result(self) -> int: return self.get_products_number() - def execute(self, model: VariabilityModel) -> 'Glucose3ProductsNumber': + def execute(self, model: VariabilityModel) -> 'PySATProductsNumber': model = cast(PySATModel, model) for clause in model.get_all_clauses(): # AC es conjunto de conjuntos diff --git a/flamapy/metamodels/pysat_metamodel/operations/glucose3_valid.py b/flamapy/metamodels/pysat_metamodel/operations/pysat_valid.py similarity index 88% rename from flamapy/metamodels/pysat_metamodel/operations/glucose3_valid.py rename to flamapy/metamodels/pysat_metamodel/operations/pysat_valid.py index 1656384..5d01b23 100644 --- a/flamapy/metamodels/pysat_metamodel/operations/glucose3_valid.py +++ b/flamapy/metamodels/pysat_metamodel/operations/pysat_valid.py @@ -8,7 +8,7 @@ from flamapy.core.models import VariabilityModel -class Glucose3Valid(Valid): +class PySATValid(Valid): def __init__(self) -> None: self.result = False @@ -20,7 +20,7 @@ def is_valid(self) -> bool: def get_result(self) -> bool: return self.is_valid() - def execute(self, model: VariabilityModel) -> 'Glucose3Valid': + def execute(self, model: VariabilityModel) -> 'PySATValid': model = cast(PySATModel, model) for clause in model.get_all_clauses(): # AC es conjunto de conjuntos diff --git a/flamapy/metamodels/pysat_metamodel/operations/glucose3_valid_configuration.py b/flamapy/metamodels/pysat_metamodel/operations/pysat_valid_configuration.py similarity index 90% rename from flamapy/metamodels/pysat_metamodel/operations/glucose3_valid_configuration.py rename to flamapy/metamodels/pysat_metamodel/operations/pysat_valid_configuration.py index f70410b..25fcd1f 100644 --- a/flamapy/metamodels/pysat_metamodel/operations/glucose3_valid_configuration.py +++ b/flamapy/metamodels/pysat_metamodel/operations/pysat_valid_configuration.py @@ -10,7 +10,7 @@ from flamapy.core.models import VariabilityModel -class Glucose3ValidConfiguration(ValidConfiguration): +class PySATValidConfiguration(ValidConfiguration): def __init__(self) -> None: self.result = False @@ -26,7 +26,7 @@ def get_result(self) -> bool: def set_configuration(self, configuration: Configuration) -> None: self.configuration = configuration - def execute(self, model: VariabilityModel) -> 'Glucose3ValidConfiguration': + def execute(self, model: VariabilityModel) -> 'PySATValidConfiguration': model = cast(PySATModel, model) for clause in model.get_all_clauses(): # AC es conjunto de conjuntos diff --git a/flamapy/metamodels/pysat_metamodel/operations/glucose3_valid_product.py b/flamapy/metamodels/pysat_metamodel/operations/pysat_valid_product.py similarity index 93% rename from flamapy/metamodels/pysat_metamodel/operations/glucose3_valid_product.py rename to flamapy/metamodels/pysat_metamodel/operations/pysat_valid_product.py index fde5a0a..3964cd1 100644 --- a/flamapy/metamodels/pysat_metamodel/operations/glucose3_valid_product.py +++ b/flamapy/metamodels/pysat_metamodel/operations/pysat_valid_product.py @@ -9,7 +9,7 @@ from flamapy.core.models import VariabilityModel -class Glucose3ValidProduct(ValidProduct): +class PySATValidProduct(ValidProduct): def __init__(self) -> None: self.result = False @@ -25,7 +25,7 @@ def get_result(self) -> bool: def set_configuration(self, configuration: Configuration) -> None: self.configuration = configuration - def execute(self, model: VariabilityModel) -> 'Glucose3ValidProduct': + def execute(self, model: VariabilityModel) -> 'PySATValidProduct': model = cast(PySATModel, model) for clause in model.get_all_clauses(): # AC es conjunto de conjuntos diff --git a/flamapy/metamodels/pysat_metamodel/transformations/fm_to_pysat.py b/flamapy/metamodels/pysat_metamodel/transformations/fm_to_pysat.py index b2e8a07..df9bcd9 100644 --- a/flamapy/metamodels/pysat_metamodel/transformations/fm_to_pysat.py +++ b/flamapy/metamodels/pysat_metamodel/transformations/fm_to_pysat.py @@ -24,6 +24,7 @@ def __init__(self, source_model: FeatureModel) -> None: self.source_model = source_model self.counter = 1 self.destination_model = PySATModel() + self.destination_model.original_model =source_model # self.r_cnf = self.destination_model.r_cnf # self.ctc_cnf = self.destination_model.ctc_cnf