package com.yahoo.labs.samoa.learners.classifiers.trees; /* * #%L * SAMOA * %% * Copyright (C) 2013 Yahoo! Inc. * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ import com.esotericsoftware.kryo.Kryo; import com.esotericsoftware.kryo.Serializer; import com.esotericsoftware.kryo.io.Input; import com.esotericsoftware.kryo.io.Output; import com.yahoo.labs.samoa.core.ContentEvent; /** * Attribute Content Event represents the instances that split vertically * based on their attribute * @author Arinto Murdopo * */ public final class AttributeContentEvent implements ContentEvent { private static final long serialVersionUID = 6652815649846676832L; private final long learningNodeId; private final int obsIndex; private final double attrVal; private final int classVal; private final double weight; private final transient String key; private final boolean isNominal; public AttributeContentEvent(){ learningNodeId = -1; obsIndex = -1; attrVal = 0.0; classVal = -1; weight = 0.0; key = ""; isNominal = true; } private AttributeContentEvent(Builder builder){ this.learningNodeId = builder.learningNodeId; this.obsIndex = builder.obsIndex; this.attrVal = builder.attrVal; this.classVal = builder.classVal; this.weight = builder.weight; this.isNominal = builder.isNominal; this.key = builder.key; } @Override public String getKey() { return this.key; } @Override public void setKey(String str) { //do nothing, maybe useful when we want to reuse the object for serialization/deserialization purpose } @Override public boolean isLastEvent() { return false; } long getLearningNodeId(){ return this.learningNodeId; } int getObsIndex(){ return this.obsIndex; } int getClassVal(){ return this.classVal; } double getAttrVal(){ return this.attrVal; } double getWeight(){ return this.weight; } boolean isNominal(){ return this.isNominal; } static final class Builder{ //required parameters private final long learningNodeId; private final int obsIndex; private final String key; //optional parameters private double attrVal = 0.0; private int classVal = 0; private double weight = 0.0; private boolean isNominal = false; Builder(long id, int obsIndex, String key){ this.learningNodeId = id; this.obsIndex = obsIndex; this.key = key; } private Builder(long id, int obsIndex){ this.learningNodeId = id; this.obsIndex = obsIndex; this.key = ""; } Builder attrValue(double val){ this.attrVal = val; return this; } Builder classValue(int val){ this.classVal = val; return this; } Builder weight(double val){ this.weight = val; return this; } Builder isNominal(boolean val){ this.isNominal = val; return this; } AttributeContentEvent build(){ return new AttributeContentEvent(this); } } /** * The Kryo serializer class for AttributeContentEvent when executing on top of Storm. * This class allow us to change the precision of the statistics. * @author Arinto Murdopo * */ public static final class AttributeCESerializer extends Serializer<AttributeContentEvent>{ private static double PRECISION = 1000000.0; @Override public void write(Kryo kryo, Output output, AttributeContentEvent event) { output.writeLong(event.learningNodeId, true); output.writeInt(event.obsIndex, true); output.writeDouble(event.attrVal, PRECISION, true); output.writeInt(event.classVal, true); output.writeDouble(event.weight, PRECISION, true); output.writeBoolean(event.isNominal); } @Override public AttributeContentEvent read(Kryo kryo, Input input, Class<AttributeContentEvent> type) { AttributeContentEvent ace = new AttributeContentEvent.Builder(input.readLong(true), input.readInt(true)) .attrValue(input.readDouble(PRECISION, true)) .classValue(input.readInt(true)) .weight(input.readDouble(PRECISION, true)) .isNominal(input.readBoolean()) .build(); return ace; } } /** * The Kryo serializer class for AttributeContentEvent when executing on top of Storm * with full precision of the statistics. * @author Arinto Murdopo * */ public static final class AttributeCEFullPrecSerializer extends Serializer<AttributeContentEvent>{ @Override public void write(Kryo kryo, Output output, AttributeContentEvent event) { output.writeLong(event.learningNodeId, true); output.writeInt(event.obsIndex, true); output.writeDouble(event.attrVal); output.writeInt(event.classVal, true); output.writeDouble(event.weight); output.writeBoolean(event.isNominal); } @Override public AttributeContentEvent read(Kryo kryo, Input input, Class<AttributeContentEvent> type) { AttributeContentEvent ace = new AttributeContentEvent.Builder(input.readLong(true), input.readInt(true)) .attrValue(input.readDouble()) .classValue(input.readInt(true)) .weight(input.readDouble()) .isNominal(input.readBoolean()) .build(); return ace; } } }