Skip to content

Add forall() tutorial and example and index - #165

Open
juliannab-5 wants to merge 4 commits into
lab-v2:mainfrom
juliannab-5:forall-tutorial
Open

juliannab-5 wants to merge 4 commits into
lab-v2:mainfrom
juliannab-5:forall-tutorial

Conversation

@juliannab-5

Copy link
Copy Markdown

This was the tutorial for the forall() quantifier. I used Colton's example in the documentation.

Comment thread examples/forall_threshold_ex.py Outdated

pr.add_rule(
pr.Rule(
"ViewedByAll(y) <- HaveAccess(x,y), Viewed(x)",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This version doesn't use forall(), so the tutorial's "full code" link points to a file that doesn't use the feature. Look at the example Colton did, you can build from it instead of making a new different file

PyReason Forall Functionality
=================================

In this tutorial, we will look at how to utilize the forall function in a knowledge graph. The rule will fire only when all of the groundings of a given clause are true.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would help to say what a grounding is here, since the tutorial relies on the word. For example: "In this example, the groundings of x are the people who have access to the message."

))

The ``head`` of the rule is ``ViewedByAll(y)`` and the body is ``HaveAccess(x,y), forall(Viewed(x))``. The head and body are separated by an arrow which means the rule will start evaluating from
timestep ``0``.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The arrow <- means the head is inferred in the same timestep the body holds. <-1 would infer it one timestep later. It doesn't set when evaluation starts

The ``head`` of the rule is ``ViewedByAll(y)`` and the body is ``HaveAccess(x,y), forall(Viewed(x))``. The head and body are separated by an arrow which means the rule will start evaluating from
timestep ``0``.

``Viewed(x)`` checks to see if each grounding of ``x`` is true (or in this case has viewed the message). By wrapping the clause in ``forall(...)`` it fires only once all the groundings are true (in this case viewed the message).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the key part of the tutorial, so it's worth showing what forall changes. Without forall, the same rule fires at t=0, because by default one satisfying grounding is enough (Zach and Justin view at t=0). With forall it waits until t=2. A short "without forall" snippet with its output would make that clear. You could also mention that forall behaves the same as custom thresholds of number >= 1 and percent total >= 100, and link to custom_thresholds_tutorial as reference

In our case we want one person to view the ``TextMessage`` at a particular timestep.
For example, we create facts stating:

- ``Zach`` and ``Justin`` view the ``TextMessage`` from at timestep ``0``

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say at timestep 0 instead of "from at timestep 0"

- ``Zach`` and ``Justin`` view the ``TextMessage`` from at timestep ``0``
- ``Michelle`` views the ``TextMessage`` at timestep ``1``
- ``Amy`` views the ``TextMessage`` at timestep ``2``
- ``3`` is the last timestep the rule is active for all.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 is the end time of the facts, meaning each Viewed fact holds until timestep 3


.. code:: python

# Run the program for three timesteps to see the forall(..) function fire

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This runs through timestep 3, so the output shows four timesteps (0 to 3). Maybe say "run until timestep 3"

print()

This specifies how many timesteps to run for.
This formats the output to display the filtered node and edge data.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two sentences feel incomplete, maybe merge them into one line explaining the reason call and the output loop

1. For timestep 0, we set ``Zach -> Viewed: [1,1]`` and ``Justin -> Viewed: [1,1]`` in the facts
2. For timestep 1, ``Michelle`` views the TextMessage as stated in facts ``Michelle -> Viewed: [1,1]``.
3. For timestep 2, since ``Amy`` has just viewed the ``TextMessage``, therefore ``Amy -> Viewed: [1,1]``. As per the rule,
since all the people have viewed the ``TextMessage``, the message is marked as ``ViewedByAll``.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you say explicitly that t=2 is the first timestep where every grounding holds, which is why forall fires there? And add a line for timestep 3: it's still ViewedByAll because the Viewed facts hold through t=3

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

Successfully merging this pull request may close these issues.

2 participants