I'm in the planning stages of a website that will match two users together periodically.
Each person in the pool will have several preferences that are used in the matching process, e.g. what genres of music they like and which days of the week they are available. For the purposes of this project, I'd like to assign higher weight/match priority if the preferences are specific; i.e. two people who ONLY like 'science fiction' are a better match than simply putting together two people who checked off 'all of the above'. I'm thinking that a standard greedy matching algorithm would probably work, but is there any algorithm out there that is more efficient?
It is not that simple, you need to create a utility function that lets you know which is better matching. For example, which will be better:
(1) one pair with excellent match, the other is terribly poor.
(2) two pairs, with an average match.
I suggest using some well proven artificial intelligence tools for this problem.
first, some definitions:
P={all persons}
S={all possibilities to match all people}
- let
u:PxP->R
be a scoring function for a pair: u(p1,p2)=their
score as a match
[depends on your data of course]
- let
U:S->R
be a scoring function for the whole matching: U(aMatch)
= Sigma(u(p1,p2)) for each paired couple
.
- let
next:S->2^S
be: next(S)={all possible matchings which are
different from S by swapping two people only}
Now, with the above definition you can use steepest ascent hill climbing or a genethic algorithm, which are proven Artificial Intelligence tools for getting a good result.
Steepest Ascent Hill Climbing [SAHC] is simple, start with as random matching, and make a small change, until you reach a point where you cannot make a local improvement. This point is a local maximum, and a candidate to be the best solution. restart the process with a different initial state.
pseudo code:
1. best<- -INFINITY
2. while there is more time
3. choose a random matching
4. NEXT <- next(s)
5. if max{ U(v) | for each v in NEXT} < U(s): //s is a local maximum
5.1. if u(s) > best: best <- u(s) //if s is better then the previous result - store it.
5.2. go to 2. //restart the hill climbing from a different random point.
6. else:
6.1. s <- max { NEXT }
6.2. goto 4.
7. return best //when out of time, return the best solution found so far.
Note1: that this algorithm is anytime, which means it will get better results as you give it more time. and if your time->infinity, the algorithm will eventually find the optimal solution.
Note2: the utility function U
is just a suggestion, you could also use max{u(p1,p2) | for each pair in the match}
, or any other utility function you find fits.
EDIT:
Even the simpler problem, which is: two people can simply "match" or "not match" [u(p1,p2)=0
or u(p1,p2)=1
] is actually the maximal matching problem, which is NP-Hard, thus there is no known polynomial solution for this problem, and a heuristical solution, such as suggested above should probably be used.
Note that if your graph is bipartite [i.e. you cannot match male with male/female with female], this problem is solveable in polynomial time. More info: matching in bipartite graphs