⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aiphighhope.cpp

📁 aiParts is a set of C++ classes that can be used to develop artificial intelligence for multi-decisi
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//**********************************************************************
//  aipHighHope.cpp  -  function bodies for aipHighHope.h
//
//  Copyright (c)  1999, 2005, 2008  Brian Marshall
//
//  See the license at end of this file.
//
//  Developers/Contributers:
//    [BRM] Brian Marshall - Calgary - bmarshal@agt.net
//
//  08/06/16  [BRM] added decision is_decided(), 
//                  removed decision groups, modified deciding,
//                  new next_decision(), added aipHHImportance,
//                  decisions may be decided more than once,
//                  removed dcsn.m_opt_prev; small changes
//  05/11/18  [BRM] added decision groups
//                  worst decision optionally has extra weight
//                  a failed decision gets increase in fear
//                  moved call disable_slowly_degrade() to aipHHHope
//                  fixed minor bug re: problem members: m_is_many_xxx
//                  fixed minor bug re: m_tries_since_change_count
//  05/11/12  [BRM] moved logic from problem to hope aspects
//  05/11/07  [BRM] moved random_num() to class aipBase
//  05/11/01  [BRM] count tries to get to best try 
//  05/10/20  [BRM] fixed bug re: count since improvement
//                  disabled hope emotions slowly degrading
//                  modified how decision and option hopes change
//  05/10/02  [BRM] split out from aipProblem and aipDecision
//  05/09/26  [BRM] development began
//
//----------------------------------------------------------------------
//  The key functions are...
//
//  aipG aipHHProblem::solve()
//    implements the High-Hope problem-solving technique
//
//  void aipHHDecision::take_msg (aipMsg *m)
//  void aipHHOption::take_msg (aipMsg *m)
//  void aipHHFearAspect::take_msg (aipMsg *m)
//  void aipHHGreedAspect::take_msg (aipMsg *m)
//  void aipHHCuriosityAspect::take_msg (aipMsg *m)
//     decisions and options are affected by a received message
//
//  Maybe:
//  void aipHHProblem::normalize_option_goodnesses()
//    something like this might be used in some kinds of problems
//    in which (some) options have a constant goodness that should
//    affect which option is chosen.
//
//  Note that shortest-path-from-A-to-B problems, for example,
//  do not use  normalize_option_goodnesses()  - a short step is
//  not favored over a long step - people like non-stop flights.
//
//----------------------------------------------------------------------

#include "aipHighHope.h"

#include <string.h>
#include <iostream>
using namespace std;

//======================================================================
//  aipHHImportance  -  importance for choosing decisions
//
//----------------------------------------------------------------------
//  take_msg  -  take a message and maybe do something because of it

void aipHHImportance::take_msg (aipMsg *mm) {

  aipHHMsg *m = (aipHHMsg *)mm;

  if (m->typ() == HH_Try_Has_Ended) {

    if (m->is_the_failure()) m_been_prob += 16;
    long imp_val = val();
    if (imp_val > 64) {
      m_been_prob -= 12;
    } else if (imp_val > 16) {
      m_been_prob -= 4;
    }

  } else if (m->typ() == HH_No_Recent_Improve) {

    m_been_prob /= 2;

  }

  aipImportance::take_msg(mm);

}

//======================================================================
//  aipHHHope  -  Hope with High-Hope aspects
//
//----------------------------------------------------------------------
//  Constructor

aipHHHope::aipHHHope () {

  aipHHFearAspect *fear_aspect = new aipHHFearAspect;
  aipHHGreedAspect *greed_aspect = new aipHHGreedAspect;
  aipHHCuriosityAspect *curiosity_aspect = new aipHHCuriosityAspect;

  if (fear_aspect && greed_aspect && curiosity_aspect) {
    if (fear())           fear()->add_aspect(fear_aspect);
    if (greed())         greed()->add_aspect(greed_aspect);
    if (curiosity()) curiosity()->add_aspect(curiosity_aspect);
  }

  disable_slowly_degrade();

}

