/** Returns TRUE if t is losing **/
static char
is_losing(tuple* t, antichain* losing_PO, antichain* losing_PI) {
	char to_return;
	if(t->cf->player == P_O) {
		to_return = contains_element(losing_PO, t, (void*)compare_tuples_reverse);
	}
	else {
		to_return = contains_element(losing_PI, t, (void*)compare_tuples_reverse);
	}
	return to_return;
}
Example #2
0
/*
  I wanted to experiment on passing by reference in arrays...
  another aproach for this function would be to return the new
  array without the element. However, this approach has the advantage
  of having fewer memory leaks.
*/
int remove_element(int element, int **array, int length) {
  int i = 0;
  if (contains_element(element, *array, length)) {
    int removed = 0;
    int* new_array = (int*) malloc(sizeof(int) * (length - 1));
    int j = 0;
    int current_element;
    for(i = 0; i < length; i++) {
      current_element = *(*array + i);
      if (element == current_element && !removed) {
        removed = 1;
      }
      else {
        new_array[j] = current_element;
        j++;
      }
    }
    if(removed) {
      free(*array);
      *array = new_array;
      return 1;
    }
    else {
      print_array(*array, length);
      return 0;
    }
  }
  else {
    return 0;
  }
}
/** Returns TRUE if t has a successor in the safety game, FALSE otherwise
  	Note that t is supposed to be an antichain of P_O -> no test is done here **/
static char
has_successor_in_safety_game(tuple* t, alphabet_info* alphabet, antichain* safety_game_PI) {
	int i, sigma_size = alphabet->sigma_output_size;
	tuple* cur_succ;
	for(i=0; i<sigma_size; i++) {
		cur_succ = tuple_succ(t, i, alphabet);
		if(contains_element(safety_game_PI, cur_succ, (void*)compare_tuples) == TRUE) {
			free_tuple_full(cur_succ);
			return TRUE;
		}
		free_tuple_full(cur_succ);
	}
	return FALSE;
}
/** Critical input signals optimization: Computes a minimal critical set of inputs signals for antichain
    For each element f of antichain, for each symbol s_O of the output alphabet, find a critical input signal,
    i.e. a signal s_I s.t. succ(succ(f, s_O), s_I) does not belong to antichain (+ privilege already added signals to try to minimize the set)
    Stops when the critical signals for one one-step-loosing tuple is found															**/
