diff options
Diffstat (limited to 'sci_gateway/cpp/sym_data_query_functions.cpp')
-rw-r--r-- | sci_gateway/cpp/sym_data_query_functions.cpp | 404 |
1 files changed, 404 insertions, 0 deletions
diff --git a/sci_gateway/cpp/sym_data_query_functions.cpp b/sci_gateway/cpp/sym_data_query_functions.cpp new file mode 100644 index 0000000..b0d0989 --- /dev/null +++ b/sci_gateway/cpp/sym_data_query_functions.cpp @@ -0,0 +1,404 @@ +/* + * Implementation Symphony Tool Box for Scilab + * sym_data_query_functions.cpp + * contains Data Query Functions( 13 functions) + * Author: Sai Kiran + */ + +#include <symphony.h> +#include <sci_iofunc.hpp> +extern sym_environment* global_sym_env;//defined in globals.cpp + +extern "C" { +#include <api_scilab.h> +#include <Scierror.h> +#include <BOOL.h> +#include <localization.h> +#include <sciprint.h> + +#include <string.h> + +// Function to print termination status of a function +void show_termination_status(int status) { + if (status == FUNCTION_TERMINATED_ABNORMALLY) + sciprint("\nFunction invoked unsuccessfully.\n"); + //else + //sciprint("\nFunction invoked successfully.\n"); + } + +/* + * Generelized function for sym_getNumVars, + * sym_getNumConstrs,sym_get_NumElements +*/ +int sci_sym_get_num_int(char *fname, unsigned long fname_len){ + + int result=-1;/* Result of the callar */ + + //check whether we have no input and one output argument or not + CheckInputArgument(pvApiCtx, 0, 0) ; //no input argument + CheckOutputArgument(pvApiCtx, 1, 1) ; //one output argument + + /* Array of possible callers of this function */ + char* arr_caller[]={"sym_getNumConstr","sym_getNumVar","sym_getNumElements"}; + + /* Array of functions to be called */ + int (*fun[])(sym_environment*,int*)= { sym_get_num_rows, + sym_get_num_cols, + sym_get_num_elements + }; + + if(global_sym_env==NULL) //There is no environment opened. + sciprint("Error: Symphony environment is not initialized.\n"); + else { + //There is an environment opened + int iter=0,length=sizeof(arr_caller)/sizeof(char*),found_at= -1; + for (;iter < length ;++iter){ + if (!strcmp(fname,arr_caller[iter])) + found_at=iter; + } + if (found_at != -1) { + int ret_val=fun[found_at](global_sym_env,&result); + show_termination_status(ret_val); + if (ret_val == FUNCTION_TERMINATED_ABNORMALLY) + result=-1; + } + else //very rare case + sciprint("\nError in function mapping in scilab script\n"); + } + + //Copy the result to scilab. Location is position next to input arguments. + return returnDoubleToScilab(result); + } + +/* This is generelized function for + * sym_getVarLower,sym_getVarUpper,sym_getRhs,sym_getConstrRange,sym_getConstrLower, + * sym_getConstrUpper and sym_getObjCoeff . + * (Functions taking symphony env and pointer to array of doubles as arguments) +*/ +int sci_sym_get_dbl_arr(char *fname, unsigned long fname_len){ + + int result_len=0;/* Length of the output double array */ + double *result=NULL;/* Pointer to output double array */ + + //check whether we have no input and one output argument or not + CheckInputArgument(pvApiCtx, 0, 0) ; //no input argument + CheckOutputArgument(pvApiCtx, 1, 1) ; //one output argument + + /* Array of possible callers of this function */ + char* arr_caller[]={"sym_getVarLower","sym_getVarUpper", + "sym_getRhs","sym_getConstrRange", + "sym_getConstrLower","sym_getConstrUpper", + "sym_getObjCoeff"}; + + /* Array of functions to be called */ + int (*fun[])(sym_environment*,double*)= {sym_get_col_lower,sym_get_col_upper, + sym_get_rhs,sym_get_row_range, + sym_get_row_lower,sym_get_row_upper, + sym_get_obj_coeff }; + + /* Array of functions the above functions depend on */ + int (*fun_depends[])(sym_environment*,int*) = {sym_get_num_cols,sym_get_num_cols, + sym_get_num_rows,sym_get_num_rows, + sym_get_num_rows,sym_get_num_rows, + sym_get_num_cols }; + + /* We want to ouput row-matrix if we are dealing with column data . + * column matrix if we are dealing with row data . + * 0 - output a row matrix. + * 1 - output a column matrix. + */ + int representation = 0; //output a row matrix + + /* Array of representations of output depending on the above functions. + * It's length is same as above arrays. + */ + int matrix_representation[] = { 0 ,0 , 1, 1, 1, 1, 0}; + if(global_sym_env==NULL) //There is no environment opened. + sciprint("Error: Symphony environment is not initialized.\n"); + else { + //There is an environment opened + int iter=0,length=sizeof(arr_caller)/sizeof(char*),found_at= -1; + for (;iter < length ;++iter){ + if (!strcmp(fname,arr_caller[iter])) + found_at=iter; + } + if (found_at != -1){ + int status1=fun_depends[found_at](global_sym_env,&result_len); + if ( status1 == FUNCTION_TERMINATED_NORMALLY && result_len ) { + result=(double*)malloc( sizeof(double) * result_len ); + int ret_val=fun[found_at](global_sym_env,result); + show_termination_status(ret_val); + if (ret_val == FUNCTION_TERMINATED_ABNORMALLY) + result_len=0; + else { + if (found_at == 6) {//if called function is sym_getObjCoeff + int iter=0,sense=0,status2 = sym_get_obj_sense(global_sym_env,&sense); + if (sense == -1) // Multiply with -1 while showing + for (;iter < result_len;++iter) result[iter] *= -1; + } + representation = matrix_representation[found_at]; + } + } + else + sciprint("\n Is a problem loaded ? \n"); + } + else //very rare case + sciprint("\nError in function mapping in scilab script\n"); + } + + //Copy the result to scilab. Location is position next to input arguments. + SciErr err; + if (representation) // output a column-matrix + err=createMatrixOfDouble(pvApiCtx,nbInputArgument(pvApiCtx)+1,result_len,1,result); + else // output a row-matrix + err=createMatrixOfDouble(pvApiCtx,nbInputArgument(pvApiCtx)+1,1,result_len,result); + free(result); //Free the allocated space + result=NULL; //Set to NULL + if (err.iErr){ //Process error + AssignOutputVariable(pvApiCtx, 1) = 0; + printError(&err, 0); + return 1; + } + + //assign result position to output argument + AssignOutputVariable(pvApiCtx, 1) = nbInputArgument(pvApiCtx) + 1; + ReturnArguments(pvApiCtx); + return 0; + } + +/* This function returns rows sense of the problem loaded +*/ +int sci_sym_get_row_sense(char *fname, unsigned long fname_len) { + + //check whether we have no input and one output argument or not + CheckInputArgument(pvApiCtx, 0, 0) ; //no input argument + CheckOutputArgument(pvApiCtx, 1, 1) ; //one output argument + + // Create a dummy string + char *dummy=(char*)malloc(sizeof(char)); + char **correct=NULL; // Correct result of the function + dummy[0]='\0'; + char **row_senses=&dummy; + int num_rows=0; + if(global_sym_env==NULL) //There is no environment opened. + sciprint("Error: Symphony environment is not initialized.\n"); + else { + int status=sym_get_num_rows(global_sym_env,&num_rows); + if (status != FUNCTION_TERMINATED_ABNORMALLY) { //If function terminated normally + char senses[num_rows]; + char *ptr=senses; + // Take rows sense from symphony + int status1=sym_get_row_sense(global_sym_env,ptr); + if (status1 == FUNCTION_TERMINATED_ABNORMALLY) { + sciprint("\n Is a problem loaded ? \n"); + show_termination_status(status1); + row_senses=&dummy; + num_rows=0; + } + else { // If function terminated normally + // Convert every character to string + correct=(char**)malloc(sizeof(char*) * num_rows); + int iter=0; + for (;iter < num_rows;++iter) { + correct[iter]=(char*)malloc(sizeof(char)*2); + correct[iter][0]=senses[iter]; + correct[iter][1]='\0'; + } + row_senses=correct; + show_termination_status(status1);// Show termination status of caller + } + } + else show_termination_status(status); + } + // Write output to scilab memory + SciErr err=createMatrixOfString(pvApiCtx,nbInputArgument(pvApiCtx)+1,num_rows,1,row_senses); + free(dummy); //free dummy variable + dummy=NULL; + if (correct){ // If we have allocated + int iter=0; + for (;iter < num_rows;++iter){ + free(correct[iter]); // Free each element in it + } + free(correct); // Free it + correct=NULL; + } + if (err.iErr){ //Process error + printError(&err, 0); + AssignOutputVariable(pvApiCtx, 1) = 0; + return 0; + } + + //assign result position to output argument + AssignOutputVariable(pvApiCtx, 1) = nbInputArgument(pvApiCtx) + 1; + ReturnArguments(pvApiCtx); + return 0; + } + +/* + * Proto-type of function that converts column-major (sparse) representation + * to row-major (sparse) representation . +*/ +void column_major_to_row_major(int,int,int,double *,int *,int *,double *,int *,int *); + + +/* This function is to retrieve the problem's constraint matrix (sparse) . + * Symphony uses column-major (sparse) representation. + * Scilab uses row-major (sparse) representation. + * So, This function takes column-major (sparse) representation from symphony , + * converts that to row-major (sparse) representation and writes to scilab's memory. + * + **/ +int sci_sym_get_matrix(char *fname, unsigned long fname_len){ + int nz_ele=0;// No.of non-zero elements of the matrix + int rows=0; //No. of rows in constraint matrix + int columns=0; //No. of columns in constraint matrix + + /* Variables that store column-major representation of matrix. + * These variables will be filled by symphony + */ + int *column_start=NULL;// Starting index(in elements array) of each column + int *row_indices=NULL;// Row indices corresponding to each non-zero element + double *elements=NULL;// Non-zero elements of matrix + + /* Variables that store row-major representation of matrix. + * Filled by a function column_major_to_row_major. + */ + double *new_list=NULL; // Non-zero elements of row-major representation + int *count_per_row=NULL; //Count of non-zero elements in earch row + int *column_position=NULL; //Column of each non-zero element + + //check whether we have no input and one output argument or not + CheckInputArgument(pvApiCtx, 0, 0) ; //no input argument + CheckOutputArgument(pvApiCtx, 1, 1) ; //one output argument + + if(global_sym_env==NULL) //There is no environment opened. + sciprint("Error: Symphony environment is not initialized.\n"); + else { //There is an environment opened + int status1=sym_get_num_elements(global_sym_env,&nz_ele); //No. of non-zero elements + int status2=sym_get_num_cols(global_sym_env , &columns); //Columns + int status3=sym_get_num_rows(global_sym_env , &rows); //Rows + int status4=FUNCTION_TERMINATED_ABNORMALLY; + + //Make sure functions terminated normally + if (status1 == status2 && status1 == status3 && status1 == FUNCTION_TERMINATED_NORMALLY){ + //Allocate memory for column-major representation + column_start=(int*)malloc(sizeof(int) * (columns+1)); + row_indices=(int*)malloc(sizeof(int) * nz_ele); + elements=(double*)malloc(sizeof(double) * nz_ele); + + //Take column-major representation from symphony + status4=sym_get_matrix(global_sym_env,&nz_ele,column_start,row_indices,elements); + if (status1 == status4) { //Check termination status of function, if normal + //Show status of caller as normal termination + show_termination_status(FUNCTION_TERMINATED_NORMALLY); + + //Allocate memory for row-major representation + new_list=(double*) calloc( nz_ele , sizeof(double)); + count_per_row=(int*) calloc( rows, sizeof(int ) ); + column_position=(int*) calloc( nz_ele, sizeof(int)); + + //Convert column-major representation to row-major representation + column_major_to_row_major(rows,columns,nz_ele,elements,row_indices,column_start,new_list,count_per_row,column_position); + + /* + (Important)Scilab considers indices from 1 , But we have column indices starting from 0 in column_position. + Hence add 1 to each index + */ + int iter=0; + for (;iter < nz_ele ; ++iter) column_position[iter]++; + + } + else { //If termination status is abnormal + show_termination_status(FUNCTION_TERMINATED_ABNORMALLY); + sciprint("\n Is a problem loaded ? \n"); + } + } + else //If termination status of any of functions is abnormal + show_termination_status(FUNCTION_TERMINATED_ABNORMALLY); + + } + + //Copy the result to scilab. Location is position next to input arguments. + SciErr err=createSparseMatrix(pvApiCtx,nbInputArgument(pvApiCtx)+1,rows,columns,nz_ele,count_per_row,column_position,new_list); + + /* + *Free allocated memory before exit + */ + free(row_indices); + free(column_start); + free(elements); + free(new_list); + free(count_per_row); + free(column_position); + + if (err.iErr){ //Process error + printError(&err, 0); + AssignOutputVariable(pvApiCtx, 1) = 0; + return 1; + } + + //assign result position to output argument + AssignOutputVariable(pvApiCtx, 1) = nbInputArgument(pvApiCtx) + 1; + ReturnArguments(pvApiCtx); + return 0; + } + +/* + * It converts column-major representation to row-major representation + * :: ARGUMENTS :: + * rows - No. of rows IN + * columns - No. of columns IN + * nz_ele - No. of non-zero elements IN + * elements - Non-zero elements in column-major representation IN + * row_indices - Row index( starts from 0 : symphony) of each non-zero element IN + * column_start - Starting index in elements of each column IN + * new_list - Non-zero elements in row-major representation OUT + * count_per_row - Count of non-zero elements in each row OUT + * column_position - Column index ( starts from 0 (we'll add 1 to each index later)) of each non-zero element OUT +*/ +void column_major_to_row_major(int rows,int columns,int nz_ele,double *elements,int *row_indices,int *column_start,double *new_list,int *count_per_row,int *column_position) { + + int iter=0,iter2,iter3=0,index=0; + for (iter=0;iter < rows;++iter) { + for (iter2=0;iter2 < nz_ele;++iter2) { + if (row_indices[iter2] == iter) { + count_per_row[iter]++; //Count of non-zero elements per row. + new_list[index]=elements[iter2]; + for (iter3=0; iter3 < columns+1 ; ++iter3) { + if (iter2 < column_start[iter3]) + break; + } + column_position[index] = iter3 - 1; + index++ ; + } + } + } + } + + +/* + * This function is used to get iteration count after solving a problem +*/ +int sci_sym_get_iteration_count(char *fname, unsigned long fname_len){ + + //check whether we have no input and one output argument or not + CheckInputArgument(pvApiCtx, 0, 0) ; //no input argument + CheckOutputArgument(pvApiCtx, 1, 1) ; //one output argument + + int iteration_count=0; // return value to the caller + if(global_sym_env==NULL) //There is no environment opened. + sciprint("Error: Symphony environment is not initialized.\n"); + else { //There is an environment opened + //Call symphony function + int status=sym_get_iteration_count(global_sym_env,&iteration_count); + show_termination_status(status); + if (status == FUNCTION_TERMINATED_ABNORMALLY) { + sciprint("\nHave you solved a problem ?\n"); + iteration_count = 0; + } + } + // Write the result to scilab + return returnDoubleToScilab(iteration_count); + } + +} |