Example #1
0
class CNFReader(TextToModel):
    """
    Read a CNF formula representing a feature model.
    The expected format is the generated by FeatureIDE as Textual Symbols:
    (feature1) and (not feature2 or feature3) and (not feature4 or feature5) and...
    """
    @staticmethod
    def get_source_extension() -> str:
        return 'txt'

    def __init__(self, path: str):
        self._path = path
        self.counter = 1
        self.destination_model = PySATModel()
        self.cnf = self.destination_model.cnf

    def transform(self) -> PySATModel:
        self._read_clauses(self._path)
        return self.destination_model

    def _add_feature(self, feature_name):
        if feature_name not in self.destination_model.variables.keys():
            self.destination_model.variables[feature_name] = self.counter
            self.destination_model.features[self.counter] = feature_name
            self.counter += 1

    def _read_clauses(self, filepath: str):
        with open(filepath) as file:
            cnf_line = file.readline()
            clauses = list(
                map(lambda c: c[1:len(c) - 1], cnf_line.split(
                    ' and ')))  # Remove initial and final parenthesis
            if ')' in clauses[len(clauses) - 1]:
                clauses[len(clauses) - 1] = clauses[
                    len(clauses) -
                    1][:
                       -1]  # Remove final parenthesis of last clause (because of '\n')
            for c in clauses:
                tokens = c.split(' ')
                tokens = list(filter(lambda t: t != 'or', tokens))
                logic_not = False
                cnf_clause = []
                for feature in tokens:
                    if feature == 'not':
                        logic_not = True
                    else:
                        self._add_feature(feature)
                        if logic_not:
                            cnf_clause.append(
                                -1 * self.destination_model.variables[feature])
                        else:
                            cnf_clause.append(
                                self.destination_model.variables[feature])
                        logic_not = False
                self.destination_model.add_constraint(cnf_clause)
Example #2
0
    def execute(self, model: PySATModel) -> 'Glucose3ValidProduct':
        glucose = Glucose3()
        for clause in model.get_all_clauses():  # AC es conjunto de conjuntos
            glucose.add_clause(clause)  # añadimos la constraint

        assumptions = []

        config: list[str] = []
        if self.configuration is not None:
            config = [feat.name for feat in self.configuration.elements]

        for feat in config:
            if feat not in model.variables.keys():
                self.result = False
                return self

        for feat in model.features.values():
            if feat in config:
                assumptions.append(model.variables[feat])
            else:
                assumptions.append(-model.variables[feat])

        self.result = glucose.solve(assumptions=assumptions)
        glucose.delete()
        return self
 def execute(self, model: PySATModel) -> 'Glucose3Valid':
     glucose = Glucose3()
     for clause in model.get_all_clauses():  # AC es conjunto de conjuntos
         glucose.add_clause(clause)  # añadimos la constraint
     self.result = glucose.solve()
     glucose.delete()
     return self
    def execute(self, model: PySATModel) -> 'Glucose3ProductsNumber':
        glucose = Glucose3()
        for clause in model.get_all_clauses():  # AC es conjunto de conjuntos
            glucose.add_clause(clause)  # añadimos la constraint

        for _ in glucose.enum_models():
            self.products_number += 1
        glucose.delete()
        return self
    def execute(self, model: PySATModel) -> 'Glucose3DeadFeatures':
        glucose = Glucose3()

        for clause in model.get_all_clauses():  # AC es conjunto de conjuntos
            glucose.add_clause(clause)  # añadimos la constraint

        dead_features = []
        for variable in model.variables.items():
            if not glucose.solve(assumptions=[variable[1]]):
                dead_features.append(variable[0])
        self.dead_features = dead_features
        glucose.delete()
        return self
Example #6
0
    def execute(self, model: PySATModel) -> 'Glucose3Products':
        glucose = Glucose3()

        for clause in model.get_all_clauses():  # AC es conjunto de conjuntos
            glucose.add_clause(clause)  # añadimos la constraint

        for solutions in glucose.enum_models():
            product = []
            for variable in solutions:
                if variable > 0:
                    product.append(model.features.get(variable))
            self.products.append(product)
        glucose.delete()
        return self
    def execute(self, model: PySATModel) -> 'Glucose3ValidConfiguration':
        glucose = Glucose3()

        for clause in model.get_all_clauses():  # AC es conjunto de conjuntos
            glucose.add_clause(clause)  # añadimos la constraint

        assumptions = []
        for feat in self.configuration.elements.items():
            if feat[1]:
                assumptions.append(model.variables[feat[0].name])
            elif not feat[1]:
                assumptions.append(-model.variables[feat[0].name])

        self.result = glucose.solve(assumptions=assumptions)
        glucose.delete()
        return self
def get_false_optional_features(sat_model: PySATModel, feature_model: FeatureModel) -> list[Any]:
    real_optional_features = [f for f in feature_model.get_features() 
                              if not f.is_root() and not f.is_mandatory()]

    result = []
    solver = Glucose3()
    for clause in sat_model.get_all_clauses():
        solver.add_clause(clause)

    for feature in real_optional_features:
        variable = sat_model.variables.get(feature.name)
        parent_variable = sat_model.variables.get(feature.get_parent().name)
        assert variable is not None
        satisfiable = solver.solve(assumptions=[parent_variable, -variable])
        if not satisfiable:
            result.append(feature.name)
    solver.delete()
    return result