int*
compute_critical_set(antichain *a, alphabet_info *alphabet) {
//  Note: local cache memories optimization disabled since it seems less efficient
//	GHashTable *cache_lvl1 = g_hash_table_new_full(hash_key, compare_keys, (GDestroyNotify)free_hash_table_key, NULL); //cache memory used to avoid redondant computation (for the successors of t)
//	GHashTable *cache_lvl2 = g_hash_table_new_full(hash_key, compare_keys, (GDestroyNotify)free_hash_table_key, NULL); //cache memory used to avoid redondant computation (for the successors of the successors of t)

	char found, inC, is_one_step_loosing, is_in_antichain;
	char *info_lvl1, *info_lvl2;
	char *true_value = malloc(sizeof(char));
	true_value[0] = TRUE;
	char *false_value = malloc(sizeof(char));
	false_value[0] = FALSE;

	int i, input_size = alphabet->sigma_input_size;
	tuple *t, *succ_t, *succ_succ_t;
	antichain *min_succ;

	int* c = (int*)malloc((input_size+1)*sizeof(int)); //array of critical signals index in the input alphabet
	char* c_bool = (char*)malloc((input_size)*sizeof(char)); //array of booleans representing the critical set on a boolean format
	int* curC = (int*)malloc((input_size+1)*sizeof(int)); //array of signals found to be critical till here and for t (will be added to c only if t is one step loosing)
	char* curC_bool = (char*)malloc((input_size)*sizeof(char)); //c_bool but on a boolean format

	// Initialize c and c_bool
	c[0] = 0;
	for(i=0; i<input_size; i++) {
		c[i+1] = -1;
		c_bool[i] = FALSE;
	}

	GList *succ_t_link, *cur_link = a->incomparable_elements;
	while(cur_link != NULL) { //for each element t of the antichain
		t = cur_link->data;

		//Copy c and c_bool in curC and curC_bool
		curC[0] = c[0];
		for(i=0; i<input_size; i++) {
			curC[i+1] = c[i+1];
			curC_bool[i] = c_bool[i];
		}

		is_one_step_loosing = TRUE;
		min_succ = (antichain*)get_from_cache(cache_min_succ, t, -1);
		if(min_succ == NULL) { //cache miss
			min_succ = minimal_tuple_succ(t, alphabet); //compute the antichain of minimal successors of t (no need of analyzing non minimal successors)
			add_to_cache(cache_min_succ, clone_tuple(t), -1, (void*)min_succ); //add the computed antichain to cache
		}
		succ_t_link = min_succ->incomparable_elements;
		while(succ_t_link != NULL) { //for all succ of t s.t. succ is minimal
			found = FALSE; //will be set to TRUE if a critical s_I is found for t
			inC = FALSE; //will be set to True if the critical signal s_I found has already been for another t or min_succ
			succ_t = clone_tuple(succ_t_link->data);

			//Seek on cache if succ_t has already been processed, i.e. if we have already checked if there exists a s_I s.t. succ(succ_t, s_I) does not belong to the antichain
			//info_lvl1 = get_from_cache(cache_lvl1, succ_t, -1); //attempt to retrieve data from cache_lvl1
			//if(info_lvl1 == NULL) { //cache miss
				for(i=1; i<=curC[0]; i++) { //for s_I in c (privilege already added signals)
					succ_succ_t = (tuple*)get_from_cache(cache_succ, succ_t, curC[i]);
					if(succ_succ_t == NULL) { // cache miss
						succ_succ_t = tuple_succ(succ_t, curC[i], alphabet);
						add_to_cache(cache_succ, clone_tuple(succ_t), curC[i], (void*)succ_succ_t); //add the computed succ to cache
					}

					//Seek on cache if succ_succ_t has already been processed
					//info_lvl2 = get_from_cache(cache_lvl2, succ_succ_t, -1); //attempt to retrieve data from cache_lvl2
					//if(info_lvl2 == NULL) { //cache miss
						is_in_antichain = contains_element(a, succ_succ_t, (void*)compare_tuples);
						/*if(is_in_antichain == TRUE) {
							add_to_cache(cache_lvl2, clone_tuple(succ_succ_t), -1, true_value); //add the computed result to cache_lvl2
						}
						else {
							add_to_cache(cache_lvl2, clone_tuple(succ_succ_t), -1, false_value); //add the computed result to cache_lvl2
						}
					}
					else {
						//free_tuple_full(succ_succ_t);
						is_in_antichain = info_lvl2[0];
					}*/

					if(is_in_antichain == FALSE) {
						inC = TRUE;
						break;
					}
				}

				if(inC == FALSE) { //if not found yet
					for(i=0; i<input_size; i++) { //for s_I in input alphabet
						if(curC_bool[i] == FALSE) { //if s_I does not belong to curC (otherwise it has already been tested)
							succ_succ_t = (tuple*)get_from_cache(cache_succ, succ_t, i);
							if(succ_succ_t == NULL) { // cache miss
								succ_succ_t = tuple_succ(succ_t, i, alphabet);
								add_to_cache(cache_succ, clone_tuple(succ_t), i, (void*)succ_succ_t); //add the computed succ to cache
							}

							//Seek on cache if succ_succ_t has already been processed
							//info_lvl2 = get_from_cache(cache_lvl2, succ_succ_t, -1); //attempt to retrieve data from cache_lvl2
							//if(info_lvl2 == NULL) { //cache miss
								is_in_antichain = contains_element(a, succ_succ_t, (void*)compare_tuples);
								/*if(is_in_antichain == TRUE) {
									add_to_cache(cache_lvl2, clone_tuple(succ_succ_t), -1, true_value); //add the computed result to cache_lvl2
								}
								else {
									add_to_cache(cache_lvl2, clone_tuple(succ_succ_t), -1, false_value); //add the computed result to cache_lvl2
								}
							}
							else {
								//free_tuple_full(succ_succ_t);
								is_in_antichain = info_lvl2[0];
							}*/

							if(is_in_antichain == FALSE) {
								found = TRUE; //there exists a s_I s.t. succ(succ(f, s_O), s_I) does not belong to antichain
								curC[0] = curC[0]+1; //increment the number of critical signals
								curC[curC[0]] = i; //add s_I to curC
								curC_bool[i] = TRUE; //set the boolean of s_I to True
								break;
							}
						}
					}
				}

				if(found == FALSE && inC == FALSE) { //there exists a s_O s.t. for all s_I succ(succ(t, s_O), s,I) belongs to antichain -> t is not one step loosing
					is_one_step_loosing = FALSE;
				}
				/*if(is_one_step_loosing == TRUE) {
					add_to_cache(cache_lvl1, clone_tuple(succ_t), -1, true_value); //add the computed result to cache_lvl1
				}
				else {
					add_to_cache(cache_lvl1, clone_tuple(succ_t), -1, false_value); //add the computed result to cache_lvl1
				}
			}
			else { //cache hit
				free_tuple_full(succ_t);
				is_one_step_loosing = info_lvl1[0];
			}*/

			if(is_one_step_loosing == FALSE) {
				break; //not one step loosing -> skip to the next t
			}

			succ_t_link = succ_t_link->next;
		}

		//free_antichain_full(min_succ, (void*)free_tuple_full); // Not freed here because min_succ is added in cache (will be freed at the end on the fix point computation)

		// If f is one step loosing, add signals in curC to c
		if(is_one_step_loosing == TRUE) {
			c[0] = curC[0];
			for(i=0; i<input_size; i++) {
				c[i+1] = curC[i+1];
				c_bool[i] = curC_bool[i];
			}
			break; //break here because we found critical signals for one one-step-loosing tuple (enough)
		}

		cur_link = cur_link->next;
	}
	free(c_bool);
	free(curC);
	free(curC_bool);
	free(true_value);
	free(false_value);

//	g_hash_table_destroy(cache_lvl1);
//	g_hash_table_destroy(cache_lvl2);

	return c;
}
/** Adds to waiting list edges from t to each minimal (resp. maximal) successor of t, where t belongs to P_O (resp. P_I)
 	If t belongs to P_O: computes the minimal successors of t, sorts them and adds them to succ_to_visit[t]. The first successor passed in this list is then added to waiting and remove from succ_to_visit[t]
 	If t belongs to P_I: computes the maximal successors of t, sorts them and adds them to waiting (some of them might then be skipped if enough information is known) **/
