static int add_feasible_solution(wctproblem *problem, solution *new_sol) { int val = 0; wctdata *root_pd = &(problem->root_pd); SS *scatter_search = &(problem->scatter_search); solution_calc(new_sol, root_pd->jobarray); localsearch_wrap(new_sol, problem->global_lower_bound, 0); solution_unique(new_sol); if (!solution_in_pool(scatter_search, new_sol)) { add_solution_pool(scatter_search, new_sol); update_bestschedule(problem, new_sol); scatter_search->p->PSize++; if (root_pd->ccount == 0 && problem->parms.construct != 0) { update_Schedulesets(&root_pd->cclasses, &root_pd->ccount, problem->bestschedule, problem->nbestschedule); root_pd->gallocated = root_pd->ccount; } else if (problem->parms.construct != 0) { partlist_to_Scheduleset(new_sol->part, new_sol->nmachines, new_sol->njobs, &(root_pd->newsets), &(root_pd->nnewsets)); add_newsets(root_pd); } } else { solution_free(new_sol); CC_IFFREE(new_sol, solution); } return val; }
int construct_wspt(Job *jobarray, int njobs, int nmachines, solution *new_sol) { int i, val = 0; pmcheap *heap = (pmcheap *) NULL; partlist *temp = (partlist *) NULL; Job *j = (Job *) NULL; pmcheap_init(&heap, nmachines); CCcheck_NULL_2(heap, "Failed to initialize heap"); for (i = nmachines - 1; i >= 0; i--) { pmcheap_insert(heap, new_sol->part[i].completiontime, new_sol->part + i); } for (i = 0; i < njobs; i++) { j = jobarray + i; temp = (partlist *) pmcheap_min(heap); val = partlist_insert(temp, new_sol->vlist, j); CCcheck_val_2(val, "Failed in partlist_insert_order"); pmcheap_insert(heap, temp->completiontime, temp); } CLEAN: if (val) { solution_free(new_sol); } pmcheap_free(heap); return 0; }
/*libera un elemento de lista*/ void elelist_free(EleList *pele){ if(!pele){ return; } solution_free(pele->info); free(pele); return; }
/*Modifica los datos de un elemento*/ EleList * elelist_setInfo(EleList *pele, void *pvoid){ if(!pele || !pvoid){ return NULL; } if(pele->info){ solution_free(pele->info); } pele->info = (Solution *)pvoid; return pele; }
void P_free(P *p) { if (p) { for (GList *it = p->list; it; it = it->next) { solution_free((solution *)it->data); CC_IFFREE(it->data, solution); } p->PSize = 0; g_list_free(p->list); P_init(p); } }
int add_solution_refset(SS *scatter_search) { int i; int val = 0; REFSET *refset = scatter_search->rs; P *pool = scatter_search->p; switch (scatter_search->status) { case init: pool->list = g_list_sort(pool->list, order_totalweightcomptime_list); for (i = 0; i < scatter_search->b1; ++i) { void *data = pool->list->data; pool->list = g_list_remove(pool->list, data); g_ptr_array_add(refset->list1, data); } scatter_search->status = add; break; case add: for (i = 0; i < scatter_search->b2; ++i) { void *data = maximum_distance(scatter_search); CCcheck_NULL_2(data, "Failed in maximum_distance"); pool->list = g_list_remove(pool->list, data); update_distance(scatter_search, (solution *)data); g_ptr_array_add(refset->list2, data); } g_ptr_array_sort(refset->list2, order_distance); scatter_search->status = update; for (GList *it = pool->list; it; it = it->next) { solution_free((solution *)it->data); CC_IFFREE(it->data, solution); } g_list_free(pool->list); pool->list = (GList *) NULL; break; case update: diversification_update(scatter_search); break; case opt: break; } CLEAN: return val; }
solution_t * solution_choose_best(solution_t *best1, solution_t *best2) { if (best1 != NIL(solution_t)) { if (best2 != NIL(solution_t)) { if (best1->cost <= best2->cost) { solution_free(best2); return best1; } else { solution_free(best1); return best2; } } else { return best1; } } else { if (best2 != NIL(solution_t)) { return best2; } else { return NIL(solution_t); } } }
solution_t* solution_cpy(solution_t* dst, solution_t* src) { int i,j; if (dst!=NULL) { solution_free(dst); dst=NULL; } dst=solution_new(src->n); dst->matches=src->matches; for (i=0;i<dst->n;i++) { for (j=0;j<dst->n;j++) { dst->mat[i][j]=piece_new(src->mat[i][j]->square_index,src->mat[i][j]->rotation); } } return(dst); }
solution *new_sol_init(int nmachines, int vcount) { int val = 0; solution *sol = (solution *) NULL; sol = CC_SAFE_MALLOC(1, solution); CCcheck_NULL_2(sol, "Failed to allocate memory") solution_init(sol); val = solution_alloc(sol, nmachines, vcount); CCcheck_val_2(val, "Failed in solution_alloc"); CLEAN: if (val) { solution_free(sol); CC_IFFREE(sol, solution); } return sol; }
void free_sol(void *data, void *user_data) { solution *sol = (solution *)data; solution_free(sol); CC_IFFREE(sol, solution); sol = (solution *)user_data; }
int combinePathRelinking(SS *scatter_search, GPtrArray *array, int *subsetsol, int *found) { int i, val = 0; int njobs = scatter_search->njobs; int nmachines = scatter_search->nmachines; int dist = 0; int counter = 0; Job **jobarray = scatter_search->jobarray; REFSET *refset = scatter_search->rs; GList *list = (GList *) NULL; GList *it = (GList *) NULL; GList *pool = (GList *) NULL; solution *prev = (solution *) NULL; solution sol_g; solution sol_c; solution *sol1 = (solution *)g_ptr_array_index(array, subsetsol[1] - 1); solution *sol2 = (solution *)g_ptr_array_index(array, subsetsol[2] - 1); if (sol1->totalweightcomptime < sol2->totalweightcomptime) { val = solution_copy(&sol_g, *sol1); val = solution_copy(&sol_c, *sol2); } else { val = solution_copy(&sol_c, *sol1); val = solution_copy(&sol_g, *sol2); } for (i = 0; i < njobs; ++i) { partlist *temp1 = sol_g.vlist[i].part; partlist *temp2 = sol_c.vlist[i].part; if (temp1->key != temp2->key) { dist++; list = g_list_append(list, jobarray[i]); } } prev = &(sol_c); while (dist > 0) { Job *minjob = (Job *) NULL; partlist *minmach = (partlist *) NULL; solution *sol = CC_SAFE_MALLOC(1, solution); solution_init(sol); solution_alloc(sol, nmachines, njobs); solution_update(sol, *prev); int max = INT_MIN; int temp; for (it = list; it; it = it->next) { Job *j = (Job *)it->data; partlist *mach_c = sol->vlist[j->job].part; partlist *mach_g = sol->part + sol_g.vlist[j->job].part->key; temp = moveSS(j, mach_c, mach_g); if (temp > max) { minjob = j; minmach = mach_g; max = temp; } } partlist_move_order(minmach, sol->vlist, minjob, njobs); sol->totalweightcomptime -= max; pool = g_list_append(pool, sol); list = g_list_remove(list, minjob); dist--; prev = sol; } counter = 0; GList *l = pool; while (l != NULL) { GList *next = l->next; if (counter % 10 == 0) { solution *sol = (solution *)l->data; localsearch_wrap(sol, scatter_search->lowerbound, 0); solution_unique(sol); } else { solution *sol = (solution *)l->data; solution_free(sol); CC_IFFREE(sol, solution); pool = g_list_delete_link(pool, l); } counter++; l = next; } l = pool; while (l != NULL) { solution *last1 = (solution *) g_ptr_array_index(refset->list1, refset->list1->len - 1); solution *last2 = (solution *) g_ptr_array_index(refset->list2, 0); GList *next = l->next; solution *new_sol = (solution *)l->data; int not_in_refset = !solution_in_refset(scatter_search, new_sol); if (new_sol->totalweightcomptime < last1->totalweightcomptime && not_in_refset) { new_sol->dist = 0; refset->newsol = 1; new_sol->iter = scatter_search->iter + 1; g_ptr_array_remove(refset->list1, last1); g_ptr_array_remove(array, last1); g_ptr_array_add(refset->list1, new_sol); g_ptr_array_add(array, new_sol); g_ptr_array_sort(refset->list1, order_totalweightcomptime); g_ptr_array_sort(array, order_totalweightcomptime); solution_free(last1); CC_IFFREE(last1, solution); *found = 1; } else if (not_in_refset) { SSrefset_distance(scatter_search, new_sol); if (new_sol->dist > last2->dist) { refset->newsol = 1; new_sol->iter = scatter_search->iter + 1; g_ptr_array_remove(refset->list2, last2); g_ptr_array_remove(array, last2); g_ptr_array_add(refset->list2, new_sol); g_ptr_array_add(array, new_sol); g_ptr_array_sort(refset->list2, order_distance); g_ptr_array_sort(array, order_distance); solution_free(last2); CC_IFFREE(last2, solution); *found = 1; } else { solution_free(new_sol); CC_IFFREE(new_sol, solution); } } else { solution_free(new_sol); CC_IFFREE(new_sol, solution); } pool = g_list_delete_link(pool, l); l = next; } g_list_free(pool); solution_free(&sol_g); solution_free(&sol_c); return val; }
int SSrun_scatter_search(SS *scatter_search, CCutil_timer *timer) { guint i; REFSET *refset = scatter_search->rs; int flag, val = 0; int nbnew_sol = 0; int nbjobs = scatter_search->njobs; int nmachines = scatter_search->nmachines; int nb_noimprovements = 0; int *totsubset = (int *) NULL; double limit = scatter_search->timelimit; totsubset = CC_SAFE_MALLOC(scatter_search->b1 + 1, int); CCcheck_NULL_2(totsubset, "Failed tot allocate memory to tot subset"); if (refset->list1->len == 0) { printf("We can't run scatter search, refset is empty\n"); val = 1; goto CLEAN; } printf("PMCombination method\n"); CCutil_suspend_timer(timer); CCutil_resume_timer(timer); while (refset->newsol && scatter_search->status != opt && timer->cum_zeit < limit) { GPtrArray *list = g_ptr_array_new(); for (i = 0; i < refset->list1->len; ++i) { g_ptr_array_add(list, g_ptr_array_index(refset->list1, i)); } for (i = 0; i < refset->list2->len; ++i) { g_ptr_array_add(list, g_ptr_array_index(refset->list2, i)); } compute_fitness(scatter_search); refset->newsol = 0; if (scatter_search->iter > 0) { int best = scatter_search->upperbound; CCutil_suspend_timer(timer); CCutil_resume_timer(timer); double rel_error = ((double)best - (double)scatter_search->lowerbound) / (double)scatter_search->lowerbound; printf("iteration %d with best wct %d and rel error %f, number of new solutions %d, time = %f\n", scatter_search->iter, best, rel_error, nbnew_sol, timer->cum_zeit); } nbnew_sol = 0; k_subset_init(list->len, 2, totsubset, &flag); while (flag && scatter_search->status != opt) { solution *new_sol = CC_SAFE_MALLOC(1, solution); solution_init(new_sol); solution_alloc(new_sol, nmachines, nbjobs); int rval = 1; rval = combine_PM(scatter_search, list, totsubset, 2, new_sol); if (!rval) { solution_calc(new_sol, *(scatter_search->jobarray)); new_sol->iter = scatter_search->iter + 1; localsearch_random_k(new_sol, scatter_search->lowerbound, 2); solution_unique(new_sol); if (!dynamic_update(scatter_search, list, new_sol)) { if (new_sol->totalweightcomptime < scatter_search->upperbound) { scatter_search->upperbound = new_sol->totalweightcomptime; } if (new_sol->totalweightcomptime == scatter_search->lowerbound) { scatter_search->status = opt; printf("Found optimal with SS with subset generation 1\n"); } nbnew_sol++; } else { solution_free(new_sol); CC_IFFREE(new_sol, solution); } } else { solution_free(new_sol); CC_IFFREE(new_sol, solution); } k_subset_lex_successor(list->len, 2, totsubset, &flag); } k_subset_init(list->len, 3, totsubset, &flag); solution *sol = (solution *)NULL; sol = (solution *) g_ptr_array_index(list, 0); while (flag && scatter_search->status != opt) { solution *new_sol = CC_SAFE_MALLOC(1, solution); solution_init(new_sol); solution_alloc(new_sol, nmachines, nbjobs); int rval = 1; rval = combine_PM(scatter_search, list, totsubset, 3, new_sol); //Dell'Amico et al. if (!rval) { solution_calc(new_sol, *(scatter_search->jobarray)); new_sol->iter = scatter_search->iter + 1; localsearch_random_k(new_sol, scatter_search->lowerbound, 2); solution_unique(new_sol); if (!dynamic_update(scatter_search, list, new_sol)) { if (new_sol->totalweightcomptime < scatter_search->upperbound) { scatter_search->upperbound = new_sol->totalweightcomptime; } if (new_sol->totalweightcomptime == scatter_search->lowerbound) { scatter_search->status = opt; printf("Found optimal with SS\n"); } nbnew_sol++; } else { solution_free(new_sol); CC_IFFREE(new_sol, solution); } } else { solution_free(new_sol); CC_IFFREE(new_sol, solution); } k_subset_lex_successor(list->len, 3, totsubset, &flag); sol = (solution *) g_ptr_array_index(list, totsubset[1] - 1); } k_subset_init(list->len, 4, totsubset, &flag); sol = (solution *) g_ptr_array_index(list, 0); solution *temp_sol = (solution *) g_ptr_array_index(list, 1); while (flag && scatter_search->status != opt && sol->totalweightcomptime <= scatter_search->upperbound && temp_sol->totalweightcomptime <= scatter_search->upperbound) { solution *new_sol = CC_SAFE_MALLOC(1, solution); solution_init(new_sol); solution_alloc(new_sol, nmachines, nbjobs); int rval = 1; rval = combine_PM(scatter_search, list, totsubset, 4, new_sol); if (!rval) { solution_calc(new_sol, *(scatter_search->jobarray)); new_sol->iter = scatter_search->iter + 1; localsearch_random_k(new_sol, scatter_search->lowerbound, 2); solution_unique(new_sol); if (!dynamic_update(scatter_search, list, new_sol)) { if (new_sol->totalweightcomptime < scatter_search->upperbound) { scatter_search->upperbound = new_sol->totalweightcomptime; } if (new_sol->totalweightcomptime == scatter_search->lowerbound) { scatter_search->status = opt; printf("Found optimal with SS\n"); } nbnew_sol++; } else { solution_free(new_sol); CC_IFFREE(new_sol, solution); } } else { solution_free(new_sol); CC_IFFREE(new_sol, solution); } k_subset_lex_successor(list->len, 4, totsubset, &flag); sol = (solution *) g_ptr_array_index(list, totsubset[1] - 1); temp_sol = (solution *)g_ptr_array_index(list, totsubset[2] - 1); } for (i = 0; i < refset->list2->len + 1; ++i) { totsubset[i] = i; } for (i = 5; i < refset->list2->len + 1 && scatter_search->status != opt; i++) { solution *new_sol = CC_SAFE_MALLOC(1, solution); solution_init(new_sol); solution_alloc(new_sol, nmachines, nbjobs); int rval = 1; rval = combine_PM(scatter_search, list, totsubset, i, new_sol); if (!rval) { solution_calc(new_sol, *(scatter_search->jobarray)); new_sol->iter = scatter_search->iter + 1; localsearch_random_k(new_sol, scatter_search->lowerbound, 2); solution_unique(new_sol); if (!dynamic_update(scatter_search, list, new_sol)) { if (new_sol->totalweightcomptime < scatter_search->upperbound) { scatter_search->upperbound = new_sol->totalweightcomptime; } if (new_sol->totalweightcomptime == scatter_search->lowerbound) { scatter_search->status = opt; printf("Found optimal with SS\n"); } nbnew_sol++; } else { solution_free(new_sol); CC_IFFREE(new_sol, solution); } } else { solution_free(new_sol); CC_IFFREE(new_sol, solution); } } scatter_search->iter++; if (nbnew_sol == 0) { nb_noimprovements++; } if (refset->newsol == 0 && scatter_search->iter < 10 && nb_noimprovements < 5) { add_solution_refset(scatter_search); refset->newsol = 1; } g_ptr_array_free(list, TRUE); } CLEAN: CC_IFFREE(totsubset, int); return val; }
int main (int argc, char** argv) { int n; solution_t *start=NULL; solution_t *curr=NULL; tabuListNum Tln; int TabuSizeCorner,TabuSizeEdge,TabuSizeInner; int ExpireTime,MaxSteps,MaxNotImp; cornerGenerator Cg; edgeGenerator Eg; innerGenerator Ig; int rd; int seed; struct timeval tvBegin, tvEnd, tvDiff; /* //DEBUG neigh_t* neighborhood_inner=NULL; neigh_t* neighborhood_edge=NULL; neigh_t* neighborhood_corner=NULL; neighbor_t* candidate=NULL; */ if (argc==15) { if (strcmp(argv[3],"SINGLE")==0) Tln=SINGLE; else if (strcmp(argv[3],"TRIPLE")==0) Tln=TRIPLE; else { print_err(WRONG_PARAM_TLN); return(FAILURE); } sscanf(argv[4],"%d",&TabuSizeCorner); sscanf(argv[5],"%d",&TabuSizeEdge); sscanf(argv[6],"%d",&TabuSizeInner); sscanf(argv[7],"%d",&ExpireTime); sscanf(argv[8],"%d",&MaxSteps); sscanf(argv[9],"%d",&MaxNotImp); if (strcmp(argv[10],"CCORNER_FIRST")==0) { Cg=CCORNER_FIRST; } else if (strcmp(argv[10],"CCORNER_NEXT")==0) { Cg=CCORNER_NEXT; } else if (strcmp(argv[10],"CCORNER_OPPOSITE")==0) { Cg=CCORNER_OPPOSITE; } else { print_err(WRONG_PARAM_CORNER); return(FAILURE); } if (strcmp(argv[11],"EEDGE_POS_OPPOSITE")==0) { Eg=EEDGE_POS_OPPOSITE; } else if (strcmp(argv[11],"EEDGE_NEXT")==0) { Eg=EEDGE_NEXT; } else if (strcmp(argv[11],"EEDGE_NEXT_ANTI")==0) { Eg=EEDGE_NEXT_ANTI; } else { print_err(WRONG_PARAM_EDGE); return(FAILURE); } if (strcmp(argv[12],"IINNER_NEXT")==0) { Ig=IINNER_NEXT; } else if (strcmp(argv[12],"IINNER_OPPOSITE")==0) { Ig=IINNER_OPPOSITE; } else if (strcmp(argv[12],"IINNER_OPPOSITE_AUX")==0) { Ig=IINNER_OPPOSITE_AUX; } else if (strcmp(argv[12],"IINNER_RAND")==0) { Ig=IINNER_RAND; } else { print_err(WRONG_PARAM_INNER); return(FAILURE); } if (strcmp(argv[13],"RANDOM_START")==0) { rd=RANDOM_START; } else if (strcmp(argv[13],"STATIC_START")==0) { rd=STATIC_START; } else { print_err(WRONG_PARAM_START); return(FAILURE); } sscanf(argv[14],"%d",&seed); } else { if (argc==6) { sscanf(argv[3],"%d",&MaxSteps); sscanf(argv[4],"%d",&MaxNotImp); sscanf(argv[5],"%d",&seed); rd=RANDOM_START; } else { //DEBUG //printf("%d\n",argc); print_err(WRONG_NUM_PARAM); return(FAILURE); } } squares=read_input(argv[1], &n); if (argc==15) { printf("####################################\n"); printf("------------------------------------\nPARAMETERS\n"); printf("PiecesNumber: %dx%d\n",n,n); printf("MaximumScore: %d\n",solution_max_matches(n)); printf("TabuListsNumber: %s\n",argv[3]); printf("TabuSizeCorner: %s\n",argv[4]); printf("TabuSizeEdge: %s\n",argv[5]); printf("TabuSizeInner: %s\n",argv[6]); printf("ExpireTime: %s\n",argv[7]); printf("StepsThreshold: %s\n",argv[8]); printf("NotImprovingStepsThreshold: %s\n",argv[9]); printf("CornerGenerator: %s\n",argv[10]); printf("EdgeGenerator: %s\n",argv[11]); printf("InnerGenerator: %s\n",argv[12]); printf("RandomStarting: %s\n",argv[13]); printf("RandomizeSeed: %s\n",argv[14]); printf("------------------------------------\n"); } else { printf("####################################\n"); printf("------------------------------------\nPARAMETERS\n"); printf("PiecesNumber: %dx%d\n",n,n); printf("MaximumScore: %d\n",solution_max_matches(n)); printf("StepsThreshold: %s\n",argv[3]); printf("NotImprovingStepsThreshold: %s\n",argv[4]); printf("RandomizeSeed: %s\n",argv[5]); printf("------------------------------------\n"); } //BEGIN TIME gettimeofday(&tvBegin, NULL); start=solution_greedy(n); if (rd==RANDOM_START) start=solution_shuffle(start,seed); printf("StartScore: %d\n",solution_get_matches(start)); curr=solution_cpy(curr,start); if(argc==15) { //PARAM Version //(solution_t *start,tabuListNum,tabuSizeA,tabuSizeB,tabuSizeC,expire,step,noImpr,cornerGenerator corner,edgeGenerator edge,innerGenerator inner,innerInit ii); //First short run to provide a good starting solution for real tabu search curr=tabuSearchP(curr,Tln,TabuSizeCorner,TabuSizeEdge,TabuSizeInner,ExpireTime,MAX_STEPS_FIRST,MAX_NOT_IMP_FIRST,Cg,Eg,Ig,seed, PRE, SILENT); //Local search //curr=tabuSearchP(curr,Tln,0,0,0,ExpireTime,MAX_STEPS_FIRST,MAX_NOT_IMP_FIRST,Cg,Eg,Ig,seed, SILENT); printf("SecondStartScore: %d\n",solution_get_matches(curr)); //Real tabu Search curr=tabuSearchP(curr,Tln,TabuSizeCorner,TabuSizeEdge,TabuSizeInner,ExpireTime,MaxSteps,MaxNotImp,Cg,Eg,Ig,seed,POST,NORMAL); } else { //First short run to provide a good starting solution for real tabu search curr=tabuSearchDefaultPreliminary(curr,MAX_STEPS_FIRST,MAX_NOT_IMP_FIRST, SILENT); printf("SecondStartScore: %d\n",solution_get_matches(curr)); //Real tabu Search curr=tabuSearchDefault(curr,MaxSteps,MaxNotImp, seed, NORMAL); } //end gettimeofday(&tvEnd, NULL); // diff timeval_subtract(&tvDiff, &tvEnd, &tvBegin); printf("ExecutionTime: %ld.%06ld\n", tvDiff.tv_sec, tvDiff.tv_usec); printf("####################################\n"); write_output(argv[2], curr); solution_free(start); solution_free(curr); return(SUCCESS); }
/* ---------------------------------------------------------------------- */ int spread_row_to_solution (struct spread_row *heading, struct spread_row *units, struct spread_row *data, struct defaults defaults) /* ---------------------------------------------------------------------- */ { int i, j, n, l, next_keyword_save; int n_user, n_user_end; int default_pe, alk; int count_isotopes; int max_mass_balance, count_mass_balance; char *ptr, *ptr1; char *description; char token[MAX_LENGTH], token1[MAX_LENGTH]; char string[2 * MAX_LENGTH]; LDBLE dummy; int return_value, opt; char *next_char; const char *opt_list[] = { "temp", /* 0 */ "temperature", /* 1 */ "dens", /* 2 */ "density", /* 3 */ "units", /* 4 */ "redox", /* 5 */ "ph", /* 6 */ "pe", /* 7 */ "unit", /* 8 */ "isotope", /* 9 */ "water", /* 10 */ "description", /* 11 */ "desc", /* 12 */ "descriptor" /* 13 */ }; int count_opt_list = 14; /* * look for solution number */ n_user = -1; n_user_end = -1; description = string_duplicate (""); for (i = 0; i < heading->count; i++) { if (strcmp_nocase (heading->char_vector[i], "number") == 0) { break; } } if (i == heading->count || data->type_vector[i] == EMPTY || data->count <= i) { n_user = -1; #ifdef SKIP for (i = 0; i < count_solution; i++) { if (n_user <= solution[i]->n_user) { n_user = solution[i]->n_user + 1; } } #endif } else if (data->type_vector[i] == STRING) { input_error++; sprintf (error_string, "Expected solution number or number range in 'number' column, found: %s.", data->char_vector[i]); error_msg (error_string, CONTINUE); } else { strcpy (string, "solution_s "); strcat (string, data->char_vector[i]); ptr = string; description = (char *) free_check_null (description); next_keyword_save = next_keyword; next_keyword = 42; read_number_description (ptr, &n_user, &n_user_end, &description); next_keyword = next_keyword_save; } /* * set up solution */ if (n_user >= 0 && solution_bsearch (n_user, &n, FALSE) != NULL) { solution_free (solution[n]); } else { n = count_solution++; if (count_solution >= max_solution) { space ((void **) ((void *) &(solution)), count_solution, &max_solution, sizeof (struct solution *)); } } solution[n] = solution_alloc (); solution[n]->n_user = n_user; solution[n]->n_user_end = n_user_end; if (use.solution_in == FALSE) { use.solution_in = TRUE; use.n_solution_user = n_user; } max_mass_balance = MAX_MASS_BALANCE; /* * Set default ph, temp, density, pe, units */ solution[n]->description = description; solution[n]->tc = defaults.temp; solution[n]->ph = defaults.ph; solution[n]->density = defaults.density; solution[n]->solution_pe = defaults.pe; solution[n]->mass_water = defaults.water; solution[n]->ah2o = 1.0; solution[n]->mu = 1e-7; solution[n]->cb = 0.0; default_pe = 0; solution[n]->units = defaults.units; solution[n]->totals[0].description = NULL; count_mass_balance = 0; count_isotopes = 0; default_pe = pe_data_store (&(solution[n]->pe), defaults.redox); /* * Read concentration data */ return_value = UNKNOWN; for (i = 0; i < heading->count; i++) { if (strcmp_nocase (heading->char_vector[i], "number") == 0) continue; if (strcmp_nocase (heading->char_vector[i], "uncertainty") == 0) continue; if (strcmp_nocase (heading->char_vector[i], "uncertainties") == 0) continue; if (strcmp_nocase (heading->char_vector[i], "isotope_uncertainty") == 0) continue; /* * Copy in element name */ if (heading->type_vector[i] == EMPTY) continue; strcpy (string, heading->char_vector[i]); strcat (string, " "); /* * Copy in concentration data */ if (i >= data->count || data->type_vector[i] == EMPTY) continue; strcat (string, data->char_vector[i]); strcat (string, " "); /* * Copy in concentration data */ if (units != NULL && i < units->count && units->type_vector[i] != EMPTY) { strcat (string, units->char_vector[i]); } /* * Parse string just like read_solution input */ next_char = string; opt = get_option_string (opt_list, count_opt_list, &next_char); if (opt == OPTION_DEFAULT && heading->type_vector[i] == NUMBER) { opt = 9; } switch (opt) { case OPTION_EOF: /* end of file */ return_value = EOF; break; case OPTION_KEYWORD: /* keyword */ return_value = KEYWORD; break; case OPTION_ERROR: input_error++; error_msg ("Unknown input in SOLUTION keyword.", CONTINUE); error_msg (line_save, CONTINUE); break; case 0: /* temperature */ case 1: sscanf (next_char, SCANFORMAT, &(solution[n]->tc)); break; case 2: /* density */ case 3: sscanf (next_char, SCANFORMAT, &(solution[n]->density)); break; case 4: /* units */ case 8: /* unit */ if (copy_token (token, &next_char, &l) == EMPTY) break; if (check_units (token, FALSE, FALSE, solution[n]->units, TRUE) == OK) { solution[n]->units = string_hsave (token); } else { input_error++; } break; case 5: /* redox */ if (copy_token (token, &next_char, &l) == EMPTY) break; if (parse_couple (token) == OK) { default_pe = pe_data_store (&(solution[n]->pe), token); } else { input_error++; } break; case 6: /* ph */ next_char = string; if (read_conc (n, count_mass_balance, next_char) == ERROR) { input_error++; break; } solution[n]->ph = solution[n]->totals[count_mass_balance].input_conc; if (solution[n]->totals[count_mass_balance].equation_name == NULL) { break; } solution[n]->totals[count_mass_balance].description = string_hsave ("H(1)"); count_mass_balance++; break; case 7: /* pe */ next_char = string; if (read_conc (n, count_mass_balance, next_char) == ERROR) { input_error++; break; } solution[n]->solution_pe = solution[n]->totals[count_mass_balance].input_conc; if (solution[n]->totals[count_mass_balance].equation_name == NULL) { break; } solution[n]->totals[count_mass_balance].description = string_hsave ("E"); count_mass_balance++; break; case 9: /* isotope */ next_char = string; if (copy_token (token, &next_char, &l) != DIGIT) { input_error++; sprintf (error_string, "Expected isotope name to" " begin with an isotopic number."); error_msg (error_string, CONTINUE); continue; } solution[n]->isotopes = (struct isotope *) PHRQ_realloc (solution[n]->isotopes, (size_t) (count_isotopes + 1) * sizeof (struct isotope)); if (solution[n]->isotopes == NULL) malloc_error (); /* read and save element name */ ptr1 = token; get_num (&ptr1, &(solution[n]->isotopes[count_isotopes].isotope_number)); if (ptr1[0] == '\0' || isupper ((int) ptr1[0]) == FALSE) { error_msg ("Expecting element name.", CONTINUE); error_msg (line_save, CONTINUE); input_error++; return (ERROR); } solution[n]->isotopes[count_isotopes].elt_name = string_hsave (ptr1); /* read and store isotope ratio */ if (copy_token (token, &next_char, &l) != DIGIT) { input_error++; sprintf (error_string, "Expected numeric value for isotope ratio."); error_msg (error_string, CONTINUE); continue; } sscanf (token, SCANFORMAT, &(solution[n]->isotopes[count_isotopes].ratio)); /* read and store isotope ratio uncertainty */ /* first choice is next column */ if ((i + 1) < heading->count && (strcmp_nocase (heading->char_vector[i + 1], "uncertainty") == 0 || strcmp_nocase (heading->char_vector[i + 1], "isotope_uncertainty") == 0 || strcmp_nocase (heading->char_vector[i + 1], "uncertainties") == 0) && (i + 1) < data->count && data->type_vector[i + 1] == NUMBER) { solution[n]->isotopes[count_isotopes].ratio_uncertainty = data->d_vector[i + 1]; } else { next_char = string; copy_token (token, &next_char, &l); for (j = 0; j < defaults.count_iso; j++) { if (strcmp (token, defaults.iso[j].name) == 0) { solution[n]->isotopes[count_isotopes].ratio_uncertainty = defaults.iso[j].uncertainty; break; } } if (j == defaults.count_iso) { solution[n]->isotopes[count_isotopes].ratio_uncertainty = NAN; } } count_isotopes++; break; case 10: /* water */ j = copy_token (token, &next_char, &l); if (j == EMPTY) { solution[n]->mass_water = 1.0; } else if (j != DIGIT) { input_error++; sprintf (error_string, "Expected numeric value for mass of water in solution."); error_msg (error_string, CONTINUE); } else { sscanf (token, SCANFORMAT, &dummy); solution[n]->mass_water = (LDBLE) dummy; } break; case 11: /* description */ case 12: /* desc */ case 13: /* descriptor */ solution[n]->description = (char *) free_check_null (solution[n]->description); solution[n]->description = string_duplicate (next_char); break; case OPTION_DEFAULT: /* * Read concentration */ next_char = string; if (copy_token (token, &next_char, &l) == LOWER) continue; next_char = string; if (read_conc (n, count_mass_balance, next_char) == ERROR) { #ifdef SKIP input_error++; break; #endif } count_mass_balance++; break; } if (count_mass_balance + 1 >= max_mass_balance) { space ((void **) ((void *) &(solution[n]->totals)), count_mass_balance + 1, &max_mass_balance, sizeof (struct conc)); } if (return_value == EOF || return_value == KEYWORD) break; } /* * Sort totals by description */ qsort (solution[n]->totals, (size_t) count_mass_balance, (size_t) sizeof (struct conc), conc_compare); /* * fix up default units and default pe */ for (i = 0; i < count_mass_balance; i++) { strcpy (token, solution[n]->totals[i].description); str_tolower (token); if (solution[n]->totals[i].units == NULL) { solution[n]->totals[i].units = solution[n]->units; } else { alk = FALSE; if (strstr (token, "alk") == token) alk = TRUE; strcpy (token1, solution[n]->totals[i].units); if (check_units (token1, alk, TRUE, solution[n]->units, TRUE) == ERROR) { input_error++; } else { solution[n]->totals[i].units = string_hsave (token1); } } if (solution[n]->totals[i].n_pe < 0) { solution[n]->totals[i].n_pe = default_pe; } } solution[n]->default_pe = default_pe; /* * Mark end of solution */ solution[n]->totals[count_mass_balance].description = NULL; solution[n]->count_isotopes = count_isotopes; if (count_isotopes > 0) { qsort (solution[n]->isotopes, (size_t) count_isotopes, (size_t) sizeof (struct isotope), isotope_compare); } else { solution[n]->isotopes = (struct isotope *) free_check_null (solution[n]->isotopes); } return (return_value); }