aboutsummaryrefslogtreecommitdiffstats
path: root/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/objectives/impl/CompositeObjective.java
blob: cc48d22e9f4ff3ce6f02a6684ce8c6a61ba91ed8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*******************************************************************************
 * Copyright (c) 2010-2014, Miklos Foldenyi, Andras Szabolcs Nagy, Abel Hegedus, Akos Horvath, Zoltan Ujhelyi and Daniel Varro
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-v20.html.
 * 
 * SPDX-License-Identifier: EPL-2.0
 *******************************************************************************/
package org.eclipse.viatra.dse.objectives.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import org.eclipse.viatra.dse.base.ThreadContext;
import org.eclipse.viatra.dse.objectives.IObjective;
import org.eclipse.viatra.query.runtime.matchers.util.Preconditions;

/**
 * This objective collects a list of other objectives. It returns the weighted sum of the objectives.
 * 
 * @author Andras Szabolcs Nagy
 *
 */
public class CompositeObjective extends BaseObjective {

    public static final String DEFAULT_NAME = "CompositeObjective";
    protected List<IObjective> objectives;
    protected List<Double> weights;
    protected boolean hardObjective;

    public CompositeObjective(String name, List<IObjective> objectives, List<Double> weights) {
        super(name);
        Objects.requireNonNull(objectives, "The list of objectives cannot be null.");
        Objects.requireNonNull(weights, "The list of weights cannot be null.");
        Preconditions.checkState(objectives.size() == weights.size(), "The size of the objectives and weights must match.");
        this.objectives = objectives;
        this.weights = weights;
    }

    public CompositeObjective(List<IObjective> objectives, List<Double> weights) {
        this(DEFAULT_NAME, objectives, weights);
    }

    public CompositeObjective(String name) {
        this(name, new ArrayList<IObjective>(), new ArrayList<Double>());
    }

    public CompositeObjective() {
        this(DEFAULT_NAME, new ArrayList<IObjective>(), new ArrayList<Double>());
    }

    /**
     * Adds a new objective.
     * 
     * @param objective
     * @return The actual instance to enable builder pattern like usage.
     */
    public CompositeObjective withObjective(IObjective objective) {
        objectives.add(objective);
        weights.add(1d);
        return this;
    }

    /**
     * Adds a new objective.
     * 
     * @param objective
     * @return The actual instance to enable builder pattern like usage.
     */
    public CompositeObjective withObjective(IObjective objective, double weight) {
        objectives.add(objective);
        weights.add(weight);
        return this;
    }

    @Override
    public Double getFitness(ThreadContext context) {

        double result = 0;

        for (int i = 0; i < objectives.size(); i++) {
            IObjective objective = objectives.get(i);
            Double weight = weights.get(i);
            result += objective.getFitness(context) * weight;
        }
        return result;
    }

    @Override
    public void init(ThreadContext context) {
        super.init(context);
        hardObjective = false;
        for (IObjective objective : objectives) {
            objective.init(context);
            if (objective.isHardObjective()) {
                hardObjective = true;
            }
        }
    }

    @Override
    public IObjective createNew() {

        List<IObjective> newObjectives = new ArrayList<IObjective>();

        for (IObjective objective : objectives) {
            newObjectives.add(objective.createNew());
        }

        CompositeObjective objective = new CompositeObjective(name, newObjectives, weights);
        if (isThereFitnessConstraint) {
            objective.withHardConstraintOnFitness(fitnessConstraint, fitnessConstraintComparator);
        }

        return objective.withComparator(comparator).withLevel(level);
    }

    @Override
    public boolean isHardObjective() {
        return hardObjective;
    }

    @Override
    public boolean satisifiesHardObjective(Double fitness) {

        boolean hardObjectiveSatisfied = true;

        for (IObjective objective : objectives) {
            hardObjectiveSatisfied = objective.satisifiesHardObjective(fitness) ? hardObjectiveSatisfied : false;
        }

        hardObjectiveSatisfied = super.satisifiesHardObjective(fitness) ? hardObjectiveSatisfied : false;

        return hardObjectiveSatisfied;
    }
}