(*
This file is part of the dpll(t) engine sammy
Copyright (C) 2004  The University of Iowa

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*)

(* global.ml *)

(** Data types and utility functions used in most other modules. *)

type pred_id = Global_id.pred_id
type term_id = Global_id.term_id
type var_id = Global_id.var_id
type type_id = Global_id.type_id

(* pred_id manipulations *)
let id_compare = Global_id.id_compare
let compl = Global_id.compl
let is_positive = Global_id.is_positive
let is_negative = Global_id.is_negative
let unsigned = Global_id.unsigned
let id_string = Global_id.id_string

let sid_string = Global_id.sid_string


type status = Valid | Unsat | Undet 

let debug = false
let adebug = false
let extra_test = debug

(*
(* debuggin output (uncomment to activiate) *)
let debug x = ()
(* Printf.printf "%s" (x^"\n");flush stdout *)
let adebug x = (**)
( Printf.printf "%s" (x^"\n");flush stdout )
*)

let status_complement (s:status) = match s with
    Valid -> Unsat
  | Unsat -> Valid
  | Undet -> Undet

let val_string x = match x with
    Valid -> "Valid"
  | Unsat -> "Unsat"
  | _ -> "???"

(* NOTE: DOES PRESERVE ORDER! *)
let rec append_list s l = List.append s l
(*match s with 
                            [] -> l
                          |  h::t-> append_list t (h::l)
*)

(* output a list of ids *)
let rec pintl x = match x with 
[] -> Printf.printf "\n"; flush stdout;
| h::t -> Printf.printf "%s " (id_string h); pintl t

(* output a list of ints *)
let rec printl x = match x with 
[] -> Printf.printf "\n"; flush stdout;
| h::t -> Printf.printf "%d " h; printl t

type pars_type = { (* all integer values must be positive *)
                   mutable max_lemmas : int; (* can be zero *)
                   mutable max_active_lemmas : int;
                   mutable max_instance_lemmas : int;
                 (*mutable init_phase : int;*)
                   mutable activity_cycle: int;
                   mutable activity_behavior: int;
                   mutable restart_cycle: int;
                   mutable pred_table_size: int;
                   mutable timeout: float;
                   mutable global_timeout: float;
                   mutable split_on_abstract: bool;
                   mutable conflict_analysis: int;
                   mutable augment_theory_return: bool;
                   mutable negate_queries: bool;
                   mutable verbose: bool;
                   mutable max_instances: int;
                   mutable dynamic_extraction: bool;
                   mutable static_extraction: bool;
                   mutable exhaustive: bool;
                   mutable random_seed: int;
                   mutable cnf_input: bool;
                   mutable stop_on_partial_model: bool;
                   mutable nonwatched_lits_last: bool; (* if we favor watched lits *)
                   mutable use_favored_polarity: bool; (* if we account for and/or *)
                   mutable favor_ite_guards: bool; (* if we account for ites *)
                   mutable favor_depth: bool; (* if we use depth *)
                   mutable favor_min_depth: bool; (* if we use the highest *)
                   mutable narrow_model_rejection: bool; (* create a lemma that rejects this exact model (used in zolc) *)
                   mutable check_model: bool;
                   mutable only_positive_quantified_preds: bool;
                   mutable have_random_seed: bool;
                   mutable parse_only: bool; (* debugging option, forces the program not to call Dpllt.satisfiable -- do not solve *)
                   mutable no_term_generation : bool (* completely random terms in instantiations, may have repetition *)
     }