Example #9
0
    def execute(self, model: PySATModel) -> 'Glucose3Filter':
        glucose = Glucose3()
        for clause in model.get_all_clauses():  # AC es conjunto de conjuntos
            glucose.add_clause(clause)  # añadimos la constraint

        assumptions = [
            model.variables.get(feat[0].name)
            if feat[1] else -model.variables.get(feat[0].name)
            for feat in self.configuration.elements.items()
        ]

        for solution in glucose.enum_models(assumptions=assumptions):
            product = []
            for variable in solution:
                if variable > 0:
                    product.append(model.features.get(variable))
            self.filter_products.append(product)
        glucose.delete()
        return self
Example #10
0
 def __init__(self, path: str):
     self._path = path
     self.counter = 1
     self.destination_model = PySATModel()
     self.cnf = self.destination_model.cnf
Example #11
0
from famapy.metamodels.fm_metamodel.transformations.xml_transformation import XMLTransformation

from famapy.metamodels.pysat_metamodel.models.pysat_model import PySATModel
from famapy.metamodels.pysat_metamodel.operations.glucose3_products import Glucose3Products
from famapy.metamodels.pysat_metamodel.operations.glucose3_valid import Glucose3Valid
from famapy.metamodels.pysat_metamodel.transformations.fm_to_pysat import FmToPysat

# Parse a file
xmlreader = XMLTransformation("example.fama")
fm = xmlreader.transform()

# print the model
print(fm)

# Create a detination metamodel (Pysat for the record)
sat = PySATModel()

# Transform the first onto the second
transform = FmToPysat(fm, sat)
transform.transform()

# Create the operation
valid = Glucose3Valid()

# Execute the operation . TODO Investigate how t avoid that sat parameter
valid.execute(sat)

# Print the result
print("Is the model valid: " + str(valid.isValid()))

# Create the operation
Example #12
0
 def __init__(self, source_model: VariabilityModel):
     self.source_model = source_model
     self.counter = 1
     self.destination_model = PySATModel()
     self.r_cnf = self.destination_model.r_cnf
     self.ctc_cnf = self.destination_model.ctc_cnf
class CNFReader(TextToModel):
    """
    Read a CNF formula as a string representing a feature model.

    The expected format is the generated by FeatureIDE when exporting the model as CNF (.txt).
    That generates a file with the CNF formula in four different notations:
        Logical Symbols:
            (A) ∧ (¬B ∨ C) ∧ ...
        Textual Symbols:
            (A) and (not B or C) and ...
        Java Symbols:
            (A) && (!B || C) && ...
        Short Symbols:
            (A) & (-B | C) & ...
    This class is able to read any of these notations, but only one notation,
    so the .txt file should be modified to include only
    one of those notations by removing the others.
    """
    @staticmethod
    def get_source_extension() -> str:
        return 'txt'

    def __init__(self, path: str):
        self._path = path
        self.counter = 1
        self.destination_model = PySATModel()

    def transform(self) -> PySATModel:
        cnf_model = TextCNFModel()
        cnf_model.from_textual_cnf_file(self._path)
        cnf_notation = cnf_model.get_textual_cnf_notation()
        cnf_formula = cnf_model.get_textual_cnf_formula(cnf_notation)

        self._extract_clauses(cnf_formula, cnf_notation)
        return self.destination_model

    def _add_feature(self, feature_name: str) -> None:
        if feature_name not in self.destination_model.variables:
            self.destination_model.variables[feature_name] = self.counter
            self.destination_model.features[self.counter] = feature_name
            self.counter += 1

    def _extract_clauses(self, cnf_formula: str,
                         cnf_notation: TextCNFNotation) -> None:
        and_symbol_pattern = ' ' + cnf_notation.value[
            CNFLogicConnective.AND] + ' '
        clauses = list(
            map(lambda c: c[1:len(c) - 1],
                cnf_formula.split(and_symbol_pattern)))
        # Remove initial and final parenthesis

        # Remove final parenthesis of last clause (because of the possible end of line: '\n')
        if ')' in clauses[len(clauses) - 1]:
            clauses[len(clauses) - 1] = clauses[len(clauses) - 1][:-1]

        for _c in clauses:
            tokens = _c.split(' ')
            tokens = list(
                filter(
                    lambda t: t != cnf_notation.value[CNFLogicConnective.OR],
                    tokens))
            logic_not = False
            cnf_clause = []
            for feature in tokens:
                if feature == cnf_notation.value[CNFLogicConnective.NOT]:
                    logic_not = True
                elif feature.startswith(
                        cnf_notation.value[CNFLogicConnective.NOT]):
                    feature = feature.replace(
                        cnf_notation.value[CNFLogicConnective.NOT], '', 1)
                    self._add_feature(feature)
                    cnf_clause.append(
                        -1 * self.destination_model.variables[feature])
                else:
                    self._add_feature(feature)
                    if logic_not:
                        cnf_clause.append(
                            -1 * self.destination_model.variables[feature])
                    else:
                        cnf_clause.append(
                            self.destination_model.variables[feature])
                    logic_not = False
            self.destination_model.add_clause(cnf_clause)