autoActivation FFNet_Categories_to_Activation (FFNet me, Categories thee) {
	try {
		autoCategories uniq = Categories_selectUniqueItems (thee);

		if (! my outputCategories) {
			Melder_throw (U"The FFNet does not have categories.");
		}
		long nl = OrderedOfString_isSubsetOf (uniq.get(), my outputCategories.get(), 0);
		if (nl == 0) {
			Melder_throw (U"The Categories do not match the categories of the FFNet.");
		}

		autoActivation him = Activation_create (thy size, my nOutputs);
		for (long i = 1; i <= thy size; i ++) {
			const char32 *citem = OrderedOfString_itemAtIndex_c (thee, i);
			long pos = OrderedOfString_indexOfItem_c (my outputCategories.get(), citem);
			if (pos < 1) {
				Melder_throw (U"The FFNet doesn't know the category ", citem, U".");
			}
			his z [i] [pos] = 1.0;
		}
		return him;
	} catch (MelderError) {
		Melder_throw (me, U": no Activation created.");
	}
}
OrderedOfString OrderedOfString_selectUniqueItems (I, int sort) {
	iam (OrderedOfString);
	try {
		if (! sort) {
			autoOrderedOfString him = OrderedOfString_create ();
			for (long i = 1; i <= my size; i++) {
				SimpleString ss = (SimpleString) my item[i];
				if (! OrderedOfString_indexOfItem_c (him.peek(), ss -> string)) {
					autoSimpleString item = Data_copy (ss);
					Collection_addItem (him.peek(), item.transfer());
				}
			}
			Collection_shrinkToFit (him.peek());
			return him.transfer();
		}
		autoSortedSetOfString thee = SortedSetOfString_create ();
		/* Collection_to_SortedSet (I, int (*compare)(I, thou)) */
		for (long i = 1; i <= my size; i++) {
			if (! thy hasItem (my item[i])) {
				autoSimpleString item = Data_copy ( (SimpleString) my item[i]);
				Collection_addItem (thee.peek(), item.transfer());
			}
		}
		autoOrderedOfString him = OrderedOfString_create ();
		for (long i = 1; i <= thy size; i++) {
			autoSimpleString item = Data_copy ( (SimpleString) thy item[i]);
			Collection_addItem (him.peek(), item.transfer());
		}
		return him.transfer();
	} catch (MelderError) {
		Melder_throw (me, ": unique items not selected.");
	}
}
Activation FFNet_Categories_to_Activation (FFNet me, Categories thee)
{
	Activation him = NULL; 
	Categories uniq;
	long i, nl, cSize = thy size, hasCategories = 1;
	
	uniq = Categories_selectUniqueItems (thee, 1);
	if (uniq == NULL)  Melder_error1 (L"There is not enough memory to create a Categories."); 
	
	if (my outputCategories == NULL)
	{
		if (my nUnitsInLayer[my nLayers] == uniq -> size)
		{
			my outputCategories = uniq;
			hasCategories = 0;
		}
		else
		{
			(void) Melder_error1 (L"");
			goto end;
		}
	}
	else if (! ( (nl = OrderedOfString_isSubsetOf (uniq, my outputCategories, NULL)) &&
		nl == uniq -> size && my nOutputs >= uniq -> size))
	{
		 (void) Melder_error1 (L"The Categories do not match the categories of the FFNet.");
		goto end;
	}
	
	him = Activation_create (cSize, my nOutputs);
	if (him == NULL) goto end;
	for (i=1; i <= cSize; i++)
	{
		long pos =  OrderedOfString_indexOfItem_c (my outputCategories, OrderedOfString_itemAtIndex_c (thee, i));
		if (pos < 1)
		{
			 (void) Melder_error3 (L"The FFNet doesn't know the category ", OrderedOfString_itemAtIndex_c (thee, i), L" from Categories.");
				goto end;
		}
		his z[i][pos] = 1.0;
	}
	
end:

	if (hasCategories) forget (uniq);
	if (Melder_hasError ()) forget (him);
	
	return him;
}