//======================================================================
//  aipHHFearAspect  -  how messages affect fear in hope
//
//----------------------------------------------------------------------
// take_msg

void aipHHFearAspect::take_msg (aipMsg *mm) {

  aipHHMsg *m = (aipHHMsg *)mm;

  aipHHSolveStat *ss = m->solve_stat();

  if (!fear() || !ss) return;

  if (m->typ() == HH_Starting_Solve) {

    fear()->set_g(aipNeutral);

  } else if (m->typ() == HH_No_Recent_Change) {


  } else if (m->typ() == HH_No_Recent_Improve) {

    fear()->weaken(aipIntensity_A_Little);

  } else if (m->typ() == HH_No_Recent_Best_So_Far) {

    fear()->weaken(aipIntensity_Somewhat);

  } else if (m->typ() == HH_Try_Has_Ended) {

    if ( ss->try_result() == HH_Try_Has_Failed ) {

      if (m->is_in_cur_solution()) {
        fear()->strengthen(aipIntensity_Slightly);
      } else if (m->is_the_failure()) {
        fear()->strengthen(aipIntensity_A_Little);
      }

    } else {   // a complete solution was found

      if (m->is_in_cur_solution()) {
        fear()->weaken(aipIntensity_A_Little);
      }

    }  // end of block for when a complete solution was found

  }

  aipAspect::take_msg(mm);

}

//======================================================================
//  aipHHGreedAspect  -  how messages affect greed in hope
//
//----------------------------------------------------------------------
// take_msg

void aipHHGreedAspect::take_msg (aipMsg *mm) {

  aipHHMsg *m = (aipHHMsg *)mm;

  aipHHSolveStat *ss = m->solve_stat();

  if (m->typ() == HH_Starting_Solve) {

    greed()->set_g(aipNeutral);

  } else if (m->typ() == HH_Try_Has_Ended) {

    if ( ss->try_result() == HH_Try_Is_New_Best ) {
      if (greed()->g() >= Greed_For_Best) {
        greed()->set_g(Greed_For_Was_Best);
      }
    }

    if ( ss->try_result() == HH_Try_Is_Improved ) {
      if (greed()->g() == Greed_For_Improved) {
        greed()->set_g(Greed_For_Changed);
      }
    }

    if ( ss->try_result() == HH_Try_Is_Changed ) {
      if (greed()->g() == Greed_For_Changed) {
        greed()->set_g(Greed_For_Complete);
      }
    }

    if ( ss->try_result() == HH_Try_Has_Failed ) {

    } else {   // a complete solution was found

      if (m->is_in_cur_solution()) {

        if ( ss->try_result() == HH_Try_Is_New_Best ) {
          greed()->set_g(Greed_For_New_Best);
        } else if ( ss->try_result()  == HH_Try_Is_A_Best ) {
          greed()->set_g(Greed_For_Best);
        } else if ( ss->try_result() == HH_Try_Is_Improved &&
                    greed()->g() < Greed_For_Improved ) {
          greed()->set_g(Greed_For_Improved);
        } else if ( ss->try_result() == HH_Try_Is_Changed &&
                    greed()->g() < Greed_For_Changed ) {
          greed()->set_g(Greed_For_Changed);
        } else if ( ss->try_result() == HH_Try_Is_Complete &&
                    greed()->g() < Greed_For_Complete ) {
          greed()->set_g(Greed_For_Complete);
        }

      }   // end of block for decision in current solution

    }  // end of block for when a complete solution was found

  }

  aipAspect::take_msg(mm);

}

//======================================================================
//  aipHHCuriosityAspect  -  how messages affect curiosityin hope
//
//----------------------------------------------------------------------
// take_msg