(* Parameter usage:
   
   - [pars.max_lemmas] must be >= 4. 
     It stores the maximum number of learned lemmas & new instances.
     Not used in satbox version.
   
   - [pars.max_active_lemmas] must be >= 2, must be =< pars.max_lemmas-2
     Store the number of active (higher priority) learned lemmas.  Lemmas may
     be either active or inactive.  A lemma starts out as inactive, and 
     becomes active when it has recently been used in a conflict.  Only 
     inactive lemmas are dropped.
     Not used in satbox version.

   - [pars.activity_cycle] must be > 0. 
     If its value is n, the system will reduce the activity level of predicates
     every n conflicts.

   - [pars.restart_cycle] must be > 0. 
     If its value is n, the system will restart the search from scratch
     (but keeping the learned lemmas) every n conflicts. (n increases with
     each restart)
     Its default value is max_int, which amounts to no restarts.

   - [pars.activity_behavior] bitmap
     Defines the circumstances under which a perdicate's activity is increased.
     bit    activity increased when predicate...
     32     use total predicate score (instead of literal scores)
      16    appears in a lemma
       8    returns a list of chenged literals (increases by list size, not 1)
        4   appears in lemma
         2  complement appears in lemma
          1 encountered in input parse
     1+2=3 is the default value

   - [pars.pred_table_size] int > 0
     initial size of the predicate table

   - [pars.timeout] must be >= 0.0
     Number of seconds after which the program will attmept to abort a 
     single search.

   - [pars.global_timeout] must be >= 0.0
     Number of seconds after which the program will attempt to self-abort.

   - [pars.conflict_analysis] enumeration
     Determines which form of conflict analysis to use
     1  1ST UIP (chaff) (not supported)
     2  GRASP (not supported)
     3  full regression (default)
     Not used with satbox.

   - [pars.split_on_abstract] boolean
     Favor abstracted (non-input) variables for split decisions.

   - [pars.verbose]
     Print out more detailed statistics iff set to true

   - [pars.max_instances] must be > 0
     The maximum number of instances the quantifier will generate at one time.
     
   - [pars.exhaustive] boolean
     Attempt to fully instantiate quantifiers iff set to true

   - [pars.augment_theory_return] boolean
     Asks theory for status of additional predicates when one is asserted.
     Currenty disabled.
     
   - [pars.random_seed] (integer)
     Uses specified seed to initialize random number generator iff
     [pars.have_random_seed] is set to true.

   - [pars.have_random_seed] int
     Uses [pars.random_seed] to initialize random number generator iff
     set to true, otherwise uses system-dependant random initial seed.

   - [pars.nagate_queries] boolean
     Checks the negation of input queries (to determine their validity 
     instead of satisfiability)

   - [pars.dynamic_extraction]  boolean
     Not currently used.

   - [pars.static_extraction]  boolean
     Not currently used.

   - [pars.cnf_input]  boolean
     Input in dimacs-like format; no clausal translation required.
     Not currently used.

   - [pars.stop_on_partial_model] boolean
     Halt the search as soon as a partial model that satisfies the input
     is generated (normally a complete model is generated)

   - [pars.nonwatched_literals_last] boolean
     Modifies decision heuristic to favor watched literals.

   - [pars.use_favored_polarity] boolean
     Modifies decision heuristic to use a specified favored polarity based on
     how the type of variable.  Usually "false" is the default.

   - [pars.favor_ite_guards] boolean
     Modifies decision heuristic to favor variables that are ite guards

   - [pars.favor_depth] boolean
     Modifies decision heuristic to favor variable that are either deep or 
     shallow

   - [pars.favor_min_depth] boolean
     If favor_depth is set, preference is given to shallow (true) or deep 
     (false) variables

   - [pars.narrow_model_rejection] boolean
     When rejecting a model (in quantified search, eg), provide a very
     specific (large) lemma.

   - [pars.check_model] boolean
     Perform an extra (debugging) check of the generated model to ensure
     if satifies the input clauses.

   - [pars.only_positive_quantified_preds] boolean
     When rejecting a model, only include "quantified" preds that are currently
     true.

   - [pars.parse_only] boolean
     Do not perform a check.  Only read in the file & perform clause conversion.

   - [pars.no_term_generation] boolean
     If true, randomly pick terms for instantiation -- may have repetition.

*)

let pars = { max_lemmas = 512;
             max_active_lemmas = 128;
             max_instance_lemmas = 1024;
             (*init_phase = 0;*)
             activity_cycle = 512;
             activity_behavior = 3;
             restart_cycle = max_int;
             pred_table_size = 128;
             timeout = 3600.0;
             global_timeout = 3600.0;
             split_on_abstract = true;
             conflict_analysis = 3;
             augment_theory_return = true;
             negate_queries = true;
             verbose = true;
             max_instances = 30;
             exhaustive = false;
             dynamic_extraction = false;
             static_extraction = false;
             random_seed = 0;
             cnf_input = false;
             stop_on_partial_model = false;
             nonwatched_lits_last = true;
             use_favored_polarity = true;
             favor_ite_guards = true;
             favor_depth = true;
             favor_min_depth = true;
             narrow_model_rejection = false;
             check_model = true;
             only_positive_quantified_preds = false;
             have_random_seed = false;
             parse_only = false; 
             no_term_generation = false
     }

