def test_generate_derivations_within_trial():
    assert DerivationProcessor.generate_derivations(blk) == [
        Derivation(4, [[0, 2], [1, 3]], con_factor),
        Derivation(5, [[0, 3], [1, 2]], con_factor)
    ]

    integer = Factor("integer", ["1", "2"])
    numeral = Factor("numeral", ["I", "II"])
    text = Factor("text", ["one", "two"])

    twoConLevel = DerivedLevel("twoCon",
                               WithinTrial(two_con, [integer, numeral, text]))
    twoNotConLevel = DerivedLevel(
        "twoNotCon", WithinTrial(two_not_con, [integer, numeral, text]))
    two_con_factor = Factor("twoCon?", [twoConLevel, twoNotConLevel])

    one_two_design = [integer, numeral, text, two_con_factor]
    one_two_crossing = [integer, numeral, text]

    assert DerivationProcessor.generate_derivations(
        fully_cross_block(one_two_design, one_two_crossing, [])) == [
            Derivation(6,
                       [[0, 2, 5], [0, 3, 4], [0, 3, 5], [1, 2, 4], [1, 2, 5],
                        [1, 3, 4]], two_con_factor),
            Derivation(7, [[0, 2, 4], [1, 3, 5]], two_con_factor)
        ]
Пример #2
0
def test_generate_derivations_when_derived_factor_precedes_dependencies():
    block = fully_cross_block([congruency, motion, color, task],
                              [color, motion, task], [])
    derivations = DerivationProcessor.generate_derivations(block)

    assert Derivation(0, [[4, 2], [5, 3]], congruency) in derivations
    assert Derivation(1, [[4, 3], [5, 2]], congruency) in derivations
def test_generate_derivations_with_window():
    block = fully_cross_block([color, text, congruent_bookend], [color, text], [])

    assert DerivationProcessor.generate_derivations(block) == [
        Derivation(16, [[0, 2], [1, 3]], congruent_bookend),
        Derivation(17, [[0, 3], [1, 2]], congruent_bookend)
    ]
def test_generate_derivations_transition(design):
    block = fully_cross_block(design, [color, text], [])

    assert DerivationProcessor.generate_derivations(block) == [
        Derivation(16, [[0, 4], [1, 5]], color_repeats_factor),
        Derivation(17, [[0, 5], [1, 4]], color_repeats_factor)
    ]
Пример #5
0
def fully_cross_block(design: List[Factor],
                      crossing: List[Factor],
                      constraints: List[Constraint],
                      cnf_fn=to_cnf_tseitin) -> Block:
    all_constraints = cast(List[Constraint],
                           [FullyCross, Consistency]) + constraints
    block = FullyCrossBlock(design, crossing, all_constraints, cnf_fn)
    block.constraints += DerivationProcessor.generate_derivations(block)
    return block
Пример #6
0
def test_generate_derivations_with_transition_that_depends_on_derived_levels():
    block = fully_cross_block(
        [color, motion, task, response, response_transition],
        [color, motion, task], [])
    derivations = DerivationProcessor.generate_derivations(block)

    assert Derivation(64, [[6, 14], [7, 15]],
                      response_transition) in derivations
    assert Derivation(65, [[6, 15], [7, 14]],
                      response_transition) in derivations