void aipHHCuriosityAspect::take_msg (aipMsg *mm) {

  aipHHMsg *m = (aipHHMsg *)mm;

  aipHHSolveStat *ss = m->solve_stat();

  if (m->typ() == HH_Starting_Solve) {

    curiosity()->set_g(Curiosity_Starting);

  } else if (m->typ() == HH_No_Recent_Change) {

    if ( ! m->is_in_cur_solution() ) {
      curiosity()->set_g(Curiosity_Starting);
    }

  } else if (m->typ() == HH_No_Recent_Improve) {

    curiosity()->set_g(Curiosity_Starting);

  } else if (m->typ() == HH_No_Recent_Best_So_Far) {

    curiosity()->set_g(Curiosity_Starting);
    curiosity()->strengthen(aipIntensity_Somewhat);

  } else if (m->typ() == HH_Try_Has_Ended) {

    if ( ss->try_result() == HH_Try_Has_Failed ) {

      if (m->is_in_cur_solution()) {
        curiosity()->weaken(aipIntensity_A_Little);
      }

    } else {   // a complete solution was found

      if (m->is_in_cur_solution()) {

        curiosity()->weaken(aipIntensity_Somewhat);

        if ( ss->try_result() == HH_Try_Is_New_Best ) {
          // Greed will go up, curiosity comes down...
          curiosity()->weaken(aipIntensity_Somewhat);    // more
        }

      }   // end of block for decision in current solution

    }  // end of block for when a complete solution was found

  }

  aipAspect::take_msg(mm);

}

//======================================================================
//  aipHHProblem
//
//----------------------------------------------------------------------
//  Constructor

aipHHProblem::aipHHProblem () {

  m_num_try = 1000;
  m_dcsn_is_progress = m_worst_is_extra_bad = 0;
  m_should_log_tries = 1;  // default to: write to log about tries

  m_solve_stat = new aipHHSolveStat (this);

}

//----------------------------------------------------------------------
//  Destructor

aipHHProblem::~aipHHProblem () {

  if (m_solve_stat) delete m_solve_stat;

}

//----------------------------------------------------------------------
//  add_hh_decision

void aipHHProblem::add_hh_decision (aipHHDecision *x) {

  aipProblem::add_decision(x);

}

//----------------------------------------------------------------------
//  hh_decision_iterator

aipHHDecisionItr aipHHProblem::hh_decision_iterator() const { 

  aipHHDecisionItr i(decision_pandemonium());

  return i;

}

//----------------------------------------------------------------------
//  return the number of decisions to be made

long aipHHProblem::num_decisions() const {

  long num_dcsn = 0;

  aipHHDecisionItr itr = hh_decision_iterator();
  aipHHDecision *d;
  for ( d = itr.first(); d; d = itr.next() ) {
    num_dcsn += d->num_to_decide();
  }

  return num_dcsn;

}

//----------------------------------------------------------------------
//  g  -  goodness meaningful to user

aipG aipHHProblem::g() { 

  return solve_stat()->g_usr_bsf(); 

}

//----------------------------------------------------------------------
//  normalize_option_goodnesses  -  sample - for some problems
//
//  A function like this SAMPLE might be used in some types of 
//  problems, in which the goodness of an option (to the user) 
//  should be considered in picking options.
//
//  This function is used to convert values meaningful to the user
//  (ex. miles, dollars, minutes) to goodness values that can be 
//  combined and compared with other goodness values.
//
//  A normalize_option_goodnesses() function (that might or might not
//  look like this sample) might be used in staff-scheduling, where
//  a supervisor could work a shift as a clerk, but only if it was
//  absolutely necessary.
//
//  A normalize_option_goodnesses() function would not generally
//  be used in a find-the-shortest-path-from-A-to-B problem, where
//  a short step is not favored over a longer step; taking a short
//  step can simply mean another longer step is required.
//  
//  Option goodness m_g_constant is initially set to m_g_user_constant.
//  If these values are normal goodnesses, this function is not used.
//
//  Note that m_g_constant and m_g_user_constant may contain negative
//  values because:
//   - they are values the user considers to be negative, or,
//   - they are value that the user wants solve() to minimize.
//
//  This can really be improved, but for a first version...
//
//  Calculate a divisor as: max-absolute-value / 16, and then:
//   - for positive values:  x = (x / divisor) + 1
//   - for negative values:  x = (x / divisor) - 1
//
//  This could work ok.  It will work very poorly if most of the
//  values are between, say, 1 and 100, and there are a few values
//  that are greater than 100000; all the smaller values will be 
//  normalized to 1.

