int main() try { vector<string> vs; vs.push_back("Technicalities"); vs.push_back("a"); vs.push_back("A"); vs.push_back("hellohellohell"); // same length as "Technicalities" vs.push_back("Hellohellohell"); // lexicographically 'H' < 'h' // vs.push_back(""); // the empty string vs.push_back("Technicalities"); // More technicalities vs.push_back("!"); // same length as "a" cout << "sizes: "; vector<int> lengths = get_sizes(vs); for (int i=0; i<lengths.size(); ++i) cout << lengths[i] << ' '; cout << '\n'; int i = longest(vs); cout << "longest(): index==" << i << "; string=='" << vs[i] << "'\n"; // note the quotes: I want to be able to see the empty string cout << "shortest(): '" << shortest(vs) << "'\n"; // note the quotes: I want to be able to see the empty string cout << "lex_first(): '" << lex_first(vs) << "'\n"; lex_last(vs,i); // pass 'i' for lex_last() to return into cout << "lex_last(): index==" << i << "; string=='" << vs[i] << "'\n"; // note the quotes: I want to be able to see the empty string // note: had vs been empty, this code would have accessed vs[-1]; Ouch! keep_window_open("~"); // For some Windows(tm) setups } catch (runtime_error e) { // this code is to produce error messages cout << e.what() << '\n'; keep_window_open("~"); // For some Windows(tm) setups }
typename Container::const_reference shortest_levenshtein( Container const &_container, typename Container::const_reference _ref ) { typedef typename Container::value_type string_type; typedef typename string_type::size_type size_type; typedef typename Container::const_iterator const_iterator; size_type shortest_dist( ::fcppt::algorithm::levenshtein( *_container.begin(), _ref ) ); const_iterator shortest( _container.begin() ); for( const_iterator it( boost::next( _container.begin() ) ); it != _container.end(); ++it ) { size_type const new_shortest_dist( ::fcppt::algorithm::levenshtein( *it, _ref ) ); if( new_shortest_dist < shortest_dist ) { shortest = it; shortest_dist = new_shortest_dist; } } return *shortest; }
int main(int argc, char const *argv[]) { int visited[] = {-1,-1,-1,-1,-1}; printf("%ld\n", shortest(visited, 5, 0, 0)); return 0; }
double shortest(long l, long r) { if (r - l == 1) return dist(pt[l], pt[r]); if (r - l == 2) return getmin(getmin(dist(pt[l], pt[l+1]), dist(pt[l], pt[r])), dist(pt[l+1], pt[r])); long i, j, mid = (l + r) >> 1; double curmin = getmin(shortest(l, mid), shortest(mid + 1, r)); arrl = 0; for (i = mid; i >= l && pt[mid+1].x - pt[i].x <= curmin; i --) arr[arrl++] = i; for (i = mid + 1; i <= r && pt[i].x - pt[mid].x <= curmin; i ++) arr[arrl++] = i; qsort(arr, arrl, sizeof(arr[0]), arrcmp); for (i = 0; i < arrl; i ++) for (j = i + 1; j < arrl && pt[arr[j]].y - pt[arr[i]].y <= curmin; j ++) curmin = getmin(curmin, dist(pt[arr[i]], pt[arr[j]])); return curmin; }
/* * lacon - lookaround-constraint checker for miss() */ static int /* predicate: constraint satisfied? */ lacon(struct vars * v, struct cnfa * pcnfa, /* parent cnfa */ chr *cp, pcolor co) /* "color" of the lookaround constraint */ { int n; struct subre *sub; struct dfa *d; chr *end; int satisfied; /* Since this is recursive, it could be driven to stack overflow */ if (STACK_TOO_DEEP(v->re)) { ERR(REG_ETOOBIG); return 0; } n = co - pcnfa->ncolors; assert(n > 0 && n < v->g->nlacons && v->g->lacons != NULL); FDEBUG(("=== testing lacon %d\n", n)); sub = &v->g->lacons[n]; d = getladfa(v, n); if (d == NULL) return 0; if (LATYPE_IS_AHEAD(sub->subno)) { /* used to use longest() here, but shortest() could be much cheaper */ end = shortest(v, d, cp, cp, v->stop, (chr **) NULL, (int *) NULL); satisfied = LATYPE_IS_POS(sub->subno) ? (end != NULL) : (end == NULL); } else { /* * To avoid doing O(N^2) work when repeatedly testing a lookbehind * constraint in an N-character string, we use matchuntil() which can * cache the DFA state across calls. We only need to restart if the * probe point decreases, which is not common. The NFA we're using is * a search NFA, so it doesn't mind scanning over stuff before the * nominal match. */ satisfied = matchuntil(v, d, cp, &v->lblastcss[n], &v->lblastcp[n]); if (!LATYPE_IS_POS(sub->subno)) satisfied = !satisfied; } FDEBUG(("=== lacon %d satisfied %d\n", n, satisfied)); return satisfied; }
main() { long n, i; while (1) { scanf("%d", &n); if (!n) break; for (i = 0; i < n; i ++) scanf("%lf%lf", &pt[i].x, &pt[i].y); qsort(pt, n, sizeof(pt[0]), sortcmp); printf("%.2lf\n", shortest(0, n - 1) / 2); } }
int main(){ int x,y; char a[3],b[3]; memset(k,10,sizeof(k)); //attention shortest(); while(scanf("%s%s",&a,&b) != EOF){ x=(a[0]-'a')*8+(a[1]-'1'); y=(b[0]-'a')*8+(b[1]-'1'); printf("To get from %s to %s takes %d knight moves.\n",a,b,k[x][y]); } return 0; }
Interval shortestClosure(const vector<T>& haystack, const vector<T>& needles) { Interval shortest(0, haystack.size() - 1); LocationLists locLists = buildLocationLists(haystack, needles); for (;;) { Interval candidate = nextCandidate(locLists); if (!candidate.valid()) { break; } if (candidate.length() < shortest.length()) { shortest = candidate; } } return shortest; }
long shortest(int* visited, int size, long current, int last){ int i=0; long ret=-1; if(all_visited(visited, size)){ return current + paths[visited[0]][visited[last]]; } for(i=0;i<size;i++){ if(visited[i] == -1){ visited[i] = i; int candidate = shortest(visited, size, current+paths[last][i], i); printf("i: %d, candidate: %d\n", i, candidate); if(ret == -1 || ret > candidate){ ret = candidate; } visited[i] = -1; } } return ret; }
float week03::random_graph::avg(int src_vertex_idx) { int total_distance = 0; int meaningful_evaluations = 0; int shortest_distance; for (int i = 0; i < size(); ++i) { if (i == src_vertex_idx) { continue; } shortest_distance = shortest(src_vertex_idx, i); if (shortest_distance > 0 && shortest_distance != INFINITY) { ++meaningful_evaluations; total_distance += shortest_distance; } } if (meaningful_evaluations > 0) { return total_distance /meaningful_evaluations; } else { return 0; } }
/* - complicatedReversedDissect - determine backref shortest-first subexpression - matches * The retry memory stores the offset of the trial midpoint from begin, plus 1 * so that 0 uniquely means "clean slate". ^ static int complicatedReversedDissect(struct vars *, struct subre *, chr *, chr *); */ static int /* regexec return code */ complicatedReversedDissect( struct vars *const v, struct subre *const t, chr *const begin, /* beginning of relevant substring */ chr *const end) /* end of same */ { struct dfa *d, *d2; chr *mid; assert(t->op == '.'); assert(t->left != NULL && t->left->cnfa.nstates > 0); assert(t->right != NULL && t->right->cnfa.nstates > 0); assert(t->left->flags&SHORTER); /* * Concatenation -- need to split the substring between parts. */ d = newDFA(v, &t->left->cnfa, &v->g->cmap, DOMALLOC); if (ISERR()) { return v->err; } d2 = newDFA(v, &t->right->cnfa, &v->g->cmap, DOMALLOC); if (ISERR()) { freeDFA(d); return v->err; } MDEBUG(("cRev %d\n", t->retry)); /* * Pick a tentative midpoint. */ if (v->mem[t->retry] == 0) { mid = shortest(v, d, begin, begin, end, NULL, NULL); if (mid == NULL) { freeDFA(d); freeDFA(d2); return REG_NOMATCH; } MDEBUG(("tentative midpoint %ld\n", LOFF(mid))); v->mem[t->retry] = (mid - begin) + 1; } else { mid = begin + (v->mem[t->retry] - 1); MDEBUG(("working midpoint %ld\n", LOFF(mid))); } /* * Iterate until satisfaction or failure. */ for (;;) { /* * Try this midpoint on for size. */ if (longest(v, d2, mid, end, NULL) == end) { int er = complicatedDissect(v, t->left, begin, mid); if (er == REG_OKAY) { er = complicatedDissect(v, t->right, mid, end); if (er == REG_OKAY) { /* * Satisfaction. */ MDEBUG(("successful\n")); freeDFA(d); freeDFA(d2); return REG_OKAY; } } if (er != REG_OKAY && er != REG_NOMATCH) { freeDFA(d); freeDFA(d2); return er; } } /* * That midpoint didn't work, find a new one. */ if (mid == end) { /* * All possibilities exhausted. */ MDEBUG(("%d no midpoint\n", t->retry)); freeDFA(d); freeDFA(d2); return REG_NOMATCH; } mid = shortest(v, d, begin, mid+1, end, NULL, NULL); if (mid == NULL) { /* * Failed to find a new one. */ MDEBUG(("%d failed midpoint\n", t->retry)); freeDFA(d); freeDFA(d2); return REG_NOMATCH; } MDEBUG(("%d: new midpoint %ld\n", t->retry, LOFF(mid))); v->mem[t->retry] = (mid - begin) + 1; zapSubtree(v, t->left); zapSubtree(v, t->right); } }
int main(int argc, char **argv) { Graph graph; MstVertex *mst_start, *mst_vertex, mst_vertex1, *mst_vertex2; PathVertex *pth_start, *pth_vertex, pth_vertex1, *pth_vertex2; TspVertex *tsp_start, *tsp_vertex; List span, paths, vertices, tour; ListElmt *element; double distance, total, x, y; int i; /***************************************************************************** * * * Compute a minimum spanning tree. * * * *****************************************************************************/ graph_init(&graph, match_mst, free); fprintf(stdout, "Computing a minimum spanning tree\n"); for (i = 0; i < MSTVCT; i++) { if ((mst_vertex = (MstVertex *) malloc(sizeof(MstVertex))) == NULL) return 1; if (i == 0) mst_start = mst_vertex; mst_vertex->data = MstTestV[i]; if (graph_ins_vertex(&graph, mst_vertex) != 0) return 1; } for (i = 0; i < MSTECT; i++) { if ((mst_vertex2 = (MstVertex *) malloc(sizeof(MstVertex))) == NULL) return 1; mst_vertex1.data = MstTestE[i].vertex1; mst_vertex2->data = MstTestE[i].vertex2; mst_vertex2->weight = MstTestE[i].weight; if (graph_ins_edge(&graph, &mst_vertex1, mst_vertex2) != 0) return 1; } print_graph_mst(&graph); if (mst(&graph, mst_start, &span, match_mst) != 0) return 1; for (element = list_head(&span); element != NULL; element = list_next(element)) { mst_vertex = list_data(element); fprintf(stdout, "vertex=%s, parent=%s\n", (char *) mst_vertex->data, mst_vertex->parent != NULL ? (char *) mst_vertex->parent->data : "*"); } list_destroy(&span); graph_destroy(&graph); /***************************************************************************** * * * Compute shortest paths. * * * *****************************************************************************/ graph_init(&graph, match_pth, free); fprintf(stdout, "Computing shortest paths\n"); for (i = 0; i < PTHVCT; i++) { if ((pth_vertex = (PathVertex *) malloc(sizeof(PathVertex))) == NULL) return 1; if (i == 0) pth_start = pth_vertex; pth_vertex->data = PthTestV[i]; if (graph_ins_vertex(&graph, pth_vertex) != 0) return 1; } for (i = 0; i < PTHECT; i++) { if ((pth_vertex2 = (PathVertex *) malloc(sizeof(PathVertex))) == NULL) return 1; pth_vertex1.data = PthTestE[i].vertex1; pth_vertex2->data = PthTestE[i].vertex2; pth_vertex2->weight = PthTestE[i].weight; if (graph_ins_edge(&graph, &pth_vertex1, pth_vertex2) != 0) return 1; } print_graph_pth(&graph); if (shortest(&graph, pth_start, &paths, match_pth) != 0) return 1; for (element = list_head(&paths); element != NULL; element = list_next(element)) { pth_vertex = list_data(element); fprintf(stdout, "vertex=%s, parent=%s, d=%.1lf\n", (char *) pth_vertex->data, pth_vertex->parent != NULL ? (char *) pth_vertex->parent->data : "*", pth_vertex->d); } list_destroy(&paths); graph_destroy(&graph); /***************************************************************************** * * * Solve the traveling-salesman problem. * * * *****************************************************************************/ /*list_init(&vertices, free); fprintf(stdout, "Solving a traveling-salesman problem\n"); for (i = 0; i < TSPVCT; i++) { if ((tsp_vertex = (TspVertex *)malloc(sizeof(TspVertex))) == NULL) return 1; if (i == 0) tsp_start = tsp_vertex; tsp_vertex->data = TspTestV[i].vertex; tsp_vertex->x = TspTestV[i].x; tsp_vertex->y = TspTestV[i].y; if (list_ins_next(&vertices, list_tail(&vertices), tsp_vertex) != 0) return 1; } print_list_tsp(&vertices); if (tsp(&vertices, tsp_start, &tour, match_tsp) != 0) return 1; total = 0; for (element = list_head(&tour); element != NULL; element = list_next(element)) { tsp_vertex = list_data(element); if (!list_is_head(&tour, element)) { distance = sqrt(pow(tsp_vertex->x-x, 2.0) + pow(tsp_vertex->y-y, 2.0)); total = total + distance; } x = tsp_vertex->x; y = tsp_vertex->y; if (!list_is_head(&tour, element)) { fprintf(stdout, "vertex=%s, distance=%.2lf\n", (char *)tsp_vertex-> data, distance); } else fprintf(stdout, "vertex=%s\n", (char *)tsp_vertex->data); } fprintf(stdout, "total=%.2lf\n", total); list_destroy(&vertices); list_destroy(&tour);*/ return 0; }
/* - crevcondissect - dissect match for concatenation node, shortest-first ^ static int crevcondissect(struct vars *, struct subre *, chr *, chr *); */ static int /* regexec return code */ crevcondissect( struct vars *v, struct subre *t, chr *begin, /* beginning of relevant substring */ chr *end) /* end of same */ { struct dfa *d, *d2; chr *mid; assert(t->op == '.'); assert(t->left != NULL && t->left->cnfa.nstates > 0); assert(t->right != NULL && t->right->cnfa.nstates > 0); assert(t->left->flags&SHORTER); d = getsubdfa(v, t->left); NOERR(); d2 = getsubdfa(v, t->right); NOERR(); MDEBUG(("crevcon %d\n", t->id)); /* * Pick a tentative midpoint. */ mid = shortest(v, d, begin, begin, end, (chr **) NULL, (int *) NULL); if (mid == NULL) { return REG_NOMATCH; } MDEBUG(("tentative midpoint %ld\n", LOFF(mid))); /* * Iterate until satisfaction or failure. */ for (;;) { /* * Try this midpoint on for size. */ if (longest(v, d2, mid, end, NULL) == end) { int er = cdissect(v, t->left, begin, mid); if (er == REG_OKAY) { er = cdissect(v, t->right, mid, end); if (er == REG_OKAY) { /* * Satisfaction. */ MDEBUG(("successful\n")); return REG_OKAY; } } if (er != REG_NOMATCH) { return er; } } /* * That midpoint didn't work, find a new one. */ if (mid == end) { /* * All possibilities exhausted. */ MDEBUG(("%d no midpoint\n", t->id)); return REG_NOMATCH; } mid = shortest(v, d, begin, mid+1, end, NULL, NULL); if (mid == NULL) { /* * Failed to find a new one. */ MDEBUG(("%d failed midpoint\n", t->id)); return REG_NOMATCH; } MDEBUG(("%d: new midpoint %ld\n", t->id, LOFF(mid))); zaptreesubs(v, t->left); zaptreesubs(v, t->right); } }
/* * condissect - determine concatenation subexpression matches (uncomplicated) */ static int /* regexec return code */ condissect(struct vars * v, struct subre * t, chr *begin, /* beginning of relevant substring */ chr *end) /* end of same */ { struct dfa *d; struct dfa *d2; chr *mid; int i; int shorter = (t->left->flags & SHORTER) ? 1 : 0; chr *stop = (shorter) ? end : begin; assert(t->op == '.'); assert(t->left != NULL && t->left->cnfa.nstates > 0); assert(t->right != NULL && t->right->cnfa.nstates > 0); d = newdfa(v, &t->left->cnfa, &v->g->cmap, &v->dfa1); NOERR(); d2 = newdfa(v, &t->right->cnfa, &v->g->cmap, &v->dfa2); if (ISERR()) { assert(d2 == NULL); freedfa(d); return v->err; } /* pick a tentative midpoint */ if (shorter) mid = shortest(v, d, begin, begin, end, (chr **) NULL, (int *) NULL); else mid = longest(v, d, begin, end, (int *) NULL); if (mid == NULL) { freedfa(d); freedfa(d2); return REG_ASSERT; } MDEBUG(("tentative midpoint %ld\n", LOFF(mid))); /* iterate until satisfaction or failure */ while (longest(v, d2, mid, end, (int *) NULL) != end) { /* that midpoint didn't work, find a new one */ if (mid == stop) { /* all possibilities exhausted! */ MDEBUG(("no midpoint!\n")); freedfa(d); freedfa(d2); return REG_ASSERT; } if (shorter) mid = shortest(v, d, begin, mid + 1, end, (chr **) NULL, (int *) NULL); else mid = longest(v, d, begin, mid - 1, (int *) NULL); if (mid == NULL) { /* failed to find a new one! */ MDEBUG(("failed midpoint!\n")); freedfa(d); freedfa(d2); return REG_ASSERT; } MDEBUG(("new midpoint %ld\n", LOFF(mid))); } /* satisfaction */ MDEBUG(("successful\n")); freedfa(d); freedfa(d2); i = dissect(v, t->left, begin, mid); if (i != REG_OKAY) return i; return dissect(v, t->right, mid, end); }
/* * find - find a match for the main NFA (no-complications case) */ static int find(struct vars * v, struct cnfa * cnfa, struct colormap * cm) { struct dfa *s; struct dfa *d; chr *begin; chr *end = NULL; chr *cold; chr *open; /* open and close of range of possible starts */ chr *close; int hitend; int shorter = (v->g->tree->flags & SHORTER) ? 1 : 0; /* first, a shot with the search RE */ s = newdfa(v, &v->g->search, cm, &v->dfa1); assert(!(ISERR() && s != NULL)); NOERR(); MDEBUG(("\nsearch at %ld\n", LOFF(v->start))); cold = NULL; close = shortest(v, s, v->search_start, v->search_start, v->stop, &cold, (int *) NULL); freedfa(s); NOERR(); if (v->g->cflags & REG_EXPECT) { assert(v->details != NULL); if (cold != NULL) v->details->rm_extend.rm_so = OFF(cold); else v->details->rm_extend.rm_so = OFF(v->stop); v->details->rm_extend.rm_eo = OFF(v->stop); /* unknown */ } if (close == NULL) /* not found */ return REG_NOMATCH; if (v->nmatch == 0) /* found, don't need exact location */ return REG_OKAY; /* find starting point and match */ assert(cold != NULL); open = cold; cold = NULL; MDEBUG(("between %ld and %ld\n", LOFF(open), LOFF(close))); d = newdfa(v, cnfa, cm, &v->dfa1); assert(!(ISERR() && d != NULL)); NOERR(); for (begin = open; begin <= close; begin++) { MDEBUG(("\nfind trying at %ld\n", LOFF(begin))); if (shorter) end = shortest(v, d, begin, begin, v->stop, (chr **) NULL, &hitend); else end = longest(v, d, begin, v->stop, &hitend); NOERR(); if (hitend && cold == NULL) cold = begin; if (end != NULL) break; /* NOTE BREAK OUT */ } assert(end != NULL); /* search RE succeeded so loop should */ freedfa(d); /* and pin down details */ assert(v->nmatch > 0); v->pmatch[0].rm_so = OFF(begin); v->pmatch[0].rm_eo = OFF(end); if (v->g->cflags & REG_EXPECT) { if (cold != NULL) v->details->rm_extend.rm_so = OFF(cold); else v->details->rm_extend.rm_so = OFF(v->stop); v->details->rm_extend.rm_eo = OFF(v->stop); /* unknown */ } if (v->nmatch == 1) /* no need for submatches */ return REG_OKAY; /* submatches */ zapsubs(v->pmatch, v->nmatch); return dissect(v, v->g->tree, begin, end); }
int gridSteinerFH(Graph *grid_graph, AdjList**** Edge2Adj, int width, int height, CoordData *term, int no_terminals, double *L,int net_num, int *edge_count_OUT, int **SteinerTree_OUT, int l, int K) { int i,j; /* globals */ int GRID_WIDTH, GRID_HEIGHT, NO_TERMINALS; Graph ND; /* distance network of terminals */ /*used to generate grid graph */ PathVertex *path_vertex; sPathData *sPath_vertex; CoordData *coord; /* used in shortest paths computations */ PathVertex **terminals; /* a (1D) array of terminal (pointers) */ List *tempPaths, /* tempporary */ **sPaths; /* 2d array of shortest path lists */ ListElmt *element; /* temp, used to traverse a list */ /* used in computing MST of ND */ MstVertex *mst_start, *mst_vertex, *mst_vertex1, *mst_vertex2; List TD; /* spanning tree of ND */ /* used in final steps of algorithm */ Graph NTD; /* complete distance network */ List T; /* spanning tree of NTD (eventually the steiner tree)*/ int isSteiner; /* boolean flag */ double tree_cost; /* total cost of the steiner tree (unused, this is computed after*/ GRID_WIDTH = width; GRID_HEIGHT = height; NO_TERMINALS = no_terminals; mst_start = NULL; /*-----------------------------------------------*/ /* If the number of terminals is two, then we */ /* only need to perform one call of Dijkstra to */ /* get the Steiner Tree */ /*-----------------------------------------------*/ if (NO_TERMINALS == 2) { PathVertex *v1,*v2; /* the two terminals*/ CoordData *c1,*c2; /* coordinates of the two terminals*/ List P; /* P-Array in Dijkstra's*/ ListElmt *e; /* list counter*/ List T; /* steiner tree*/ double tree_cost; int j; int first_edge,last_edge; PathVertex *u; u = NULL; /* allocate vertices */ v1 = (PathVertex*) malloc(sizeof(PathVertex)); v2 = (PathVertex*) malloc(sizeof(PathVertex)); c1 = (CoordData*) malloc(sizeof(CoordData)); c2 = (CoordData*) malloc(sizeof(CoordData)); /* set terminal data */ c1->x = term[0].x; c1->y = term[0].y; c1->z = term[0].z; c2->x = term[1].x; c2->y = term[1].y; c2->z = term[1].z; v1->data = c1; v2->data = c2; /* compute shortest path from v1 */ if (shortest(grid_graph, v1 , &P, match_coord,GRID_WIDTH,GRID_HEIGHT) != 0) return 1; /* initialize the tree */ list_init(&T,NULL); /* find the end vertex (v2)*/ for (e = list_head(&P); e != NULL; e = list_next(e)) if ( match_coord(v2,list_data(e))) u = (PathVertex*)list_data(e); first_edge = 1; last_edge = 0; /* follow the end vertex back to the start vertex*/ while (u->parent != NULL) { int ux,uy,uz,upx,upy,upz; AdjList *a; ListElmt *ee; /*current vertex*/ ux = ((CoordData*)((PathVertex*)u)->data)->x; uy = ((CoordData*)((PathVertex*)u)->data)->y; uz = ((CoordData*)((PathVertex*)u)->data)->z; /*connecting vertex (parent)*/ upx = ((CoordData*)((PathVertex*)u->parent)->data)->x; upy = ((CoordData*)((PathVertex*)u->parent)->data)->y; upz = ((CoordData*)((PathVertex*)u->parent)->data)->z; /* get the index of the edge that connects (ux,uy,uz) and its parent*/ a = Edge2Adj[ux][uy][uz]; for (ee = list_head(&a->adjacent); ee != NULL; ee = list_next(ee)) { PathVertex *v; int *i; int vx,vy,vz; v = (PathVertex*)list_data(ee); vx = ((CoordData*)v->data)->x; vy = ((CoordData*)v->data)->y; vz = ((CoordData*)v->data)->z; /* found it*/ if (( vx == upx ) && ( vy == upy ) && ( vz == upz )) { /*don't insert if its a via*/ if (first_edge) { first_edge = 0; if (v->index > ((grid_graph->ecount / 2) - (grid_graph->vcount/2))) continue; } /*check if its the last edge*/ if (u->parent != NULL) if (u->parent->parent == NULL) last_edge = 1; /* don't insert if its a via*/ if (last_edge) if (v->index > ((grid_graph->ecount / 2) - (grid_graph->vcount/2))) continue; i = (int*) malloc(sizeof(int)); tree_cost += v->weight; *i = v->index; list_ins_next(&T, list_tail(&T),i); } } /* next */ u = u->parent; } /* count total edges*/ *edge_count_OUT = list_size(&T); /* write the solution (including vias)*/ if ((*(SteinerTree_OUT) = (int*) malloc(sizeof(int)*(list_size(&T))))==NULL) { printf("gsFH.h : SteinerTree_OUT mem allocation error\n"); fflush(stdout); exit(1); } e = list_head(&T); for (j = 0; ((j < list_size(&T))&&(e!=NULL)); j++,e=list_next(e)) (*SteinerTree_OUT)[j] = *((int*)list_data(e)); /* free up some temps*/ free(v1->data); free(v1); free(v2->data); free(v2); list_destroy(&P); list_destroy(&T); return 0; } /*--------------------------------------------------------*/ /* General case of 3 or more terminals begins here. The */ /* above code for 2 terminals or less can be removed */ /* without affecting the block solution. However, it is */ /* faster with the special case */ /*--------------------------------------------------------*/ /* Create Path Vertices out of the original terminal set */ if ((terminals = (PathVertex**) malloc(sizeof(PathVertex*)*NO_TERMINALS))==NULL) { printf("gsFH.h : terminals mem allocation error\n"); fflush(stdout); exit(1); } for (i = 0; i < NO_TERMINALS; i++) { int x,y,z; x = term[i].x; y = term[i].y; z = term[i].z; path_vertex = (PathVertex*) malloc(sizeof(PathVertex)); coord = (CoordData*) malloc(sizeof(CoordData)); if ((path_vertex == NULL)||(coord == NULL)) { printf("gsFH.h : terminal[i] mem allocation error\n"); fflush(stdout); exit(1); } coord->x = x; coord->y = y; coord->z = z; path_vertex->data = coord; terminals[i] = path_vertex; } /* inialize an array of list pointers used in extracting shortest paths from Dijkstra */ sPaths = (List**) malloc(sizeof(List*)*NO_TERMINALS); if (sPaths == NULL) { printf("gsFH.h : sPaths mem allocation error\n"); fflush(stdout); exit(1); } if ((tempPaths = (List*) malloc(sizeof(List)*NO_TERMINALS))==NULL) { printf("gsFH.h : tempPaths mem allocation error\n"); fflush(stdout); exit(1); } for (i = 0; i < NO_TERMINALS; i++) if ((sPaths[i] = (List*) malloc(sizeof(List)*NO_TERMINALS))==NULL) { printf("gsFH.h : sPaths[i] mem allocation error\n"); fflush(stdout); exit(1); } /*--------------------------------------------------------------------------------------*/ /* COMPUTE THE SHORTEST PATHS */ /* Shortest paths are computed using O(EV^2) version of Dijkstras Algorithm */ /*--------------------------------------------------------------------------------------*/ /* for each terminal (stored as a path vertex), find the shortest path */ /* The shortest path for terminal[i] is stored in the List pointed to by */ /* paths[i]. */ for (i = 0; i < NO_TERMINALS; i++) { if (shortest(grid_graph, terminals[i], &tempPaths[i], match_coord,GRID_WIDTH,GRID_HEIGHT) != 0) return 1; /* copy out the shortest path data, if we don't do this, it will get overwritten*/ for (j = 0; j < NO_TERMINALS; j++) if (i != j) copy_sPath(&tempPaths[i], &(sPaths[i][j]), (CoordData*)((PathVertex*)terminals[j])->data); } /*--------------------------------------------------------------------------------------------------*/ /* Generate complete distance network ND */ /*--------------------------------------------------------------------------------------------------*/ /* initialize the graph */ graph_init(&ND, match_coord, (void*)mst_vertex_free); /* insert the verticies. Verticies consist of all the terminals */ for (i = 0; i < NO_TERMINALS; i++) { /* allocate space for a MST vertex */ if ((mst_vertex = (MstVertex*) malloc(sizeof(MstVertex))) == NULL) { printf("Error allocating space for mst_vertex\n"); printf("Terminating..\n"); return 1; } /* if it's the first, make it the start. It doesn't matter which one is the start */ if (i == 1) mst_start = mst_vertex; /* set the data */ if ((coord = (CoordData*) malloc(sizeof(CoordData)))==NULL) { printf("gsFH.h : coord mem allocation error\n"); fflush(stdout); exit(1); } coord->x = ((CoordData*)(((PathVertex*)terminals[i])->data))->x; coord->y = ((CoordData*)(((PathVertex*)terminals[i])->data))->y; coord->z = ((CoordData*)(((PathVertex*)terminals[i])->data))->z; mst_vertex->data = coord; /* insert */ if (graph_ins_vertex(&ND, mst_vertex) != 0) { printf("Error inserting vertex into mst_graph\n"); printf("Terminating...\n"); return 1; } } /* now we must insert the edges into the distance network graph ND. We do this by accessing the shortest path lists (sPath) computed in the previous step */ for (i = 0; i < NO_TERMINALS; i++) { int ux,uy,uz; ux = ((CoordData*)((PathVertex*)terminals[i])->data)->x; uy = ((CoordData*)((PathVertex*)terminals[i])->data)->y; uz = ((CoordData*)((PathVertex*)terminals[i])->data)->z; for (j = 0; j < NO_TERMINALS; j++) { int vx,vy,vz; /* shouldn't be an edge from a terminal to itself */ if (i != j) { double weight; CoordData *v1,*v2; int eCode; vx = ((CoordData*)((PathVertex*)terminals[j])->data)->x; vy = ((CoordData*)((PathVertex*)terminals[j])->data)->y; vz = ((CoordData*)((PathVertex*)terminals[j])->data)->z; /* now we must find how far away vx is from vy. we do this by looking for at the head element in sPath[i][j] */ element = list_head(&(sPaths[i][j])); sPath_vertex = list_data(element); weight = ((sPathData*)sPath_vertex)->d; /* allocate an edge */ if ((v1 = (CoordData*) malloc(sizeof(CoordData))) == NULL) { printf("gsFH.h : v1 mem allocation error\n"); fflush(stdout); exit(1); } if ((v2 = (CoordData*) malloc(sizeof(CoordData))) == NULL) { printf("gsFH.h : v2 mem allocation error\n"); fflush(stdout); exit(1); } v1->x = ux; v1->y = uy; v1->z = uz; v2->x = vx; v2->y = vy; v2->z = vz; if ((mst_vertex1 = (MstVertex*) malloc(sizeof(MstVertex))) == NULL) { printf("gsFH.h : mst_vertex1 mem allocation error\n"); fflush(stdout); exit(1); } if ((mst_vertex2 = (MstVertex*) malloc(sizeof(MstVertex))) == NULL) { printf("gsFH.h : mst_vertex2 mem allocation error\n"); fflush(stdout); exit(1); } mst_vertex1->data =v1; mst_vertex2->data = v2; mst_vertex2->weight = weight; if ((eCode = graph_ins_edge(&ND, mst_vertex1, mst_vertex2)) != 0) { printf("Error inserting edge into ND\n"); printf("graph_ins_edge returned the value %d\n",eCode); return 1; } free(mst_vertex1->data); free(mst_vertex1); }/* endif i!=j */ }/* endfor j */ }/* endfor i */ /*--------------------------------------------------------------------------------------------------*/ /* Copmute TD (Min Span Tree of ND) */ /*--------------------------------------------------------------------------------------------------*/ if (mst(&ND, mst_start,&TD, match_coord) != 0) { printf("Error computing minimum spanning tree\n"); return 1; } /* set leaves */ /* initialize */ for ( element = list_head(&TD); element != NULL; element = list_next(element)) { mst_vertex = list_data(element); mst_vertex->is_leaf = 1; } /* for each node, set the parent is_leaf to 0. Then, all leaves will remain */ for (element = list_head(&TD); element != NULL; element = list_next(element)) { mst_vertex = list_data(element); if (mst_vertex->parent != NULL) mst_vertex->parent->is_leaf = 0; } /*--------------------------------------------------------------------------------------------------*/ /* Find N[TD] */ /*--------------------------------------------------------------------------------------------------*/ graph_init(&NTD,match_coord,(void*)mst_vertex_free); /* for each edge in TD */ for (element = list_head(&TD); element != NULL; element = list_next(element)) { MstVertex *nextVertex; int v,p; p = -1; v = -1; nextVertex = list_data(element); /* if it is not the root */ if (nextVertex->parent != NULL) { int vx,vy,vz,px,py,pz; ListElmt *currentV, *nextV; int done; vx = ((CoordData*)((MstVertex*)nextVertex)->data)->x; vy = ((CoordData*)((MstVertex*)nextVertex)->data)->y; vz = ((CoordData*)((MstVertex*)nextVertex)->data)->z; px = ((CoordData*)(MstVertex*)(nextVertex->parent)->data)->x; py = ((CoordData*)(MstVertex*)(nextVertex->parent)->data)->y; pz = ((CoordData*)(MstVertex*)(nextVertex->parent)->data)->z; /* find terminal index of nextVertex and nextVertex->parent */ for (i = 0; i < NO_TERMINALS; i++) { int tx,ty,tz; tx = ((CoordData*)((PathVertex*)terminals[i])->data)->x; ty = ((CoordData*)((PathVertex*)terminals[i])->data)->y; tz = ((CoordData*)((PathVertex*)terminals[i])->data)->z; if ((tx == vx)&&(ty == vy)&&(tz == vz)) v = i; if ((tx == px)&&(ty == py)&&(tz == pz)) p = i; } /* now, we must step through the list of sPathData elements found in sPaths[p][v]. For each element in the list, we must insert vertices for the vertex and parent, then make an edge with the appropriate weight and insert it */ currentV = list_head(&(sPaths[p][v])); nextV = list_next(currentV); done = 0; while ( !done ) { MstVertex *u,*v, *mst_vertex1, *mst_vertex2; CoordData *uc,*vc; sPathData *currentVData, *nextVData; int cvx,cvy,cvz,nvx,nvy,nvz; double weight; /*---------------------------------------*/ /* insert vertices u and v into NTD */ /*---------------------------------------*/ /* make a vertex for currentV and nextV */ u = (MstVertex*) malloc(sizeof(MstVertex)); v = (MstVertex*) malloc(sizeof(MstVertex)); uc = (CoordData*) malloc(sizeof(CoordData)); vc = (CoordData*) malloc(sizeof(CoordData)); if ((u == NULL)||(uc==NULL)||(v==NULL)||(vc==NULL)) { printf("gsFH.h : error allocating vertex for NTD\n"); fflush(stdout); exit(1); } /* get vertices from the sPaths list */ currentVData = list_data(currentV); nextVData = list_data(nextV); /* get vertex data */ cvx = ((CoordData*)((sPathData*)currentVData)->vertex)->x; cvy = ((CoordData*)((sPathData*)currentVData)->vertex)->y; cvz = ((CoordData*)((sPathData*)currentVData)->vertex)->z; nvx = ((CoordData*)((sPathData*)nextVData)->vertex)->x; nvy = ((CoordData*)((sPathData*)nextVData)->vertex)->y; nvz = ((CoordData*)((sPathData*)nextVData)->vertex)->z; /* set vertex data */ uc->x = cvx; uc->y = cvy; uc->z = cvz; vc->x = nvx; vc->y = nvy; vc->z = nvz; u->data = uc; v->data = vc; /* calculate weight between u and v */ weight = currentVData->d - nextVData->d; /* try and insert u, if it exists, then delete the memory we allocated for it */ if ( graph_ins_vertex(&NTD, u) == 1 ) { free(uc); free(u); } else { /* doesnt' matter which one is the start */ mst_start = u; } /* try and insert v, if it exists, then delete the memorr we allocated for it */ if ( graph_ins_vertex(&NTD, v) == 1) { free(vc); free(v); } /* now the vertices u and v are in the graph. we now have to make an edge for uv */ /* make edge going forward */ if ((uc = (CoordData*)malloc(sizeof(CoordData))) == NULL) { printf("gsFH.h : uc mem allocation error\n"); fflush(stdout); exit(1); } if ((vc = (CoordData*)malloc(sizeof(CoordData))) == NULL) { printf("gsFH.h : vc mem allocation error\n"); fflush(stdout); exit(1); } uc->x = cvx; uc->y = cvy; uc->z = cvz; vc->x = nvx; vc->y = nvy; vc->z = nvz; if ((mst_vertex1 = (MstVertex*) malloc(sizeof(MstVertex))) == NULL) { printf("gsFH.h : mst_Vertex1 mem allocation error\n"); fflush(stdout); exit(1); } if ((mst_vertex2 = (MstVertex*)malloc(sizeof(MstVertex))) == NULL) { printf("gsFH.h : mst_vertex2 mem allocation error\n"); fflush(stdout); exit(1); } mst_vertex1->data = uc; mst_vertex2->data = vc; mst_vertex2->weight = weight; /* try and insert, if it exists, free previously allocated mem */ if ( graph_ins_edge(&NTD, mst_vertex1, mst_vertex2) == 1) { free(vc); free(mst_vertex2); } /* free the label */ free(mst_vertex1->data); free(mst_vertex1); /* make edge going backward */ if ((uc = (CoordData*)malloc(sizeof(CoordData))) == NULL) { printf("gsFH.h : uc mem allocation error\n"); fflush(stdout); exit(1); } if ((vc = (CoordData*)malloc(sizeof(CoordData))) == NULL) { printf("gsFH.h : vc mem allocation error\n"); fflush(stdout); exit(1); } uc->x = cvx; uc->y = cvy; uc->z = cvz; vc->x = nvx; vc->y = nvy; vc->z = nvz; if ((mst_vertex1 = (MstVertex*) malloc(sizeof(MstVertex))) == NULL) { printf("gsFH.h : mst_Vertex1 mem allocation error\n"); fflush(stdout); exit(1); } if ((mst_vertex2 = (MstVertex*)malloc(sizeof(MstVertex))) == NULL) { printf("gsFH.h : mst_Vertex2 mem allocation error\n"); fflush(stdout); exit(1); } mst_vertex1->data = vc; mst_vertex2->data = uc; mst_vertex2->weight = weight; /* try and insert, if it exists, free previously allocated mem */ if ( graph_ins_edge(&NTD, mst_vertex1, mst_vertex2) == 1) { free(uc); free(mst_vertex2); } /* free the label */ free(mst_vertex1->data); free(mst_vertex1); /* follow pointers */ currentV = list_next(currentV); nextV = list_next(nextV); /* check to see if we're finished */ if (nextV == NULL) done = 1; } } } /*----------------------------------------------------------------------------------------------------------*/ /* Compute T (minimum spanning tree of NTD) */ /*----------------------------------------------------------------------------------------------------------*/ /* call minimum spanning tree subroutine */ if (mst(&NTD, mst_start,&T, match_coord) != 0) { printf("Error computing minimum spanning tree\n"); return 1; } /* set leaves */ for ( element = list_head(&T); element != NULL; element = list_next(element)) { mst_vertex = list_data(element); mst_vertex->is_leaf = 1; } /* for each node, set the parent is_leaf to 0. Then, all leaves will remain */ for (element = list_head(&T); element != NULL; element = list_next(element)) { mst_vertex = list_data(element); if (mst_vertex->parent != NULL) mst_vertex->parent->is_leaf = 0; } /*--------------------------------------------------------------------------------------*/ /* Compute Steiner Tree Sk */ /*--------------------------------------------------------------------------------------*/ isSteiner = 0; /* we remove all leaves that arent' terminals, when all leaves are terminals then we have a Steiner Tree */ while (!isSteiner) { ListElmt *prev; /* assume we have it */ isSteiner = 1; /* check if each leaf is a terminal */ prev = list_head(&T); element = list_next(prev); while (element != NULL) { int mx,my,mz; mst_vertex = list_data(element); mx = ((CoordData*)((MstVertex*)mst_vertex)->data)->x; my = ((CoordData*)((MstVertex*)mst_vertex)->data)->y; mz = ((CoordData*)((MstVertex*)mst_vertex)->data)->z; if (mst_vertex->is_leaf) { int found; found = 0; for (i = 0; i < NO_TERMINALS; i++) { int tx,ty,tz; tx = ((CoordData*)((PathVertex*)terminals[i])->data)->x; ty = ((CoordData*)((PathVertex*)terminals[i])->data)->y; tz = ((CoordData*)((PathVertex*)terminals[i])->data)->z; if ( (tx==mx)&&(ty==my)&&(tz==mz)) found = 1; } /* remove it if we can't find it */ if (!found) { MstVertex *junk; ListElmt *e; isSteiner = 0; /* not done yet */ list_rem_next(&T, prev, (void**)(&junk)); /*reset leaves */ /* initialize */ for ( e = list_head(&T); e != NULL; e = list_next(e)) { mst_vertex = list_data(e); mst_vertex->is_leaf = 1; } /* for each node, set the parent is_leaf to 0. Then, all leaves will remain */ for (e = list_head(&T); e != NULL; e = list_next(e)) { mst_vertex = list_data(e); if (mst_vertex->parent != NULL) mst_vertex->parent->is_leaf = 0; } /* start over at beginning of list */ prev = list_head(&T); element = list_next(prev); } else { prev = list_next(prev); element = list_next(element); } } else { prev = list_next(prev); element = list_next(element); } } } /* we can further eliminate vias that connect to a terminal leaf. These are not neccessary*/ isSteiner = 0; while (!isSteiner) { ListElmt *prev; /* assume we have it */ isSteiner = 1; /* check if each leaf is a terminal */ prev = list_head(&T); element = list_next(prev); while (element != NULL) { int mx,my,mz; mst_vertex = list_data(element); mx = ((CoordData*)((MstVertex*)mst_vertex)->data)->x; my = ((CoordData*)((MstVertex*)mst_vertex)->data)->y; mz = ((CoordData*)((MstVertex*)mst_vertex)->data)->z; if (mst_vertex->is_leaf) { int remove; int px,py; remove = 0; px = ((CoordData*)((MstVertex*)mst_vertex->parent)->data)->x; py = ((CoordData*)((MstVertex*)mst_vertex->parent)->data)->y; if ((px == mx)&&(py == my)) remove = 1; /* remove it if neccessary */ if (remove) { MstVertex *junk; ListElmt *e; isSteiner = 0; /* not done yet */ list_rem_next(&T, prev, (void**)(&junk)); /*reset leaves */ /* initialize */ for ( e = list_head(&T); e != NULL; e = list_next(e)) { mst_vertex = list_data(e); mst_vertex->is_leaf = 1; } /* for each node, set the parent is_leaf to 0. Then, all leaves will remain */ for (e = list_head(&T); e != NULL; e = list_next(e)) { mst_vertex = list_data(e); if (mst_vertex->parent != NULL) mst_vertex->parent->is_leaf = 0; } /* start over at beginning of list */ prev = list_head(&T); element = list_next(prev); } else { prev = list_next(prev); element = list_next(element); } } else { prev = list_next(prev); element = list_next(element); } } } /* get the total cost of the tree */ tree_cost = 0; for (element = list_head(&T); element != NULL; element = list_next(element)) { CoordData *u, *v; mst_vertex = list_data(element); if (( mst_vertex->parent == NULL)) continue; else { double temp; u = (CoordData*)mst_vertex->data; v = (CoordData*)mst_vertex->parent->data; /* look up cost of edge uv */ temp = find_edge_weight(grid_graph,u,v); tree_cost += temp; } } *edge_count_OUT = list_size(&T)-1; if ((*(SteinerTree_OUT) = (int*) malloc(sizeof(int)*(list_size(&T)-1)))==NULL) { printf("gsFH.h : SteinerTree_OUT mem allocation error\n"); fflush(stdout); exit(1); } i = 0; for ( element = list_head(&T); element != NULL; element = list_next(element)) { int vx,vy,vz,px,py,pz; int tx,ty,tz; AdjList *a; ListElmt *e; int edge_index; double edge_weight; mst_vertex = list_data(element); vx = ((CoordData*)mst_vertex->data)->x; vy = ((CoordData*)mst_vertex->data)->y; vz = ((CoordData*)mst_vertex->data)->z; if (mst_vertex->parent != NULL) { px = ((CoordData*)mst_vertex->parent->data)->x; py = ((CoordData*)mst_vertex->parent->data)->y; pz = ((CoordData*)mst_vertex->parent->data)->z; edge_weight = mst_vertex->weight; } else { px = -1; py = -1; pz = -1; } a = (AdjList*)Edge2Adj[vx][vy][vz]; tx = ((CoordData*)((PathVertex*)(a->vertex))->data)->x; ty = ((CoordData*)((PathVertex*)(a->vertex))->data)->y; tz = ((CoordData*)((PathVertex*)(a->vertex))->data)->z; for ( e = list_head(&(a->adjacent)); e != NULL; e = list_next(e) ) { PathVertex *p; p = (PathVertex*)list_data(e); tx = ((CoordData*)p->data)->x; ty = ((CoordData*)p->data)->y; tz = ((CoordData*)p->data)->z; if ((tx == px)&&(ty == py)&&(tz == pz)) { /*found*/ edge_index = p->index; (*SteinerTree_OUT)[i] = edge_index; i++; } } } /*-------------------------------------------------------------------------------------*/ /* Clean Up */ /*-------------------------------------------------------------------------------------*/ /* free our list of temporary paths*/ for (i = 0; i < NO_TERMINALS; i++) list_destroy(&tempPaths[i]); free(tempPaths); /* destroy distance network*/ graph_destroy(&ND); /* deystroy all the shortest path lists*/ for (i = 0; i < NO_TERMINALS; i++) for (j = 0; j < NO_TERMINALS; j++) if ( i != j ) list_destroy(&sPaths[i][j]); /* destroy the pointers to the shortest path lists*/ for (i = 0; i < NO_TERMINALS; i++) free(sPaths[i]); free(sPaths); /* destroy the minimum spanning tree*/ list_destroy(&TD); /* destroy grid spanning tree*/ graph_destroy(&NTD); /* destroy the terminal list*/ for (i = 0; i < NO_TERMINALS; i++) { path_vertex_free(terminals[i]); } free(terminals); /*destroy the steiner tree*/ list_destroy(&T); return 0; }
typename boost::range_reference< Range >::type shortest_levenshtein( Range &_range, Value const &_element ) { typedef typename boost::range_value< Range >::type string_type; typedef typename string_type::size_type size_type; typedef typename boost::range_iterator< Range >::type iterator; size_type shortest_dist( ::fcppt::algorithm::levenshtein( *boost::begin( _range), _element ) ); iterator shortest( boost::begin( _range) ); for( iterator it( std::next( boost::begin( _range) ) ); it != boost::end(_range); ++it ) { size_type const new_shortest_dist( ::fcppt::algorithm::levenshtein( *it, _element ) ); if( new_shortest_dist < shortest_dist ) { shortest = it; shortest_dist = new_shortest_dist; } } return *shortest; }
/* * Simulates a multilevel feedback queue cpu scheduling algorithm * TODO Update the file parsing to be smarter and provide documentation */ int main(int argc, char** argv) { const int FIELD_LENGTH = 1024; //Default string allocation char line[FIELD_LENGTH]; //Buffer for line reading of master file char* sub_out; //Output of substring checks for certain fields int read_T1 = 0; //0 if T1 hasnt been read yet int read_T2 = 0; //0 if T2 hasnt been read yet int T1, T2; //Time Quantums int processCount = 0; //Number of processes read from the file int processCompleted = 0; //Counter for number of process completed Queue* futureProcesses = new_queue(0); //Queue of all the processes that havent technically been submitted yet Queue* completed = new_queue(-1); //Queue of all completed processes, for output of averaging at the end int i; //Open the file passed in as the only argument to the program FILE* master_file = fopen(argv[1], "rt"); if (master_file == 0) { fprintf(stderr, "Failed to open %s\n", argv[1]); exit(1); } //Open output file for logging functions of the simulator FILE* out_file = fopen("cpu_output.txt", "w"); fprintf(out_file, "############################################################\n"); fprintf(out_file, "Logging for Multi-Level Queue Scheduling Simulation Started!\n"); fprintf(out_file, "############################################################\n\n"); //Read in the file and create necessary process objects if (master_file != NULL) { //Read line by line to get T1 and T2 while (fgets(line, FIELD_LENGTH, master_file) != NULL) { if (strcmp(line, "\n") == 0) { //SKIP NEW LINES IN THE FILE } else { //Change the line to all lowercase array_to_lower(line); //Read in TQ#1 and TQ#2 if (!read_T1) { sub_out = strstr(line, "time quantum 1:"); if (sub_out != NULL) { read_T1 = 1; T1 = get_num(sub_out); } } else if (!read_T2) { sub_out = strstr(line, "time quantum 2:"); if (sub_out != NULL) { read_T2 = 1; T2 = get_num(sub_out); break; } } } } //Initialize a CPU CPU* cpu = new_cpu(T1, T2); //Read in the rest of the file and create all processes and their associated bursts while (fgets(line, FIELD_LENGTH, master_file) != NULL) { if (strcmp(line, "\n") == 0) { //SKIP NEW LINES IN THE FILE } else { //Change the line to all lowercase array_to_lower(line); Process* end = get_end(futureProcesses); //Get the process id and create a new process for it sub_out = strstr(line, "process id:"); if (sub_out != NULL) { int id = get_num(sub_out); Process* process = new_process(id); if (end != NULL) { end->next = process; } else { futureProcesses->processes = process; } processCount++; } //Get the arrival time of the most recently created process sub_out = strstr(line, "arrival time:"); if (sub_out != NULL) { int arrival = get_num(sub_out); end->arrival_time = arrival; } //Create a cpu burst of the recently created process sub_out = strstr(line, "cpu burst:"); if (sub_out != NULL) { int length = get_num(sub_out); Burst* cpu_burst = new_cpu_burst(length); Burst* burst_end = get_last_burst(end); if (burst_end != NULL) { burst_end->next_burst = cpu_burst; } else { end->bursts = cpu_burst; } } //Create a i/o burst for the recently created process sub_out = strstr(line, "i/o burst:"); if (sub_out != NULL) { int length = get_num(sub_out); Burst* io_burst = new_io_burst(length); Burst* burst_end = get_last_burst(end); if (burst_end != NULL) { burst_end->next_burst = io_burst; } else { end->bursts = io_burst; } } //Set the device id for the recently created i/o burst sub_out = strstr(line, "i/o device id:"); if (sub_out != NULL) { int id = get_num(sub_out); Burst* burst_end = get_last_burst(end); if (burst_end != NULL) { burst_end->device_num = id; } else { end->bursts->device_num = id; } } } } fclose(master_file); //Handle if no processes are read in if (processCount == 0) { fclose(out_file); fprintf(stderr, "Zero processes were read in.\nThis could be correct or an error in the format of the input file.\nPlease verify that the input file is formatted correctly. \n"); exit(1); } //Run the simulation of the cpu until all processes have been completed while (processCompleted < processCount) { //Go through the list of processes that havent arrived yet Process* tempProc = futureProcesses->processes; Process* lastTemp = NULL; while (tempProc != NULL) { if (tempProc->arrival_time == cpu->time) { //Create a copy of the process to move to the cpu Process* moved = copy_process(tempProc); fprintf(out_file, "Time: %-5d\tProcess#%d Arrived\n", cpu->time, moved->id); if (moved->bursts->type == 1) { //Initial burst is cpu printf("NEW PROCESS CPU FIRST\n"); fprintf(out_file, "Time: %-5d\tInitial burst of Process#%d is a CPU burst\n", cpu->time, moved->id); if (cpu->idle == 1) { //If nothing is running on the cpu fprintf(out_file, "Time: %-5d\tCPU was found to be idle, running process on CPU\n", cpu->time); moved->state = 1; cpu->current_process = moved; cpu->idle = 0; cpu->queue = 1; printQueues(out_file, cpu); } else { //If cpu is occupied put new process in Q1 fprintf(out_file, "Time: %-5d\tCPU was found to be busy, putting process in Q1\n", cpu->time); Process* end = get_end(cpu->Q1); moved->state = 2; if (end != NULL) { //If Stuff is already in Q1 end->next = moved; } else { //If nothing is in Q1 cpu->Q1->processes = moved; cpu->Q1->isEmpty = 0; } printQueues(out_file, cpu); } } else { //Initial burst is I/O printf("NEW PROCESS I/O FIRST\n"); Burst* i_burst = moved->bursts; int device = i_burst->device_num; IODevice* devQ; switch (device) { case 1: //Next burst is on D1 devQ = cpu->D1; break; case 2: //Next burst is on D2 devQ = cpu->D2; break; case 3: //Next burst is on D3 devQ = cpu->D3; break; case 4: //Next burst is on D4 devQ = cpu->D4; break; case 5: //Next burst is on D5 devQ = cpu->D5; break; } //Move the process to the correct i/o device fprintf(out_file, "Time: %-5d\tInitial burst of Process#%d is a I/O burst on device %d\n", cpu->time, cpu->current_process->id, devQ->id); Process* io_end = get_io_proc_end(devQ); if (io_end != NULL) { io_end->next = moved; } else { fprintf(out_file, "Time: %-5d\tProcess#%d running on I/O Device Queue %d\n", cpu->time, cpu->current_process->id, devQ->id); devQ->processes = moved; } printQueues(out_file, cpu); } //Remove the process from futureProcesses if (lastTemp != NULL) { //This wasnt the first lastTemp->next = tempProc->next; tempProc = lastTemp->next; } else { //Process was the first or only in future list futureProcesses->processes = tempProc->next; tempProc = futureProcesses->processes; } } else { //Times not equal get next process in list lastTemp = tempProc; tempProc = tempProc->next; } } //Increment running process time on cpu and decrement its remaining time //If remaining time is 0, if last burst move process to completed otherwise move it to correct i/o queue if (cpu->idle == 0) { printf("CPU NOT IDLE\n"); Burst* burst = get_next_incomplete_burst(cpu->current_process); if (burst != NULL) { printf("NEXT BURST IS NOT NULL\n"); burst->time_active++; burst->time_remaining--; if (burst->time_remaining == 0) { //Burst is complete printf("BURST COMPLETE\n"); burst->completed = 1; fprintf(out_file, "Time: %-5d\tCPU burst of Process#%d completed\n", cpu->time, cpu->current_process->id); if (burst->next_burst != NULL) { printf("MORE BURSTS\n"); int device = burst->next_burst->device_num; IODevice* devQ; switch (device) { case 1: //Next burst is on D1 devQ = cpu->D1; break; case 2: //Next burst is on D2 devQ = cpu->D2; break; case 3: //Next burst is on D3 devQ = cpu->D3; break; case 4: //Next burst is on D4 devQ = cpu->D4; break; case 5: //Next burst is on D5 devQ = cpu->D5; break; } //Move the process to the correct i/o device fprintf(out_file, "Time: %-5d\tProcess#%d moved to I/O Device Queue %d\n", cpu->time, cpu->current_process->id, devQ->id); Process* io_end = get_io_proc_end(devQ); cpu->current_process->next = NULL; if (io_end != NULL) { io_end->next = cpu->current_process; } else { fprintf(out_file, "Time: %-5d\tProcess#%d running on I/O Device Queue %d\n", cpu->time, cpu->current_process->id, devQ->id); devQ->processes = cpu->current_process; } } else { printf("PROCESS COMPLETE\n"); cpu->current_process->state = 0; fprintf(out_file, "Time: %-5d\tProcess#%d completed. Time waiting for CPU: %d Time waiting for I/O: %d Total completion time: %d\n", cpu->time, cpu->current_process->id, cpu->current_process->waiting_cpu, cpu->current_process->waiting_io, (cpu->time - cpu->current_process->arrival_time)); cpu->current_process->completion_t = cpu->time; processCompleted++; Process* end = get_end(completed); if (end != NULL) { //If there are already processes in completed end->next = cpu->current_process; } else { //If this is the first process in completed completed->processes = cpu->current_process; } } //Cpu is empty cpu->current_process = NULL; cpu->idle = 1; cpu->queue = 0; printQueues(out_file, cpu); } } } //Increase cpu wait time for all processes in all 3 queues Process* pq1 = get_end(cpu->Q1); while (pq1 != NULL) { printf("INCREMENTING Q1 WAIT TIMES\n"); pq1->waiting_cpu++; pq1 = pq1->next; } Process* q2 = get_end(cpu->Q2); while (q2 != NULL) { printf("INCREMENTING Q2 WAIT TIMES\n"); q2->waiting_cpu++; q2 = q2->next; } Process* pq3 = get_end(cpu->Q3); while (pq3 != NULL) { printf("INCREMENTING Q3 WAIT TIMES\n"); pq3->waiting_cpu++; pq3 = pq3->next; } //For the first process in each device queue decrement time remaining //If remaining time is 0, if last burst move process to completed otherwise move it to Q1 //Increment waiting time of process moved to front of device queue Process* pd1 = cpu->D1->processes; Process* pd2 = cpu->D2->processes; Process* pd3 = cpu->D3->processes; Process* pd4 = cpu->D4->processes; Process* pd5 = cpu->D5->processes; if (pd1 != NULL) { //Handle running process in device 1 printf("PROCESS IN D1\n"); Burst* bd1 = get_next_incomplete_burst(pd1); if (bd1 != NULL) { printf("D1 PROCESS BURST EXISTS\n"); bd1->time_remaining--; if (bd1->time_remaining == 0) { printf("BURST IN D1 FINISHED\n"); bd1->completed = 1; fprintf(out_file, "Time: %-5d\tI/O burst of Process#%d completed on device %d\n", cpu->time, pd1->id, bd1->device_num); cpu->D1->processes = pd1->next; if (cpu->D1->processes != NULL) { cpu->D1->processes->waiting_io++; fprintf(out_file, "Time: %-5d\tI/O burst of Process#%d running on device %d\n", cpu->time, pd1->next->id, bd1->device_num); } if (bd1->next_burst != NULL) { printf("MOVING PROCESS FROM D1 to Q1\n"); Process* end_q = get_end(cpu->Q1); fprintf(out_file, "Time: %-5d\tMoving Process#%d to Q1\n", cpu->time, pd1->id); pd1->next = NULL; if (end_q != NULL) { end_q->next = pd1; } else { cpu->Q1->processes = pd1; cpu->Q1->isEmpty = 0; } printQueues(out_file, cpu); } else { printf("PROCESS COMPLETED IN D1\n"); pd1->state = 0; Process* end_completed = get_end(completed); processCompleted++; pd1->completion_t = cpu->time; fprintf(out_file, "Time: %-5d\tProcess#%d completed. Time waiting for CPU: %d Time waiting for I/O: %d Total completion time: %d\n", cpu->time, pd1->id, pd1->waiting_cpu, pd1->waiting_io, (cpu->time - pd1->arrival_time)); if (end_completed != NULL) { end_completed->next = pd1; } else { completed->processes = pd1; completed->isEmpty = 0; } printQueues(out_file, cpu); } } } } if (pd2 != NULL) { //Handle running process in device 2 printf("PROCESS IN D2\n"); Burst* bd2 = get_next_incomplete_burst(pd2); if (bd2 != NULL) { printf("D2 PROCESS BURST EXISTS\n"); bd2->time_remaining--; if (bd2->time_remaining == 0) { printf("BURST IN D2 FINISHED\n"); bd2->completed = 1; fprintf(out_file, "Time: %-5d\tI/O burst of Process#%d completed on device %d\n", cpu->time, pd2->id, bd2->device_num); cpu->D2->processes = pd2->next; if (cpu->D1->processes != NULL) { cpu->D2->processes->waiting_io++; fprintf(out_file, "Time: %-5d\tI/O burst of Process#%d running on device %d\n", cpu->time, pd2->next->id, bd2->device_num); } if (bd2->next_burst != NULL) { printf("MOVING PROCESS FROM D2 to Q1\n"); Process* end_q = get_end(cpu->Q1); fprintf(out_file, "Time: %-5d\tMoving Process#%d to Q1\n", cpu->time, pd2->id); pd2->next = NULL; if (end_q != NULL) { end_q->next = pd2; } else { cpu->Q1->processes = pd2; cpu->Q1->isEmpty = 0; } printQueues(out_file, cpu); } else { printf("PROCESS COMPLETED IN D2\n"); pd2->state = 0; Process* end_completed = get_end(completed); processCompleted++; pd2->completion_t = cpu->time; fprintf(out_file, "Time: %-5d\tProcess#%d completed. Time waiting for CPU: %d Time waiting for I/O: %d Total completion time: %d\n", cpu->time, pd2->id, pd2->waiting_cpu, pd2->waiting_io, (cpu->time - pd2->arrival_time)); if (end_completed != NULL) { end_completed->next = pd2; } else { completed->processes = pd2; completed->isEmpty = 0; } printQueues(out_file, cpu); } } } } if (pd3 != NULL) { //Handle running process in device 3 printf("PROCESS IN D3\n"); Burst* bd3 = get_next_incomplete_burst(pd3); if (bd3 != NULL) { printf("D3 PROCESS BURST EXISTS\n"); bd3->time_remaining--; if (bd3->time_remaining == 0) { printf("BURST IN D3 FINISHED\n"); bd3->completed = 1; fprintf(out_file, "Time: %-5d\tI/O burst of Process#%d completed on device %d\n", cpu->time, pd3->id, bd3->device_num); cpu->D3->processes = pd3->next; if (cpu->D1->processes != NULL) { cpu->D3->processes->waiting_io++; fprintf(out_file, "Time: %-5d\tI/O burst of Process#%d running on device %d\n", cpu->time, pd3->next->id, bd3->device_num); } if (bd3->next_burst != NULL) { printf("MOVING PROCESS FROM D3 to Q1\n"); Process* end_q = get_end(cpu->Q1); fprintf(out_file, "Time: %-5d\tMoving Process#%d to Q1\n", cpu->time, pd3->id); pd3->next = NULL; if (end_q != NULL) { end_q->next = pd3; } else { cpu->Q1->processes = pd3; cpu->Q1->isEmpty = 0; } printQueues(out_file, cpu); } else { printf("PROCESS COMPLETED IN D3\n"); pd3->state = 0; Process* end_completed = get_end(completed); processCompleted++; pd3->completion_t = cpu->time; fprintf(out_file, "Time: %-5d\tProcess#%d completed. Time waiting for CPU: %d Time waiting for I/O: %d Total completion time: %d\n", cpu->time, pd3->id, pd3->waiting_cpu, pd3->waiting_io, (cpu->time - pd3->arrival_time)); if (end_completed != NULL) { end_completed->next = pd3; } else { completed->processes = pd3; completed->isEmpty = 0; } printQueues(out_file, cpu); } } } } if (pd4 != NULL) {//Handle running process in device 4 printf("PROCESS IN D4\n"); Burst* bd4 = get_next_incomplete_burst(pd4); if (bd4 != NULL) { printf("D4 PROCESS BURST EXISTS\n"); bd4->time_remaining--; if (bd4->time_remaining == 0) { printf("BURST IN D4 FINISHED\n"); bd4->completed = 1; fprintf(out_file, "Time: %-5d\tI/O burst of Process#%d completed on device %d\n", cpu->time, pd4->id, bd4->device_num); cpu->D4->processes = pd4->next; if (cpu->D1->processes != NULL) { cpu->D4->processes->waiting_io++; fprintf(out_file, "Time: %-5d\tI/O burst of Process#%d running on device %d\n", cpu->time, pd4->next->id, bd4->device_num); } if (bd4->next_burst != NULL) { printf("MOVING PROCESS FROM D4 to Q1\n"); Process* end_q = get_end(cpu->Q1); fprintf(out_file, "Time: %-5d\tMoving Process#%d to Q1\n", cpu->time, pd4->id); pd4->next = NULL; if (end_q != NULL) { end_q->next = pd4; } else { cpu->Q1->processes = pd4; cpu->Q1->isEmpty = 0; } printQueues(out_file, cpu); } else { printf("PROCESS COMPLETED IN D4\n"); pd4->state = 0; Process* end_completed = get_end(completed); processCompleted++; pd4->completion_t = cpu->time; fprintf(out_file, "Time: %-5d\tProcess#%d completed. Time waiting for CPU: %d Time waiting for I/O: %d Total completion time: %d\n", cpu->time, pd4->id, pd4->waiting_cpu, pd4->waiting_io, (cpu->time - pd4->arrival_time)); if (end_completed != NULL) { end_completed->next = pd4; } else { completed->processes = pd4; completed->isEmpty = 0; } printQueues(out_file, cpu); } } } } if (pd5 != NULL) {//Handle running process in device 5 printf("PROCESS IN D5\n"); Burst* bd5 = get_next_incomplete_burst(pd5); if (bd5 != NULL) { printf("D5 PROCESS BURST EXISTS\n"); bd5->time_remaining--; if (bd5->time_remaining == 0) { printf("BURST IN D5 FINISHED\n"); bd5->completed = 1; fprintf(out_file, "Time: %-5d\tI/O burst of Process#%d completed on device %d\n", cpu->time, pd5->id, bd5->device_num); cpu->D5->processes = pd5->next; if (cpu->D1->processes != NULL) { cpu->D5->processes->waiting_io++; fprintf(out_file, "Time: %-5d\tI/O burst of Process#%d running on device %d\n", cpu->time, pd5->next->id, bd5->device_num); } if (bd5->next_burst != NULL) { printf("MOVING PROCESS FROM D5 to Q1\n"); Process* end_q = get_end(cpu->Q1); fprintf(out_file, "Time: %-5d\tMoving Process#%d to Q1\n", cpu->time, pd5->id); pd5->next = NULL; if (end_q != NULL) { end_q->next = pd5; } else { cpu->Q1->processes = pd5; cpu->Q1->isEmpty = 0; } printQueues(out_file, cpu); } else { printf("PROCESS COMPLETED IN D5\n"); pd5->state = 0; Process* end_completed = get_end(completed); processCompleted++; pd5->completion_t = cpu->time; fprintf(out_file, "Time: %-5d\tProcess#%d completed. Time waiting for CPU: %d Time waiting for I/O: %d Total completion time: %d\n", cpu->time, pd5->id, pd5->waiting_cpu, pd5->waiting_io, (cpu->time - pd5->arrival_time)); if (end_completed != NULL) { end_completed->next = pd5; } else { completed->processes = pd5; completed->isEmpty = 0; } printQueues(out_file, cpu); } } } } //Increment the io waiting time for all processes in device queues after the first process in each pd1 = cpu->D1->processes; pd2 = cpu->D2->processes; pd3 = cpu->D3->processes; pd4 = cpu->D4->processes; pd5 = cpu->D5->processes; if (pd1 != NULL) { //Handle device 1 pd1 = pd1->next; while (pd1 != NULL) { printf("Incrementing device 1 waiting\n"); pd1->waiting_io++; pd1 = pd1->next; } } if (pd2 != NULL) { //Handle device 2 pd2 = pd2->next; while (pd2 != NULL) { printf("Incrementing device 2 waiting\n"); pd2->waiting_io++; pd2 = pd2->next; } } if (pd3 != NULL) { //Handle device 3 pd3 = pd3->next; while (pd3 != NULL) { printf("Incrementing device 3 waiting\n"); pd3->waiting_io++; pd3 = pd3->next; } } if (pd4 != NULL) { //Handle device 4 pd4 = pd4->next; while (pd4 != NULL) { printf("Incrementing device 4 waiting\n"); pd4->waiting_io++; pd4 = pd4->next; } } if (pd5 != NULL) { //Handle device 5 pd5 = pd5->next; while (pd5 != NULL) { printf("Incrementing device 5 waiting\n"); pd5->waiting_io++; pd5 = pd5->next; } } //If cpu is running in Q3 //Check for other processes with shorter remaining times //If there is one move running process to end of Q3 //Check if Q1 and Q2 are empty, if either isnt free up the cpu and put the running process back into Q3 if (cpu->queue == 3 && cpu->current_process != NULL) { printf("CPU is in Q3\n"); if (cpu->Q1->processes != NULL || cpu->Q2->processes != NULL || shortest(cpu->current_process, cpu->Q3) == 0) { printf("PROCESS IN Q3 IS BEING PREEMTED\n"); Process* end_que = get_end(cpu->Q3); cpu->current_process->state = 2; fprintf(out_file, "Time: %-5d\tProcess#%d has been moved back into Q3 due to there being a shorter process in Q3 to run or there are processes in Q2 or Q1 that need to be run\n", cpu->time, cpu->current_process->id); if (end_que != NULL) { end_que->next = cpu->current_process; } else { cpu->Q3->processes = cpu->current_process; cpu->Q3->isEmpty = 0; } cpu->current_process = NULL; cpu->idle = 1; cpu->queue = 0; printQueues(out_file, cpu); } else { printf("NOTHING IN Q3 PREMTED\n"); } } //If cpu is running in Q2 //If the current process time on cpu > TQ2 //Move process to Q3 and set cpu to idle //If Q1 isnt empty move running process back into Q2, but dont reset its time on the cpu if (cpu->queue == 2) { printf("CPU is in Q2\n"); if (get_next_incomplete_burst(cpu->current_process) != NULL && get_next_incomplete_burst(cpu->current_process)->time_active > cpu->TQ2) { //Time ran out for the process move it to Q3 printf("TIME RAN OUT FOR PROCESS IN Q2\n"); fprintf(out_file, "Time: %-5d\tProcess#%d moved to Q3 for not being able to complete within the Time Quantum of Q2\n", cpu->time, cpu->current_process->id); Process* end_q3 = get_end(cpu->Q3); cpu->current_process->state = 2; if (end_q3 != NULL) { end_q3->next = cpu->current_process; } else { cpu->Q3->processes = cpu->current_process; cpu->Q3->isEmpty = 0; } cpu->current_process = NULL; cpu->idle = 1; cpu->queue = 0; printQueues(out_file, cpu); } else if (cpu->Q1->isEmpty == 0) { //Preempt the process since there are processes in Q1 printf("PREMETING PROCESS IN Q2 FOR ONE IN Q1\n"); fprintf(out_file, "Time: %-5d\tProcess#%d moved back into Q2 because there are processes in Q1 that need to be run\n", cpu->time, cpu->current_process->id); Process* end_q2 = get_end(cpu->Q2); cpu->current_process->state = 2; if (end_q2 != NULL) { end_q2->next = cpu->current_process; } else { cpu->Q2->processes = cpu->current_process; cpu->Q2->isEmpty = 0; } cpu->current_process = NULL; cpu->idle = 1; cpu->queue = 0; printQueues(out_file, cpu); } else { printf("NOTHING MOVED OFF CPU FROM Q2\n"); } } //If the cpu is running in Q1 //If the current process time on cpu > TQ1 //Move the process to Q2 and set cpu to idle if (cpu->queue == 1) { printf("CPU is in Q1\n"); if (get_next_incomplete_burst(cpu->current_process) != NULL && get_next_incomplete_burst(cpu->current_process)->time_active > cpu->TQ1) { //Time ran out for the process move it to Q2 printf("TIME RAN OUT FOR PROCESS IN Q1\n"); fprintf(out_file, "Time: %-5d\tProcess#%d moved to Q2 because it could not complete within the Time Quantum of Q1\n", cpu->time, cpu->current_process->id); Process* end_q2 = get_end(cpu->Q2); get_next_incomplete_burst(cpu->current_process)->time_active = 0; cpu->current_process->state = 2; if (end_q2 != NULL) { end_q2->next = cpu->current_process; } else { cpu->Q2->processes = cpu->current_process; cpu->Q2->isEmpty = 0; } cpu->current_process = NULL; cpu->idle = 1; cpu->queue = 0; printQueues(out_file, cpu); } else { printf("NOTHING REMOVED FOR TIME FROM Q1\n"); } } //If Q1 has stuff in it and the cpu is free //Put the first thing from Q1 onto the cpu if (cpu->Q1->processes != NULL && cpu->idle == 1) { printf("Q1 not empty and CPU idle\n"); Process* q1_popped = cpu->Q1->processes; fprintf(out_file, "Time: %-5d\tMoving Process#%d from Q1 onto the CPU\n", cpu->time, q1_popped->id); cpu->Q1->processes = q1_popped->next; q1_popped->next = NULL; if (cpu->Q1->processes == NULL) { cpu->Q1->isEmpty = 1; } cpu->current_process = q1_popped; cpu->queue = 1; cpu->idle = 0; q1_popped->state = 1; printQueues(out_file, cpu); }//Else If Q2 has stuff in it and the cpu is free //Put the first thing from Q2 onto the cpu else if (cpu->Q2->processes != NULL && cpu->idle == 1) { printf("Q2 not empty and CPU idle\n"); Process* q2_popped = cpu->Q2->processes; fprintf(out_file, "Time: %-5d\tMoving Process#%d from Q2 onto the CPU\n", cpu->time, q2_popped->id); cpu->Q2->processes = q2_popped->next; q2_popped->next = NULL; if (cpu->Q2->processes == NULL) { cpu->Q2->isEmpty = 1; } cpu->current_process = q2_popped; cpu->queue = 2; cpu->idle = 0; q2_popped->state = 1; printQueues(out_file, cpu); }//Else If Q3 has stuff in it and the cpu is free //Put the lowest time remaining onto the cpu else if (cpu->Q3->processes != NULL && cpu->idle == 1) { printf("Q3 not empty and CPU idle\n"); //FIX THIS //Process* shortest = get_shortest_remaining(cpu->Q3); Process* shortest = cpu->Q3->processes; cpu->Q3->processes = shortest->next; fprintf(out_file, "Time: %-5d\tMoving Process#%d from Q3 onto the CPU\n", cpu->time, shortest->id); cpu->current_process = shortest; cpu->queue = 3; cpu->idle = 0; shortest->state = 1; if (cpu->Q3->processes == NULL) { cpu->Q3->isEmpty = 1; } printQueues(out_file, cpu); } cpu->time++; printf("TIME: %d\n", cpu->time); } //Write final average data to the output file //Average waiting time //Average turnaround time int waiting_sum = 0; int total_sum = 0; Process* itr = completed->processes; while (itr != NULL) { waiting_sum += itr->waiting_cpu; total_sum += (itr->completion_t - itr->arrival_time); itr = itr->next; } fprintf(out_file, "\n\nAverage waiting time: %d\nAverage turnaround time: %d\n", waiting_sum / processCompleted, total_sum / processCompleted); fprintf(out_file, "\n\n############################################################\n"); fprintf(out_file, "Logging for Multi-Level Queue Scheduling Simulation Ended!\n"); fprintf(out_file, "############################################################\n"); fclose(out_file); } return (EXIT_SUCCESS); }
/* - creviterdissect - dissect match for iteration node, shortest-first ^ static int creviterdissect(struct vars *, struct subre *, chr *, chr *); */ static int /* regexec return code */ creviterdissect(struct vars * v, struct subre * t, chr *begin, /* beginning of relevant substring */ chr *end) /* end of same */ { struct dfa *d; chr **endpts; chr *limit; int min_matches; size_t max_matches; int nverified; int k; int i; int er; assert(t->op == '*'); assert(t->left != NULL && t->left->cnfa.nstates > 0); assert(t->left->flags & SHORTER); assert(begin <= end); /* * If zero matches are allowed, and target string is empty, just declare * victory. OTOH, if target string isn't empty, zero matches can't work * so we pretend the min is 1. */ min_matches = t->min; if (min_matches <= 0) { if (begin == end) return REG_OKAY; min_matches = 1; } /* * We need workspace to track the endpoints of each sub-match. Normally * we consider only nonzero-length sub-matches, so there can be at most * end-begin of them. However, if min is larger than that, we will also * consider zero-length sub-matches in order to find enough matches. * * For convenience, endpts[0] contains the "begin" pointer and we store * sub-match endpoints in endpts[1..max_matches]. */ max_matches = end - begin; if (max_matches > (size_t)t->max && t->max != DUPINF) max_matches = t->max; if (max_matches < (size_t)min_matches) max_matches = min_matches; endpts = (chr **) MALLOC((max_matches + 1) * sizeof(chr *)); if (endpts == NULL) return REG_ESPACE; endpts[0] = begin; d = getsubdfa(v, t->left); if (ISERR()) { FREE(endpts); return v->err; } MDEBUG(("creviter %d\n", t->id)); /* * Our strategy is to first find a set of sub-match endpoints that are * valid according to the child node's DFA, and then recursively dissect * each sub-match to confirm validity. If any validity check fails, * backtrack the last sub-match and try again. And, when we next try for * a validity check, we need not recheck any successfully verified * sub-matches that we didn't move the endpoints of. nverified remembers * how many sub-matches are currently known okay. */ /* initialize to consider first sub-match */ nverified = 0; k = 1; limit = begin; /* iterate until satisfaction or failure */ while (k > 0) { /* disallow zero-length match unless necessary to achieve min */ if (limit == endpts[k - 1] && limit != end && (k >= min_matches || min_matches - k < end - limit)) limit++; /* if this is the last allowed sub-match, it must reach to the end */ if ((size_t)k >= max_matches) limit = end; /* try to find an endpoint for the k'th sub-match */ endpts[k] = shortest(v, d, endpts[k - 1], limit, end, (chr **) NULL, (int *) NULL); if (endpts[k] == NULL) { /* no match possible, so see if we can lengthen previous one */ k--; goto backtrack; } MDEBUG(("%d: working endpoint %d: %ld\n", t->id, k, LOFF(endpts[k]))); /* k'th sub-match can no longer be considered verified */ if (nverified >= k) nverified = k - 1; if (endpts[k] != end) { /* haven't reached end yet, try another iteration if allowed */ if ((size_t)k >= max_matches) { /* must try to lengthen some previous match */ k--; goto backtrack; } k++; limit = endpts[k - 1]; continue; } /* * We've identified a way to divide the string into k sub-matches * that works so far as the child DFA can tell. If k is an allowed * number of matches, start the slow part: recurse to verify each * sub-match. We always have k <= max_matches, needn't check that. */ if (k < min_matches) goto backtrack; MDEBUG(("%d: verifying %d..%d\n", t->id, nverified + 1, k)); for (i = nverified + 1; i <= k; i++) { zaptreesubs(v, t->left); er = cdissect(v, t->left, endpts[i - 1], endpts[i]); if (er == REG_OKAY) { nverified = i; continue; } if (er == REG_NOMATCH) break; /* oops, something failed */ FREE(endpts); return er; } if (i > k) { /* satisfaction */ MDEBUG(("%d successful\n", t->id)); FREE(endpts); return REG_OKAY; } /* match failed to verify, so backtrack */ backtrack: /* * Must consider longer versions of the current sub-match. */ while (k > 0) { if (endpts[k] < end) { limit = endpts[k] + 1; /* break out of backtrack loop, continue the outer one */ break; } /* can't lengthen k'th sub-match any more, consider previous one */ k--; } } /* all possibilities exhausted */ MDEBUG(("%d failed\n", t->id)); FREE(endpts); return REG_NOMATCH; }
/* * cfindloop - the heart of cfind */ static int cfindloop(struct vars * v, struct cnfa * cnfa, struct colormap * cm, struct dfa * d, struct dfa * s, chr **coldp) /* where to put coldstart pointer */ { chr *begin; chr *end; chr *cold; chr *open; /* open and close of range of possible starts */ chr *close; chr *estart; chr *estop; int er; int shorter = v->g->tree->flags & SHORTER; int hitend; assert(d != NULL && s != NULL); cold = NULL; close = v->search_start; do { MDEBUG(("\ncsearch at %ld\n", LOFF(close))); close = shortest(v, s, close, close, v->stop, &cold, (int *) NULL); if (close == NULL) break; /* NOTE BREAK */ assert(cold != NULL); open = cold; cold = NULL; MDEBUG(("cbetween %ld and %ld\n", LOFF(open), LOFF(close))); for (begin = open; begin <= close; begin++) { MDEBUG(("\ncfind trying at %ld\n", LOFF(begin))); estart = begin; estop = v->stop; for (;;) { if (shorter) end = shortest(v, d, begin, estart, estop, (chr **) NULL, &hitend); else end = longest(v, d, begin, estop, &hitend); if (hitend && cold == NULL) cold = begin; if (end == NULL) break; /* NOTE BREAK OUT */ MDEBUG(("tentative end %ld\n", LOFF(end))); zapsubs(v->pmatch, v->nmatch); zapmem(v, v->g->tree); er = cdissect(v, v->g->tree, begin, end); if (er == REG_OKAY) { if (v->nmatch > 0) { v->pmatch[0].rm_so = OFF(begin); v->pmatch[0].rm_eo = OFF(end); } *coldp = cold; return REG_OKAY; } if (er != REG_NOMATCH) { ERR(er); *coldp = cold; return er; } if ((shorter) ? end == estop : end == begin) { /* no point in trying again */ *coldp = cold; return REG_NOMATCH; } /* go around and try again */ if (shorter) estart = end + 1; else estop = end - 1; } } } while (close < v->stop); *coldp = cold; return REG_NOMATCH; }
/* - simpleFind - find a match for the main NFA (no-complications case) ^ static int simpleFind(struct vars *, struct cnfa *, struct colormap *); */ static int simpleFind( struct vars *const v, struct cnfa *const cnfa, struct colormap *const cm) { struct dfa *s, *d; chr *begin, *end = NULL; chr *cold; chr *open, *close; /* Open and close of range of possible * starts */ int hitend; int shorter = (v->g->tree->flags&SHORTER) ? 1 : 0; /* * First, a shot with the search RE. */ s = newDFA(v, &v->g->search, cm, &v->dfa1); assert(!(ISERR() && s != NULL)); NOERR(); MDEBUG(("\nsearch at %ld\n", LOFF(v->start))); cold = NULL; close = shortest(v, s, v->start, v->start, v->stop, &cold, NULL); freeDFA(s); NOERR(); if (v->g->cflags®_EXPECT) { assert(v->details != NULL); if (cold != NULL) { v->details->rm_extend.rm_so = OFF(cold); } else { v->details->rm_extend.rm_so = OFF(v->stop); } v->details->rm_extend.rm_eo = OFF(v->stop); /* unknown */ } if (close == NULL) { /* not found */ return REG_NOMATCH; } if (v->nmatch == 0) { /* found, don't need exact location */ return REG_OKAY; } /* * Find starting point and match. */ assert(cold != NULL); open = cold; cold = NULL; MDEBUG(("between %ld and %ld\n", LOFF(open), LOFF(close))); d = newDFA(v, cnfa, cm, &v->dfa1); assert(!(ISERR() && d != NULL)); NOERR(); for (begin = open; begin <= close; begin++) { MDEBUG(("\nfind trying at %ld\n", LOFF(begin))); if (shorter) { end = shortest(v, d, begin, begin, v->stop, NULL, &hitend); } else { end = longest(v, d, begin, v->stop, &hitend); } if (ISERR()) { freeDFA(d); return v->err; } if (hitend && cold == NULL) { cold = begin; } if (end != NULL) { break; /* NOTE BREAK OUT */ } } assert(end != NULL); /* search RE succeeded so loop should */ freeDFA(d); /* * And pin down details. */ assert(v->nmatch > 0); v->pmatch[0].rm_so = OFF(begin); v->pmatch[0].rm_eo = OFF(end); if (v->g->cflags®_EXPECT) { if (cold != NULL) { v->details->rm_extend.rm_so = OFF(cold); } else { v->details->rm_extend.rm_so = OFF(v->stop); } v->details->rm_extend.rm_eo = OFF(v->stop); /* unknown */ } if (v->nmatch == 1) { /* no need for submatches */ return REG_OKAY; } /* * Find submatches. */ zapallsubs(v->pmatch, v->nmatch); return cdissect(v, v->g->tree, begin, end); }
/* * crevdissect - determine backref shortest-first subexpression matches * The retry memory stores the offset of the trial midpoint from begin, * plus 1 so that 0 uniquely means "clean slate". */ static int /* regexec return code */ crevdissect(struct vars * v, struct subre * t, chr *begin, /* beginning of relevant substring */ chr *end) /* end of same */ { struct dfa *d; struct dfa *d2; chr *mid; int er; assert(t->op == '.'); assert(t->left != NULL && t->left->cnfa.nstates > 0); assert(t->right != NULL && t->right->cnfa.nstates > 0); assert(t->left->flags & SHORTER); /* concatenation -- need to split the substring between parts */ d = newdfa(v, &t->left->cnfa, &v->g->cmap, DOMALLOC); if (ISERR()) return v->err; d2 = newdfa(v, &t->right->cnfa, &v->g->cmap, DOMALLOC); if (ISERR()) { freedfa(d); return v->err; } MDEBUG(("crev %d\n", t->retry)); /* pick a tentative midpoint */ if (v->mem[t->retry] == 0) { mid = shortest(v, d, begin, begin, end, (chr **) NULL, (int *) NULL); if (mid == NULL) { freedfa(d); freedfa(d2); return REG_NOMATCH; } MDEBUG(("tentative midpoint %ld\n", LOFF(mid))); v->mem[t->retry] = (mid - begin) + 1; } else { mid = begin + (v->mem[t->retry] - 1); MDEBUG(("working midpoint %ld\n", LOFF(mid))); } /* iterate until satisfaction or failure */ for (;;) { /* try this midpoint on for size */ er = cdissect(v, t->left, begin, mid); if (er == REG_OKAY && longest(v, d2, mid, end, (int *) NULL) == end && (er = cdissect(v, t->right, mid, end)) == REG_OKAY) break; /* NOTE BREAK OUT */ if (er != REG_OKAY && er != REG_NOMATCH) { freedfa(d); freedfa(d2); return er; } /* that midpoint didn't work, find a new one */ if (mid == end) { /* all possibilities exhausted */ MDEBUG(("%d no midpoint\n", t->retry)); freedfa(d); freedfa(d2); return REG_NOMATCH; } mid = shortest(v, d, begin, mid + 1, end, (chr **) NULL, (int *) NULL); if (mid == NULL) { /* failed to find a new one */ MDEBUG(("%d failed midpoint\n", t->retry)); freedfa(d); freedfa(d2); return REG_NOMATCH; } MDEBUG(("%d: new midpoint %ld\n", t->retry, LOFF(mid))); v->mem[t->retry] = (mid - begin) + 1; zapmem(v, t->left); zapmem(v, t->right); } /* satisfaction */ MDEBUG(("successful\n")); freedfa(d); freedfa(d2); return REG_OKAY; }
/* - complicatedFindLoop - the heart of complicatedFind ^ static int complicatedFindLoop(struct vars *, struct cnfa *, struct colormap *, ^ struct dfa *, struct dfa *, chr **); */ static int complicatedFindLoop( struct vars *const v, struct cnfa *const cnfa, struct colormap *const cm, struct dfa *const d, struct dfa *const s, chr **const coldp) /* where to put coldstart pointer */ { chr *begin, *end; chr *cold; chr *open, *close; /* Open and close of range of possible * starts */ chr *estart, *estop; int er, hitend; int shorter = v->g->tree->flags&SHORTER; assert(d != NULL && s != NULL); cold = NULL; close = v->start; do { MDEBUG(("\ncsearch at %ld\n", LOFF(close))); close = shortest(v, s, close, close, v->stop, &cold, NULL); if (close == NULL) { break; /* NOTE BREAK */ } assert(cold != NULL); open = cold; cold = NULL; MDEBUG(("cbetween %ld and %ld\n", LOFF(open), LOFF(close))); for (begin = open; begin <= close; begin++) { MDEBUG(("\ncomplicatedFind trying at %ld\n", LOFF(begin))); estart = begin; estop = v->stop; for (;;) { if (shorter) { end = shortest(v, d, begin, estart, estop, NULL, &hitend); } else { end = longest(v, d, begin, estop, &hitend); } if (hitend && cold == NULL) { cold = begin; } if (end == NULL) { break; /* NOTE BREAK OUT */ } MDEBUG(("tentative end %ld\n", LOFF(end))); zapallsubs(v->pmatch, v->nmatch); er = cdissect(v, v->g->tree, begin, end); if (er == REG_OKAY) { if (v->nmatch > 0) { v->pmatch[0].rm_so = OFF(begin); v->pmatch[0].rm_eo = OFF(end); } *coldp = cold; return REG_OKAY; } if (er != REG_NOMATCH) { ERR(er); *coldp = cold; return er; } if ((shorter) ? end == estop : end == begin) { break; } /* * Go around and try again */ if (shorter) { estart = end + 1; } else { estop = end - 1; } } } } while (close < v->stop); *coldp = cold; return REG_NOMATCH; }