【问题标题】:Clips create Multifield in c++Clips 在 C++ 中创建多域
【发布时间】:2016-03-14 22:37:03
【问题描述】:

我想创建一个看起来像这样的模板:

; initial and final state of a single IF instance
    (deftemplate InitialAndFinalState
    (slot initial_state)
    (multislot final_state)
)

使用 c++ 接口,我按以下方式使用:

void* ifs_template = EnvFindDeftemplate(clips_environment_,
  "InitialAndFinalState");
void* ifs_fact = EnvCreateFact(clips_environment_, ifs_template);
if (ifs_fact != NULL) {
  DATA_OBJECT field;
  field.type = FACT_ADDRESS;

  field.value = 
      addSpinWaveToClipsEnvironment(initial_state);
  EnvPutFactSlot(clips_environment_, ifs_fact, "initial_state", &field);

  void* multifield_ptr = EnvCreateMultifield(clips_environment_,
      final_state.size());

  for (unsigned int i = 0; i < final_state.size(); ++i) {
    SetMFType(multifield_ptr, i + 1, FACT_ADDRESS);
    SetMFValue(multifield_ptr, i + 1,
       addSpinWaveToClipsEnvironment(final_state[i]));//);
  }

  DATA_OBJECT final_states;
  SetDOBegin(final_states, 1);
  SetDOEnd(final_states, final_state.size());

  SetType(final_states, MULTIFIELD);
  SetValue(final_states, multifield_ptr);

  EnvPutFactSlot(clips_environment_, ifs_fact, "final_state", &final_states);

  EnvAssert(clips_environment_, ifs_fact);
}

addSpinWaveToClipsEnviroment 函数将添加 SpinWave 事实或查找现有事实并返回事实地址。