void aipHHProblem::normalize_option_goodnesses () {

  aipHHDecisionItr d_itr = hh_decision_iterator();
  aipHHDecision *dec;  // used with the decision-iterator
  aipHHOption   *opt;  // used with the option-iterator

  aipG g_min = aipManditory;  // Find min and max
  aipG g_max = aipForbidden;
  for ( dec = d_itr.first(); dec; dec = d_itr.next() ) {

    aipHHOptionItr o_itr = dec->hh_option_iterator();
    for ( opt = o_itr.first(); opt; opt = o_itr.next() ) {
      if (opt->g_user_constant() < g_min) 
                        g_min = opt->g_user_constant();
      if (opt->g_user_constant() > g_max) 
                        g_max = opt->g_user_constant();
    }   // end of loop through options in the decision
  }   // end of loop through decisions

  long max_abs_val = g_min.absolute_value();
  if (g_max.numeric_value() > max_abs_val) {
    max_abs_val = g_max.numeric_value();
  }

  if (max_abs_val < 20) return;

  long divisor = max_abs_val / 16;

  for ( dec = d_itr.first(); dec; dec = d_itr.next() ) {
    aipHHOptionItr o_itr = dec->hh_option_iterator();
    for ( opt = o_itr.first(); opt; opt = o_itr.next() ) {
      long val = opt->g_user_constant().numeric_value();
      if (val > 0) {
        val = (val / divisor) + 1;
      } else if (val < 0) {
        val = (val / divisor) - 1;
      }
      if (val) opt->set_norm_g_constant(val);
    }
  }

}


//----------------------------------------------------------------------
//  solve
//
//  Return a goodness that is meaningful to the user - this might
//  be a goodness, or it might be dollars, miles, hours, etc.
//
//  This function, plus the take_msg() function on decisions and
//  options, are the implementation of the High-Hope technique.
//
//  It would seem that it would be appropriate to have a separate 
//  try() function, but it would be only a small proportion of this
//  function, and it would change variables set in this function.
//  Having it all in this function is the clearest way.

aipG aipHHProblem::solve() {

  aipHHSolveStat * ss = solve_stat();

  aipHHMsg  msg_starting_solve     (this, HH_Starting_Solve);
  aipHHMsg  msg_solve_has_ended    (this, HH_Solve_Has_Ended);
  aipHHMsg  msg_starting_try       (this, HH_Starting_New_Try);
  aipHHMsg  msg_try_has_ended      (this, HH_Try_Has_Ended);
  aipHHMsg  msg_this_is_bsf        (this, HH_This_Is_Best_So_Far);
  aipHHMsg  msg_no_recent_bsf      (this, HH_No_Recent_Best_So_Far);
  aipHHMsg  msg_no_recent_improve  (this, HH_No_Recent_Improve);
  aipHHMsg  msg_no_recent_change   (this, HH_No_Recent_Change);

  take_msg(&msg_starting_solve);

  ss->m_g_cmp_cur = ss->m_g_cmp_bsf = ss->m_g_usr_bsf = aipForbidden;

  for (ss->m_i_try=0; ss->m_i_try<m_num_try; ss->m_i_try++) {

    ss->m_g_cmp_prev = ss->m_g_cmp_cur;
    ss->m_g_cmp_cur = aipNeutral;

    ss->m_num_decisions_prev = ss->m_num_decisions_made;
    ss->m_num_decisions_made = 0;
    ss->m_failed_decision = 0;
    ss->m_worst_decision = 0;
    ss->m_worst_decision_g_cmp = aipForbidden;

    take_msg(&msg_starting_try);

    try_to_find_solution();                   // try

    take_msg(&msg_try_has_ended);

    if (ss->try_is_new_best()) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -