📄 lpkit.c
字号:
#include "lpkit.h"#include "lpglob.h"#include <stdlib.h>#include <stdarg.h>#include <stdio.h>#include <string.h>#define HASHSIZE 10007/* Globals */int Rows;int Columns;int Sum;int Non_zeros;int Level;REAL Trej;short Maximise;REAL Extrad;int Warn_count; /* used in CHECK version of rounding macro */void error(char *format, ...){ va_list ap; va_start(ap, format); vfprintf(stderr, format, ap); fputc('\n', stderr); va_end(ap); exit(EXIT_FAILURE);}lprec *make_lp(int rows, int columns){ lprec *newlp; int i, sum; if(rows < 0 || columns < 0) error("rows < 0 or columns < 0"); sum = rows + columns; CALLOC(newlp, 1); strcpy(newlp->lp_name, "unnamed"); newlp->verbose = FALSE; newlp->print_duals = FALSE; newlp->print_sol = FALSE; newlp->debug = FALSE; newlp->print_at_invert = FALSE; newlp->trace = FALSE; newlp->rows = rows; newlp->columns = columns; newlp->sum = sum; newlp->rows_alloc = rows; newlp->columns_alloc = columns; newlp->sum_alloc = sum; newlp->names_used = FALSE; newlp->obj_bound = DEF_INFINITE; newlp->infinite = DEF_INFINITE; newlp->epsilon = DEF_EPSILON; newlp->epsb = DEF_EPSB; newlp->epsd = DEF_EPSD; newlp->epsel = DEF_EPSEL; newlp->non_zeros = 0; newlp->mat_alloc = 1; CALLOC(newlp->mat, newlp->mat_alloc); CALLOC(newlp->col_no, newlp->mat_alloc + 1); CALLOC(newlp->col_end, columns + 1); CALLOC(newlp->row_end, rows + 1); newlp->row_end_valid = FALSE; CALLOC(newlp->orig_rh, rows + 1); CALLOC(newlp->rh, rows + 1); CALLOC(newlp->rhs, rows + 1); CALLOC(newlp->must_be_int, sum + 1); for(i = 0; i <= sum; i++) newlp->must_be_int[i] = FALSE; CALLOC(newlp->orig_upbo, sum + 1); for(i = 0; i <= sum; i++) newlp->orig_upbo[i] = newlp->infinite; CALLOC(newlp->upbo, sum + 1); CALLOC(newlp->orig_lowbo, sum + 1); CALLOC(newlp->lowbo, sum + 1); newlp->basis_valid = TRUE; CALLOC(newlp->bas, rows+1); CALLOC(newlp->basis, sum + 1); CALLOC(newlp->lower, sum + 1); for(i = 0; i <= rows; i++) { newlp->bas[i] = i; newlp->basis[i] = TRUE; } for(i = rows + 1; i <= sum; i++) newlp->basis[i] = FALSE; for(i = 0 ; i <= sum; i++) newlp->lower[i] = TRUE; newlp->eta_valid = TRUE; newlp->eta_size = 0; newlp->eta_alloc = INITIAL_MAT_SIZE; newlp->max_num_inv = DEFNUMINV; newlp->nr_lagrange = 0; CALLOC(newlp->eta_value, newlp->eta_alloc); CALLOC(newlp->eta_row_nr, newlp->eta_alloc); /* +1 reported by Christian Rank */ CALLOC(newlp->eta_col_end, newlp->rows_alloc + newlp->max_num_inv + 1); newlp->bb_rule = FIRST_NI; newlp->break_at_int = FALSE; newlp->break_value = 0; newlp->iter = 0; newlp->total_iter = 0; CALLOC(newlp->solution, sum + 1); CALLOC(newlp->best_solution, sum + 1); CALLOC(newlp->duals, rows + 1); newlp->maximise = FALSE; newlp->floor_first = TRUE; newlp->scaling_used = FALSE; newlp->columns_scaled = FALSE; CALLOC(newlp->ch_sign, rows + 1); for(i = 0; i <= rows; i++) newlp->ch_sign[i] = FALSE; newlp->valid = FALSE; /* create two hash tables for names */ newlp->rowname_hashtab = create_hash_table(HASHSIZE); newlp->colname_hashtab = create_hash_table(HASHSIZE); return(newlp);}void delete_lp(lprec *lp){ int i; if(lp->names_used) { free(lp->row_name); free(lp->col_name); } free(lp->mat); free(lp->col_no); free(lp->col_end); free(lp->row_end); free(lp->orig_rh); free(lp->rh); free(lp->rhs); free(lp->must_be_int); free(lp->orig_upbo); free(lp->orig_lowbo); free(lp->upbo); free(lp->lowbo); free(lp->bas); free(lp->basis); free(lp->lower); free(lp->eta_value); free(lp->eta_row_nr); free(lp->eta_col_end); free(lp->solution); free(lp->best_solution); free(lp->duals); free(lp->ch_sign); if(lp->scaling_used) free(lp->scale); if(lp->nr_lagrange > 0) { free(lp->lag_rhs); free(lp->lambda); free(lp->lag_con_type); for(i = 0; i < lp->nr_lagrange; i++) free(lp->lag_row[i]); free(lp->lag_row); } free_hash_table(lp->rowname_hashtab); free_hash_table(lp->colname_hashtab); free(lp);} lprec *copy_lp(lprec *lp){ lprec *newlp; int i, rowsplus, colsplus, sumplus; rowsplus = lp->rows_alloc + 1; colsplus = lp->columns_alloc + 1; sumplus = lp->sum_alloc + 1; MALLOCCPY(newlp, lp, 1); /* copy all non pointers */ if(newlp->names_used) { MALLOCCPY(newlp->col_name, lp->col_name, colsplus); MALLOCCPY(newlp->row_name, lp->row_name, rowsplus); } newlp->rowname_hashtab = copy_hash_table(lp->rowname_hashtab); newlp->colname_hashtab = copy_hash_table(lp->colname_hashtab); MALLOCCPY(newlp->mat, lp->mat, newlp->mat_alloc); MALLOCCPY(newlp->col_end, lp->col_end, colsplus); MALLOCCPY(newlp->col_no, lp->col_no, newlp->mat_alloc + 1); MALLOCCPY(newlp->row_end, lp->row_end, rowsplus); MALLOCCPY(newlp->orig_rh, lp->orig_rh, rowsplus); MALLOCCPY(newlp->rh, lp->rh, rowsplus); MALLOCCPY(newlp->rhs, lp->rhs, rowsplus); MALLOCCPY(newlp->must_be_int, lp->must_be_int, sumplus); MALLOCCPY(newlp->orig_upbo, lp->orig_upbo, sumplus); MALLOCCPY(newlp->orig_lowbo, lp->orig_lowbo, sumplus); MALLOCCPY(newlp->upbo, lp->upbo, sumplus); MALLOCCPY(newlp->lowbo, lp->lowbo, sumplus); MALLOCCPY(newlp->bas, lp->bas, rowsplus); MALLOCCPY(newlp->basis, lp->basis, sumplus); MALLOCCPY(newlp->lower, lp->lower, sumplus); MALLOCCPY(newlp->eta_value, lp->eta_value, lp->eta_alloc); MALLOCCPY(newlp->eta_row_nr, lp->eta_row_nr, lp->eta_alloc); MALLOCCPY(newlp->eta_col_end, lp->eta_col_end, lp->rows_alloc + lp->max_num_inv + 1); MALLOCCPY(newlp->solution, lp->solution, sumplus); MALLOCCPY(newlp->best_solution, lp->best_solution, sumplus); MALLOCCPY(newlp->duals, lp->duals, rowsplus); MALLOCCPY(newlp->ch_sign, lp->ch_sign, rowsplus); if(newlp->scaling_used) MALLOCCPY(newlp->scale, lp->scale, sumplus); if(newlp->nr_lagrange > 0) { MALLOCCPY(newlp->lag_rhs, lp->lag_rhs, newlp->nr_lagrange); MALLOCCPY(newlp->lambda, lp->lambda, newlp->nr_lagrange); MALLOCCPY(newlp->lag_con_type, lp->lag_con_type, newlp->nr_lagrange); MALLOC(newlp->lag_row, newlp->nr_lagrange); for(i = 0; i < newlp->nr_lagrange; i++) MALLOCCPY(newlp->lag_row[i], lp->lag_row[i], colsplus); } return(newlp);}void inc_mat_space(lprec *lp, int maxextra){ if(lp->non_zeros + maxextra >= lp->mat_alloc) { /* let's allocate at least INITIAL_MAT_SIZE entries */ if(lp->mat_alloc < INITIAL_MAT_SIZE) lp->mat_alloc = INITIAL_MAT_SIZE; /* increase the size by 50% each time it becomes too small */ while(lp->non_zeros + maxextra >= lp->mat_alloc) lp->mat_alloc *= 1.5; REALLOC(lp->mat, lp->mat_alloc); REALLOC(lp->col_no, lp->mat_alloc + 1); }} void inc_row_space(lprec *lp){ if(lp->rows > lp->rows_alloc) { lp->rows_alloc = lp->rows+10; lp->sum_alloc = lp->rows_alloc + lp->columns_alloc; REALLOC(lp->orig_rh, lp->rows_alloc + 1); REALLOC(lp->rh, lp->rows_alloc + 1); REALLOC(lp->rhs, lp->rows_alloc + 1); REALLOC(lp->orig_upbo, lp->sum_alloc + 1); REALLOC(lp->upbo, lp->sum_alloc + 1); REALLOC(lp->orig_lowbo, lp->sum_alloc + 1); REALLOC(lp->lowbo, lp->sum_alloc + 1); REALLOC(lp->solution, lp->sum_alloc + 1); REALLOC(lp->best_solution, lp->sum_alloc + 1); REALLOC(lp->row_end, lp->rows_alloc + 1); REALLOC(lp->basis, lp->sum_alloc + 1); REALLOC(lp->lower, lp->sum_alloc + 1); REALLOC(lp->must_be_int, lp->sum_alloc + 1); REALLOC(lp->bas, lp->rows_alloc + 1); REALLOC(lp->duals, lp->rows_alloc + 1); REALLOC(lp->ch_sign, lp->rows_alloc + 1); REALLOC(lp->eta_col_end, lp->rows_alloc + lp->max_num_inv + 1); if(lp->names_used) REALLOC(lp->row_name, lp->rows_alloc + 1); if(lp->scaling_used) REALLOC(lp->scale, lp->sum_alloc + 1); }}void inc_col_space(lprec *lp){ if(lp->columns >= lp->columns_alloc) { lp->columns_alloc = lp->columns + 10; lp->sum_alloc = lp->rows_alloc + lp->columns_alloc; REALLOC(lp->must_be_int, lp->sum_alloc + 1); REALLOC(lp->orig_upbo, lp->sum_alloc + 1); REALLOC(lp->upbo, lp->sum_alloc + 1); REALLOC(lp->orig_lowbo, lp->sum_alloc + 1); REALLOC(lp->lowbo, lp->sum_alloc + 1); REALLOC(lp->solution, lp->sum_alloc + 1); REALLOC(lp->best_solution, lp->sum_alloc + 1); REALLOC(lp->basis, lp->sum_alloc + 1); REALLOC(lp->lower, lp->sum_alloc + 1); if(lp->names_used) REALLOC(lp->col_name, lp->columns_alloc + 1); if(lp->scaling_used) REALLOC(lp->scale, lp->sum_alloc + 1); REALLOC(lp->col_end, lp->columns_alloc + 1); }}void set_mat(lprec *lp, int Row, int Column, REAL Value){ int elmnr, lastelm, i; /* This function is very inefficient if used to add new matrix entries in other places than at the end of the matrix. OK for replacing existing non-zero values */ if(Row > lp->rows || Row < 0) error("Row out of range"); if(Column > lp->columns || Column < 1) error("Column out of range"); /* scaling is performed twice? MB */ if(lp->scaling_used) Value *= lp->scale[Row] * lp->scale[lp->rows + Column]; if (lp->basis[Column] == TRUE && Row > 0) lp->basis_valid = FALSE; lp->eta_valid = FALSE; /* find out if we already have such an entry */ elmnr = lp->col_end[Column - 1]; while((elmnr < lp->col_end[Column]) && (lp->mat[elmnr].row_nr != Row)) elmnr++; if((elmnr != lp->col_end[Column]) && (lp->mat[elmnr].row_nr == Row)) { /* there is an existing entry */ if(my_abs(Value) > lp->epsilon) { /* we replace it by something non-zero */ if (lp->scaling_used) { if(lp->ch_sign[Row]) lp->mat[elmnr].value = -Value * lp->scale[Row] * lp->scale[Column]; else lp->mat[elmnr].value = Value * lp->scale[Row] * lp->scale[Column]; } else { /* no scaling */ if(lp->ch_sign[Row]) lp->mat[elmnr].value = -Value; else lp->mat[elmnr].value = Value; } } else { /* setting existing non-zero entry to zero. Remove the entry */ /* this might remove an entire column, or leave just a bound. No nice solution for that yet */ /* Shift the matrix */ lastelm = lp->non_zeros; for(i = elmnr; i < lastelm ; i++) lp->mat[i] = lp->mat[i + 1]; for(i = Column; i <= lp->columns; i++) lp->col_end[i]--; lp->non_zeros--; } } else if(my_abs(Value) > lp->epsilon) { /* no existing entry. make new one only if not nearly zero */ /* check if more space is needed for matrix */ inc_mat_space(lp, 1); /* Shift the matrix */ lastelm = lp->non_zeros; for(i = lastelm; i > elmnr ; i--) lp->mat[i] = lp->mat[i - 1]; for(i = Column; i <= lp->columns; i++) lp->col_end[i]++; /* Set new element */ lp->mat[elmnr].row_nr = Row; if (lp->scaling_used) { if(lp->ch_sign[Row]) lp->mat[elmnr].value = -Value * lp->scale[Row] * lp->scale[Column]; else lp->mat[elmnr].value = Value * lp->scale[Row] * lp->scale[Column]; } else /* no scaling */ { if(lp->ch_sign[Row]) lp->mat[elmnr].value = -Value; else lp->mat[elmnr].value = Value; } lp->row_end_valid = FALSE; lp->non_zeros++; } }void set_obj_fn(lprec *lp, REAL *row){ int i; for(i = 1; i <= lp->columns; i++) set_mat(lp, 0, i, row[i]);}void str_set_obj_fn(lprec *lp, char *row){ int i; REAL *arow; char *p, *newp; CALLOC(arow, lp->columns + 1); p = row; for(i = 1; i <= lp->columns; i++) { arow[i] = (REAL) strtod(p, &newp); if(p == newp) error("Bad string in str_set_obj_fn"); else p = newp; } set_obj_fn(lp, arow); free(arow);}void add_constraint(lprec *lp, REAL *row, short constr_type, REAL rh){ matrec *newmat; int i, j; int elmnr; int stcol; int *addtoo; MALLOC(addtoo, lp->columns + 1); for(i = 1; i <= lp->columns; i++) if(row[i] != 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -