Exemple #1
0
def random_sampling(simulations: int, input_fm_name: str,
                    input_fm_cnf_name: str, mcts_stats_its):
    print(
        "Problem 1 (Random sampling): Finding defective configurations in the AAFMs Python Framework feature model."
    )
    print(
        "----------------------------------------------------------------------------------------------------"
    )

    print("Setting up the problem...")

    print("Creating output folders...")
    if not os.path.exists(OUTPUT_RESULTS_PATH):
        os.makedirs(OUTPUT_RESULTS_PATH)
    if not os.path.exists(HEATMAP_PATH):
        os.makedirs(HEATMAP_PATH)
    if not os.path.exists(STATS_PATH):
        os.makedirs(STATS_PATH)

    input_fm = INPUT_PATH + input_fm_name + ".xml"

    print(f"Loading feature model: {input_fm_name} ...")
    fide_parser = FeatureIDEParser(input_fm, no_read_constraints=True)
    fm = fide_parser.transform()
    print(
        f"Feature model loaded with {len(fm.get_features())} features, {len(fm.get_constraints())} constraints, {len(fm.get_relations())} relations."
    )

    # Read the feature model as CNF model with complex constraints
    cnf_reader = CNFReader(INPUT_PATH + input_fm_cnf_name + ".txt")
    cnf_model = cnf_reader.transform()

    # AAFMs
    aafms_helper = AAFMsHelper(fm, cnf_model)
    all_configurations = aafms_helper.get_configurations()
    total_time_start = time.time()
    if simulations > len(all_configurations):
        simulations = len(all_configurations)
    sample = random.sample(all_configurations, simulations)
    defective_configurations = [c for c in sample if count_errors(fm, c) > 0]
    total_time_end = time.time()
    mcts_stats_its.add_step('Random Sampling', 0, {}, simulations, len(sample),
                            len(defective_configurations),
                            total_time_end - total_time_start)
    def reward(self) -> float:
        """
        Two objective function as defined in Lopez-Herrejon2015 [JSS] - An assessment of search-based techniques for reverse engineering FMs.
            1. Relaxed: Express the concern of capturing primarily the configurations provided.
                Its value is the number of configurations (self.configurations) that are valid according to the feature model represented by this state.
                We want to maximize this value.
            2. Minimal Difference (MinDiff): Express the concern of obtaining a closer-fit to the configurations provided (other configurations are not relevant).
                Its value is 'deficit' + 'surplus' where:
                    'deficit' is the number of configurations (self.configurations) that are not contained in the configuration of the feature model.
                    'surplus' is the number of configurations of the feature model that are not contained in the required configuration (self.configurations).
                We want to minimize this value.
        """
        aafms_helper = AAFMsHelper(self.feature_model)
        #configurations_captured = aafms_helper.get_configurations()
        relaxed_value = reduce(lambda count, c: count + (aafms_helper.is_valid_configuration(c)), self.configurations, 0)
        #deficit_value = reduce(lambda count, c: count + (c not in configurations_captured), self.configurations, 0)
        #surplus_value = reduce(lambda count, c: count + (c not in self.configurations), configurations_captured, 0)

        return relaxed_value #- (deficit_value + surplus_value)
