<commit_before>/* -*- mode: C; c-basic-offset: 4; -*- */
/* ex: set shiftwidth=4 tabstop=4 expandtab: */
/*
 * Copyright (c) 2016, Rice University
 * All rights reserved.
 *
 * Author(s): <NAME> <<EMAIL>>
 *
 *   Redistribution and use in source and binary forms, with or
 *   without modification, are permitted provided that the following
 *   conditions are met:
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of copyright holder the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 *   CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 *   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 *   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 *   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 *   AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *   POSSIBILITY OF SUCH DAMAGE.
 *
 */


#include "amino.h"
#include "amino/opt/lp.h"

#include <lpsolve/lp_lib.h>

int aa_opt_lp_lpsolve (
    size_t m, size_t n,
    const double *A, size_t ldA,
    const double *b_lower, const double *b_upper,
    const double *c,
    const double *x_lower, const double *x_upper,
    double *x )
{
    assert( sizeof(REAL) == sizeof(*A) );

    int mi = (int)m;
    int ni = (int)n;
    int r = -1;
    lprec *lp = make_lp(mi, ni);

    if( NULL == lp ) goto ERROR;
    set_add_rowmode(lp, FALSE);
    set_maxim(lp);

    /* TODO: maybe rearrange c/A and give to lp_solve together? */

    /*  printf("A:\n"); aa_dump_mat(stdout, A, ldA, n ); */
    /* printf("bl:"); aa_dump_vec(stdout, b_lower, m ); */
    /* printf("bu:"); aa_dump_vec(stdout, b_upper, m ); */
    /* printf("c:"); aa_dump_vec(stdout, c, n ); */
    /* printf("xl:"); aa_dump_vec(stdout, x_lower, n ); */
    /* printf("xu:"); aa_dump_vec(stdout, x_upper, n ); */

    /* c */
    for( size_t j = 0; j < n; j ++ ) {
        set_obj( lp, 1+(int)j, c[j] );
    }

    /* A, b */
    int ilp = 1;
    for( size_t i = 0; i < m; i ++ ) {
        /* set row */
        for( size_t j = 0; j < n; j ++ ) {
            int col = 1 + (int)j;
            double v = AA_MATREF(A, ldA, i, j);
            set_mat( lp, ilp, col, v );
        }

        /* set row bound */
        double rh;
        int con_type;
        {
            double l=b_lower[i], u=b_upper[i];
            if( aa_feq(l,u,0) ) {
                // equality
                rh = u;
                con_type = EQ;
            } else if (-DBL_MAX >= l ||
                       -1 == isinf(l) ) {
                // less than
                rh = u;
                con_type = LE;
            } else if (DBL_MAX <= u ||
                       1 == isinf(u)) {
                rh = l;
                con_type = GE;
            } else {
                // leq
                set_rh(lp,ilp,u);
                if( ! set_constr_type( lp, ilp, LE ) ) goto ERROR;
                ilp++;
                // geq
                for( size_t j = 0; j < n; j ++ ) {
                    int col = 1 + (int)j;
                    double v = AA_MATREF(A, ldA, i, j);
                    set_mat( lp, ilp, col, v );
                }
                rh = l;
                con_type = GE;
            }
        }
        set_rh(lp,ilp,rh);
        if( ! set_constr_type( lp, ilp, con_type ) ) goto ERROR;
        ilp++;
    }

    /* l/u */
    for( size_t j = 0; j < n; j ++ ) {
        set_bounds( lp, 1+(int)j, x_lower[j], x_upper[j] );
    }

    /* solve */
    r = solve(lp);
    assert(ni == get_Ncolumns(lp));

    /* result */
    get_variables(lp,x);

     /* printf("x:"); aa_dump_vec(stdout, x, n ); */

ERROR:
    if( lp ) delete_lp(lp);
    return r;

}<commit_msg>Use sparse matrix for lp-solve<commit_after>/* -*- mode: C; c-basic-offset: 4; -*- */
/* ex: set shiftwidth=4 tabstop=4 expandtab: */
/*
 * Copyright (c) 2016, Rice University
 * All rights reserved.
 *
 * Author(s): <NAME> <<EMAIL>>
 *
 *   Redistribution and use in source and binary forms, with or
 *   without modification, are permitted provided that the following
 *   conditions are met:
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of copyright holder the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 *   CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 *   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 *   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 *   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 *   AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *   POSSIBILITY OF SUCH DAMAGE.
 *
 */


#include "amino.h"
#include "amino/opt/lp.h"

#include <lpsolve/lp_lib.h>

static int aa_opt_lp_lpsolve_finish (
    lprec *lp,
    size_t m, size_t n,
    const double *c,
    const double *x_lower, const double *x_upper,
    double *x )
{
    int ni = (int)n;
    int mi = (int)m;
    (void)mi;

    /* c */
    for( size_t j = 0; j < n; j ++ ) {
        set_obj( lp, 1+(int)j, c[j] );
    }

    /* l/u */
    for( size_t j = 0; j < n; j ++ ) {
        set_bounds( lp, 1+(int)j, x_lower[j], x_upper[j] );
    }

    /* solve */
    int r = solve(lp);
    assert(ni == get_Ncolumns(lp));

    /* result */
    get_variables(lp,x);
    return r;
}