type paramtype = 
    MAX_LEMMAS of int
  | MAX_ACTIVE_LEMMAS of int
  | MAX_INSTANCE_LEMMAS of int
  | ACTIVITY_CYCLE of int
  | ACTIVITY_BEHAVIOR of int
  | RESTART_CYCLE of int
  | PRED_TABLE_SIZE of int
  | TIMEOUT of float
  | GLOBAL_TIMEOUT of float
  | SPLIT_ON_ABSTRACT of bool
  | CONFLICT_ANALYSIS of int
  | AUGMENT_THEORY_RETURN of bool
  | NEGATE_QUERIES of bool
  | VERBOSE of bool
  | MAX_INSTANCES of int
  | DYNAMIC_EXTRACTION of bool
  | STATIC_EXTRACTION of bool
  | EXHAUSTIVE of bool
  | CNF_INPUT of bool
  | STOP_ON_PARTIAL of bool
  | NONWATCHED_LITS_LAST of bool
  | FAVOR_ITE_GUARDS of bool
  | USE_FAVORED_POLARITY of bool
  | FAVOR_DEPTH of bool
  | FAVOR_MIN_DEPTH of bool
  | RANDOM_SEED of int
  | NARROW_MODEL_REJECTION of bool
  | CHECK_MODEL of bool
  | ONLY_POSITIVE_QUANTIFIED_PREDS of bool
  | HAVE_RANDOM_SEED of bool
  | PARSE_ONLY of bool
  | NO_TERM_GENERATION of bool

let set_param (p:paramtype) =
  match p with
    MAX_LEMMAS x -> 
      pars.max_lemmas <- x
  | MAX_ACTIVE_LEMMAS x -> 
      pars.max_active_lemmas <- x
  | MAX_INSTANCE_LEMMAS x -> 
      pars.max_active_lemmas <- x
  | ACTIVITY_CYCLE x -> 
      pars.activity_cycle <- x
  | ACTIVITY_BEHAVIOR x -> 
      pars.activity_behavior <- x
  | RESTART_CYCLE x -> 
      pars.restart_cycle <- x
  | PRED_TABLE_SIZE x -> 
      pars.pred_table_size <- x
  | TIMEOUT x -> 
      pars.timeout <- x
  | GLOBAL_TIMEOUT x -> 
      pars.global_timeout <- x
  | SPLIT_ON_ABSTRACT x -> 
      pars.split_on_abstract <- x
  | CONFLICT_ANALYSIS x -> 
      pars.conflict_analysis <- x
  | AUGMENT_THEORY_RETURN x -> 
      pars.augment_theory_return <- x
  | NEGATE_QUERIES x -> 
      pars.negate_queries <- x
  | VERBOSE x -> 
      pars.verbose <- x
  | MAX_INSTANCES x -> 
      pars.max_instances <- x
  | DYNAMIC_EXTRACTION x -> 
      pars.dynamic_extraction <- x
  | STATIC_EXTRACTION x ->
      pars.static_extraction <- x
  | EXHAUSTIVE x ->
      pars.exhaustive <- x
  | CNF_INPUT x ->
      pars.cnf_input <- x
  | STOP_ON_PARTIAL x ->
      pars.stop_on_partial_model <- x
  | NONWATCHED_LITS_LAST x ->
      pars.nonwatched_lits_last <- x
  | USE_FAVORED_POLARITY x ->
      pars.use_favored_polarity <- x
  | FAVOR_ITE_GUARDS x ->
      pars.favor_ite_guards <- x
  | FAVOR_DEPTH x ->
      pars.favor_depth <- x
  | FAVOR_MIN_DEPTH x ->
      pars.favor_min_depth <- x
  | RANDOM_SEED x -> 
      pars.random_seed <- x;
      pars.have_random_seed <- true
  | NARROW_MODEL_REJECTION x ->
      pars.narrow_model_rejection <- x
  | CHECK_MODEL x ->
      pars.check_model <- x
  | ONLY_POSITIVE_QUANTIFIED_PREDS x ->
      pars.only_positive_quantified_preds <- x
  | HAVE_RANDOM_SEED x ->
      pars.have_random_seed <- x
  | PARSE_ONLY x ->
      pars.parse_only <- x
  | NO_TERM_GENERATION x ->
      pars.no_term_generation <- x
  | _ -> Printf.printf("Unknown parameter")
