<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2011 <NAME>
 * Copyright (C) 2011 Berlin Institute of Technology and Max-Planck-Society
 */

#include "modelselection/ModelSelectionParameters.h"
#include "lib/DataType.h"
#include "base/DynArray.h"
#include "base/Parameter.h"

using namespace shogun;

CModelSelectionParameters::CModelSelectionParameters()
{
	m_node_name=NULL;
	m_sgobject=NULL;
}

CModelSelectionParameters::CModelSelectionParameters(const char* node_name) :
	m_node_name(node_name)
{
	m_sgobject=NULL;
}

CModelSelectionParameters::CModelSelectionParameters(const char* node_name,
		CSGObject* sgobject) :
	m_sgobject(sgobject), m_node_name(node_name)
{
	SG_REF(sgobject);
}

CModelSelectionParameters::~CModelSelectionParameters()
{
	delete[] m_values.vector;
	SG_UNREF(m_sgobject);
}

void CModelSelectionParameters::destroy()
{
	for (index_t i=0; i<m_child_nodes.get_num_elements(); ++i)
		m_child_nodes[i]->destroy();

	delete this;
}

void CModelSelectionParameters::append_child(CModelSelectionParameters* child)
{
	/* only possible if there are no values set */
	if (m_values.vector)
		SG_ERROR("not possible to append child: there already is a range\n");

	/* do a basic check if the add is possible (does this node's CSGObject
	 * contain a parameter with the name of the child?) to prevent problems
	 * when trying to set parameters that do not exist */
	if (m_sgobject)
	{
		if (child->m_node_name)
		{
			if (!m_sgobject->m_parameters->contains_parameter(child->m_node_name))
			{
				SG_ERROR("Not possible to add child, node with CSGObject \"%s\""
						" does not contain a parameter called \"%s\"\n",
						m_sgobject->get_name(), child->m_node_name);
			}
		}
		else
		{
			SG_ERROR("Not possible to add child which has no name.\n");
		}
	}
	m_child_nodes.append_element(child);
}

void CModelSelectionParameters::set_range(float64_t min, float64_t max,
		ERangeType type, float64_t step, float64_t type_base)
{
	if (m_sgobject || has_children())
	{
		SG_ERROR("unable to set range for an CSGObject model selection "
				"parameter\n");
	}

	/* possibly delete old range values */
	delete[] m_values.vector;

	if (max<min)
		SG_ERROR("unable to set range: maximum=%f < minimum=%f\n", max, min);

	/* create value vector */
	index_t num_values=CMath::round(max-min)/step+1;
	m_values.length=num_values;
	m_values.vector=new float64_t[num_values];

	/* fill array */
	for (index_t i=0; i<num_values; ++i)
	{
		float64_t current=min+i*step;

		switch (type)
		{
		case R_LINEAR:
			m_values.vector[i]=current;
			break;
		case R_EXP:
			m_values.vector[i]=CMath::pow(type_base, current);
			break;
		case R_LOG:
			if (current<=0)
				SG_ERROR("log(x) with x=%f\n", current);

			/* custom base b: log_b(i*step)=log_2(i*step)/log_2(b) */
			m_values.vector[i]=CMath::log2(current)/CMath::log2(type_base);
			break;
		}
	}
}

