20
May
Calling a function on the power set of a sequence
Author: Dave Cassel | Category: Software Development[Update: This post was originally labelled "Calling a function on all permutations of a sequence". John Boyer was kind enough to point out that the function works for power sets rather than permutations, so I've updated this post accordingly. Thanks, John!]
A project I’m working on required me to call a function on the power set of a sequence. I said to myself, “Surely, you can’t be the only person needing to do that in XQuery”. Having heard that from such a reliable source, I figured I should share.
(: Print an index and the selected members of the sequence. :)
declare function local:print($index, $values, $selections, $connector) {
fn:concat($index, ": ", fn:string-join($values[$selections], $connector))
};
(: Apply the specified function to each permutation of $seq. $data is
: provided as a pass-through.
:)
declare function local:apply-on-power-set($seq as item()*,
$function as xdmp:function, $data)
{
let $len := fn:count($seq)
for $i in (1 to xs:int(math:pow(2, $len) - 1))
let $targets :=
for $bit in (1 to $len)
let $shifted :=
if ($bit > 1) then
xs:int($i div (math:pow(2, $bit - 1)))
else $i
return
if (math:fmod($shifted, 2) eq 1) then
$bit
else ()
return
xdmp:apply($function, $i, $seq, $targets, $data)
};
let $seq := ('a', 'b', 'c', 'd')
return local:apply-on-power-set($seq, xdmp:function(xs:QName("local:print")), ',')
Calling this function generates this output:
1: a 2: b 3: a,b 4: c 5: a,c 6: b,c 7: a,b,c 8: d 9: a,d 10: b,d 11: a,b,d 12: c,d 13: a,c,d 14: b,c,d 15: a,b,c,d
I’m sure you’ll sleep better tonight knowing that this is available to you.
Tags: xquery
September 27th, 2011 at 1:19 pm
Hi,
These aren’t permutations. You’re generating the power set of a set (less the null set).
There are 4!=24 permutations of {a, b, c, d}. Lexicographically, they are (a b c d), (a b d c), (a c b d), … (d c a b), (d c b a).
The blog entry below [1] explains how to generate a permutation in XForms, but also contains information on how to generate a permutation in general, which you could perhaps provide the xquery version of. If you do, please leave a comment on my blog so I’ll know to read about it.
[1] https://www.ibm.com/developerworks/mydeveloperworks/blogs/JohnBoyer/entry/randomizing_the_responses_to_a_survey_question_in_xforms29
September 28th, 2011 at 5:27 pm
John, thanks for your comment. I stand corrected — this code does generate power sets, as you say. That is the problem I was trying to solve; I mislabeled it. I’ll try to set aside some time to update the post to use the correct terminology.