Пример #1
0
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
}
Пример #2
0
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;
}
Пример #3
0
int main(int argc, char const *argv[])
{
	
	int visited[] = {-1,-1,-1,-1,-1};

	printf("%ld\n", shortest(visited, 5, 0, 0));

	return 0;
}
Пример #4
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; 
}
Пример #5
0
/*
 * 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;
}
Пример #6
0
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);    
	} 
}
Пример #7
0
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;
}
Пример #9
0
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;
    }
}
Пример #11
0
Файл: regexec.c Проект: dgsb/tcl
/*
 - 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);
    }
}
Пример #12
0
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;

}
Пример #13
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);
    }
}
Пример #14
0
/*
 * 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);
}
Пример #15
0
/*
 * 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);
}
Пример #16
0
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;
}
Пример #17
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;
}
Пример #18
0
/*
 * 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);
}
Пример #19
0
/*
 - 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;
}
Пример #20
0
/*
 * 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;
}
Пример #21
0
/*
 - 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&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, 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&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;
    }

    /*
     * Find submatches.
     */

    zapallsubs(v->pmatch, v->nmatch);
    return cdissect(v, v->g->tree, begin, end);
}
Пример #22
0
/*
 * 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;
}
Пример #23
0
/*
 - 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;
}