blob: e80f77c9b91a19e102def5bba1b8e053320051ec [file] [log] [blame]
/*********************************************************************
* Copyright (c) 2008 The University of York.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
package org.eclipse.epsilon.flexmi;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class AssignmentCalculator {
public static void main(String[] args) {
Map<Object, Object> assignment = new AssignmentCalculator().calculateAssignment(Arrays.asList(10, 20), Arrays.asList(5,6,7), (left, right) -> {
int leftInt = (Integer) left;
int rightInt = (Integer) right;
if (leftInt > rightInt) {
return rightInt / (float) leftInt;
}
else {
return -1;
}
});
for (Object key : assignment.keySet()) {
System.out.println(key + "->" + assignment.get(key));
}
}
public Map<Object, Object> calculateAssignment(List<?> leftList, List<?> rightList, AssignmentScorer scorer) {
ArrayList<?> leftArrayList = toArrayList(leftList);
ArrayList<?> rightArrayList = toArrayList(rightList);
List<Assignment> bestAssignment = null;
float maxScore = Float.NEGATIVE_INFINITY;
for (List<Assignment> assignmentList : calculateAssignments(leftArrayList, rightArrayList)) {
float score = 0;
for (Assignment assignment : assignmentList) {
score += scorer.score(assignment.getLeft(), assignment.getRight());
}
if (score > maxScore) {
maxScore = score;
bestAssignment = assignmentList;
}
}
HashMap<Object, Object> map = new HashMap<>();
if (bestAssignment != null) {
for (Assignment assignment : bestAssignment) {
if (scorer.score(assignment.getLeft(), assignment.getRight()) >= 0) {
map.put(assignment.getLeft(), assignment.getRight());
}
}
}
return map;
}
private static ArrayList<?> toArrayList(List<?> list) {
if (list instanceof ArrayList<?>) {
return (ArrayList<?>) list;
}
else {
return new ArrayList<Object>(list);
}
}
private ArrayList<ArrayList<Assignment>> calculateAssignments(ArrayList<?> leftList, ArrayList<?> rightList) {
Tree<Assignment> root = new Tree<>();
calculateAssignments(root, leftList, rightList);
ArrayList<ArrayList<Tree<Assignment>>> allPaths = root.getAllPaths();
ArrayList<ArrayList<Assignment>> assignmentLists = new ArrayList<>(allPaths.size());
for (ArrayList<Tree<Assignment>> path : allPaths) {
ArrayList<Assignment> assignmentList = new ArrayList<>(path.size());
for (Tree<Assignment> tree : path) {
assignmentList.add(tree.getValue());
}
assignmentLists.add(assignmentList);
}
return assignmentLists;
}
private void calculateAssignments(Tree<Assignment> parent, ArrayList<?> leftList, ArrayList<?> rightList) {
if (leftList.isEmpty()) return;
Object firstLeft = leftList.get(0);
for (Object right : rightList) {
Tree<Assignment> tree = new Tree<>();
tree.setValue(new Assignment(firstLeft, right));
parent.getChildren().add(tree);
ArrayList<Object> newLeftList = (ArrayList<Object>) leftList.clone();
newLeftList.remove(firstLeft);
ArrayList<Object> newRightList = (ArrayList<Object>) rightList.clone();
newRightList.remove(right);
calculateAssignments(tree, newLeftList, newRightList);
}
}
public interface AssignmentScorer {
public float score(Object left, Object right);
}
class Tree<T> {
protected ArrayList<Tree<T>> children = new ArrayList<>();
protected T value;
public List<Tree<T>> getChildren() {
return children;
}
public ArrayList<ArrayList<Tree<T>>> getAllPaths() {
ArrayList<ArrayList<Tree<T>>> allPaths = new ArrayList<>();
for (Tree<T> child : getChildren()) {
ArrayList<Tree<T>> path = new ArrayList<>();
path.add(child);
collectAllPaths(path, allPaths);
}
return allPaths;
}
public void collectAllPaths(ArrayList<Tree<T>> path, ArrayList<ArrayList<Tree<T>>> allPaths) {
Tree<T> lastElement = path.get(path.size()-1);
if (lastElement.getChildren().isEmpty()) {
allPaths.add(path);
}
else {
for (Tree<T> child : lastElement.getChildren()) {
ArrayList<Tree<T>> newPath = new ArrayList<>((List) path.clone());
newPath.add(child);
collectAllPaths(newPath, allPaths);
}
}
}
public void setValue(T value) {
this.value = value;
}
public T getValue() {
return value;
}
}
private class Assignment {
protected Object left;
protected Object right;
public Assignment(Object left, Object right) {
this.left = left;
this.right = right;
}
public Object getLeft() {
return left;
}
public Object getRight() {
return right;
}
@Override
public String toString() {
return left + " -> " + right;
}
}
}