void CModelSelectionParameters::get_combinations(
		DynArray<CParameterCombination*>& result)
{
	/* leaf case: node with values and no children.
	 * build trees of Parameter instances which each contain one value
	 */
	if (m_values.vector)
	{
		for (index_t i=0; i<m_values.length; ++i)
		{
			/* create tree with only one parameter element */
			Parameter* p=new Parameter();
			p->add(&m_values.vector[i], m_node_name);

			result.append_element(new CParameterCombination(p));
		}
	}
	/* two cases here, similar
	 * -case CSGObject:
	 * -case root node (no name, no values, but children
	 * build all permutations of the result trees of children with values and
	 * combine them iteratively children which are something different<commit_msg>added type check for range<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2011 <NAME>
 * Copyright (C) 2011 Berlin Institute of Technology and Max-Planck-Society
 */

#include "modelselection/ModelSelectionParameters.h"
#include "lib/DataType.h"
#include "base/DynArray.h"
#include "base/Parameter.h"

using namespace shogun;

CModelSelectionParameters::CModelSelectionParameters()
{
	m_node_name=NULL;
	m_sgobject=NULL;
}

CModelSelectionParameters::CModelSelectionParameters(const char* node_name) :
	m_node_name(node_name)
{
	m_sgobject=NULL;
}

CModelSelectionParameters::CModelSelectionParameters(const char* node_name,
		CSGObject* sgobject) :
	m_sgobject(sgobject), m_node_name(node_name)
{
	SG_REF(sgobject);
}

CModelSelectionParameters::~CModelSelectionParameters()
{
	delete[] m_values.vector;
	SG_UNREF(m_sgobject);
}

void CModelSelectionParameters::destroy()
{
	for (index_t i=0; i<m_child_nodes.get_num_elements(); ++i)
		m_child_nodes[i]->destroy();

	delete this;
}

void CModelSelectionParameters::append_child(CModelSelectionParameters* child)
{
	/* only possible if there are no values set */
	if (m_values.vector)
		SG_ERROR("not possible to append child: there already is a range\n");

	/* do a basic check if the add is possible (does this node's CSGObject
	 * contain a parameter with the name of the child?) to prevent problems
	 * when trying to set parameters that do not exist */
	if (m_sgobject)
	{
		if (child->m_node_name)
		{
			if (!m_sgobject->m_parameters->contains_parameter(child->m_node_name))
			{
				SG_ERROR("Not possible to add child, node with CSGObject \"%s\""
						" does not contain a parameter called \"%s\"\n",
						m_sgobject->get_name(), child->m_node_name);
			}
		}
		else
		{
			SG_ERROR("Not possible to add child which has no name.\n");
		}
	}
	m_child_nodes.append_element(child);
}

void CModelSelectionParameters::set_range(float64_t min, float64_t max,
		ERangeType type, float64_t step, float64_t type_base)
{
	if (m_sgobject || has_children())
	{
		SG_ERROR("unable to set range for an CSGObject model selection "
				"parameter\n");
	}

	/* possibly delete old range values */
	delete[] m_values.vector;

	if (max<min)
		SG_ERROR("unable to set range: maximum=%f < minimum=%f\n", max, min);

	/* create value vector */
	index_t num_values=CMath::round(max-min)/step+1;
	m_values.length=num_values;
	m_values.vector=new float64_t[num_values];

	/* fill array */
	for (index_t i=0; i<num_values; ++i)
	{
		float64_t current=min+i*step;

		switch (type)
		{
		case R_LINEAR:
			m_values.vector[i]=current;
			break;
		case R_EXP:
			m_values.vector[i]=CMath::pow(type_base, current);
			break;
		case R_LOG:
			if (current<=0)
				SG_ERROR("log(x) with x=%f\n", current);

			/* custom base b: log_b(i*step)=log_2(i*step)/log_2(b) */
			m_values.vector[i]=CMath::log2(current)/CMath::log2(type_base);
			break;
		default:
			SG_ERROR("unknown range type!\n");
		}
	}
}

void CModelSelectionParameters::get_combinations(
		DynArray<CParameterCombination*>& result)
{
	/* leaf case: node with values and no children.
	 * build trees of Parameter instances which each contain one value
	 */
	if (m_values.vector)
	{
		for (index_t i=0; i<m_values.length; ++i)
		{
			/* create tree with only one parameter element */
			Parameter* p=new Parameter();
			p->add(&m_values.vector[i], m_node_name);

			result.append_element(new CParameterCombination(p));
		}
	}
	/* two cases here, similar
	 * -case CSGObject:
	 * -case root node (no name, no values, but children
	 * build all permutations of the result trees of children with values and
	 * combine them iteratively children which are something different
{'fraction_non_alphanumeric': 0.11779901834151382, 'fraction_numerical': 0.007749935417204857, 'mean_word_length': 4.57451403887689, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4820881', 'n_tokens_mistral': 2840, 'n_tokens_neox': 2614, 'n_words': 705}