Пример #7
0
def fully_cross_block(design: List[Factor],
                      crossing: List[Factor],
                      constraints: List[Constraint],
                      require_complete_crossing=True,
                      cnf_fn=to_cnf_tseitin) -> Block:
    """Returns a fully crossed :class:`.Block` meant to be used in experiment
    synthesis. This is the preferred mechanism for describing an experiment.

    :param design:
        A :class:`list` of all the :class:`Factors <.Factor>` in the design.
        When a sequence of trials is generated, each trial will have one level
        from each factor in ``design``.

    :param crossing:
        A :class:`list` of :class:`Factors <.Factor>` used to produce
        crossings. The number of trials in each run of the experiment is
        determined as the product of the number of levels of factors in
        ``crossing``.

        If ``require_complete_crossing`` is ``False``, the ``constraints`` can
        reduce the total number of trials.

        Different trial sequences of the experiment will have different
        combinations of levels in different orders. The factors in ``crossing``
        supply an implicit constraint that every combination of levels in the
        cross should appear once. Derived factors impose additional
        constraints: only combinations of levels that are consistent with
        derivations can appear as a trial. Additional constraints can be
        manually imposed via the ``constraints`` parameter.

    :param constraints:
        A :class:`list` of :class:`Constraints <.Constraint>` that restrict the
        generated trials.

    :param require_complete_crossing:
        Whether every combination in ``crossing`` must appear in a block of
        trials. ``True`` by default. A ``False`` value is appropriate if
        combinations are excluded through an :class:`.Exclude`
        :class:`.Constraint`.

    :param cnf_fn:
        A CNF conversion function. Default is :func:`.to_cnf_tseitin`.
    """
    all_constraints = cast(List[Constraint],
                           [FullyCross(), Consistency()]) + constraints
    all_constraints = __desugar_constraints(
        all_constraints)  #expand the constraints into a form we can process.
    block = FullyCrossBlock(design, [crossing], all_constraints,
                            require_complete_crossing, cnf_fn)
    block.constraints += DerivationProcessor.generate_derivations(block)
    if not constraints and not list(filter(
            lambda f: f.is_derived(), crossing)) and not list(
                filter(lambda f: f.has_complex_window, design)):
        block.complex_factors_or_constraints = False
    return block
def test_generate_derivations_with_multiple_transitions(design):
    block = fully_cross_block([color, text, color_repeats_factor, text_repeats_factor],
                              [color, text],
                              [])

    assert DerivationProcessor.generate_derivations(block) == [
        Derivation(16, [[0, 4], [1, 5]], color_repeats_factor),
        Derivation(17, [[0, 5], [1, 4]], color_repeats_factor),
        Derivation(22, [[2, 6], [3, 7]], text_repeats_factor),
        Derivation(23, [[2, 7], [3, 6]], text_repeats_factor)
    ]
def test_generate_derivations():
    assert DerivationProcessor.generate_derivations(block) == [
        Derivation(16,
                   [[0, 4, 2, 7], [0, 4, 3, 6], [0, 5, 2, 6], [0, 5, 3, 7],
                    [1, 4, 2, 6], [1, 4, 3, 7], [1, 5, 2, 7], [1, 5, 3, 6]],
                   change),
        Derivation(17,
                   [[0, 4, 2, 6], [0, 4, 3, 7], [0, 5, 2, 7], [0, 5, 3, 6],
                    [1, 4, 2, 7], [1, 4, 3, 6], [1, 5, 2, 6], [1, 5, 3, 7]],
                   change)
    ]
Пример #10
0
def multiple_cross_block(design: List[Factor],
                         crossings: List[List[Factor]],
                         constraints: List[Constraint],
                         require_complete_crossing=True,
                         cnf_fn=to_cnf_tseitin) -> Block:
    """Returns a :class:`.Block` with multiple crossings, meant to be used in
    experiment synthesis. Similar to :func:`fully_cross_block`, except it can
    be configured with multiple crossings.

    :param design:
        A :class:`list` of all the :class:`Factors <.Factor>` in the design.
        When a sequence of trials is generated, each trial will have one level
        from each factor in ``design``.

    :param crossings:
        A :class:`list` of :class:`lists <list>` of :class:`Factors <.Factor>`
        representing crossings. The number of trials in each run of the
        experiment is determined by the *maximum* product among the number of
        levels in the crossings.

        Every combination of levels in each individual crossing in
        ``crossings`` appears at least once. Different crossings can refer to
        the same factors, which constrains how factor levels are chosen across
        crossings.

    :param constraints:
        A :class:`list` of :class:`Constraints <.Constraint>` that restrict the
        generated trials.

    :param require_complete_crossing:
        Whether every combination in ``crossings`` must appear in a block of
        trials. ``True`` by default. A ``False`` value is appropriate if
        combinations are excluded through an :class:`.Exclude`
        :class:`.Constraint.`

    :param cnf_fn:
        A CNF conversion function. Default is :func:`.to_cnf_tseitin`.
    """
    all_constraints = cast(List[Constraint],
                           [MultipleCross(), Consistency()]) + constraints
    all_constraints = __desugar_constraints(
        all_constraints)  #expand the constraints into a form we can process.
    block = MultipleCrossBlock(design, crossings, all_constraints,
                               require_complete_crossing, cnf_fn)
    block.constraints += DerivationProcessor.generate_derivations(block)
    return block