ANALYSIS of ALGORITHMS, Bulletin Board
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Quickselect and inversions. (IV)
Greetings.
I have found the pattern that describes the "fudge factor" mentioned
in
http://pauillac.inria.fr/algo/AofA/mailing_list/msg00434.html.
It's a binomial coefficient.
I am sending the recurrence and some code to compute the generating
functions. I am very curious whether anyone is interested in
investigating this problem or could point me to a reference where it
is discussed.
Regards,
Marko Riedel
----------------------------------------------------------------------
\documentclass{article}
\usepackage{latexsym,amsfonts,amssymb,amsmath,amstext,amsthm}
\begin{document}
\newcommand{\MWHERE}{\quad \text{where } \quad}
\title{Quickselect and inversions}
\author{Marko Riedel}
\maketitle
\section{Recurrence relation}
Consider the following question. What amount of disorder is left in a
permutation after one of its elements has been selected with
quickselect?
This can be rephrased as follows. Compute the "grand average" for the
expected number of inversions left in a permutation after one of its
elements has been selected with quickselect.
Let $r_n(z)$ be the generating function of the inversions in a random
permutation of size $n$, where $0, 1,\ldots n-1$ are the elements being
permuted. We have
\[ r_n(z) =
\prod_{k=0}^{n-1} \sum_{l=0}^k z^l =
\prod_{k=0}^{n-1} \frac{z^{k+1}-1}{z-1}.\]
Let $q_{n, l}(z)$ be the generating function of the number of
inversions after the element $l$, where $0 \le l < n$ has been
selected from a random permutation of size $n$. The base cases are:
$n=1$ and $q_{1, 0}(z) = 1$ and $n=2$ and $q_{2, 0}(z) = q_{2, 1}(z) =
2.$ We let $r_0(z) = q_{0, l}(z) = 1.$ Let $p$ denote the pivot. The
recurrence for $q_{n, l}(z)$ is as follows.
\begin{eqnarray*}
q_{n, l}(z) & = &
\sum_{p=0}^{l-1} \binom{n-1}{p} r_p(z) q_{n-1-p, l-p-1}(z) \\
& + & \binom{n-1}{l} r_l(z) r_{n-1-l}(z) \\
& + & \sum_{p=l+1}^{n-1} \binom{n-1}{p} q_{p, l}(z) r_{n-1-p}(z).
\end{eqnarray*}
Problem. Explain the presence of the factor $\binom{n-1}{p}.$
We are interested in the asymptotics of
\[ \frac{q_n'(1)}{q_n(1)} = \frac{q_n'(1)}{n \cdot n!}
\MWHERE
q_n(z) = \sum_{l=0}^{n-1} q_{n, l}(z).\]
References. Basic generating functions.
\end{document}
----------------------------------------------------------------------
#include <stdio.h>
#include <ginac/ginac.h>
using namespace std;
using namespace GiNaC;
static symbol z("z");
ex nchoosek(ex n, ex k){
return
factorial(n)/factorial(k)/factorial(n-k);
}
#define MAXN 256
static ex invgftable[MAXN];
void invgf(int k, ex *result){
ex factor=0, term;
int j;
if(invgftable[k]==-1){
for(j=0; j<k; j++){
factor+=pow(z, j);
}
if(k>1){
invgf(k-1, &term);
}
else{
term=1;
}
term*=factor;
invgftable[k]=term.expand();
}
*result=invgftable[k];
return;
}
static ex qselgftable[MAXN][MAXN];
void qselgfl(int n, int l, ex *result){
ex term, prod, gf, f=factorial(n-1);
int p;
if(qselgftable[n][l]==-1){
if(n==1 || n==2){
qselgftable[n][l]=n;
}
else{
term=0;
for(p=0; p<n; p++){
prod=1;
if(p<l){
if(p>0){
invgf(p, &gf);
prod*=gf;
}
if(n-1-p>0){
qselgfl(n-1-p, l-p-1, &gf);
prod*=gf;
}
}
else if(p>l){
if(p>0){
qselgfl(p, l, &gf);
prod*=gf;
}
if(n-1-p>0){
invgf(n-1-p, &gf);
prod*=gf;
}
}
else{
if(p>0){
invgf(p, &gf);
prod*=gf;
}
if(n-1-p>0){
invgf(n-1-p, &gf);
prod*=gf;
}
}
term+=prod*nchoosek(n-1, p);
}
qselgftable[n][l]=term.expand();
}
}
*result=qselgftable[n][l];
return;
}
void qselgf(int n, ex *result){
ex sum, term;
int l;
sum=0;
for(l=0; l<n; l++){
qselgfl(n, l, &term);
sum+=term;
}
*result=sum;
return;
}
void printgf(ex gf){
int i, maxdeg=gf.degree(z);
ex c;
for(i=gf.ldegree(z); i<=maxdeg; i++){
c=gf.coeff(z, i);
if(c==0){
continue;
}
if(i==0){
cout << c;
}
else if(i==1){
if(c!=1){
cout << c << "z";
}
else{
cout << "z";
}
}
else{
if(c!=1){
cout << c << "z^" << i;
}
else{
cout << "z^" << i;
}
}
if(i<maxdeg){
cout << " + ";
}
}
cout << endl;
return;
}
int main(int argc, char **argv){
int i, j, l, n;
ex gf, u, v, w;
if(argc!=2){
printf("usage: %s <n>\n", argv[0]);
exit(1);
}
sscanf(argv[1], "%d", &n);
if(n<1 || n>=MAXN){
printf("range: 1 to %d\n", MAXN-1);
exit(2);
}
for(i=0; i<MAXN; i++){
invgftable[i]=-1;
}
cout << "inversion gfs" << endl;
for(i=1; i<=n; i++){
invgf(i, &gf);
cout << i << " ";
printgf(gf);
}
for(i=0; i<MAXN; i++){
for(j=0; j<MAXN; j++){
qselgftable[i][j]=-1;
}
}
cout << "quickselect average gfs" << endl;
for(i=1; i<=n; i++){
for(l=0; l<i; l++){
qselgfl(i, l, &gf);
cout << l << ": ";
printgf(gf);
}
qselgf(i, &gf);
cout << i << " ";
printgf(gf);
u=gf.diff(z).subs(z==1);
v=gf.subs(z==1);
w=u/v;
cout << u << "/" << v << " " << w << " "
<< evalf(u/v) << endl;
}
}
Date Prev |
Date Next |
Date Index |
Thread Index