Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Solver class #1

Closed
jar2333 opened this issue Nov 16, 2022 · 1 comment
Closed

Solver class #1

jar2333 opened this issue Nov 16, 2022 · 1 comment

Comments

@jar2333
Copy link
Owner

jar2333 commented Nov 16, 2022

ITERATION1:
A class implementing the WFC algorithm for 2D grids. It uses an auxiliary Grid class to abstract the details of the grid. A Direction enum could help:

enum Direction { UP, DOWN, LEFT, RIGHT };

typedef std::pair<int, Direction> Side; //tile and direction for constraints

class Grid {
public:
  Grid(int N);
  inline int get(int i, int j);
  inline int set(int i, int j);
};

class Solver {
public:
  Solver(std::vector<int> tiles, std::map<Side, std::vector<int>> constraints, int seed=0);
  void setSeed(int seed);
  Grid solve(int N);

  //calls registered function with tile in collapsed grid slot
  void onCollapse(std::function<void(int, int, int)> callback);

  //calls registered function with possible tiles in collapsed grid slot
  void onPropagate(std::function<void(std::vector<int>, int, int)> callback); 
};

ITERATION 2:
Add a template parameter to determine the tile type. Makes callbacks easier to use. Options for choosing custom collapse heuristic instead of the min entropy heuristic:

template<typename T>
class Solver {
public:
  Solver(std::map<int, T> tiles, std::map<Side, std::vector<int>> constraints, int seed=0);
  void setSeed(int seed);
  Grid<T> solve(int N); //Grid parameterized in the obvious way

  //low level function to change heuristic (change vector to a span/iterable through templating?
  void setHeuristic(std::function<int(std::vector&<int>)> );
  void setHeuristic(std::function<int(std::vector&<int>, std::map<int, T>& tiles)> );

  //calls registered function with tile in collapsed grid slot
  void onCollapse(std::function<void(T, int, int)> callback);

  //calls registered function with possible tiles in collapsed grid slot
  void onPropagate(std::function<void(std::vector<T>, int, int)> callback); 

private:
   std::map<int, T> tiles
};
@jar2333 jar2333 mentioned this issue Nov 16, 2022
@jar2333
Copy link
Owner Author

jar2333 commented Nov 20, 2022

Better idea:

The adjacency constraint map is an implementation detail, instead provide an interface for setting constraints. This way, constraint creation controller classes can be created which read configuration files or such and programmatically apply the constraints to a given solver, or they can be added manually.

Points to look at:

  • abstract away grid coordinates using some Coordinate type instead of two random ints

  • templating for the callbacks? compile time evaluation can be used maybe?

  • Make the TileKey type generic! (solver/grid becomes like a map)

  • change to unordered map

  • make the default constructor that takes a vector generic for any iterable

  • make the contraint method that adds a set of neighbors generic for any iterable

  • allow fixed size for big optimization possibilities (bitset)

  • make tilekey type a concept

  • add template specializations when TileKey is an int-like thing (incrementable?) to be used with the generic iterable default constructor (trivial automatic tilekey generation)

struct Position {
   int x;
   int y;
};

template<typename TileKey, typename T>
class Solver {

public:

  //the main way of using the library, the int keys are auto-generated from vector as the indeces
  Solver(std::vector<T> tiles, int seed=0);
  //similar, but keys are provided explicitly for each tile
  Solver(std::map<TileKey, T> tiles, int seed=0);

  /*
   SOLVER API
  */

  //change seed whenever
  void setSeed(int seed);
  Grid<T> solve(int N); //Grid parameterized in the obvious way

  /*
   CONSTRAINT INTERFACE/API
  */

  /* Adjacency constraints */
  //set the constraints using this specified interface
  void addAdjacencyConstraint(TileKey t, Direction d, TileKey neighbor);
  void removeAdjacencyConstraint(TileKey t, Direction d, TileKey neighbor);

  //using initializer list
  void addAdjacencyConstraints(TileKey t, Direction d, std::initializer_list<TileKey> neighbors);
  void removeAdjacencyConstraints((TileKey t, Direction d, std::initializer_list<TileKey> neighbors);

  //using iterators
  template <InputIterator<TileKey> IT> //find the eactual name of this constraint or use requires concepts
  void addAdjacencyConstraints((TileKey t, Direction d, IT begin, IT end);
  template <InputIterator<TileKey> IT>
  void removeAdjacencyConstraints((TileKey t, Direction d, IT begin, IT end);

  /* Initial constraints */
  void setInitialConstraint(Position p, TileKey possibility);
  void setInitialConstraint(Position p, std::initializer_list<TileKey> possibilities);
  template <InputIterator<TileKey> IT>
  void setInitialConstraint(Position p,  IT begin, IT end);
  

  /*
   CALLBACK INTERFACE/API
  */
 
  //To-do: returns a receipt object to deregister when out of scope?
  //API: calls registered function with tile in collapsed grid slot
  void onCollapse(std::function<void(const T&, Position)> callback);

  //API: calls registered function with possible tiles in collapsed grid slot
  void onPropagate(std::function<void(const std::vector<T>&, Position)> callback); 

  /*
   HEURISTIC INTERFACE
  */

  //low level function to change heuristic (change vector to a span/iterable through templating)
  void setHeuristic(std::function<TileKey(std::vector&<TileKey>)> heuristic);
  void setHeuristic(std::function<TileKey(std::vector&<TileKey>, std::map<TileKey, T>&)> heuristic ); //with tile type T info

private:
   std::map<TileKey, T> tiles
   std::function<TileKey(std::vector&<TileKey>)> heuristic;

   std::list<std::function<void(const T&, Position)> collapse_callbacks;
   std::list<std::function<void(const std::vector<T>&, Position)>> propagate_callbacks;
};

@jar2333 jar2333 closed this as completed Dec 3, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant