<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE bugzilla SYSTEM "https://www.w3.org/Bugs/Public/page.cgi?id=bugzilla.dtd">

<bugzilla version="5.0.4"
          urlbase="https://www.w3.org/Bugs/Public/"
          
          maintainer="sysbot+bugzilla@w3.org"
>

    <bug>
          <bug_id>5620</bug_id>
          
          <creation_ts>2008-04-03 18:01:59 +0000</creation_ts>
          <short_desc>fts:FormCombinations is incorrect</short_desc>
          <delta_ts>2008-04-15 02:51:34 +0000</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>1</classification_id>
          <classification>Unclassified</classification>
          <product>XPath / XQuery / XSLT</product>
          <component>Full Text 1.0</component>
          <version>Working drafts</version>
          <rep_platform>PC</rep_platform>
          <op_sys>Windows XP</op_sys>
          <bug_status>CLOSED</bug_status>
          <resolution>FIXED</resolution>
          
          
          <bug_file_loc></bug_file_loc>
          <status_whiteboard></status_whiteboard>
          <keywords></keywords>
          <priority>P2</priority>
          <bug_severity>normal</bug_severity>
          <target_milestone>---</target_milestone>
          
          
          <everconfirmed>1</everconfirmed>
          <reporter name="Thomas Baby">thomas.baby</reporter>
          <assigned_to name="Jim Melton">jim.melton</assigned_to>
          
          
          <qa_contact name="Mailing list for public feedback on specs from XSL and XML Query WGs">public-qt-comments</qa_contact>

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>19725</commentid>
    <comment_count>0</comment_count>
    <who name="Thomas Baby">thomas.baby</who>
    <bug_when>2008-04-03 18:01:59 +0000</bug_when>
    <thetext>The XQuery Full-Text specification uses the function fts:FormCombinations (shown below) to implement the FTTimes operator:

declare function fts:FormCombinations (
      $sms as element(fts:match)*,
      $times as xs:integer )
   as element(fts:match)*
{
   if ( $times eq 1 ) then $sms
   else if (fn:count($sms) lt $times) then ()
   else if (fn:count($sms) eq $times) then
      &lt;fts:match&gt;{$sms/*}&lt;/fts:match&gt;
   else (
      fts:FormCombinations(fn:subsequence($sms, 2), $times),
      for $combination in
         fts:FormCombinations(fn:subsequence($sms, 2), $times - 1)
      return
      &lt;fts:match&gt;
      {
         $sms[1]/*,
         $combination/*
      }
      &lt;/fts:match&gt;
   )
};

The implementation of fts:ApplyFTTimesAtLeast simply invokes fts:FTCombinations, which suggests that the above function implements the &quot;at least $times&quot; semantic.

declare function fts:ApplyFTTimesAtLeast (
      $allMatches as element(fts:allMatches),
      $n as xs:integer )
   as element(fts:allMatches)
{
   &lt;fts:allMatches stokenNum=&quot;{$allMatches/@stokenNum}&quot;&gt;
   {fts:FormCombinations($allMatches/fts:match, $n)}
   &lt;/fts:allMatches&gt;
};


However, looking at the body of fts:FormCombinations, the assumption that it implements the &quot;at least $times&quot; semantic does not appear to be correct. For example, fts:FTCombinations invoked with a value of 2 for $times produces only 2-way combinations, and it does not produce 3-way combinations, 4-way combinations, etc. (Step 3 of the example in Section 4.3.3 should have produced 3-way combinations, but it does not.)</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>19779</commentid>
    <comment_count>1</comment_count>
    <who name="Thomas Baby">thomas.baby</who>
    <bug_when>2008-04-10 22:17:21 +0000</bug_when>
    <thetext>Michael Dyck and I have fixed this issue and other issues in the FTTimes neighborhood. We have added a new function called fts:FormCombinationsAtLeast, which generates $k-or-more combinations of a sequence, by repeatedly invoking fts:FormCombinations. fts:FormCombinations is an existing function that generates $k combinations of a sequence. Some of the base case checks in fts:FormCombinations have also been fixed. The new functions are included below:

declare function fts:FormCombinations (
      $sms as element(fts:match)*, 
      $k as xs:integer ) 
   as element(fts:match)*
(:
   Find all combinations of exactly $k elements from $sms, and
   for each such combination, construct a match whose children are
   copies of all the children of all the elements in the combination.
   Return the sequence of all such matches.
:)
{
   if ($k eq 0) then &lt;fts:match/&gt;
   else if (fn:count($sms) lt $k) then ()
   else if (fn:count($sms) eq $k) then &lt;fts:match&gt;{$sms/*}&lt;/fts:match&gt;
   else
      let $first := $sms[1],
          $rest  := fn:subsequence($sms, 2)
      return (
         (: all the combinations that don&apos;t involve $first :)
         fts:FormCombinations($rest, $k),

         (: and all the combinations that do involve $first :)
         for $combination in fts:FormCombinations($rest, $k - 1)
         return
            &lt;fts:match&gt;
            {
               $first/*,
               $combination/*
            }
            &lt;/fts:match&gt;
      )
};

declare function fts:FormCombinationsAtLeast (
      $sms as element(fts:match)*,
      $times as xs:integer)
   as element(fts:match)*
(:
   Find all combinations of $times or more elements from $sms, and
   for each such combination, construct a match whose children are
   copies of all the children of all the elements in the combination.
   Return the sequence of all such matches.
:)
{
   for $k in $times to fn:count($sms)
   return fts:FormCombinations($sms, $k)
};
</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>19780</commentid>
    <comment_count>2</comment_count>
    <who name="Thomas Baby">thomas.baby</who>
    <bug_when>2008-04-10 22:19:17 +0000</bug_when>
    <thetext>Some of the existing functions have also been changed to now invoke the new function fts:FormCombinationsAtLeast, instead of fts:FormCombinations. These functions are listed below:

declare function fts:FormRange (
      $sms as element(fts:match)*, 
      $l as xs:integer, 
      $u as xs:integer, 
      $stokenNum as xs:integer ) 
   as element(fts:allMatches)
{
   if ($l &gt; $u) then ()
   else 
      let $am1 := &lt;fts:allMatches stokenNum=&quot;{$stokenNum}&quot;&gt;
                     {fts:FormCombinationsAtLeast($sms, $l)}
                  &lt;/fts:allMatches&gt;
      let $am2 := &lt;fts:allMatches stokenNum=&quot;{$stokenNum}&quot;&gt;
                     {fts:FormCombinationsAtLeast($sms, $u+1)}
                  &lt;/fts:allMatches&gt;
      return fts:ApplyFTAnd($am1,
                            fts:ApplyFTUnaryNot($am2))
};
            

declare function fts:ApplyFTTimesAtLeast (
      $allMatches as element(fts:allMatches),
      $n as xs:integer ) 
   as element(fts:allMatches) 
{
   &lt;fts:allMatches stokenNum=&quot;{$allMatches/@stokenNum}&quot;&gt; 
   {fts:FormCombinationsAtLeast($allMatches/fts:match, $n)} 
   &lt;/fts:allMatches&gt;
};

</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>19801</commentid>
    <comment_count>3</comment_count>
    <who name="Thomas Baby">thomas.baby</who>
    <bug_when>2008-04-15 02:50:29 +0000</bug_when>
    <thetext>Okay with the resolution. </thetext>
  </long_desc>
      
      

    </bug>

</bugzilla>