int aa_opt_lp_lpsolve (
    size_t m, size_t n,
    const double *A, size_t ldA,
    const double *b_lower, const double *b_upper,
    const double *c,
    const double *x_lower, const double *x_upper,
    double *x )
{
    assert( sizeof(REAL) == sizeof(*A) );

    int mi = (int)m;
    int ni = (int)n;
    int r = -1;
    lprec *lp = make_lp(mi, ni);

    if( NULL == lp ) goto ERROR;
    set_add_rowmode(lp, FALSE);
    set_maxim(lp);

    /* TODO: maybe rearrange c/A and give to lp_solve together? */

    /*  printf("A:\n"); aa_dump_mat(stdout, A, ldA, n ); */
    /* printf("bl:"); aa_dump_vec(stdout, b_lower, m ); */
    /* printf("bu:"); aa_dump_vec(stdout, b_upper, m ); */
    /* printf("c:"); aa_dump_vec(stdout, c, n ); */
    /* printf("xl:"); aa_dump_vec(stdout, x_lower, n ); */
    /* printf("xu:"); aa_dump_vec(stdout, x_upper, n ); */


    /* A, b */
    int ilp = 1;
    for( size_t i = 0; i < m; i ++ ) {
        /* set row */
        for( size_t j = 0; j < n; j ++ ) {
            int col = 1 + (int)j;
            double v = AA_MATREF(A, ldA, i, j);
            set_mat( lp, ilp, col, v );
        }

        /* set row bound */
        double rh;
        int con_type;
        {
            double l=b_lower[i], u=b_upper[i];
            if( aa_feq(l,u,0) ) {
                // equality
                rh = u;
                con_type = EQ;
            } else if (-DBL_MAX >= l ||
                       -1 == isinf(l) ) {
                // less than
                rh = u;
                con_type = LE;
            } else if (DBL_MAX <= u ||
                       1 == isinf(u)) {
                rh = l;
                con_type = GE;
            } else {
                // leq
                set_rh(lp,ilp,u);
                if( ! set_constr_type( lp, ilp, LE ) ) goto ERROR;
                ilp++;
                // geq
                for( size_t j = 0; j < n; j ++ ) {
                    int col = 1 + (int)j;
                    double v = AA_MATREF(A, ldA, i, j);
                    set_mat( lp, ilp, col, v );
                }
                rh = l;
                con_type = GE;
            }
        }
        set_rh(lp,ilp,rh);
        if( ! set_constr_type( lp, ilp, con_type ) ) goto ERROR;
        ilp++;
    }

    r = aa_opt_lp_lpsolve_finish( lp, m, n, c, x_lower, x_upper, x);

ERROR:
    if( lp ) delete_lp(lp);
    return r;

}

AA_API int aa_opt_lp_crs_lpsolve (
    size_t m, size_t n,
    const double *A_values, int *A_cols, int *A_row_ptr,
    const double *b_lower, const double *b_upper,
    const double *c,
    const double *x_lower, const double *x_upper,
    double *x )
{
    assert( sizeof(REAL) == sizeof(*A_values) );

    int mi = (int)m;
    int ni = (int)n;
    int r = -1;
    lprec *lp = make_lp(0, ni);

    if( NULL == lp ) goto ERROR;
    set_maxim(lp);

    /* A, b_l, b_u */
    set_add_rowmode(lp, TRUE);
    for( int i = 0; i < mi; i ++ ) {
        double l=b_lower[i], u=b_upper[i];
        int start = A_row_ptr[i];
        int end = A_row_ptr[i + 1];
        int count = end - start;
        double *vals = (double*)A_values + start;
        int *inds = (int*)A_cols + start;
        double rh;
        int con_type;
        if( aa_feq(l,u,0) ) {
            // equality
            rh = u;
            con_type = EQ;
        } else if (-DBL_MAX >= l ||
                   -1 == isinf(l) ) {
            // less than
            rh = u;
            con_type = LE;
            add_constraintex(lp, count, vals, inds, EQ, u);
        } else if (DBL_MAX <= u ||
                   1 == isinf(u)) {
            rh = l;
            con_type = GE;
        } else {
            // leq
            add_constraintex(lp, count, vals, inds, LE, u);
            rh = l;
            con_type = GE;
        }
        add_constraintex(lp, count, vals, inds, con_type, rh);
    }
    set_add_rowmode(lp, FALSE);

    r = aa_opt_lp_lpsolve_finish( lp, m, n, c, x_lower, x_upper, x);

ERROR:
    if( lp ) delete_lp(lp);
    return r;

}
{'fraction_non_alphanumeric': 0.1250113399256101, 'fraction_numerical': 0.0044452508391544954, 'mean_word_length': 1.839041977852176, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 14, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3586710', 'n_tokens_mistral': 3860, 'n_tokens_neox': 3628, 'n_words': 1176}