[XSL-LIST Mailing List Archive Home]
[By Thread]
[By Date]
[xsl] A polynomial time XSLT program that generates a list of compatible roommates?
Subject: [xsl] A polynomial time XSLT program that generates a list of compatible roommates? From: "Costello, Roger L." <costello@xxxxxxxxx> Date: Sun, 22 Sep 2013 15:49:17 +0000 |
Hi Folks, Problem: you are given a list of freshmen, together with which ones are willing to room with which other ones. Pair off as many willing roommates as possible. The following XML document lists the names of freshmen and then shows for each freshmen the names of other freshmen they are willing to roommate with (i.e., compatible with): ---------------------------------------------- PairFreshmen.xml ---------------------------------------------- <RoommateFinder> <Freshmen> <Name>Sally</Name> <Name>Joan</Name> <Name>Betsy</Name> <Name>Linda</Name> <Name>Sue</Name> <Name>Carol</Name> <Name>Francine</Name> <Name>Doris</Name> </Freshmen> <CompatiblePairs> <Pair> <Name>Betsy</Name> <OkayToPairWith> <Name>Joan</Name> <Name>Sue</Name> <Name>Francine</Name> </OkayToPairWith> </Pair> <Pair> <Name>Francine</Name> <OkayToPairWith> <Name>Carol</Name> <Name>Sue</Name> <Name>Sally</Name> <Name>Joan</Name> <Name>Doris</Name> </OkayToPairWith> </Pair> <Pair> <Name>Sue</Name> <OkayToPairWith> <Name>Carol</Name> <Name>Francine</Name> <Name>Betsy</Name> </OkayToPairWith> </Pair> <Pair> <Name>Sally</Name> <OkayToPairWith> <Name>Joan</Name> <Name>Betsy</Name> <Name>Carol</Name> </OkayToPairWith> </Pair> <Pair> <Name>Joan</Name> <OkayToPairWith> <Name>Betsy</Name> <Name>Linda</Name> </OkayToPairWith> </Pair> <Pair> <Name>Linda</Name> <OkayToPairWith> <Name>Joan</Name> </OkayToPairWith> </Pair> <Pair> <Name>Carol</Name> <OkayToPairWith> <Name>Sally</Name> </OkayToPairWith> </Pair> <Pair> <Name>Doris</Name> <OkayToPairWith> <Name>Francine</Name> </OkayToPairWith> </Pair> </CompatiblePairs> </RoommateFinder> Betsy is willing to room with Joan and Joan is willing to room with Betsy, so that is a potential pairing. Below is an XSLT program that generates all possible pairings. It determined that this, among others, is a potential pairing of freshmen: { Francine , Doris } { Betsy , Sue } { Joan , Linda } { Sally , Carol } The XSLT program does a brute-force search. The time it requires to find all the compatible pairs of freshmen is exponential, N^N. (Yikes!) I have read that there is a polynomial time algorithm for this problem. Do you have ideas on how to solve this problem in polynomial time? ---------------------------------------------- PairFreshmen.xsl ---------------------------------------------- <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:map="http://www.w3.org/2005/xpath-functions/map" xmlns:math="http://www.w3.org/2005/xpath-functions/math" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:f="function" version="3.0"> <xsl:output method="text"/> <xsl:variable name="names" select="/RoommateFinder/Freshmen/Name" /> <xsl:variable name="compatible-pairs" select="/RoommateFinder/CompatiblePairs" /> <xsl:template match="/"> <xsl:value-of select="f:show-all-compatible-pairs(count(/RoommateFinder/Freshmen/Name))" /> </xsl:template> <!-- We wish to generate all lists of compatible pairs. The brute force approach is to generate every possible sequence of persons and then pair the first person to the second person, the third person to the fourth person, the fifth person to the sixth person, and so on. Output the sequence if the students are compatible in each pair. for person1 = (Sally, Joan, Betsy, Linda, Sue, Carol, Francine, Doris) for person2 = (Sally, Joan, Betsy, Linda, Sue, Carol, Francine, Doris) for person3 = (Sally, Joan, Betsy, Linda, Sue, Carol, Francine, Doris) for person4 = (Sally, Joan, Betsy, Linda, Sue, Carol, Francine, Doris) for person5 = (Sally, Joan, Betsy, Linda, Sue, Carol, Francine, Doris) for person6 = (Sally, Joan, Betsy, Linda, Sue, Carol, Francine, Doris) for person7 = (Sally, Joan, Betsy, Linda, Sue, Carol, Francine, Doris) for person8 = (Sally, Joan, Betsy, Linda, Sue, Carol, Francine, Doris) if (compatible person1 person2) and (compatible person3 person4) and (compatible person5 person6) and (compatible person7 person8) then Output: {person1, person2}, {person3, person4}, {person5, person6}, {person7, person8} The number of iterations is: 8 * 8 * 8 * 8 * 8 * 8 * 8 * 8 = 8^8 The number of iterations for N persons is N^N Wow! That is an exponential number of iterations. --> <xsl:function name="f:show-all-compatible-pairs"> <xsl:param name="N" as="xs:integer" /> <!-- Total number of iterations is N^N --> <xsl:variable name="total" select="xs:integer(math:pow($N, $N) - 1)" as="xs:integer" /> <xsl:for-each select="0 to $total"> <xsl:variable name="number" select="." as="xs:integer" /> <!-- $number is an encoding of a sequence of students. $number = 0 represents (Sally, Sally, Sally, Sally, Sally, Sally, Sally, Sally) $number = 1 represents (Sally, Sally, Sally, Sally, Sally, Sally, Sally, Joan) $number = 2 represents (Sally, Sally, Sally, Sally, Sally, Sally, Sally, Betsy) $number = 3 represents (Sally, Sally, Sally, Sally, Sally, Sally, Sally, Linda) ... $number = 8 represents (Sally, Sally, Sally, Sally, Sally, Sally, Joan, Sally) ... $number = $total represents (Doris, Doris, Doris, Doris, Doris, Doris, Doris, Doris) The purpose of the following iterate loop is to decode $number. This is achieved as follows: $N is the number of students Iterate from i = 1 to $N $num is a value in the range 0 .. $total The i'th student in the sequence is the student whose position() (offset by 1) equals $num mod $N --> <xsl:iterate select="1 to $N"> <xsl:param name="num" select="$number" as="xs:integer" /> <xsl:param name="pairs" select="()" as="xs:string*" /> <xsl:variable name="remainder" select="$num mod $N" as="xs:integer" /> <xsl:variable name="student" select="$names[(position() - 1) eq $remainder]" /> <xsl:next-iteration> <xsl:with-param name="num" select="$num idiv $N" /> <xsl:with-param name="pairs" select="($pairs, $student)" /> </xsl:next-iteration> <xsl:on-completion> <xsl:variable name="pair1" select="$pairs[position() mod 2 = 0]" /> <xsl:variable name="pair2" select="$pairs[position() mod 2 = 1]" /> <xsl:if test="f:all-pairs-are-compatible($pair1, $pair2) eq true()"> <xsl:value-of select="f:print-pairs($pair1, $pair2)" /> </xsl:if> </xsl:on-completion> </xsl:iterate> </xsl:for-each> </xsl:function> <xsl:function name="f:all-pairs-are-compatible" as="xs:boolean"> <xsl:param name="pair1" as="xs:string*" /> <xsl:param name="pair2" as="xs:string*" /> <xsl:choose> <xsl:when test="count($pair1) ne count($pair2)"> <xsl:value-of select="false()" /> </xsl:when> <xsl:otherwise> <xsl:iterate select="$pair1"> <xsl:variable name="posn" select="position()" /> <xsl:variable name="compatible" select="f:compatible(., $pair2[position() eq $posn])" as="xs:boolean" /> <xsl:if test="$compatible eq false()"> <xsl:break> <xsl:value-of select="false()" /> </xsl:break> </xsl:if> <xsl:on-completion> <xsl:value-of select="true()" /> </xsl:on-completion> </xsl:iterate> </xsl:otherwise> </xsl:choose> </xsl:function> <xsl:function name="f:compatible" as="xs:boolean"> <xsl:param name="name1" as="xs:string" /> <xsl:param name="name2" as="xs:string" /> <xsl:value-of select="($name2 = $compatible-pairs/Pair[Name eq $name1]/OkayToPairWith/Name) and ($name1 = $compatible-pairs/Pair[Name eq $name2]/OkayToPairWith/Name)" /> </xsl:function> <xsl:function name="f:print-pairs" as="xs:string*"> <xsl:param name="pair1" as="xs:string*" /> <xsl:param name="pair2" as="xs:string*" /> <xsl:if test="count($pair1) eq count(distinct-values($pair1)) and count($pair2) eq count(distinct-values($pair2)) and count(($pair1, $pair2)) eq count(distinct-values(($pair1, $pair2)))"> <xsl:text>Compatible Roommates: </xsl:text> <xsl:for-each select="$pair1"> <xsl:text>{</xsl:text> <xsl:value-of select="." /> <xsl:text>, </xsl:text> <xsl:variable name="posn" select="position()" /> <xsl:value-of select="$pair2[position() eq $posn]" /> <xsl:text>} </xsl:text> </xsl:for-each> <xsl:text> </xsl:text> </xsl:if> </xsl:function> </xsl:stylesheet>
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] convert xml to fixed leng, Wendell Piez | Thread | Re: [xsl] A polynomial time XSLT pr, sean |
Re: [xsl] convert xml to fixed leng, Wendell Piez | Date | Re: [xsl] A polynomial time XSLT pr, sean |
Month |