//package uk.ac.man.cs.lethe.dl.abduction.experiments
//
//import java.io.File
//import java.util
//
//import uk.ac.man.cs.lethe.internal.dl.abduction.filtering.FullAbducer
//import org.semanticweb.owlapi.apibinding.OWLManager
//import org.semanticweb.owlapi.model.parameters.Imports
//import org.semanticweb.owlapi.model.{OWLAxiom, OWLEquivalentClassesAxiom, OWLOntology}
//import uk.ac.man.cs.lethe.internal.dl.abduction.KBNegator
//import uk.ac.man.cs.lethe.internal.dl.abduction.forgetting._
//import uk.ac.man.cs.lethe.internal.dl.datatypes.{Assertion, Axiom, DLStatement, Individual, InverseRole, NominalSet, Ontology}
//import uk.ac.man.cs.lethe.internal.dl.filters.OWLOntologyFilters
//import uk.ac.man.cs.lethe.internal.dl.forgetting.direct.ALCFormulaPreparations
//import uk.ac.man.cs.lethe.internal.dl.owlapi.{ModuleExtractor, OWLApiConverter}
//import uk.ac.man.cs.lethe.internal.tools.formatting.SimpleDLFormatter
//
//import scala.collection.JavaConverters
//import scala.collection.JavaConverters._
//import scala.util.Random
//
//object AbductionExperimentRandom {
//
//  object ExperimentType extends Enumeration {
//    type ExperimentType = Value
//    val KBExperiment, ABoxExperiment, NoExperiment = Value
//  }
//  import ExperimentType._
//
//  def printUsageAndExit(): Unit = {
//    println("Usage: ")
//    println("java "+this.getClass+" ONTOLOGY-FILE MAX_OBSERVATION_SIZE abox-experiment [verbose]")
//    println("java "+this.getClass+" ONTOLOGY-FILE MAX_OBSERVATION_SIZE kb-experiment [verbose]")
//    println()
//    println("Example:")
//    println("java "+this.getClass+" ore_ont456.owl abox-experiment")
//    println("  perform one instance of the ABox experiment. Don't print observations or hypotheses.")
//    println()
//    println("java "+this.getClass+" ore_ont456.owl kb-experiment verbose")
//    println("  perform one instance of the KB experiment. Print observations or hypotheses.")
//    System.exit(0)
//  }
//
//
//
//  def main(args: Array[String]): Unit = {
//    if(args.length<3){
//      printUsageAndExit()
//    }
//
//    val ontologyFile = args(0)
//
//    val maxObservationSize = args(1).toInt
//
//    val experimentType = args(2) match {
//      case "abox-experiment" => ABoxExperiment
//      case "kb-experiment" => KBExperiment
//      case other => printUsageAndExit(); NoExperiment
//    }
//
//    val verbose = if(args.length>3) {
//      if (!(args(3) == "verbose"))
//        printUsageAndExit()
//      true
//    } else
//      false
//
//    ALCFormulaPreparations.reuseDefiners=true
//
//    val man = OWLManager.createOWLOntologyManager()
//
//    var inputOntology = man.loadOntologyFromOntologyDocument(new File(args(0)))
//
//    OWLOntologyFilters.restrictToALC(inputOntology)
//
//    if(!verbose)
//      ExtendedABoxForgetter.deactivateProgressBar
//
//    val equivalentClasses = inputOntology.getLogicalAxioms().asScala.filter(_.isInstanceOf[OWLEquivalentClassesAxiom])
//
//    equivalentClasses.foreach{ ax =>
//      inputOntology.removeAxiom(ax)
//      inputOntology.addAxioms(ax.asInstanceOf[OWLEquivalentClassesAxiom].asOWLSubClassOfAxioms())
//    }
//
//    if(inputOntology.getAxiomCount()>50*1000 || inputOntology.getAxiomCount()<100) {
//      println("Ignoring due number of axioms: "+ inputOntology.getAxiomCount())
//      System.exit(0)
//    }
//
//
//    if(experimentType.equals(KBExperiment)) {
//      var module = Set[OWLAxiom]();
//      while(module.size<100) {
//        module ++= ModuleExtractor.randomGenuineModule(inputOntology)
//      }
//      inputOntology = man.createOntology(module.asJava)
//    }
//
//
//    var observationSize = Random.nextInt(maxObservationSize) + 1
//
//    /*
//    //TODO: for mixed tbox/abox experiment
//    var requestedObsTBoxSize = Random.nextInt(observationSize)
//    var requestedObsABoxSize = observationSize - requestedObsTBoxSize
//
//    //TODO: Note -- for abox only experiment
//    //var requestedObsTBoxSize = 0
//    //var requestedObsABoxSize = observationSize
//
//    val inputTBoxSize =  inputOntology.getTBoxAxioms(Imports.fromBoolean(false)).size()
//    val inputABoxSize =  inputOntology.getABoxAxioms(Imports.fromBoolean(false)).size()
//
//    (if(requestedObsTBoxSize > inputTBoxSize) {
//      requestedObsTBoxSize = Random.nextInt(math.ceil(0.5*inputTBoxSize).toInt) //small ontologies, avoid obs being whole ontology
//    }
//    if(requestedObsABoxSize > inputABoxSize) {
//      requestedObsABoxSize = Random.nextInt(math.ceil(0.5*inputABoxSize).toInt)
//    }
//
//    observationSize = requestedObsTBoxSize + requestedObsABoxSize
//     */
//
//    //Random obs
//    val observationAxioms =
//      generateObservation(inputOntology, observationSize, experimentType)
//
//    val backgroundAxioms = inputOntology.getAxioms()
//    backgroundAxioms.removeAll(observationAxioms)
//
//    //conversions
//    val backgroundOntology = OWLApiConverter.convert(man.createOntology(backgroundAxioms))
//    val observationStatements = JavaConverters.asScalaSet(observationAxioms).map(ax => OWLApiConverter.convert(ax)).toSet.flatten
//    val observation = Ontology.buildFrom(observationStatements)
//
//    if(verbose){
//      println("Observation: ")
//      println(SimpleDLFormatter.format(observation))
//    }
//
//    //val percentAbducible = 100 - (Random.nextInt(9) + 1)
//    val percentAbducible = 60
//    println("PERCENT ABDUCIBLE: " + percentAbducible)
//
//    val abducibles = generateAbducibles(backgroundOntology, observationStatements, percentAbducible)
//
//    val abducer = new FullAbducer()
//    abducer.setBackgroundOntology(backgroundOntology)
//    abducer.setAbducibles(abducibles)
//
//    //Forgetting
//    val forgetStart = System.nanoTime()
//    val forgettingResultBeforeSimplification = abducer.forget(observation)
//    val forgetStop = System.nanoTime()
//    val hypothesisBeforeSimplification = KBNegator.negate(forgettingResultBeforeSimplification)
//
//    val hypothesisSize = hypothesisBeforeSimplification.size
//    val hypothesisDisjuncts = hypothesisBeforeSimplification match {
//      case DisjunctiveDLStatement(ds) => ds.size
//      case other => 1
//    }
//    val (countABox, countTBox) = countABoxTBox(hypothesisBeforeSimplification)
//    val nominals = hypothesisBeforeSimplification.subConcepts.exists(c => c._1.isInstanceOf[NominalSet])
//    val inverseRoles = hypothesisBeforeSimplification.roles.exists(c => c.isInstanceOf[InverseRole])
//    val fixpoints = hypothesisBeforeSimplification.subConcepts.exists(c=> c._1.isInstanceOf[LeastFixpoint]||c._1.isInstanceOf[GreatestFixpoint])
//
//    print("observationSize: "+observation.size
//	  + " observationTBox: "+observation.tbox.axioms.size
//	  + " observationABox: "+observation.abox.assertions.size
//	  + " backgroundSignatureSize: " + backgroundOntology.signature.size
//	  + " non-abducibles: " + (backgroundOntology.signature.size - abducibles.size) )
//
//    println()
//
//    println("BEFORE SIMPLIFICATION: " + "forgetting time taken: " + (forgetStop - forgetStart) + " hypothesisSize: "+hypothesisSize+" disjuncts: "+hypothesisDisjuncts+" tboxAxioms: "+countTBox+" aboxAssertions: "+countABox+
//      " fixpoints: "+fixpoints+ " nominals: "+nominals+" inverseRoles: "+inverseRoles)
//    println()
//
//    if(hypothesisSize>0) {
//      //Simplification
//      val simplificationStart = System.nanoTime()
//      val forgettingResultAfterSimplification = abducer.simplify(forgettingResultBeforeSimplification)
//      val simplificationStop = System.nanoTime()
//
//      val hypothesisAfterSimplification = KBNegator.negate(forgettingResultAfterSimplification)
//
//      val hypothesisSizeSimplified = hypothesisAfterSimplification.size
//      val hypothesisDisjunctsSimplified = hypothesisAfterSimplification match {
//        case DisjunctiveDLStatement(ds) => ds.size
//        case other => 1
//      }
//      val (countABoxSimplified, countTBoxSimplified) = countABoxTBox(hypothesisAfterSimplification)
//      val fixpointsSimplified = hypothesisAfterSimplification.subConcepts.exists(c => c._1.isInstanceOf[LeastFixpoint] || c._1.isInstanceOf[GreatestFixpoint])
//      val nominalsSimplified = hypothesisAfterSimplification.subConcepts.exists(c => c._1.isInstanceOf[NominalSet])
//      val inverseRolesSimplified = hypothesisAfterSimplification.roles.exists(c => c.isInstanceOf[InverseRole])
//
//      println("AFTER SIMPLIFICATION: " + "simplification time taken: " + (simplificationStop - simplificationStart) + " hypothesisSize: " + hypothesisSizeSimplified + " disjuncts: " + hypothesisDisjunctsSimplified + " tboxAxioms: " + countTBoxSimplified + " aboxAssertions: " + countABoxSimplified +
//        " fixpoints: " + fixpointsSimplified + " nominals: " + nominalsSimplified + " inverseRoles: " + inverseRolesSimplified)
//      println()
//
//      if(verbose){
//	println("Optimal hypothesis before redundancy elimination:")
//	println(SimpleDLFormatter.format(hypothesisAfterSimplification))
//      }
//
//
//      //Filtering
//      println("FILTERING STARTED")
//      val filterStart = System.nanoTime()
//      val hypothesisAfterFiltering = abducer.filter(forgettingResultAfterSimplification)
//      val filterStop = System.nanoTime()
//
//      val hypothesisSizeFiltered = hypothesisAfterFiltering.size
//      val hypothesisDisjunctsFiltered = hypothesisAfterFiltering match {
//        case DisjunctiveDLStatement(ds) => ds.size
//        case other => 1
//      }
//      val (countABoxFiltered, countTBoxFiltered) = countABoxTBox(hypothesisAfterFiltering)
//      val fixpointsFiltered = hypothesisAfterFiltering.subConcepts.exists(c => c._1.isInstanceOf[LeastFixpoint] || c._1.isInstanceOf[GreatestFixpoint])
//      val nominalsFiltered = hypothesisAfterFiltering.subConcepts.exists(c => c._1.isInstanceOf[NominalSet])
//      val inverseRolesFiltered = hypothesisAfterFiltering.roles.exists(c => c.isInstanceOf[InverseRole])
//
//      println("AFTER FILTERING: " + "filtering time taken: " + (filterStop - filterStart) + " hypothesisSize: " + hypothesisSizeFiltered + " disjuncts: " + hypothesisDisjunctsFiltered + " tboxAxioms: " + countTBoxFiltered + " aboxAssertions: " + countABoxFiltered +
//        " fixpoints: " + fixpointsFiltered + " nominals: " + nominalsFiltered + " inverseRoles: " + inverseRolesFiltered)
//
//      if(verbose){
//	println("Hypothesis after redundancy elimination:")
//	println(SimpleDLFormatter.format(hypothesisAfterFiltering))
//      }
//    }
//  }
//
//  def countABoxTBox(dlStatement: DLStatement): (Int,Int) = dlStatement match {
//    case DisjunctiveDLStatement(ds) => ds.toSeq.map(countABoxTBox).fold((0,0))((a1,a2) => (a1._1+a2._1, a1._2+a2._2))
//    case ConjunctiveDLStatement(ds) => ds.toSeq.map(countABoxTBox).fold((0,0))((a1,a2) => (a1._1+a2._1, a1._2+a2._2))
//    case DisjunctiveAssertion(ds) => ds.toSeq.map(countABoxTBox).fold((0,0))((a1,a2) => (a1._1+a2._1, a1._2+a2._2))
//    case ConjunctiveAssertion(ds) => ds.toSeq.map(countABoxTBox).fold((0,0))((a1,a2) => (a1._1+a2._1, a1._2+a2._2))
//    case _: Assertion => (1, 0)
//    case _: Axiom => (0,1)
//  }
//
//  def generateObservation(backgroundOntology: OWLOntology,
//                          observationSize: Int,
//                          experimentType: ExperimentType): java.util.Set[OWLAxiom] = {
//
//    val observationGenerator = new ObservationGenerator(true)
//
//    experimentType match {
//      case KBExperiment => observationGenerator.extractObservation(backgroundOntology, observationSize)
//      case ABoxExperiment => observationGenerator.generateABoxObservations(backgroundOntology, observationSize)
//      case NoExperiment => throw new AssertionError("No valid experiment type selected")
//    }
//  }
//
//  /*def generateObservation(backgroundOntology: OWLOntology, observationSize: (Int, Int)): java.util.Set[OWLAxiom] = {
//
//    val observationGenerator = new ObservationGenerator()
//
//    val (numTBox, numABox) = observationSize
//
//    val observations = observationGenerator.extractObservation(backgroundOntology, numTBox, numABox)
//
//    observations
//  }*/
//
//  def generateAbducibles(backgroundOntology: Ontology, observation: scala.collection.immutable.Set[DLStatement], percentAbducible: Int): Set[String] = {
//    val numAbducibles = math.floor(backgroundOntology.signature.size*(percentAbducible.toFloat/100))
//    println("NUMABDUCIBLES: " + numAbducibles)
//
//    //select abducibles
//    var abducibles = scala.collection.mutable.Set[String]()
//
//    val statementSeq = backgroundOntology.statements.toSeq ++ observation.toSeq
//    while(abducibles.size<numAbducibles) {
//      val st = statementSeq(Random.nextInt(statementSeq.size)) //note: to take symbol frequency into account
//      val sigSeq = st.signature.toSeq
//      if(sigSeq.nonEmpty) {
//        val symbol = sigSeq(Random.nextInt(sigSeq.size))
//        if (!abducibles.contains(symbol)) {
//          abducibles += symbol
//        }
//      }
//    }
//    var nonAbducibles = (backgroundOntology.signature -- abducibles)
//
//    //ensure one symbol from entire observation is in non-abducibles
//    var obsSig = scala.collection.mutable.Set[String]()
//    for(st <- observation) {
//      obsSig ++= st.signature.toSeq
//    }
//
//    if(obsSig.intersect(nonAbducibles).isEmpty) {
//      val symbol = obsSig.toSeq(Random.nextInt(obsSig.size))
//      println("Added name from the observation to non-abducible set.")
//      abducibles -= symbol
//      nonAbducibles += symbol
//    }
//
//    //ensure at least one symbol from each axiom in observation is in non-abducible set (avoid trivial hypothesis)
//    /*
//    for(st <- observation) {
//      val sigSeq = st.signature.toSeq
//      if(sigSeq.nonEmpty && sigSeq.intersect(nonAbducibles.toSeq).isEmpty) {
//        val symbol = sigSeq(Random.nextInt(sigSeq.size))
//        abducibles -= symbol
//        nonAbducibles += symbol
//        println("Obs axiom has no non-abducible, removing abducible: " + symbol)
//      }
//    }
//    */
//    abducibles.toSet
//  }
//}
