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

Variation conditionals #91

Open
sk33z3r opened this issue Jun 23, 2022 · 5 comments
Open

Variation conditionals #91

sk33z3r opened this issue Jun 23, 2022 · 5 comments
Assignees
Labels
enhancement New feature or request
Milestone

Comments

@sk33z3r
Copy link
Collaborator

sk33z3r commented Jun 23, 2022

Examples:

"conditions": { // Variation-level condition
    "Black": {"include_when": {"Colour": "Green"}}, // "Black" variation for this layer is included if the "Colour" layer variation is Green
    "Blue": {"exclude_when": {"Colour": "Orange"}}, // "Blue" variation for this layer is excluded if the "Colour" layer variation is Orange
    "Brown": {"exclude_when": { NOT: {"Colour": "Blue"}}}, // "Brown" variation for this layer is excluded if the "Colour" variation is NOT Blue
    "Green": {"include_when": { AND: {"Colour": "Yellow"}, {"Hat": "Beret"}}}, // "Green" variation for this layer is included if Colour is Yellow AND Hat is Beret
    "Green": {"exclude_when": { OR: {"Colour": "Yellow"}, {"Hat": "Cowboy"}}}, // "Green" variation for this layer is excluded if Colour is Yellow OR Hat is Cowboy
}
@sk33z3r sk33z3r added the enhancement New feature or request label Jun 23, 2022
@sk33z3r sk33z3r added this to the 1.1.0 milestone Jun 23, 2022
@sk33z3r
Copy link
Collaborator Author

sk33z3r commented Jun 23, 2022

Rarity for whole layers

@Montspy
Copy link
Owner

Montspy commented Jun 29, 2022

A few things need to come together for this feature:

  • More efficient random sampling algorithm (without replacement): dev/faster-random-sampling
  • Efficient algorithm to exclude invalid variation combinations from the random sample pool
    Because they violate one or more layer-level or variation-level conditionals
    • Ideally without replacement (never randomly pick invalid combinations)
    • Or with a single replacement (randomly pick combination, check that it is invalid, never pick again)
      Such an algorithm is much simpler to implement if a condition on layer i can only dependent on layers j < i
  • Parsing of the conditions layer key into boolean expressions
  • In-UI conditions "builder"

@Montspy Montspy self-assigned this Jun 29, 2022
@Montspy
Copy link
Owner

Montspy commented Jul 7, 2022

Some minor corrections to the JSON format:

"conditions": { // Variation-level condition
    "Black": { "include_when": { "Colour": "Green"} }, // "Black" variation for this layer is included if the "Colour" layer variation is Green
    "Blue": { "exclude_when": { "Colour": "Orange" } }, // "Blue" variation for this layer is excluded if the "Colour" layer variation is Orange
    "Brown": { "exclude_when": { "NOT": { "Colour": "Blue" } } }, // "Brown" variation for this layer is excluded if the "Colour" variation is NOT Blue
    "Green": {
        "include_when": { "AND": { "Colour": "Yellow" }, { "Hat": "Beret" } }, // "Green" variation for this layer is included if Colour is Yellow AND Hat is Beret
        "exclude_when": { "OR": { "Colour": "Yellow" }, { "Hat": "Cowboy" } } // "Green" variation for this layer is excluded if Colour is Yellow OR Hat is Cowboy
    }
}

@Montspy
Copy link
Owner

Montspy commented Jul 7, 2022

Proof of concept of the variation conditionals working with the new random sampler is here 10c3633
It implements a single replacement algorithm, and allows for conditions on layer i to depend on any layer j != i

Example of a validation callback for the random sampler:

rs = RandomSampler(weights)
rs.set_validation_callback( # layer["Color"] == 'Blue' and layer["Landscape"] == 'Tunnel' is invalid
    lambda pick: True if len(pick) < 2 else not (pick[0] == 2 and pick[1] == 2),
    validate_each_layer=True
)

No parsing of the conditions from JSON or UI yet.

@Montspy
Copy link
Owner

Montspy commented Jul 8, 2022

Turns out, we don't need to re-invent the wheel!
Boolean expressions can be represented by a binary expression tree

To keep it JSON compatible, we can keep using dictionaries to represent the tree in Python and in JSON.
Binary operators (values of op key):

  • OR: evaluated to node['left'] OR node['right']
  • AND: evaluated to node['left'] AND node['right']

Unary operators (only left key parsed):

  • NOT: evaluated to NOT node['left']

Leaves "operators" (used to parse values):

  • VALUE: evaluated to bool(node['value']) (should be true or false)
  • VARIATION: evaluated to
(node['layer'] in layers) and (layers[node['layer']] == node['variation'])

Each layer variation that needs a conditional will follow the same basic syntax:

"conditions": { // Variation-level conditions (a binary expression tree per variation)
    "VARIATION_NAME1": { 
        "op": "AND", 
        "left": {
            // `include_when` binary expression tree
        },
        "right": {
            "op": "NOT",
            "left": {
                // `exclude_when` binary expression tree
            }
        }
    },
    "VARIATION_NAME2": {
        // ...
    }
}

Example for "Black" and "Green":

"conditions": { // Variation-level conditions (a binary expression tree per variation)
    "Black": { 
        "op": "AND", 
        "left": { // `include_when` binary expression tree
            "op": "VARIATION",
            "layer": "Colour",
            "variation": "Green"
        },
        "right": { // `NOT exclude_when` binary expression tree
            "op": "NOT",
            "left": { "op": "VALUE", "value": false }
        }
    },
    "Green": { 
        "op": "AND", 
        "left": { // `include_when` binary expression tree
            "op": "AND",
            "left": {
                "op": "VARIATION",
                "layer": "Colour",
                "variation": "Yellow"
            },
            "right": {
                "op": "VARIATION",
                "layer": "Hat",
                "variation": "Beret"
            }
        },
        "right": { // `NOT exclude_when` binary expression tree
            "op": "NOT",
            "left": { // `exclude_when` binary expression tree
                "op": "OR",
                "left": {
                    "op": "VARIATION",
                    "layer": "Colour",
                    "variation": "Red"
                },
                "right": {
                    "op": "VARIATION",
                    "layer": "Hat",
                    "variation": "Cowboy"
                }
            }
        }
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants