package svm.instances.precomputed;

import svm.AbstractSVMStructInstance;
import svm.SVMStruct;
import base.SparseVector;

public class PrecomputedFeaturesInstance extends AbstractSVMStructInstance<PrecomputedFeaturesInput, PrecomputedFeaturesOutput>
{

//	private void quadratic(SparseVector ret)
//	{
//		SparseVector x = new SparseVector(ret);
//		for(Entry<String,Double> e : x.entrySet())
//		{
//			for(Entry<String,Double> f : x.entrySet())
//			{
//				if(e.getKey().compareTo(f.getKey())>=0)
//					ret.put(e.getKey()+"x"+f.getKey(),e.getValue()*f.getValue());
//			}
//		}
//	}
	@Override
	public SparseVector phi(PrecomputedFeaturesInput x, PrecomputedFeaturesOutput y)
	{
		return x.get(y.selected);
//		SparseVector ret = new SparseVector(x.get(y.selected));
//		quadratic(ret);
//		ret.put("oldCriteria3",ret.get("littleTravelTime3")*ret.get("littleWrongTurns3"));
//		ret.put("oldCriteria2",ret.get("littleTravelTime2")*ret.get("littleWrongTurns2"));
//		ret.put("oldCriteria1",ret.get("littleTravelTime1")*ret.get("littleWrongTurns1"));
//		for(int i=1;i<10;i++)
//			for(int j=1;j<10;j++)
//				ret.put("cross"+i+""+j, ret.get("littleTravelTime"+i)*ret.get("littleWrongTurns"+j));
////		System.out.println(ret.size());

//////		System.out.println(ret.size()+" "+ret.keySet());
//		return ret;
	}

	@Override
	public PrecomputedFeaturesOutput predict(PrecomputedFeaturesInput x, SVMStruct svm)
	{
		double max = Double.NEGATIVE_INFINITY;
		int maxi = -1;
		for(int i=0;i<x.size();i++)
		{
			SparseVector s = x.get(i);
			double score = s.multiply(svm.w, svm.wMap);
			if(score>max)
			{
				max = score;
				maxi = i;
			}
		}
		if(max!=-1)
		{
			PrecomputedFeaturesOutput ypred = new PrecomputedFeaturesOutput(x,maxi);
			return ypred;
		}
		return null;
	}

	@Override
	public PrecomputedFeaturesOutput marginRescaling(PrecomputedFeaturesInput x, PrecomputedFeaturesOutput y, SVMStruct svm)
	{
		double max = Double.NEGATIVE_INFINITY;
		int maxi = -1;
		
		for(int i=0;i<x.size();i++)
		{
			
			SparseVector s = x.get(i);
			double score = x.loss.get(i) + s.multiply(svm.w, svm.wMap);
			if(score>max)
			{
				max = score;
				maxi = i;
			}
		}
		if(max!=-1)
		{
			PrecomputedFeaturesOutput ypred = new PrecomputedFeaturesOutput(x,maxi);
			return ypred;
		}
		return null;
	}

	@Override
	public PrecomputedFeaturesOutput slackRescaling(PrecomputedFeaturesInput x, PrecomputedFeaturesOutput y, SVMStruct svm)
	{
		double max = Double.NEGATIVE_INFINITY;
		int maxi = -1;
		for(int i=0;i<x.size();i++)
		{
			SparseVector s = new SparseVector(x.get(i));
			s.subtract(x.get(y.selected));
			double score = x.loss.get(i) * (1 + s.multiply(svm.w, svm.wMap));
			if(score>max)
			{
				max = score;
				maxi = i;
			}
		}
		if(max!=-1)
		{
			PrecomputedFeaturesOutput ypred = new PrecomputedFeaturesOutput(x,maxi);
			return ypred;
		}
		return null;
	}

	@Override
	public double loss(PrecomputedFeaturesOutput y, PrecomputedFeaturesOutput predY)
	{
		return predY.input.loss.get(predY.selected).doubleValue();
	}

}