void* DecayGenerator::addSpinWaveToClipsEnvironment(const SpinWave& spinwave) {
  std::vector<std::pair<std::string, int> > spin_qn_name_value_pairs;
  for (auto spin_like_qn = spinwave.spin_like_quantum_numbers_.begin();
      spin_like_qn != spinwave.spin_like_quantum_numbers_.end();
      ++spin_like_qn) {
    spin_qn_name_value_pairs.push_back(
        std::make_pair(spin_like_qn->first,
            addSpinQuantumNumberToClipsEnvironment(spin_like_qn->second)));
  }

  std::stringstream clips_query;
  std::stringstream values_part;
  values_part << "(explode$ \"";
  clips_query << "(find-spinwave-fact-list (explode$ \"";
  for (auto spin_like_qn = spin_qn_name_value_pairs.begin();
      spin_like_qn != spin_qn_name_value_pairs.end(); ++spin_like_qn) {
    clips_query << "\\\"" << spin_like_qn->first << "\\\" ";
    values_part << spin_like_qn->second << " ";
  }
  for (auto int_like_qn = spinwave.integer_like_quantum_numbers_.begin();
      int_like_qn != spinwave.integer_like_quantum_numbers_.end();
      ++int_like_qn) {
    clips_query << "\\\"" << int_like_qn->first << "\\\" ";
    values_part << int_like_qn->second << " ";
  }
  for (auto double_like_qn = spinwave.double_like_quantum_numbers_.begin();
      double_like_qn != spinwave.double_like_quantum_numbers_.end();
      ++double_like_qn) {
    clips_query << "\\\"" << double_like_qn->first << "\\\" ";
    values_part << double_like_qn->second << " ";
  }
  values_part << "\")";
  clips_query << "\") " << values_part.str() << ")";

  DATA_OBJECT found_spin_waves_facts;
  EnvEval(clips_environment_, clips_query.str().c_str(),
      &found_spin_waves_facts);

  void* spinwave_fact;
  if (0 < GetDOLength(found_spin_waves_facts)) {
    spinwave_fact = GetMFValue(GetValue(found_spin_waves_facts), 1);
  }
  else {
    void* spinwave_template = EnvFindDeftemplate(clips_environment_,
        "SpinWave");
    // set the facts
    spinwave_fact = EnvCreateFact(clips_environment_, spinwave_template);
    if (spinwave_fact != NULL) {

      unsigned int total_qn_count = spinwave.spin_like_quantum_numbers_.size()
          + spinwave.integer_like_quantum_numbers_.size()
          + spinwave.double_like_quantum_numbers_.size();

      void* qn_names_ptr = EnvCreateMultifield(clips_environment_,
          total_qn_count);

      void* qn_values_ptr = EnvCreateMultifield(clips_environment_,
          total_qn_count);

      unsigned int counter(1);
      for (auto spin_like_qn = spin_qn_name_value_pairs.begin();
          spin_like_qn != spin_qn_name_value_pairs.end(); ++spin_like_qn) {
        SetMFType(qn_names_ptr, counter, STRING);
        SetMFValue(qn_names_ptr, counter,
            EnvAddSymbol(clips_environment_, spin_like_qn->first.c_str()));
        SetMFType(qn_values_ptr, counter, INTEGER);
        SetMFValue(qn_values_ptr, counter,
            EnvAddLong(clips_environment_, spin_like_qn->second));
        ++counter;
      }
      for (auto int_like_qn = spinwave.integer_like_quantum_numbers_.begin();
          int_like_qn != spinwave.integer_like_quantum_numbers_.end();
          ++int_like_qn) {
        SetMFType(qn_names_ptr, counter, STRING);
        SetMFValue(qn_names_ptr, counter,
            EnvAddSymbol(clips_environment_, int_like_qn->first.c_str()));
        SetMFType(qn_values_ptr, counter, INTEGER);
        SetMFValue(qn_values_ptr, counter,
            EnvAddLong(clips_environment_, int_like_qn->second));
        ++counter;
      }
      for (auto double_like_qn = spinwave.double_like_quantum_numbers_.begin();
          double_like_qn != spinwave.double_like_quantum_numbers_.end();
          ++double_like_qn) {
        SetMFType(qn_names_ptr, counter, STRING);
        SetMFValue(qn_names_ptr, counter,
            EnvAddSymbol(clips_environment_, double_like_qn->first.c_str()));
        SetMFType(qn_values_ptr, counter, INTEGER);
        SetMFValue(qn_values_ptr, counter,
            EnvAddLong(clips_environment_, double_like_qn->second));
        ++counter;
      }

      DATA_OBJECT qn_names;
      DATA_OBJECT qn_values;

      SetType(qn_names, MULTIFIELD);
      SetValue(qn_names, qn_names_ptr);

      SetDOBegin(qn_names, 1);
      SetDOEnd(qn_names, total_qn_count);

      SetType(qn_values, MULTIFIELD);
      SetValue(qn_values, qn_values_ptr);

      SetDOBegin(qn_values, 1);
      SetDOEnd(qn_values, total_qn_count);

      EnvPutFactSlot(clips_environment_, spinwave_fact, "quantum_number_names",
          &qn_names);
      EnvPutFactSlot(clips_environment_, spinwave_fact, "quantum_number_values",
          &qn_values);

      EnvAssignFactSlotDefaults(clips_environment_, spinwave_fact);
      EnvAssert(clips_environment_, spinwave_fact);
    }
  }
  return spinwave_fact;
}

问题是 final_state 多槽变量仅在某些情况下被正确填充,例如,如果我有 1、3、4、6、... 里面的值,但没有 2 和 5!当我想在里面放两个时,多槽内只有一些接近 0 的浮点数。如果我使用 5,那么它在断言事实时会崩溃。对我来说似乎是一些内存分配问题。我调试了 c++ 代码,它为 EnvCreateMultifield 函数传递了一个合适的大小值。我真的不知道是什么原因造成的。有什么想法吗?

【问题讨论】:

  • void*指针有一定的异味。
  • 是的,但那是剪辑界面......我这里真的没有选择
  • 这看起来与您之前在此处遇到的问题相同:stackoverflow.com/questions/34918259/…。由于 InitialAndFinalState 事实的创建可能需要多次调用 EnvEval 和 EnvAssert,因此我建议通过调用 EnvIncrementGCLocks/EnvDecrementGCLocks 来包装该过程,看看是否能解决您的问题。

标签: c++ clips


【解决方案1】:

正如 Gary 在评论中提到的那样,用

包装该函数
EnvIncrementGCLocks/EnvDecrementGCLocks

解决问题。

【讨论】:

    猜你喜欢
    • 2021-03-19
    • 1970-01-01
    • 2015-06-07
    • 1970-01-01
    • 1970-01-01
    • 2021-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多