########################################
# The contents of this file are subject to the MLX PUBLIC LICENSE version
# 1.0 (the "License"); you may not use this file except in
# compliance with the License.
# 
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
# the License for the specific language governing rights and limitations
# under the License.
# 
# The Original Source Code is "compClust", released 2003 September 03.
# 
# The Original Source Code was developed by the California Institute of
# Technology (Caltech).  Portions created by Caltech are Copyright (C)
# 2002-2003 California Institute of Technology. All Rights Reserved.
########################################
#
#       Author:  Lucas Scharenbroich
#
# Last Modified: Aug  1, 2001 
#

"""
Usage: Monkey.py parameter_filename input_filename output_filename

 Wrapper which performs the Monkey algorithm

 Brief Algorithm Description:

         How well can a monkey cluster data?  Assuming this is not a very
         well-trained monkey, probably no better than random.  Based on this
         assumption, the dataset is randomly partitioned into k classes and
         the labeling is returned.  There is no model for the monkey.

 Required Parameters:  (note: the list enclosed in the brakets are possible
                              values each one of parameters can take )

        k                = <x>

                           Number of bins for the monkey to throw data
                           points into

 Optional Parameters:

         seed            = <x> (optional)

                           Where x is the number used to seed the random
                           number generator.  This parameter allows runs
                           of the algorithm to be deterministic.  If the
                           parameter is omitted, it will be initialized
                           42
"""

import os
import re
import sys
import string
import random

from compClust.util   import Verify
from compClust.util.TimeStampedPrintStream import TimeStampedPrintStream

from compClust.mlx.labelings import Labeling
from compClust.mlx import ML_Algorithm
from compClust.mlx.interfaces import IModel

import compClust.mlx.wrapper  

MESSAGE_STREAM = TimeStampedPrintStream("%Y-%b-%d %H:%m: Monkey: ")

class MonkeyModel(IModel):

  def __init__(self):
    pass

  def evaluateFitness(self, dataset):
    return random.random()

#
# The Monkey clustering algorithm, randomly assign data to clusters
#

class Monkey(ML_Algorithm.ML_Algorithm):
  def __init__(self, dataset = None, parameters = None):

    self.setMessageStream( MESSAGE_STREAM )

    self.dataset    = dataset
    self.parameters = parameters
    self.labeling   = None
    self.model      = None

  def copy(self):
    new_obj = Monkey(self.dataset, self.parameters)
    new_obj.labeling = self.labeling
    new_obj.model    = self.model
    return new_obj

  def getLabeling(self):
    return self.labeling

  def getModel(self):
    if self.model is None:
      self.model = MonkeyModel()
      
    return self.model

  def run(self):
    """run()

    partitions the data randomly
    """

    #
    # Let the monkey loose

    clustering = []    
    numClusts  = self.parameters["k"]
    elements   = self.dataset.getNumRows()

    #
    # Explicitly check for a seed, if one does not exist provide a default
    # value
    #
    
    if not self.parameters.has_key( "seed" ):
      self.parameters[ "seed" ] = 42

    for i in range(elements):
      clustering.append(`random.randrange(numClusts) + 1`)
      
    #
    # build a labeling and no model
    #
    
    self.labeling = Labeling(self.dataset)
    self.labeling.labelRows(clustering)
    
    return compClust.mlx.wrapper.WRAPPER_STATUS_DONE

  def validate(self):
    """validate()

    Ensures that all parameters and environment variables nescessary
    to run the clustering algorithm (Monkey) are defined.
    """

    parameter_names   = [ "k" ]

    val = 1
    
    if Verify.parameters_exist( parameter_names, self.parameters ):
      val = 0
 
    return val
  
#
# stub for launcher
#

if (__name__ == "__main__"):
  from compClust.mlx.wrapper import Launcher

  Launcher.main(sys.argv, Monkey())

