maxitg / SetReplace

C++/Wolfram Language package for exploring set and graph rewriting systems
MIT License
219 stars 45 forks source link

Use ManagedExpressions in low-level implementation #574

Closed daneelsan closed 3 years ago

daneelsan commented 3 years ago

The problem

https://reference.wolfram.com/language/LibraryLink/tutorial/InteractionWithWolframLanguage.html#353220453

Possible solution

A clear and concise description of what you want to happen.

Alternative solutions

A clear and concise description of any alternative solutions or features you've considered.

Additional context

Add any other context or screenshots about the feature request here.

daneelsan commented 3 years ago

Might also be useful: https://community.wolfram.com/groups/-/m/t/2133603

maxitg commented 3 years ago

Hi @daneelsan, are you still working on this? If not, can I take this ticket? I need it for the low-level implementation of evolution videos #443.

daneelsan commented 3 years ago

I did work on a few things but not much. Take away :)

daneelsan commented 3 years ago

I was doing

void setManageInstance(WolframLibraryData libData, mbool mode, mint setID) {
  if (mode == 0) {
    setsToManage_.insert({setID, false});
  } else {
    const auto setToDeleteIterator = setsInstance_.find(setID);
    if (setToDeleteIterator != setsInstance_.end()) {
      setsInstance_.erase(setToDeleteIterator);
    }
    setsToManage_.erase(setID);
  }
}

int setReleaseInstance(WolframLibraryData libData, mint argc, const MArgument* argv, MArgument result) {
  if (argc != 1) {
    return LIBRARY_FUNCTION_ERROR;
  }

  mint setID = MArgument_getInteger(argv[0]);
  return libData->releaseManagedLibraryExpression("SetReplace", setID);
}

int setCreateInstance(WolframLibraryData libData, mint argc, const MArgument* argv, MArgument result) {
  if (argc != 8) {
    return LIBRARY_FUNCTION_ERROR;
  }

  std::vector<Rule> rules;
  std::vector<AtomsVector> initialExpressions;
  Set::SystemType systemType;
  Matcher::OrderingSpec orderingSpec;
  Matcher::EventDeduplication eventDeduplication;
  unsigned int randomSeed;
  try {
    rules = getRules(libData, MArgument_getMTensor(argv[0]), MArgument_getMTensor(argv[1]));
    initialExpressions = getSet(libData, MArgument_getMTensor(argv[2]));
    systemType = static_cast<Set::SystemType>(MArgument_getInteger(argv[3]));
    orderingSpec = getOrderingSpec(libData, MArgument_getMTensor(argv[4]));
    eventDeduplication = static_cast<Matcher::EventDeduplication>(MArgument_getInteger(argv[5]));
    randomSeed = static_cast<unsigned int>(MArgument_getInteger(argv[6]));
  } catch (...) {
    return LIBRARY_FUNCTION_ERROR;
  }

  SetID thisSetID = MArgument_getInteger(argv[7]);
  if (setsToManage_.find(thisSetID) == setsToManage_.end()) {
    return LIBRARY_FUNCTION_ERROR;
  }

  try {
    setsInstance_.insert({thisSetID, Set(rules, initialExpressions, systemType, orderingSpec, eventDeduplication, randomSeed)});
    setsToManage_[thisSetID] = true;
  } catch (...) {
    return LIBRARY_FUNCTION_ERROR;
  }

  MArgument_setInteger(result, thisSetID);
  return LIBRARY_NO_ERROR;
}

Where setsToManage_ keeps tabs on which ID's have been initialized or not, and setsInstance_ works just like sets_. I did it this way to avoid defining a default constructor for new Set() (and change all const attributes). So instead of initializing the ID in setManageInstance as the ManagedExpressions examples would normally do, I do it in setCreateInstance.

std::unordered_map<mint, Set> setsInstance_;
std::unordered_map<mint, bool> setsToManage_;
maxitg commented 3 years ago

@daneelsan, I think it might be better to just use LLU (your second link) which supports custom constructors. Plus, we won't have to define a new DLLEXPORT function for every property.

daneelsan commented 3 years ago

Yes I was playing with it a bit. It even allows passing and return "structs": https://wolframresearch.github.io/LibraryLinkUtilities/modules/functions.html#user-defined-types

maxitg commented 3 years ago

Very nice! Ok, let me see how we can integrate it in a reasonably seamless way.