static GList*
add_to_waiting(tuple *t, alphabet_info* alphabet, antichain* safety_game_PO, antichain* safety_game_PI, antichain* losing_PO, antichain* losing_PI, GList *waiting, GHashTable *succ_to_visit, GHashTable *passed) {
	char player = t->cf->player;
	int sigma_size;
	if(player == P_O) {
		sigma_size = alphabet->sigma_output_size;
	}
	else {
		sigma_size = alphabet->sigma_input_size;
	}

	// Compute the successors
	int i;
	GList *succ_list = NULL;
	safety_game_edge *cur_edge;
	for(i=0; i<sigma_size; i++) {
		cur_edge = (safety_game_edge*)malloc(sizeof(safety_game_edge));
		cur_edge->from = t;
		cur_edge->to = tuple_succ(t, i, alphabet);
		cur_edge->label_index = i;

		if(player == P_O) {
			if(contains_element(safety_game_PI, cur_edge->to, (void*)compare_tuples) == TRUE) { // succ safe?
				if(is_losing(cur_edge->to, losing_PO, losing_PI) == FALSE) { // succ non losing?
					succ_list = scan_add_or_remove_and_free(succ_list, cur_edge, (void*)compare_safety_game_edges_reverse, (void*)free_safety_game_edge);
				}
				else {
					free_safety_game_edge(cur_edge);
				}
			}
			else {
				free_safety_game_edge(cur_edge);
			}
		}
		else {
			succ_list = scan_add_or_remove_and_free(succ_list, cur_edge, (void*)compare_safety_game_edges, (void*)free_safety_game_edge);
		}
	}

	GList *sorted_succ_list = NULL;
	GList *curlink = succ_list;
	if(player == P_O) { //t belongs to P_O -> sort the successors and add them to succ_to_visit
		while(curlink != NULL) {
			//sorted_succ_list = g_list_prepend(sorted_succ_list, curlink->data);
			sorted_succ_list = insert_sorted(sorted_succ_list, curlink->data, (void*)compare_safety_game_edges_counters_sum_reverse); // the smallest elements will be placed at the beginning of the linked list
			curlink = curlink->next;
		}

		hash_table_key* key = (hash_table_key*)malloc(sizeof(hash_table_key));
		key->t = t;
		key->sigma_index = -1;
		g_hash_table_insert(succ_to_visit, (gconstpointer*)key, (gconstpointer*)sorted_succ_list);

		// Add the first successor passed to waiting
		waiting = g_list_append(waiting, get_first_successor_passed_non_losing(t, succ_to_visit, passed, losing_PO, losing_PI));

	}
	else { //t belongs to P_I -> sort the successors and add them to waiting
		while(curlink != NULL) {
			//sorted_succ_list = g_list_prepend(sorted_succ_list, curlink->data);
			sorted_succ_list = insert_sorted(sorted_succ_list, curlink->data, (void*)compare_safety_game_edges_counters_sum_reverse); // the largest elements will be placed at the end of the linked list -> popped first
			curlink = curlink->next;
		}

		// Add the successors to waiting
		waiting = g_list_concat(waiting, sorted_succ_list);
	}
	g_list_free(succ_list);
	return waiting;
}
Example #6
0
static void test_select_pivot_short_array(){
  int array[2] = {6,5};
  int pivot = select_pivot(array, 2);
  assert(contains_element(pivot, array, 2));
}
Example #7
0
static void test_select_pivot_long_array(){
  int array[10] = {6,5,1,9,4,7,5,12,8,4};
  int pivot = select_pivot(array, 10);
  assert(contains_element(pivot, array, 10));
}
Example #8
0
TEST fuzzy_hash_test_iterator(long size, long btree_node_size, int _commit)
{
	INIT();

	rl_btree_iterator *iterator = NULL;
	long *elements = malloc(sizeof(long) * size);
	long *nonelements = malloc(sizeof(long) * size);
	long *values = malloc(sizeof(long) * size);

	long btree_page = db->next_empty_page;
	RL_CALL_VERBOSE(rl_write, RL_OK, db, btree->type->btree_type, btree_page, btree);

	long i, element, value, *element_copy, *value_copy;

	long j;

	void *tmp;
	long prev_score = -1.0, score;

	for (i = 0; i < size; i++) {
		element = rand();
		value = rand();
		if (contains_element(element, elements, i)) {
			i--;
			continue;
		}
		else {
			elements[i] = element;
			element_copy = malloc(sizeof(long));
			*element_copy = element;
			values[i] = value;
			value_copy = malloc(sizeof(long));
			*value_copy = value;
			RL_CALL_VERBOSE(rl_btree_add_element, RL_OK, db, btree, btree_page, element_copy, value_copy);
			RL_CALL_VERBOSE(rl_btree_is_balanced, RL_OK, db, btree);
		}

		RL_CALL_VERBOSE(rl_btree_iterator_create, RL_OK, db, btree, &iterator);
		EXPECT_LONG(iterator->size, i + 1);

		j = 0;
		while (RL_OK == (retval = rl_btree_iterator_next(iterator, &tmp, NULL))) {
			score = *(long *)tmp;
			rl_free(tmp);
			if (j++ > 0) {
				if (prev_score >= score) {
					fprintf(stderr, "Tree is in a bad state in element %ld after adding child %ld\n", j, i);
					retval = RL_UNEXPECTED;
					goto cleanup;
				}
			}
			prev_score = score;
		}

		if (retval != RL_END) {
			rl_free(tmp);
			goto cleanup;
		}

		EXPECT_LONG(j, i + 1);
		iterator = NULL;

		if (_commit) {
			RL_CALL_VERBOSE(rl_commit, RL_OK, db);
			RL_CALL_VERBOSE(rl_read, RL_FOUND, db, &rl_data_type_btree_hash_long_long, btree_page, &rl_btree_type_hash_long_long, &tmp, 1);
			btree = tmp;
		}
	}


	rl_btree_iterator_destroy(iterator);
	retval = 0;
cleanup:
	free(values);
	free(elements);
	free(nonelements);
	rl_close(db);
	if (retval == 0) { PASS(); } else { FAIL(); }
}
Example #9
0
TEST fuzzy_hash_test(long size, long btree_node_size, int _commit)
{
	INIT();

	long *elements = malloc(sizeof(long) * size);
	long *nonelements = malloc(sizeof(long) * size);
	long *values = malloc(sizeof(long) * size);
	void **flatten_scores = malloc(sizeof(void *) * size);

	long btree_page = db->next_empty_page;
	RL_CALL_VERBOSE(rl_write, RL_OK, db, btree->type->btree_type, btree_page, btree);

	long i, element, value, *element_copy, *value_copy;

	long j, flatten_size;

	void *val, *tmp;

	for (i = 0; i < size; i++) {
		element = rand();
		value = rand();
		if (contains_element(element, elements, i)) {
			i--;
			continue;
		}
		else {
			RL_CALL_VERBOSE(rl_read, RL_FOUND, db, &rl_data_type_btree_hash_long_long, btree_page, &rl_btree_type_hash_long_long, &tmp, 1);
			elements[i] = element;
			element_copy = malloc(sizeof(long));
			*element_copy = element;
			values[i] = value;
			value_copy = malloc(sizeof(long));
			*value_copy = value;
			RL_CALL_VERBOSE(rl_btree_add_element, RL_OK, db, btree, btree_page, element_copy, value_copy);
			RL_CALL_VERBOSE(rl_btree_is_balanced, RL_OK, db, btree);
		}
		flatten_size = 0;
		RL_CALL_VERBOSE(rl_flatten_btree, RL_OK, db, btree, &flatten_scores, &flatten_size);
		for (j = 1; j < flatten_size; j++) {
			if (*(long *)flatten_scores[j - 1] >= *(long *)flatten_scores[j]) {
				fprintf(stderr, "Tree is in a bad state in element %ld after adding child %ld\n", j, i);
				retval = RL_UNEXPECTED;
				goto cleanup;
			}
		}
		if (_commit) {
			RL_CALL_VERBOSE(rl_commit, RL_OK, db);
			RL_CALL_VERBOSE(rl_read, RL_FOUND, db, &rl_data_type_btree_hash_long_long, btree_page, &rl_btree_type_hash_long_long, &tmp, 1);
			btree = tmp;
		}
	}

	for (i = 0; i < size; i++) {
		element = rand();
		if (contains_element(element, elements, size) || contains_element(element, nonelements, i)) {
			i--;
		}
		else {
			nonelements[i] = element;
		}
	}

	for (i = 0; i < size; i++) {
		RL_CALL_VERBOSE(rl_btree_find_score, RL_FOUND, db, btree, &elements[i], &val, NULL, NULL);
		EXPECT_LONG(*(long *)val, values[i]);
		RL_CALL_VERBOSE(rl_btree_find_score, RL_NOT_FOUND, db, btree, &nonelements[i], NULL, NULL, NULL);
	}

	retval = 0;
cleanup:
	free(values);
	free(elements);
	free(nonelements);
	free(flatten_scores);
	rl_close(db);
	if (retval == 0) { PASS(); } else { FAIL(); }
}