FunctionArguments<ArgType> simplex(
		const std::vector<Constraint<ArgType>>& constraints,
		const ObjectiveFunction<ArgType, RetType, CoeffType>& function)
{
	if(constraints.size() == 0)
		throw "No constraints";
	if(constraints[0].size() != function.size())
		throw "Size of constraints not equal to function size";
	Matrix<CoeffType> simplexTab(constraints.size() + 1,
			function.size() + constraints.size() + 2);
	unsigned long cols = simplexTab.getColumnsNumber(), rows =
			simplexTab.getRowsNumber(), constrNum = constraints.size(), argsNum =
			function.size();
	generateSimplexTab(constraints, function, simplexTab);
	std::map<unsigned long,unsigned long> slackSwaped;
	while (simplexTab.countIfInRange(rows - 1, 0, rows - 1, cols - 1,
			[](const CoeffType& x)
			{	return x<0;}))
	{
		unsigned long pivotColumn, row;
		simplexTab.findMinimumInRange(rows - 1, 0, rows - 1, cols - 3, row,
				pivotColumn);
		row = findMinInColumnBDiv(simplexTab, pivotColumn);
		slackSwaped[row]=pivotColumn;
		simplexTab.multiplyRow(1/simplexTab(row,pivotColumn),row);
		for(unsigned long j=0;j<rows;j++)
			if(j!=row)
				simplexTab.addRow(-simplexTab(j,pivotColumn),row,j);
	}
	std::cout<<simplexTab;
	FunctionArguments<ArgType> bestSolution;
	bestSolution.size(argsNum);
	for(unsigned long j=0;j<constrNum;j++)
		bestSolution.setArg(slackSwaped[j],simplexTab(j,cols-1));
	return bestSolution;
}