Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F121687500
incorder.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sun, Jul 13, 04:20
Size
14 KB
Mime Type
text/x-c
Expires
Tue, Jul 15, 04:20 (2 d)
Engine
blob
Format
Raw Data
Handle
27360302
Attached To
R1252 EMPoWER
incorder.c
View Options
/* ************************************************************
% [perm, dz] = incorder(At [,Ajc1,ifirst])
% INCORDER
% perm sorts the columns of At greedily, by iteratively picking
% the 1st unprocessed column with the least number of nonzero
% subscripts THAT ARE NOT YET COVERED (hence incremental) by
% the previously processed columns.
% dz has the corresponding incremental sparsity structure, i.e.
% each column lists only the ADDITIONAL subscripts w.r.t. the
% previous ones.
%
% SEE ALSO getada3, dpr1fact.
% ******************** INTERNAL FUNCTION OF SEDUMI ********************
function [perm, dz] = incorder(At,Ajc1,ifirst)
% This file is part of SeDuMi 1.1 by Imre Polik and Oleksandr Romanko
% Copyright (C) 2005 McMaster University, Hamilton, CANADA (since 1.1)
%
% Copyright (C) 2001 Jos F. Sturm (up to 1.05R5)
% Dept. Econometrics & O.R., Tilburg University, the Netherlands.
% Supported by the Netherlands Organization for Scientific Research (NWO).
%
% Affiliation SeDuMi 1.03 and 1.04Beta (2000):
% Dept. Quantitative Economics, Maastricht University, the Netherlands.
%
% Affiliations up to SeDuMi 1.02 (AUG1998):
% CRL, McMaster University, Canada.
% Supported by the Netherlands Organization for Scientific Research (NWO).
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
% 02110-1301, USA
************************************************************ */
#include <string.h>
#include "mex.h"
#include "blksdp.h"
#define PERM_OUT myplhs[0]
/* incremental ordering */
#define DZ_OUT myplhs[1]
/* incremental nonzero structure */
#define NPAROUT 2
#define AT_IN prhs[0]
#define NPARINMIN 1
#define AJC1_IN prhs[1]
#define IFIRST_IN prhs[2]
#define NPARIN 3
/* ************************************************************
PROCEDURE spPartTransp - Let (Ajc, Air) = At(first:lenfull-1,:)'.
INPUT
Atir - length Atjc2[m-1] subscript array.
Atjc1 - length m array, pointing to 1st index in At(:,j) that is
in range first:lenfull-1.
Atjc2 - length m array, pointing to column end.
first, lenfull - index range we're interested in. (lenud:=lenfull-first)
m - number of constraints (rows in At).
OUTPUT
Ajc - length 1+lenud mwIndex-array, column pointers
of A := At(first:lenfull-1,:)'.
Air - subscript array of output matrix A. length is:
sum(Atjc(2:m) - Atjcs(1:m)).
WORK
iwork - length lenud (=lenfull-first) integer array.
************************************************************ */
void
spPartTransp
(
mwIndex
*
Air
,
mwIndex
*
Ajc
,
const
mwIndex
*
Atir
,
const
mwIndex
*
Atjc1
,
const
mwIndex
*
Atjc2
,
const
mwIndex
first
,
const
mwIndex
lenfull
,
const
mwIndex
m
,
mwIndex
*
iwork
)
{
mwIndex
i
,
j
,
inz
;
mwIndex
*
inxnz
;
/* ------------------------------------------------------------
INIT: Make indices Ajc[first:lenfull] valid. Then set Ajc(:)=all-0.
------------------------------------------------------------ */
Ajc
-=
first
;
for
(
i
=
first
;
i
<=
lenfull
;
i
++
)
Ajc
[
i
]
=
0
;
/* ------------------------------------------------------------
For each column j=0:m-1, in each nz PSD entry Atj(i): ++inxnz[i],
where inxnz := Ajc+1. (we use Ajc[first+1:lenfull])
------------------------------------------------------------ */
inxnz
=
Ajc
+
1
;
for
(
j
=
0
;
j
<
m
;
j
++
)
for
(
inz
=
Atjc1
[
j
];
inz
<
Atjc2
[
j
];
inz
++
)
++
inxnz
[
Atir
[
inz
]];
/* ------------------------------------------------------------
cumsum(inxnz). Note that Ajc[0] =0 already.
------------------------------------------------------------ */
for
(
inz
=
0
,
i
=
first
;
i
<
lenfull
;
i
++
)
inxnz
[
i
]
+=
inxnz
[
i
-
1
];
/* ------------------------------------------------------------
Write the subscripts of A:= At(first:lenfull-1,:)'.
------------------------------------------------------------ */
memcpy
(
iwork
,
Ajc
+
first
,
(
lenfull
-
first
)
*
sizeof
(
mwIndex
));
iwork
-=
first
;
/* points to next avl. entry in A(:,i) */
for
(
j
=
0
;
j
<
m
;
j
++
)
for
(
inz
=
Atjc1
[
j
];
inz
<
Atjc2
[
j
];
inz
++
){
i
=
Atir
[
inz
];
Air
[
iwork
[
i
]
++
]
=
j
;
/* as (j,i) entry */
}
}
/* ************************************************************
PROCEDURE incorder - Greedy ordering of PSD-part of columns in At,
starting with least number of (PSD)-nonzeros. Good fot getada3.
Produces N x m sparse matrix dz, having at most lenud nonzeros.
The last columns correspond to the "deg" columns, and are not
reordered. The first m-ndeg are reordered, see "perm".
INPUT
Atjc1 - length m, start of At(first:lenful,j) for each j=1:m.
Atjc2 - column end pointers, length m.
Atir - row-subscripts of At.
Ajc, Air - sparsity structure of A := At(first:lenful,:)', is m x lenud.
m - number of columns in At.
first - first PSD subscipt.
OUTPUT
perm - length m array. perm(1:m-ndeg) is the greedy ordering,
starting from sparsest. perm(m-ndeg:m) = deg.
dzjc - length m+1, column pointers into dzir.
dzir - length dzjc[m] <= lenud. jth column lists additional
subscripts to dz(:,0:j-1).
WORK
iwork - (length m) Remaining length of PSD part
in each column j=1:m.
discard - length lenud of Booleans. 1 means index already in dz.
************************************************************ */
void
incorder
(
mwIndex
*
perm
,
mwIndex
*
dzjc
,
mwIndex
*
dzir
,
const
mwIndex
*
Atjc1
,
const
mwIndex
*
Atjc2
,
const
mwIndex
*
Atir
,
const
mwIndex
*
Ajc
,
const
mwIndex
*
Air
,
const
mwIndex
m
,
const
mwIndex
first
,
const
mwIndex
lenud
,
mwIndex
*
iwork
,
char
*
discard
)
{
mwIndex
kmin
,
lenmin
,
i
,
j
,
k
,
inz
,
jnz
,
permk
;
/* ------------------------------------------------------------
initialize: dzjc[0]=0, nperm = m - ndeg. Let Ajc-=first, so
that Ajc[first:lenfull] is valid. Similar for discard.
Initialize discard to all-0 ("False").
------------------------------------------------------------ */
dzjc
[
0
]
=
0
;
Ajc
-=
first
;
memset
(
discard
,
'\0'
,
lenud
);
/* all-0 */
discard
-=
first
;
/* ------------------------------------------------------------
Let perm(1:m) be 1:m
------------------------------------------------------------ */
for
(
i
=
0
;
i
<
m
;
i
++
)
perm
[
i
]
=
i
;
/* ------------------------------------------------------------
Set iwork = Atjc2(1:m)-Atjc1(1:m).
The number of (not yet discarded) nz-PSD indices per constraint.
------------------------------------------------------------ */
for
(
k
=
0
;
k
<
m
;
k
++
){
iwork
[
k
]
=
Atjc2
[
k
]
-
Atjc1
[
k
];
}
/* ------------------------------------------------------------
In iterate k=0:m-1, pivot on constraint with length iwork[k] minimal.
------------------------------------------------------------ */
for
(
k
=
0
;
k
<
m
;
k
++
){
kmin
=
k
;
lenmin
=
iwork
[
perm
[
k
]];
for
(
j
=
k
+
1
;
j
<
m
;
j
++
)
if
(
iwork
[
perm
[
j
]]
<
lenmin
){
lenmin
=
iwork
[
perm
[
j
]];
kmin
=
j
;
}
mxAssert
(
lenmin
>=
0
,
""
);
permk
=
perm
[
kmin
];
/* make pivot in perm */
perm
[
kmin
]
=
perm
[
k
];
perm
[
k
]
=
permk
;
/* ------------------------------------------------------------
Write the (additional) subscripts of the pivot column into
k-th column of dz, i.e. dz(:,k) = At(:,permk).
------------------------------------------------------------ */
jnz
=
dzjc
[
k
];
for
(
inz
=
Atjc1
[
permk
];
inz
<
Atjc2
[
permk
];
inz
++
){
i
=
Atir
[
inz
];
if
(
!
discard
[
i
]){
discard
[
i
]
=
1
;
dzir
[
jnz
++
]
=
i
;
}
}
mxAssert
(
jnz
==
dzjc
[
k
]
+
lenmin
,
""
);
/* ------------------------------------------------------------
Discard dz(:,k)'s subscripts: adjust the constraint lengths
where applicable.
------------------------------------------------------------ */
dzjc
[
k
+
1
]
=
jnz
;
for
(
jnz
=
dzjc
[
k
];
jnz
<
dzjc
[
k
+
1
];
jnz
++
){
i
=
dzir
[
jnz
];
/* i is discarded subscript */
for
(
inz
=
Ajc
[
i
];
inz
<
Ajc
[
i
+
1
];
inz
++
){
j
=
Air
[
inz
];
iwork
[
j
]
--
;
/* subscript discard here */
}
}
}
}
/* ************************************************************
PROCEDURE mexFunction - Entry for Matlab
[perm,dz] = incorder(At,Ajc1,ifirst)
************************************************************ */
void
mexFunction
(
int
nlhs
,
mxArray
*
plhs
[],
int
nrhs
,
const
mxArray
*
prhs
[])
{
mxArray
*
myplhs
[
NPAROUT
];
mwIndex
i
,
m
,
firstPSD
,
lenud
,
iwsiz
,
lenfull
,
maxnnz
;
mwIndex
*
iwork
,
*
Atjc1
,
*
Ajc
,
*
Air
,
*
perm
;
const
mwIndex
*
Atjc2
,
*
Atir
;
double
*
permPr
;
const
double
*
Ajc1Pr
;
char
*
cwork
;
jcir
dz
;
/* ------------------------------------------------------------
Check for proper number of arguments
------------------------------------------------------------ */
mxAssert
(
nrhs
>=
NPARINMIN
,
"incorder requires more input arguments."
);
mxAssert
(
nlhs
<=
NPAROUT
,
"incorder produces less output arguments."
);
/* --------------------------------------------------
GET STATISTICS:
-------------------------------------------------- */
if
(
nrhs
==
NPARIN
){
firstPSD
=
(
mwIndex
)
mxGetScalar
(
IFIRST_IN
);
/* double to mwIndex */
mxAssert
(
firstPSD
>
0
,
""
);
--
firstPSD
;
/* Fortran to C */
}
else
firstPSD
=
0
;
/* default: use all subscripts */
lenfull
=
mxGetM
(
AT_IN
);
lenud
=
lenfull
-
firstPSD
;
/* --------------------------------------------------
Check size At, and get At.
-------------------------------------------------- */
mxAssert
(
mxIsSparse
(
AT_IN
),
"At must be a sparse matrix."
);
m
=
mxGetN
(
AT_IN
);
Atjc2
=
mxGetJc
(
AT_IN
)
+
1
;
/* points to end of constraint */
Atir
=
mxGetIr
(
AT_IN
);
/* subscripts */
/* ------------------------------------------------------------
ALLOCATE WORKING arrays:
mwIndex Atjc1(m), Ajc(1+lenud), Air(maxnnz), perm(m),
iwork(iwsiz). iwsiz = MAX(lenud,1+m)
char cwork(lenud).
------------------------------------------------------------ */
Atjc1
=
(
mwIndex
*
)
mxCalloc
(
MAX
(
m
,
1
),
sizeof
(
mwIndex
));
Ajc
=
(
mwIndex
*
)
mxCalloc
(
1
+
lenud
,
sizeof
(
mwIndex
));
perm
=
(
mwIndex
*
)
mxCalloc
(
MAX
(
1
,
m
),
sizeof
(
mwIndex
));
iwsiz
=
MAX
(
lenud
,
1
+
m
);
iwork
=
(
mwIndex
*
)
mxCalloc
(
iwsiz
,
sizeof
(
mwIndex
));
/* iwork(iwsiz) */
cwork
=
(
char
*
)
mxCalloc
(
MAX
(
1
,
lenud
),
sizeof
(
char
));
/* ------------------------------------------------------------
Get input AJc1
------------------------------------------------------------ */
if
(
nrhs
==
NPARIN
){
Ajc1Pr
=
mxGetPr
(
AJC1_IN
);
mxAssert
(
mxGetM
(
AJC1_IN
)
*
mxGetN
(
AJC1_IN
)
>=
m
,
"Ajc1 size mismatch"
);
/* ------------------------------------------------------------
Double to mwIndex: Atjc1
------------------------------------------------------------ */
for
(
i
=
0
;
i
<
m
;
i
++
)
Atjc1
[
i
]
=
(
mwIndex
)
Ajc1Pr
[
i
];
/* double to mwIndex */
/* ------------------------------------------------------------
Let maxnnz = number of PSD nonzeros = sum(Atjc2-Atjc1)
------------------------------------------------------------ */
maxnnz
=
0
;
for
(
i
=
0
;
i
<
m
;
i
++
)
maxnnz
+=
Atjc2
[
i
]
-
Atjc1
[
i
];
}
else
{
memcpy
(
Atjc1
,
mxGetJc
(
AT_IN
),
m
*
sizeof
(
mwIndex
));
/* default column start */
maxnnz
=
Atjc2
[
m
-
1
];
/* maxnnz = nnz(At) */
}
/* ------------------------------------------------------------
ALLOCATE WORKING array mwIndex Air(maxnnz)
------------------------------------------------------------ */
Air
=
(
mwIndex
*
)
mxCalloc
(
MAX
(
1
,
maxnnz
),
sizeof
(
mwIndex
));
/* ------------------------------------------------------------
CREATE OUTPUT ARRAYS PERM(m) and DZ=sparse(lenfull,m,lenud).
------------------------------------------------------------ */
PERM_OUT
=
mxCreateDoubleMatrix
(
m
,(
mwSize
)
1
,
mxREAL
);
permPr
=
mxGetPr
(
PERM_OUT
);
DZ_OUT
=
mxCreateSparse
(
lenfull
,
m
,
lenud
,
mxREAL
);
dz
.
jc
=
mxGetJc
(
DZ_OUT
);
dz
.
ir
=
mxGetIr
(
DZ_OUT
);
/* ------------------------------------------------------------
Let (Ajc,Air) := At(first:end,:)', the transpose of PSD-part.
Uses iwork(lenud)
------------------------------------------------------------ */
spPartTransp
(
Air
,
Ajc
,
Atir
,
Atjc1
,
Atjc2
,
firstPSD
,
lenfull
,
m
,
iwork
);
/* ------------------------------------------------------------
The main job: greedy order of columns of At
------------------------------------------------------------ */
incorder
(
perm
,
dz
.
jc
,
dz
.
ir
,
Atjc1
,
Atjc2
,
Atir
,
Ajc
,
Air
,
m
,
firstPSD
,
lenud
,
iwork
,
cwork
);
/* uses iwork(m+1) */
/* ------------------------------------------------------------
REALLOC (shrink) dz to dz.jc[m] nonzeros.
------------------------------------------------------------ */
mxAssert
(
dz
.
jc
[
m
]
<=
lenud
,
""
);
maxnnz
=
MAX
(
1
,
dz
.
jc
[
m
]);
/* avoid realloc to 0 */
if
((
dz
.
ir
=
(
mwIndex
*
)
mxRealloc
(
dz
.
ir
,
maxnnz
*
sizeof
(
mwIndex
)))
==
NULL
)
mexErrMsgTxt
(
"Memory allocation error"
);
if
((
dz
.
pr
=
(
double
*
)
mxRealloc
(
mxGetPr
(
DZ_OUT
),
maxnnz
*
sizeof
(
double
)))
==
NULL
)
mexErrMsgTxt
(
"Memory allocation error"
);
mxSetPr
(
DZ_OUT
,
dz
.
pr
);
mxSetIr
(
DZ_OUT
,
dz
.
ir
);
mxSetNzmax
(
DZ_OUT
,
maxnnz
);
for
(
i
=
0
;
i
<
maxnnz
;
i
++
)
dz
.
pr
[
i
]
=
1.0
;
/* ------------------------------------------------------------
Convert C-mwIndex to Fortran-double
------------------------------------------------------------ */
for
(
i
=
0
;
i
<
m
;
i
++
)
permPr
[
i
]
=
perm
[
i
]
+
1.0
;
/* ------------------------------------------------------------
Release working arrays
------------------------------------------------------------ */
mxFree
(
cwork
);
mxFree
(
iwork
);
mxFree
(
perm
);
mxFree
(
Air
);
mxFree
(
Ajc
);
mxFree
(
Atjc1
);
/* ------------------------------------------------------------
Copy requested output parameters (at least 1), release others.
------------------------------------------------------------ */
i
=
MAX
(
nlhs
,
1
);
memcpy
(
plhs
,
myplhs
,
i
*
sizeof
(
mxArray
*
));
for
(;
i
<
NPAROUT
;
i
++
)
mxDestroyArray
(
myplhs
[
i
]);
}
Event Timeline
Log In to Comment