Applies the clique conversion method of Fukuda et al. to the positive semidefinite blocks of a cone LP.

    :param c:                 :py:class:`matrix`
    :param G:                 :py:class:`spmatrix`
    :param h:                 :py:class:`matrix`
    :param dims:              dictionary
    :param A:                 :py:class:`spmatrix` or :py:class:`matrix`
    :param b:                 :py:class:`matrix`

    The following example illustrates how to convert a cone LP:
    
    .. code-block:: python

        prob = (c,G,h,dims,A,b)
        probc, blk2sparse, symbs = convert_conelp(*prob)
    
    The return value `blk2sparse` is a list of 4-tuples
    (`blki,I,J,n`) that each defines a mapping between the sparse
    matrix representation and the converted block-diagonal
    representation, and `symbs` is a list of symbolic factorizations
    corresponding to each of the semidefinite blocks in the original cone LP.
    
    .. seealso::

         M. Fukuda, M. Kojima, K. Murota, and K. Nakata, `Exploiting Sparsity
         in Semidefinite Programming via Matrix Completion I: General Framework
         <http://dx.doi.org/10.1137/S1052623400366218>`_,
         SIAM Journal on Optimization, 11:3, 2001, pp. 647-674.

         S. Kim, M. Kojima, M. Mevissen, and M. Yamashita, `Exploiting Sparsity
         in Linear and Nonlinear Matrix Inequalities via Positive Semidefinite
         Matrix Completion <http://dx.doi.org/10.1007/s10107-010-0402-6>`_,
         Mathematical Programming, 129:1, 2011, pp.. 33-68.

def convert_conelp(c, G, h, dims, A = None, b = None, **kwargs):
    """
    Applies the clique conversion method of Fukuda et al. to the positive semidefinite blocks of a cone LP.

    :param c:                 :py:class:`matrix`
    :param G:                 :py:class:`spmatrix`
    :param h:                 :py:class:`matrix`
    :param dims:              dictionary
    :param A:                 :py:class:`spmatrix` or :py:class:`matrix`
    :param b:                 :py:class:`matrix`

    The following example illustrates how to convert a cone LP:
    
    .. code-block:: python

        prob = (c,G,h,dims,A,b)
        probc, blk2sparse, symbs = convert_conelp(*prob)
    
    The return value `blk2sparse` is a list of 4-tuples
    (`blki,I,J,n`) that each defines a mapping between the sparse
    matrix representation and the converted block-diagonal
    representation, and `symbs` is a list of symbolic factorizations
    corresponding to each of the semidefinite blocks in the original cone LP.
    
    .. seealso::

         M. Fukuda, M. Kojima, K. Murota, and K. Nakata, `Exploiting Sparsity
         in Semidefinite Programming via Matrix Completion I: General Framework
         <http://dx.doi.org/10.1137/S1052623400366218>`_,
         SIAM Journal on Optimization, 11:3, 2001, pp. 647-674.

         S. Kim, M. Kojima, M. Mevissen, and M. Yamashita, `Exploiting Sparsity
         in Linear and Nonlinear Matrix Inequalities via Positive Semidefinite
         Matrix Completion <http://dx.doi.org/10.1007/s10107-010-0402-6>`_,
         Mathematical Programming, 129:1, 2011, pp.. 33-68.

    """

    # extract linear and socp constraints
    offsets = dims['l'] + sum(dims['q'])
    G_lq = G[:offsets,:]
    h_lq = h[:offsets,0]

    # extract semidefinite blocks
    G_s = G[offsets:,:]
    h_s = h[offsets:,0]

    G_converted = [G_lq]; h_converted = [h_lq]
    G_coupling = []
    dims_list = []
    symbs = []
    
    offset = 0
    block_to_sparse = []
    for k, si in enumerate(dims['s']):
        # extract block
        G_b = G_s[offset:offset+si**2,:]
        h_b = h_s[offset:offset+si**2,0]
        offset += si**2

        # convert block
        blkk, b2s, F = convert_block(G_b, h_b, si, **kwargs)
        G1, h1, G2, blkdims = blkk
        G_converted.append(G1)
        h_converted.append(h1)
        dims_list.extend(blkdims)
        block_to_sparse.append(b2s)
        symbs.append(F)
        if G2 is not None: G_coupling.append(G2)

    G1 = sparse(G_converted)

    I,J,V = [],[],[]
    offset = [G_lq.size[0], 0]
    for Gcpl in G_coupling:
        I.append(Gcpl.I + offset[0])
        J.append(Gcpl.J + offset[1])
        V.append(Gcpl.V)
        offset[0] += Gcpl.size[0]
        offset[1] += Gcpl.size[1]
    G2 = spmatrix([v for v in itertools.chain(*V)],
                  [v for v in itertools.chain(*I)],
                  [v for v in itertools.chain(*J)],tuple(offset))
    
    if offset[0] == 0 or offset[1] == 0:
        G = G1
    else:
        G = sparse([[G1],[G2]])

    ct = matrix([c,matrix(0.0,(G2.size[1],1))])
    if A is not None:
        return (ct, G, matrix(h_converted),\
          {'l':dims['l'],'q':dims['q'],'s':dims_list},\
          sparse([[A],[spmatrix([],[],[],(A.size[0],G2.size[1]))]]),\
          b), block_to_sparse
    else:
        return (ct, G, matrix(h_converted),\
          {'l':dims['l'],'q':dims['q'],'s':dims_list}), block_to_sparse, symbs