Exemple #3
0
def main(algorithm, simulations: int, mcts_stats_its):
    print("Problem 1 (simulated): Finding defective configurations in the jHipster feature model.")
    print("--------------------------------------------------------------------------------------")

    print("Setting up the problem...")
    
    print("Creating output folders...")
    if not os.path.exists(OUTPUT_RESULTS_PATH):
        os.makedirs(OUTPUT_RESULTS_PATH)
    if not os.path.exists(HEATMAP_PATH):
        os.makedirs(HEATMAP_PATH)
    if not os.path.exists(STATS_PATH):
        os.makedirs(STATS_PATH)

    print(f"Loading feature model: {jhipster.FM_FILE} ...")
    fide_parser = FeatureIDEParser(jhipster.FM_FILE, no_read_constraints=True)
    fm = fide_parser.transform()
    print(f"Feature model loaded with {len(fm.get_features())} features, {len(fm.get_constraints())} constraints, {len(fm.get_relations())} relations.")
    
    # Read the feature model as CNF model with complex constraints
    cnf_reader = CNFReader(jhipster.CNF_FILE)
    cnf_model = cnf_reader.transform()
    
    # AAFMs
    aafms_helper = AAFMsHelper(fm, cnf_model)

    print(f"Creating set of actions...")
    actions = TreeActionsList(fm)
    print(f"{actions.get_nof_actions()} actions.")

    problem_data = ProblemData(fm, aafms_helper, actions)

    # Read the jhipster configurations as a dict of FMConfiguration -> bool (failure)
    jhipster_configurations = jhipster.read_jHipster_feature_model_configurations()
    problem_data.jhipster_configurations = jhipster_configurations
    problem_data.sample = defaultdict(bool)

    print(f"Creating initial state (configuration)...")
    initial_config = FMConfiguration()
    initial_state = FailureConfigurationState(configuration=initial_config, data=problem_data)
    print(f"Initial state: {initial_state}")

    print("Problem setted up.")

    print(f"Running algorithm {str(algorithm)}...")

    # Stats
    mcts_stats = MCTSStats()

    n = 0
    total_evaluations = 0
    state = initial_state
    total_time_start = time.time()
    while state.reward() <= 0 and state.get_actions():
        print(f"Input state {n}: {str(state)} -> valid={state.is_valid_configuration}, R={state.reward()}")
        time_start = time.time()
        new_state = algorithm.run(state)
        time_end = time.time()

        if isinstance(algorithm, MonteCarloTreeSearch):  
            # Heat map (only for MCTS)
            heatmap = Heatmap(fm, algorithm.tree, algorithm.Q, algorithm.N, state)
            heatmap.extract_feature_knowledge()
            heatmap.serialize(HEATMAP_PATH + jhipster.FM_FILENAME + "-step" + str(n) + ".csv")
        else:
            algorithm.tree = {} 

        # Stats
        mcts_stats.add_step(n, algorithm.tree, state, new_state, simulations, algorithm.n_evaluations, algorithm.n_positive_evaluations, time_end-time_start)
        total_evaluations += algorithm.n_evaluations
        algorithm.n_evaluations = 0

        state = new_state
        n += 1
        
    total_time_end = time.time()
    print("Algorithm finished.")
    print(f"Final state {n}: {str(state)} -> valid={state.is_valid_configuration}, R={state.reward()}")

    # Stats
    print("Serializing results...")
    mcts_stats.serialize(STATS_PATH + jhipster.FM_FILENAME + '-steps.csv')
    mcts_stats_its.add_step(str(algorithm), n, algorithm.tree, simulations, total_evaluations, algorithm.n_positive_evaluations, total_time_end-total_time_start)
    #mcts_stats_its.serialize(STATS_PATH + jhipster.FM_FILENAME + '-summary.csv')

    print("Done!")
