Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matching algorithm

I have a list of pencils and a list of erasers. The goal it to check whether or not all the erasers can be put on pencils. An eraser may fit on multiple different pencils. Pencils can have at most 1 eraser.

If I just loop through all the erasers and put them on pencils, I end up with erasers that fit no unoccupied pencils even though there is a solution that has all the erasers on pencils.

What algorithm could I use to figure out a combination that fits all the erasers on pencils?

public class Eraser(){
    public boolean matches(Pencil p){
    //unimportant
    }
}

public class Pencil(){
}

My attempt

public boolean doMatch(List<Eraser> erasers, List<Pencil> pencils){
for (Eraser e : erasers) {
        boolean found = false;
        Iterator it = pencils.iterator();
        while (it.hasNext()) {
            Pencil p = (Pencil) it.next();
            if (e.matches(p)) {
                found = true;
                it.remove();
                break;
            }
        }
        if (!found) {
            return false;
        }
}
return true;
}
like image 531
user3552325 Avatar asked Oct 03 '15 17:10

user3552325


People also ask

What is best matching algorithm?

BM25 [5] is the Best Matching ranking algorithm that ranks the documents according to its relevance to the given search query.

What is matching in machine learning?

What Is Data Matching? (With Machine Learning) At a high level data matching is the process of comparing data such as product data, user data, customer data, etc based on similarity by some metric.

What is matching problem in graph theory?

One of the basic problems in matching theory is to find in a given graph all edges that may be extended to a maximum matching in the graph (such edges are called maximally-matchable edges, or allowed edges). Algorithms for this problem include: For general graphs, a deterministic algorithm in time.

How do you evaluate a matching algorithm?

To evaluate your matching algorithm, you may manually identify some landmarks (keypoint) in the first image (X1) and their correspondence in the second image(Xac). Given the landmarks of the first image(X1), use your matching algorithm to find their correspondence in the second image (Xm).


2 Answers

You can formulate the problem as Constraint satisfaction problem

The variables would be e.g.

X_i=eraser put on pencil i

the domains

D_i=erasers fitting on pencil i

and the constraints are

X_i != X_j for i!=j

The problem can then be solved with a backtracking algorithm for CSPs. There are many ways to improve the backtracking search with heuristics, for example the "Minimum remaining values" heuristic. A good book is e.g. Russell, Norvig: Artificial Intelligence

like image 119
felix Avatar answered Oct 30 '22 07:10

felix


Here is a simple solution. I doubt it scales at all well. It could probably be made more efficient by starting with the erasers that fit the fewest pencils.

I have not bothered with an Eraser class. Here there is one Eraser for each index in the matches list.

private static final class Pencil {
    private final int id;
    private Pencil(int id) { this.id = id; }
    @Override
    public String toString() { return "p" + id; }
}

public static void main(String[] args) {
    Pencil p1 = new Pencil(1);
    Pencil p2 = new Pencil(2);
    Pencil p3 = new Pencil(3);
    Pencil p4 = new Pencil(4);
    Pencil p5 = new Pencil(5);
    List<Set<Pencil>> matches = new ArrayList<>();
    matches.add(new HashSet<>(Arrays.asList(p1, p2, p5)));     // First eraser only fits these 3 pencils.
    matches.add(new HashSet<>(Arrays.asList(p3, p4)));         // Second eraser only fits these 2 pencils.
    matches.add(new HashSet<>(Arrays.asList(p3, p5)));         // etc
    matches.add(new HashSet<>(Arrays.asList(p1, p2, p4)));
    matches.add(new HashSet<>(Arrays.asList(p1, p5)));
    System.out.println(allocate(matches));                     // prints [p2, p4, p3, p1, p5]
}

// Returns null if no solution can be found.
private static List<Pencil> allocate(List<Set<Pencil>> matches) {
    return allocate(matches, new ArrayList<>());
}

private static List<Pencil> allocate(List<Set<Pencil>> matches, List<Pencil> solution) {
    int size = solution.size();
    if (matches.size() == size)
        return solution;
    for (Pencil pencil : matches.get(size)) {
        if (solution.contains(pencil))
            continue;
        List<Pencil> copy = new ArrayList<>(solution);
        copy.add(pencil);
        List<Pencil> result = allocate(matches, copy);
        if (result != null)
            return result;
    }
    return null;
} 
like image 31
Paul Boddington Avatar answered Oct 30 '22 07:10

Paul Boddington