Ejemplo n.º 1
0
void color_general_colpack(
    VectorSet&        pattern ,
    const VectorSize&       row     ,
    const VectorSize&       col     ,
    CppAD::vector<size_t>&  color   )
{   size_t i, j, k;
    size_t m = pattern.n_set();
    size_t n = pattern.end();

    // Determine number of non-zero entries in each row
    CppAD::vector<size_t> n_nonzero(m);
    size_t n_nonzero_total = 0;
    for(i = 0; i < m; i++)
    {   n_nonzero[i] = 0;
        pattern.begin(i);
        j = pattern.next_element();
        while( j != pattern.end() )
        {   n_nonzero[i]++;
            j = pattern.next_element();
        }
        n_nonzero_total += n_nonzero[i];
    }

    // Allocate memory and fill in Adolc sparsity pattern
    CppAD::vector<unsigned int*> adolc_pattern(m);
    CppAD::vector<unsigned int>  adolc_memory(m + n_nonzero_total);
    size_t i_memory = 0;
    for(i = 0; i < m; i++)
    {   adolc_pattern[i]    = adolc_memory.data() + i_memory;
        adolc_pattern[i][0] = n_nonzero[i];
        pattern.begin(i);
        j = pattern.next_element();
        k = 1;
        while(j != pattern.end() )
        {   adolc_pattern[i][k++] = j;
            j = pattern.next_element();
        }
        CPPAD_ASSERT_UNKNOWN( k == 1 + n_nonzero[i] );
        i_memory += k;
    }
    CPPAD_ASSERT_UNKNOWN( i_memory == m + n_nonzero_total );

    // Must use an external routine for this part of the calculation because
    // ColPack/ColPackHeaders.h has as 'using namespace std' at global level.
    cppad_colpack_general(color, m, n, adolc_pattern);

    return;
}
Ejemplo n.º 2
0
void color_general_cppad(
    VectorSet&        pattern ,
    const VectorSize&       row     ,
    const VectorSize&       col     ,
    CppAD::vector<size_t>&  color   )
{   size_t i, j, k, ell, r;

    size_t K = row.size();
    size_t m = pattern.n_set();
    size_t n = pattern.end();

    CPPAD_ASSERT_UNKNOWN( size_t( col.size() )   == K );
    CPPAD_ASSERT_UNKNOWN( size_t( color.size() ) == m );

    // We define the set of rows, columns, and pairs that appear
    // by the set ( row[k], col[k] ) for k = 0, ... , K-1.

    // initialize rows that appear
    CppAD::vector<bool> row_appear(m);
    for(i = 0; i < m; i++)
        row_appear[i] = false;

    // rows and columns that appear
    VectorSet c2r_appear, r2c_appear;
    c2r_appear.resize(n, m);
    r2c_appear.resize(m, n);
    for(k = 0;  k < K; k++)
    {   CPPAD_ASSERT_UNKNOWN( pattern.is_element(row[k], col[k]) );
        row_appear[ row[k] ] = true;
        c2r_appear.add_element(col[k], row[k]);
        r2c_appear.add_element(row[k], col[k]);
    }

    // for each column, which rows are non-zero and do not appear
    VectorSet not_appear;
    not_appear.resize(n, m);
    for(i = 0; i < m; i++)
    {   pattern.begin(i);
        j = pattern.next_element();
        while( j != pattern.end() )
        {   if( ! c2r_appear.is_element(j , i) )
                not_appear.add_element(j, i);
            j = pattern.next_element();
        }
    }

    // initial coloring
    color.resize(m);
    ell = 0;
    for(i = 0; i < m; i++)
    {   if( row_appear[i] )
            color[i] = ell++;
        else	color[i] = m;
    }
    /*
    See GreedyPartialD2Coloring Algorithm Section 3.6.2 of
    Graph Coloring in Optimization Revisited by
    Assefaw Gebremedhin, Fredrik Maane, Alex Pothen

    The algorithm above was modified (by Brad Bell) to take advantage of the
    fact that only the entries (subset of the sparsity pattern) specified by
    row and col need to be computed.
    */
    CppAD::vector<bool> forbidden(m);
    for(i = 1; i < m; i++) // for each row that appears
        if( color[i] < m )
        {
            // initial all colors as ok for this row
            // (value of forbidden for ell > initial color[i] does not matter)
            for(ell = 0; ell <= color[i]; ell++)
                forbidden[ell] = false;

            // -----------------------------------------------------
            // Forbid colors for which this row would destroy results:
            //
            // for each column that is non-zero for this row
            pattern.begin(i);
            j = pattern.next_element();
            while( j != pattern.end() )
            {   // for each row that appears with this column
                c2r_appear.begin(j);
                r = c2r_appear.next_element();
                while( r != c2r_appear.end() )
                {   // if this is not the same row, forbid its color
                    if( (r < i) & (color[r] < m) )
                        forbidden[ color[r] ] = true;
                    r = c2r_appear.next_element();
                }
                j = pattern.next_element();
            }


            // -----------------------------------------------------
            // Forbid colors that destroy results needed for this row.
            //
            // for each column that appears with this row
            r2c_appear.begin(i);
            j = r2c_appear.next_element();
            while( j != r2c_appear.end() )
            {   // For each row that is non-zero for this column
                // (the appear rows have already been checked above).
                not_appear.begin(j);
                r = not_appear.next_element();
                while( r != not_appear.end() )
                {   // if this is not the same row, forbid its color
                    if( (r < i) & (color[r] < m) )
                        forbidden[ color[r] ] = true;
                    r = not_appear.next_element();
                }
                j = r2c_appear.next_element();
            }

            // pick the color with smallest index
            ell = 0;
            while( forbidden[ell] )
            {   ell++;
                CPPAD_ASSERT_UNKNOWN( ell <= color[i] );
            }
            color[i] = ell;
        }
    return;
}
Ejemplo n.º 3
0
size_t ADFun<Base>::SparseJacobianRev(
	const VectorBase&     x           ,
	VectorSet&            p           ,
	VectorBase&           jac         ,
	sparse_jacobian_work& work        )
{
	using   CppAD::vectorBool;
	size_t i, j, k, ell;

	CppAD::vector<size_t>& row(work.user_row);
	CppAD::vector<size_t>& col(work.user_col);
	CppAD::vector<size_t>& sort_row(work.sort_row);
	CppAD::vector<size_t>& color(work.color);

	size_t m = Range();
	size_t n = Domain();

	// some values
	const Base zero(0);
	const Base one(1);

	// check VectorBase is Simple Vector class with Base type elements
	CheckSimpleVector<Base, VectorBase>();

	CPPAD_ASSERT_UNKNOWN( size_t(x.size()) == n );
	CPPAD_ASSERT_UNKNOWN (color.size() == m || color.size() == 0 );

	// number of components of Jacobian that are required
	size_t K = size_t(jac.size());
	CPPAD_ASSERT_UNKNOWN( row.size() == K+1 );
	CPPAD_ASSERT_UNKNOWN( col.size() == K+1 );
	CPPAD_ASSERT_UNKNOWN( row[K] == m );
	CPPAD_ASSERT_UNKNOWN( col[K] == n );

	// Point at which we are evaluating the Jacobian
	Forward(0, x);

	if( color.size() == 0 )
	{	CPPAD_ASSERT_UNKNOWN( p.n_set() ==  m );
		CPPAD_ASSERT_UNKNOWN( p.end() ==  n );

		// rows and columns that are in the returned jacobian
		VectorSet r_used, c_used;
		r_used.resize(n, m);
		c_used.resize(m, n);
		k = 0;
		while( k < K )
		{	CPPAD_ASSERT_UNKNOWN( 
				row[sort_row[k]] < m && col[sort_row[k]] < n 
			);
			CPPAD_ASSERT_UNKNOWN( 
				k == 0 || row[sort_row[k-1]] <= row[sort_row[k]] 
			);
			CPPAD_ASSERT_KNOWN(
				p.is_element(row[sort_row[k]], col[sort_row[k]]) ,
				"SparseJacobianReverse: "
				"an (row, col) pair is not in sparsity pattern."
			);
			r_used.add_element(col[sort_row[k]], row[sort_row[k]]);
			c_used.add_element(row[sort_row[k]], col[sort_row[k]]);
			k++;
		}
	
		// given a column index, which rows are non-zero and not used
		VectorSet not_used;
		not_used.resize(n, m);
		for(i = 0; i < m; i++)
		{	p.begin(i);
			j = p.next_element();
			while( j != p.end() )
			{	if( ! r_used.is_element(j , i) )
					not_used.add_element(j, i);
				j = p.next_element();
			}
		}
	
		// initial coloring
		color.resize(m);
		for(i = 0; i < m; i++)
			color[i] = i;
	
		// See GreedyPartialD2Coloring Algorithm Section 3.6.2 of
		// Graph Coloring in Optimization Revisited by
		// Assefaw Gebremedhin, Fredrik Maane, Alex Pothen
		vectorBool forbidden(m);
		for(i = 1; i < m; i++)
		{
			// initial all colors as ok for this row
			// (value of forbidden for ell > i does not matter)
			for(ell = 0; ell <= i; ell++)
				forbidden[ell] = false;
	
			// -----------------------------------------------------
			// Forbid colors for which this row would destroy results 
			// for each column that is non-zero for this row
			p.begin(i);
			j = p.next_element();
			while( j != p.end() )
			{	// for each row that this column uses
				r_used.begin(j);
				ell = r_used.next_element();
				while( ell != r_used.end() )
				{	// if this is not the same row, forbid its color 
					if( ell < i )
						forbidden[ color[ell] ] = true;
					ell = r_used.next_element();
				}
				j = p.next_element();
			}

	
			// -----------------------------------------------------
			// Forbid colors that would destroy results for this row.
			// for each column that this row uses
			c_used.begin(i);
			j = c_used.next_element();
			while( j != c_used.end() )
			{	// For each row that is non-zero for this column
				// (the used rows have already been checked above).
				not_used.begin(j);
				ell = not_used.next_element();
				while( ell != not_used.end() )
				{	// if this is not the same row, forbid its color 
					if( ell < i )
						forbidden[ color[ell] ] = true;
					ell = not_used.next_element();
				}
				j = c_used.next_element();
			}

			// pick the color with smallest index
			ell = 0;
			while( forbidden[ell] )
			{	ell++;
				CPPAD_ASSERT_UNKNOWN( ell <= i );
			}
			color[i] = ell;
		}
	}
	size_t n_color = 1;
	for(ell = 0; ell < m; ell++) 
		n_color = std::max(n_color, color[ell] + 1);

	// weighting vector for calls to reverse
	VectorBase w(m);

	// location for return values from Reverse
	VectorBase dw(n);

	// initialize the return value
	for(k = 0; k < K; k++)
		jac[k] = zero;

	// loop over colors
	size_t n_sweep = 0;
	for(ell = 0; ell < n_color; ell++)
	{	bool any = false;
		k = 0;
		for(i = 0; i < m; i++) if( color[i] == ell )
		{	// find first k such that row[sort_row[k]] has color ell
			if( ! any )
			{	while( row[sort_row[k]] < i )
					k++;
				any = row[sort_row[k]] == i;
			}
		}
		if( any )
		{	n_sweep++;
			// combine all the rows with this color
			for(i = 0; i < m; i++)
			{	w[i] = zero;
				if( color[i] == ell )
					w[i] = one;
			}
			// call reverse mode for all these rows at once
			dw = Reverse(1, w);

			// set the corresponding components of the result
			for(i = 0; i < m; i++) if( color[i] == ell )
			{	// find first index in r for this row
				while( row[sort_row[k]] < i )
					k++;
				// extract the row results for this row
				while( row[sort_row[k]] == i ) 
				{	jac[ sort_row[k] ] = dw[col[sort_row[k]]];
					k++;
				}
			}
		}
	}
	return n_sweep;
}