Exemple #4
0
def main(algorithm, simulations: int, input_fm: str, input_cnf_model: str=None):
    print("Problem: Reverse engineering of feature models.")
    print("-----------------------------------------------")

    base = os.path.basename(input_fm)
    input_fm_name = os.path.splitext(base)[0]

    print("Setting up the problem...")

    print("Creating output folders...")
    if not os.path.exists(HEATMAP_PATH):
        os.makedirs(HEATMAP_PATH)
    if not os.path.exists(STATS_PATH):
        os.makedirs(STATS_PATH)
    if not os.path.exists(GENERATED_FMS_PATH):
        os.makedirs(GENERATED_FMS_PATH)

    print(f"Loading feature model: {input_fm_name} ...")
    fide_parser = FeatureIDEParser(input_fm, no_read_constraints=(input_cnf_model is not None))
    fm = fide_parser.transform()
    print(f"Feature model loaded with {len(fm.get_features())} features, {len(fm.get_constraints())} constraints, {len(fm.get_relations())} relations.")

    if input_cnf_model is not None:
        # Read the feature model as CNF model with complex constraints
        cnf_reader = CNFReader(input_cnf_model)
        cnf_model = cnf_reader.transform()
    else:
        cnf_model = None
    
    # Get configurations
    print("Generating configurations of the feature model...")
    aafms_helper = AAFMsHelper(fm, cnf_model)
    configurations = aafms_helper.get_configurations()
    print(f"#Configurations: {len(configurations)}")

    print(f"Creating initial state (empty feature model)...")
    initial_state = FMState(FeatureModel(None), configurations)

    print("Problem setted up.")

    print(f"Running algorithm {str(algorithm)}...")
    
    # Stats
    mcts_stats_re = MCTSStatsRE(STATS_PATH + input_fm_name + "-ReverseEngineering.log")

    n = 0
    state = initial_state
    total_time_start = time.time()
    while not state.is_terminal():
        print(f"State {n}: {[str(f) for f in state.feature_model.get_features()]} -> {state.reward()}")
        start_time = time.time()
        new_state = algorithm.run(state)
        end_time = time.time()
        
        if isinstance(algorithm, MonteCarloTreeSearch):  
            mcts_stats_re.add_step(n, algorithm.tree, algorithm.Q, algorithm.N, state, new_state, simulations, end_time-start_time)
        else:
            algorithm.tree = {} 
        state = new_state
        n += 1

    total_time_end = time.time()
    print("Algorithm finished.")
    print(f"Final State {n}: {[str(f) for f in state.feature_model.get_features()]} -> {state.reward()}")

    # Get configurations
    path = GENERATED_FMS_PATH + state.feature_model.root.name + "." + UVLWritter.get_destination_extension()
    print(f"Serializing generated feature model in UVL format in {path}")
    uvl_writter = UVLWritter(path=path, source_model=state.feature_model)
    uvl_writter.transform()

    # Get configurations
    print("Generating configurations of the extracted feature model...")
    aafms_helper = AAFMsHelper(state.feature_model)
    new_configurations = aafms_helper.get_configurations()
    
    print("Results:")
    print(f"#Features: {len(state.feature_model.get_features())} -> {[str(f) for f in state.feature_model.get_features()]}")
    print(f"#Configurations: {len(new_configurations)}")

    relaxed_value = reduce(lambda count, c: count + (aafms_helper.is_valid_configuration(c)), configurations, 0)
    deficit_value = reduce(lambda count, c: count + (c not in new_configurations), configurations, 0)
    surplus_value = reduce(lambda count, c: count + (c not in configurations), new_configurations, 0)
    print(f"Input configurations captured (Relaxed objective function): {relaxed_value}")
    print(f"Deficit of configurations: {deficit_value}")
    print(f"Irrelevant configurations: {surplus_value}")
    print(f"Mininal difference (MinDiff) objective function (deficit_value + surplus_value): {deficit_value} + {surplus_value} = {deficit_value+surplus_value}")
    print(f"Final objective function (Relaxed - MinDiff): {relaxed_value - (deficit_value+surplus_value)}")
    print(f"Execution time: {total_time_end-total_time_start}")
def main(algorithm,
         simulations: int,
         input_fm: str,
         input_cnf_model: str = None,
         initial_config_features: list[str] = [],
         minimum: bool = False):
    print("Problem: Completion of partial configurations.")
    print("----------------------------------------------")

    print("Setting up the problem...")

    print("Creating output folders...")
    if not os.path.exists(OUTPUT_RESULTS_PATH):
        os.makedirs(OUTPUT_RESULTS_PATH)
    if not os.path.exists(HEATMAP_PATH):
        os.makedirs(HEATMAP_PATH)
    if not os.path.exists(STATS_PATH):
        os.makedirs(STATS_PATH)

    base = os.path.basename(input_fm)
    input_fm_name = os.path.splitext(base)[0]

    print(f"Loading feature model: {input_fm} ...")
    fide_parser = FeatureIDEParser(input_fm,
                                   no_read_constraints=(input_cnf_model
                                                        is not None))
    fm = fide_parser.transform()
    print(
        f"Feature model loaded with {len(fm.get_features())} features, {len(fm.get_constraints())} constraints, {len(fm.get_relations())} relations."
    )

    if input_cnf_model is not None:
        # Read the feature model as CNF model with complex constraints
        cnf_reader = CNFReader(input_cnf_model)
        cnf_model = cnf_reader.transform()
    else:
        cnf_model = None

    # AAFMs
    aafms_helper = AAFMsHelper(fm, cnf_model)

    print(f"Creating set of actions...")
    actions = TreeActionsList(fm)
    print(f"{actions.get_nof_actions()} actions.")

    problem_data = ProblemData(fm, aafms_helper, actions)

    print(f"Creating initial state (configuration)...")
    if initial_config_features:
        elements = {}
        for feature in [
                fm.get_feature_by_name(f) for f in initial_config_features
        ]:
            elements[feature] = True
            for p in fm_utils.select_parent_features(feature):
                elements[p] = True
        initial_config = FMConfiguration(elements=elements)
    else:
        initial_config = FMConfiguration()

    if minimum:
        initial_state = ValidMinimumConfigurationState(
            configuration=initial_config, data=problem_data)
    else:
        initial_state = ValidConfigurationState(configuration=initial_config,
                                                data=problem_data)

    print(f"Initial state: {initial_state}")
    print("Problem setted up.")

    print(f"Running algorithm {str(algorithm)}...")

    # Stats
    mcts_stats = MCTSStats()
    mcts_stats_its = MCTSStatsIts()

    n = 0
    total_evaluations = 0
    state = initial_state
    total_time_start = time.time()
    while not state.is_terminal():
        print(
            f"Input state {n}: {str(state)} -> valid={state.is_valid_configuration}, R={state.reward()}"
        )
        time_start = time.time()
        new_state = algorithm.run(state)
        time_end = time.time()

        if isinstance(algorithm, MonteCarloTreeSearch):
            # Heat map (only for MCTS)
            heatmap = Heatmap(fm, algorithm.tree, algorithm.Q, algorithm.N,
                              state)
            heatmap.extract_feature_knowledge()
            heatmap.serialize(HEATMAP_PATH + input_fm_name + "-step" + str(n) +
                              ".csv")
        else:
            algorithm.tree = {}

        # Stats
        mcts_stats.add_step(n, algorithm.tree, state, new_state, simulations,
                            algorithm.n_evaluations,
                            algorithm.n_positive_evaluations,
                            time_end - time_start)
        total_evaluations += algorithm.n_evaluations
        algorithm.n_evaluations = 0

        state = new_state
        n += 1

    total_time_end = time.time()
    print("Algorithm finished.")
    print(
        f"Final state {n}: {str(state)} -> valid={state.is_valid_configuration}, R={state.reward()}"
    )

    # Stats
    print("Serializing results...")
    mcts_stats.serialize(STATS_PATH + input_fm_name + '-steps.csv')
    mcts_stats_its.add_step(str(algorithm), n, algorithm.tree, simulations,
                            total_evaluations,
                            algorithm.n_positive_evaluations,
                            total_time_end - total_time_start)
    mcts_stats_its.serialize(STATS_PATH + input_fm_name + '-summary.csv')

    # Heat for the whole process (not sure about its utility)
    if isinstance(algorithm, MonteCarloTreeSearch):
        heatmap = HeatmapFull(fm, algorithm.tree, algorithm.Q, algorithm.N)
        heatmap.extract_feature_knowledge()
        heatmap.serialize(HEATMAP_PATH + input_fm_name + "-full.csv")

    print("Done!")