diff --git a/src/beanmachine/ppl/experimental/goal_inference/agent/boundedly_rational_agent.py b/src/beanmachine/ppl/experimental/goal_inference/agent/boundedly_rational_agent.py
new file mode 100644
index 0000000000..bdcca9a51a
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/agent/boundedly_rational_agent.py
@@ -0,0 +1,338 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from __future__ import annotations
+
+import copy
+
+from typing import List, Tuple
+
+import torch
+from beanmachine.facebook.goal_inference.agent.observation_model import ObservationModel
+
+from beanmachine.facebook.goal_inference.environment import State
+from beanmachine.facebook.goal_inference.planner.planner import (
+ get_execution_path,
+ Plan,
+ Planner,
+ StateNode,
+)
+
+from beanmachine.facebook.goal_inference.planner.stoch_astar import (
+ StochasticAstarProposalPlanner,
+)
+from torch.distributions.negative_binomial import NegativeBinomial
+
+
+class BoundedRationalAgent:
+
+ """
+ An Agent that makes and executes short term plans based on budgetary contrainsts.
+
+ Arguments:
+
+ planner: The strategy for determining short term plans
+ initial_state: Initial state of the problem
+ r: Parameter of negative binomial distribution. Determines the number of failures that must be exceeded
+ p: Parameter of negative binomial distribution. Determines the success/failure rate
+ max_steps: Maximum number of steps to execute
+
+ Attributes:
+
+ planner: The strategy for determining short term plans
+ r: Parameter of negative binomial distribution. Determines the number of failures that must be exceeded
+ p: Parameter of negative binomial distribution. Determines the success/failure rate
+ max_steps: Maximum number of steps to execute
+ action_step: Action step within the current plan
+ agent_step: Total number of steps by the agent
+ budget_dist(r,p): A negative binomial distribution: Samples the number of successful trials before r failures if the probability of success is p
+ plan_history: The series of plans constructed by this agent
+ plan_index: Index of curr_plan in plan_history
+ initial_node: Graph node defining the environment at the first time step.
+ curr_node: Graph node defining environment at current time step
+ proposal_planner: Proposal planner for path rejuvenation
+ """
+
+ def __init__(
+ self,
+ planner: Planner,
+ initial_state: State,
+ r: int = 2,
+ p: float = 0.95,
+ max_steps: int = 1000,
+ ):
+ self.planner: Planner = planner
+ self.r: int = r
+ self.p: float = p
+ self.max_steps: int = max_steps
+ self.agent_step: int = 0
+ self.action_step: int = 0
+ self.budget_dist: NegativeBinomial = NegativeBinomial(r, p)
+ self.plan_history: List[Plan] = []
+ self.plan_index: int = -1
+ self.initial_node: StateNode = StateNode(initial_state, None, [])
+ self.curr_node: StateNode = self.initial_node
+ self.proposal_planner: StochasticAstarProposalPlanner = (
+ StochasticAstarProposalPlanner(self.planner)
+ )
+
+ @property
+ def curr_plan(self) -> Plan:
+ """Gets the current plan based on the plan_history and plan_index
+
+ Returns:
+ curr_plan: The current plan
+ """
+ if self.plan_index == -1:
+ return Plan([], [], [], 0)
+ else:
+ return self.plan_history[self.plan_index]
+
+ def execute_search(self) -> Tuple[Plan, bool]:
+ """Evolves the system to a solution or until max_steps is reached. Uses short term plans.
+
+ Returns:
+ plan: The plan executed by the agent
+ solved: Whether a solution to the problem was reached
+ """
+
+ while (
+ not self.planner.domain.evaluate_goal(self.curr_node.state)
+ and self.agent_step < self.max_steps
+ ):
+ self.replan()
+ self.execute_plan()
+
+ return (
+ # pyre-fixme[19]: Expected 4 positional arguments.
+ Plan(
+ *get_execution_path(self.curr_node),
+ self.planner.visited_nodes,
+ self.max_steps,
+ ),
+ self.planner.domain.evaluate_goal(self.curr_node.state),
+ )
+
+ def execute_plan(self) -> None:
+ """Executes a short term plan. Stops Early if states deviate from expectation"""
+ while self.action_step < len(self.curr_plan.actions):
+ self._execute_step()
+
+ def replan(self) -> None:
+ """Updates the current plan based on the current state"""
+ new_plan, solved = self.planner.generate_plan(
+ self.curr_node.state,
+ int(self.budget_dist.sample((1,)).item()),
+ )
+ # Don't consider empty plans which can occur if a solution is already reached
+ if len(new_plan.actions) > 0:
+ self.action_step = 0
+ self.plan_history.append(new_plan)
+ self.plan_index += 1
+
+ def _execute_step(self) -> None:
+ """Executes a single action from the current plan"""
+ if not self.is_next_step_deviating():
+ new_node = StateNode(
+ self.curr_plan.states[self.action_step + 1],
+ executed=self.curr_plan.actions[self.action_step],
+ parent_node=self.curr_node,
+ )
+ self.curr_node = new_node
+ self.agent_step += 1
+ self.action_step += 1
+
+ else:
+ # The new state can deviate from the expected plan if actions are not deterministic
+ # In that case, we need a new plan before continuing (otherwise planned actions may be invalid)
+ self.action_step = len(self.curr_plan.actions)
+
+ def is_next_step_deviating(self) -> bool:
+ """Determines if next state deviates from expected plan
+
+ Returns:
+ is_deviating: Whether the next state deviates from the expectation of the plan
+ """
+ act = self.curr_plan.actions[self.action_step]
+ next_predicted_state = self.curr_plan.states[self.action_step + 1]
+ new_state = self.planner.domain.execute(self.curr_node.state, *act)
+ return not new_state == next_predicted_state
+
+ def step(self, num_steps: int = 1) -> None:
+ """Advances the agent by one time step
+
+ Arguments:
+ num_steps: The number of time steps to advance
+ """
+ for _step in range(num_steps):
+ while (
+ self.action_step >= len(self.curr_plan.actions)
+ or self.is_next_step_deviating()
+ ):
+ if self.planner.domain.evaluate_goal(self.curr_node.state):
+ break
+ self.replan()
+ # Make sure that current plan is not empty and agent is not at end of plan
+ # This condition can fail if a solution has been reached
+ if self.curr_plan.actions and self.action_step < len(
+ self.curr_plan.actions
+ ):
+ self._execute_step()
+
+ def propose_path(
+ self,
+ observations: List[State],
+ proposal_time_deviation: int,
+ noise_model: ObservationModel,
+ ) -> None:
+ """Proposes a new path for the bounded-rational agent starting from proposal_time_deviation
+
+ Arguments:
+ observations: The observed path
+ proposal_time_deviation: The time step to start proposing a new path
+ noise_model: A model for P(observation | state)
+ """
+ # Set time of bounded-agent to where proposed path diverges from previous path
+ self._set_to_timestep(proposal_time_deviation, clear=True)
+ while (
+ not self.planner.domain.evaluate_goal(self.curr_node.state)
+ and self.agent_step < len(observations) - 1
+ ):
+ while (
+ self.action_step >= len(self.curr_plan.actions)
+ or self.is_next_step_deviating()
+ ):
+ if self.planner.domain.evaluate_goal(self.curr_node.state):
+ break
+ # Propose the next plan
+ self.propose_plan(observations, noise_model)
+ # Make sure that current plan is not empty and agent is not at end of plan
+ # This condition can fail if a solution has been reached
+ if self.curr_plan.actions and self.action_step < len(
+ self.curr_plan.actions
+ ):
+ self._execute_step()
+
+ def propose_plan(
+ self, observations: List[State], noise_model: ObservationModel
+ ) -> None:
+ """Proposes the next plan during path rejuvenation
+
+ Arguments:
+ observations: The observed path
+ noise_model: A model for P(observation | state)
+
+ """
+ new_plan, solved = self.proposal_planner.propose(
+ self.curr_node.state,
+ observations,
+ self.budget_dist.sample((1,)).item(),
+ noise_model,
+ )
+ # Add this plan to the history of this agent
+ if len(new_plan.actions) > 0:
+ self.action_step = 0
+ self.plan_history.append(new_plan)
+ self.plan_index += 1
+
+ def __copy__(self) -> BoundedRationalAgent:
+ """Creates a shallow copy of a BoundedRationalAgent
+
+ Returns:
+ agent_copy: A shallow copy of the agent
+ """
+ agent_copy = BoundedRationalAgent(
+ self.planner,
+ self.initial_node.state,
+ r=self.r,
+ p=self.p,
+ max_steps=self.max_steps,
+ )
+
+ agent_copy.agent_step = self.agent_step
+ agent_copy.action_step = self.action_step
+ agent_copy.plan_history = copy.copy(self.plan_history)
+ agent_copy.plan_index = self.plan_index
+ agent_copy.curr_node = self.curr_node
+ return agent_copy
+
+ def get_log_prob(
+ self,
+ observations: List[State],
+ proposal_time_deviation: int,
+ noise_model: ObservationModel,
+ ) -> torch.Tensor:
+ """Evaluates the log probability of a series of plans
+
+ Arguments:
+ observations: The observed path
+ proposal_time_deviation: The time step to start proposing a new path
+ noise_model: A model for P(observation | state)
+
+ Returns:
+ log_prob: The log probability of the proposed series of plans
+
+ """
+ # Plans before divergence are not changed
+ time_step = 0
+ self.plan_index = 0
+ while time_step < proposal_time_deviation:
+ time_step += len(self.curr_plan.actions)
+ self.plan_index += 1
+ log_prob = torch.tensor(0.0)
+ # Compute contribution to proposal probability from each plan
+ while self.plan_index < len(self.plan_history):
+ # Computes probability of plan budget
+ log_prob_plan_length = self.budget_dist.log_prob(
+ torch.tensor(self.curr_plan.budget)
+ )
+ # Computes probability of specific planning process
+
+ log_prob_plan_visit = self.proposal_planner.get_log_prob(
+ self.curr_plan,
+ observations[
+ self.agent_step : self.agent_step + len(self.curr_plan.states)
+ ],
+ noise_model,
+ )
+ log_prob += log_prob_plan_length
+ log_prob += log_prob_plan_visit
+ self.plan_index += 1
+ self.plan_index = len(self.plan_history) - 1
+
+ return log_prob
+
+ def _set_to_timestep(self, time_step: int, clear: bool = True):
+ """Set time of bounded-agent to where proposed path diverges from previous path
+
+ Arguments:
+ proposal_time_deviation: The time step to start proposing a new path
+ clear: Whether to remove future plans when setting the time
+
+ """
+ # Start at initial conditions of bounded agent
+ self.plan_index = 0
+ self.agent_step = 0
+ self.action_step = 0
+ self.curr_node = self.initial_node
+ # Follow execute previous plans until deviation time
+ while self.agent_step < time_step:
+ new_node = StateNode(
+ self.curr_plan.states[self.action_step + 1],
+ executed=self.curr_plan.actions[self.action_step],
+ parent_node=self.curr_node,
+ )
+ self.curr_node = new_node
+ self.agent_step += 1
+ self.action_step += 1
+ # When plan is finished switch to the next one
+ if (
+ self.action_step == len(self.curr_plan.actions)
+ and self.agent_step != time_step
+ ):
+ self.action_step = 0
+ self.plan_index += 1
+
+ # Erase the remainder of the plans from the previous path
+ # Erase when proposing NOT when evaluating probability of proposal
+ if clear:
+ self.plan_history = self.plan_history[: self.plan_index + 1]
diff --git a/src/beanmachine/ppl/experimental/goal_inference/agent/boundedly_rational_agent_test.py b/src/beanmachine/ppl/experimental/goal_inference/agent/boundedly_rational_agent_test.py
new file mode 100644
index 0000000000..829c15e00b
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/agent/boundedly_rational_agent_test.py
@@ -0,0 +1,227 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import copy
+import dataclasses
+
+import pytest
+from beanmachine.facebook.goal_inference.agent.boundedly_rational_agent import (
+ BoundedRationalAgent,
+)
+from beanmachine.facebook.goal_inference.planner.planner import (
+ get_plan_from_actions,
+ Plan,
+)
+
+
+@pytest.fixture
+def agent_one(dkg_stoch_astar_planner, dkg_state_one):
+ return BoundedRationalAgent(dkg_stoch_astar_planner, dkg_state_one, r=10, p=0.5)
+
+
+@pytest.fixture
+def agent_two(dkg_stoch_astar_planner, dkg_state_two):
+ return BoundedRationalAgent(dkg_stoch_astar_planner, dkg_state_two, r=10, p=0.5)
+
+
+@pytest.fixture
+def agent_three(dkg_stoch_astar_planner, dkg_state_three):
+ return BoundedRationalAgent(dkg_stoch_astar_planner, dkg_state_three, r=10, p=0.5)
+
+
+def test_initialize_dkg_bounded_agent(agent_one):
+ assert agent_one.agent_step == 0
+
+
+def test_dkg_bounded_agent_problem_1(agent_one):
+ plan, solved = agent_one.execute_search()
+ assert solved
+ planner = agent_one.planner
+ state = agent_one.curr_node.state
+ assert planner.domain.evaluate_goal(state)
+
+
+def test_dkg_bounded_agent_problem_2(agent_two):
+ plan, solved = agent_two.execute_search()
+ assert solved
+ planner = agent_two.planner
+ state = agent_two.curr_node.state
+ assert planner.domain.evaluate_goal(state)
+
+
+def test_dkg_bounded_agent_impossible_task(agent_two):
+ # Make task impossible
+ new_at = agent_two.curr_node.state.at
+ new_at.pop("key1")
+ agent_two.curr_node.state = dataclasses.replace(
+ agent_two.curr_node.state, keys={}, at=new_at
+ )
+ plan, solved = agent_two.execute_search()
+ assert (agent_two.agent_step >= 1000) and not solved
+
+
+def test_dkg_bounded_agent_replan(agent_two):
+ agent_two.replan()
+ curr_plan = agent_two.curr_plan
+ assert isinstance(agent_two.curr_plan, Plan)
+ assert len(curr_plan.states) == len(curr_plan.actions) + 1
+
+
+def test_replan_after_solved_is_unchanged(agent_two):
+ plan, solved = agent_two.execute_search()
+ num_plans = len(agent_two.plan_history)
+ assert solved
+ agent_two.replan()
+ curr_plan = agent_two.curr_plan
+ assert curr_plan.states == agent_two.plan_history[num_plans - 1].states
+
+
+def test_dkg_bounded_agent_execute_plan(agent_two):
+ agent_two.replan()
+ curr_plan = agent_two.curr_plan
+ initial_steps = agent_two.agent_step
+ agent_two.execute_plan()
+ assert agent_two.curr_node.state == curr_plan.states[-1]
+ assert agent_two.agent_step == initial_steps + len(curr_plan.actions)
+
+
+def test_dkg_bounded_agent_execute_plan_break(agent_two):
+ agent_two.replan()
+ while len(agent_two.curr_plan.actions) < 3:
+ agent_two.replan()
+ curr_plan = agent_two.curr_plan
+ initial_steps = agent_two.agent_step
+ # Create an unexpected state
+ curr_plan.states[-1] = curr_plan.states[0]
+ agent_two.execute_plan()
+ assert agent_two.curr_node.state == curr_plan.states[-2]
+ assert agent_two.agent_step == initial_steps + len(curr_plan.actions) - 1
+
+
+def test_dkg_bounded_agent_total_plan(agent_two):
+ plan, solved = agent_two.execute_search()
+ assert solved
+ assert isinstance(plan, Plan)
+ assert len(plan.states) == len(plan.actions) + 1
+ assert len(plan.actions) == agent_two.agent_step
+
+
+def test_execute_step_match_expected(agent_two):
+ agent_two.replan()
+ while len(agent_two.curr_plan.actions) < 3:
+ agent_two.replan()
+ curr_plan = agent_two.curr_plan
+ agent_two._execute_step()
+ assert agent_two.agent_step == 1
+ assert agent_two.action_step == 1
+ assert agent_two.curr_node.state == curr_plan.states[1]
+ agent_two._execute_step()
+ assert agent_two.agent_step == 2
+ assert agent_two.action_step == 2
+ assert agent_two.curr_node.state == curr_plan.states[2]
+
+
+def test_execute_step_break_expected(agent_two):
+ agent_two.replan()
+ while len(agent_two.curr_plan.actions) < 3:
+ agent_two.replan()
+ curr_plan = agent_two.curr_plan
+ # Create an unexpected state
+ curr_plan.states[2] = curr_plan.states[0]
+ agent_two._execute_step()
+ assert agent_two.agent_step == 1
+ assert agent_two.action_step == 1
+ assert agent_two.curr_node.state == curr_plan.states[1]
+ agent_two._execute_step()
+ assert agent_two.agent_step == 1
+ assert agent_two.action_step == len(curr_plan.actions)
+ assert agent_two.curr_node.state == curr_plan.states[1]
+
+
+def test_advance_single_time_step(agent_three):
+ agent_three.replan()
+ while len(agent_three.curr_plan.actions) < 3:
+ agent_three.replan()
+ agent_three.step()
+ curr_plan = agent_three.curr_plan
+ assert agent_three.agent_step == 1
+ assert agent_three.action_step == 1
+ assert agent_three.curr_node.state == curr_plan.states[1]
+ agent_three.step()
+ assert agent_three.agent_step == 2
+ assert agent_three.action_step == 2
+ assert agent_three.curr_node.state == curr_plan.states[2]
+
+
+def test_advance_n_time_steps(agent_three):
+ agent_three.replan()
+ while len(agent_three.curr_plan.actions) < 3:
+ agent_three.replan()
+ agent_three.step()
+ curr_plan = agent_three.curr_plan
+ assert agent_three.agent_step == 1
+ assert agent_three.action_step == 1
+ assert agent_three.curr_node.state == curr_plan.states[1]
+ # Time step through a new plan
+ steps_for_new_plan = len(curr_plan.actions)
+ agent_three.step(steps_for_new_plan)
+ curr_plan = agent_three.curr_plan
+ assert agent_three.agent_step == steps_for_new_plan + 1
+ assert agent_three.action_step == 1
+ assert agent_three.curr_node.state == curr_plan.states[1]
+
+
+def test_advance_n_time_steps_break_expected(
+ agent_three,
+):
+ agent_three.replan()
+ while len(agent_three.curr_plan.actions) < 3:
+ agent_three.replan()
+ curr_plan = agent_three.curr_plan
+ # Create an unexpected state
+ curr_plan.states[-1] = curr_plan.states[0]
+ # Should break from first plan one step early and be one step into second plan
+ agent_three.step(len(curr_plan.actions))
+ assert agent_three.agent_step == len(curr_plan.actions)
+ assert agent_three.action_step == 1
+ assert agent_three.curr_node.state == agent_three.curr_plan.states[1]
+
+
+def test_advance_time_steps_after_solution(agent_two):
+ plan, solved = agent_two.execute_search()
+ assert solved
+ old_time_step = agent_two.agent_step
+ old_state = agent_two.curr_node.state
+ agent_two.step()
+ assert agent_two.agent_step == old_time_step
+ assert agent_two.curr_node.state == old_state
+
+
+def test_agent_copy(agent_two):
+ new_agent = copy.copy(agent_two)
+ assert new_agent.agent_step == agent_two.agent_step
+ new_agent.step()
+ assert new_agent.agent_step != agent_two.agent_step
+
+
+def test_bounded_agent_set_time(dkg_stoch_astar_planner, dkg_state_three):
+ agent = BoundedRationalAgent(dkg_stoch_astar_planner, dkg_state_three, r=2, p=0.95)
+ agent_actions = [
+ ["right"],
+ ["right"],
+ ["right"],
+ ]
+ plan = get_plan_from_actions(
+ dkg_stoch_astar_planner.domain, dkg_state_three, agent_actions
+ )
+ agent.plan_history.append(plan)
+ agent.plan_index += 1
+ length_plan_one = len(agent.curr_plan.actions)
+ agent.execute_plan()
+ agent.replan()
+ agent.execute_plan()
+ agent.replan()
+ agent.execute_plan()
+ time = length_plan_one + 1
+ agent._set_to_timestep(time)
+ assert agent.plan_index == 1
+ assert agent.agent_step == time
diff --git a/src/beanmachine/ppl/experimental/goal_inference/agent/observation_model.py b/src/beanmachine/ppl/experimental/goal_inference/agent/observation_model.py
new file mode 100644
index 0000000000..8cf67e5b9d
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/agent/observation_model.py
@@ -0,0 +1,89 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import dataclasses
+from abc import ABC, abstractmethod
+from typing import List
+
+import torch
+from beanmachine.facebook.goal_inference.environment import State
+
+
+class ObservationModel(ABC):
+ """Defines a probability distribution for observing states"""
+
+ @abstractmethod
+ def apply_noise(self, state) -> State:
+ """Applies noise to a state to obtain an observation
+
+ Arguments:
+ state: The state to apply noise to
+
+ Returns:
+ noisy_state: The state with noise applied
+
+ """
+ pass
+
+ @abstractmethod
+ def get_log_prob(self, state, observation) -> torch.Tensor:
+ """Gets the log probability of a observation given a state
+
+ Arguments:
+ state: The reference state
+ observation: The noisy observation
+
+ Returns:
+ log_prob: The log of P(observation|state)
+
+ """
+ pass
+
+
+class DeterministicObservation(ObservationModel):
+ """Defines an observation model with no noise"""
+
+ def apply_noise(self, state: State) -> State:
+ """Applies no noise to a state
+
+ Arguments:
+ state: The state to apply noise to
+
+ Returns:
+ state: The state with no noise applied
+
+ """
+ return dataclasses.replace(state)
+
+ def get_log_prob(self, state: State, observation: State) -> torch.Tensor:
+ """Gets the log probability of a observation given a state assuming P(observation | state) is a delta function
+
+ Arguments:
+ state: The reference state
+ observation: The noisy observation
+
+ Returns:
+ log_prob: The log of P(observation|state)
+
+ """
+ if state == observation:
+ return torch.tensor(0.0)
+ return torch.tensor(-float("inf"))
+
+
+def apply_noise_to_states(
+ states: List[State], noise_model: ObservationModel
+) -> List[State]:
+ """Applies noise to a series of states, returning a set of observations
+
+ Arguments:
+ states: The series of states to apply noise to
+ noise_model: The model defining the applied noise
+
+ Returns:
+ observations: A series of observations corresponding to states with applied noise
+
+ """
+ observations = []
+ for state in states:
+ observations.append(noise_model.apply_noise(state))
+ return observations
diff --git a/src/beanmachine/ppl/experimental/goal_inference/agent/observation_model_test.py b/src/beanmachine/ppl/experimental/goal_inference/agent/observation_model_test.py
new file mode 100644
index 0000000000..cac4c9b4cd
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/agent/observation_model_test.py
@@ -0,0 +1,18 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import dataclasses
+
+import torch
+
+from beanmachine.facebook.goal_inference.agent.observation_model import (
+ DeterministicObservation,
+)
+
+
+def test_deterministic_noise(dkg_state_two):
+ noise_model = DeterministicObservation()
+ new_state = noise_model.apply_noise(dkg_state_two)
+ assert new_state == dkg_state_two
+ new_state_two = dataclasses.replace(dkg_state_two, x=dkg_state_two.x + 1)
+ assert torch.isneginf(noise_model.get_log_prob(new_state_two, dkg_state_two))
+ assert noise_model.get_log_prob(new_state, dkg_state_two) == 0.0
diff --git a/src/beanmachine/ppl/experimental/goal_inference/conftest.py b/src/beanmachine/ppl/experimental/goal_inference/conftest.py
new file mode 100644
index 0000000000..445f877bc7
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/conftest.py
@@ -0,0 +1,87 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import pytest
+
+from beanmachine.facebook.goal_inference.doors_keys_gems.dkg_domain import DKGDomain
+
+from beanmachine.facebook.goal_inference.doors_keys_gems.parser import parse
+
+from beanmachine.facebook.goal_inference.planner.astar import AstarPlanner
+
+from beanmachine.facebook.goal_inference.planner.planner import get_plan_from_actions
+
+from beanmachine.facebook.goal_inference.planner.stoch_astar import (
+ StochasticAstarPlanner,
+)
+
+from beanmachine.facebook.goal_inference.utils import manhattan_gem_heuristic
+
+
+@pytest.fixture(scope="module")
+def dkg_domain():
+ return DKGDomain()
+
+
+@pytest.fixture(scope="module")
+def dkg_state_one():
+ return parse(
+ "beanmachine/facebook/goal_inference/doors_keys_gems/test_problems/problem-1.pddl"
+ )
+
+
+@pytest.fixture(scope="module")
+def dkg_state_two():
+ return parse(
+ "beanmachine/facebook/goal_inference/doors_keys_gems/test_problems/problem-2.pddl"
+ )
+
+
+@pytest.fixture(scope="module")
+def dkg_state_three():
+ return parse(
+ "beanmachine/facebook/goal_inference/doors_keys_gems/test_problems/problem-3.pddl"
+ )
+
+
+@pytest.fixture(scope="module")
+def dkg_state_four():
+ return parse(
+ "beanmachine/facebook/goal_inference/doors_keys_gems/test_problems/problem-4.pddl"
+ )
+
+
+@pytest.fixture(scope="function")
+def dkg_astar_planner(dkg_domain):
+ return AstarPlanner(dkg_domain, manhattan_gem_heuristic)
+
+
+@pytest.fixture(scope="function")
+def dkg_stoch_astar_planner(dkg_domain):
+ return StochasticAstarPlanner(dkg_domain, manhattan_gem_heuristic, 0.1)
+
+
+@pytest.fixture(scope="function")
+def dkg_observation_set(dkg_domain, dkg_state_three):
+ actions = [
+ ["right"],
+ ["right"],
+ ["right"],
+ ["up"],
+ ["up"],
+ ["left"],
+ ["left"],
+ ["left"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["pickup", "key1"],
+ ["right"],
+ ["right"],
+ ["unlock", "key1", "right"],
+ ["right"],
+ ["right"],
+ ["up"],
+ ]
+ observed_plan = get_plan_from_actions(dkg_domain, dkg_state_three, actions)
+ return observed_plan.states
diff --git a/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_definitions.py b/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_definitions.py
new file mode 100644
index 0000000000..a2e613663c
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_definitions.py
@@ -0,0 +1,140 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from __future__ import annotations
+
+from dataclasses import dataclass
+from typing import Dict, List, Optional, Set, Tuple
+
+from beanmachine.facebook.goal_inference.environment import State
+
+from beanmachine.facebook.goal_inference.planner.planner import StateNode
+
+
+class Gem:
+ """A Gem object can be held by the agent
+
+ Arguments/Attributes:
+ name: The name of the Gem
+
+ """
+
+ __slots__ = "name"
+
+ def __init__(self, name: str):
+ self.name: str = name
+
+
+@dataclass(frozen=True, eq=True)
+class CGemState(State):
+ """A State of a continuous gems game is defined by the properties of the environment and the agent
+
+ Arguments/Attributes:
+
+ width: The width of the environment
+ height: The height of the environment
+
+ gems: Map from name to Gem for all gems in the problem
+ gem_size: The size of the gems. All points with manhattan distance to a gem < gem_size will be considered the gem.
+
+ has: Map from name to Gem for all gems held by agent.
+ at: Map from name to location for all gems not held by the agent.
+
+ obstacles: Positions of the center of obstacles
+ obstacle_size: The size of the obstacles. All points with manhattan distance to an obstacle < obstacle_size will be blocked.
+
+ agent_size: The size of the agent. All points with manhattan distance to a agent(x,y) < agent_size will be considered the agent.
+ x: X-position of Agent
+ y: Y-position of Agent
+ angle: Current Facing direction of agent. Angle is measured in degrees from rightward direction (0 is same as standard unit circle)
+
+ """
+
+ goal: Tuple[str, str]
+
+ width: float
+ height: float
+
+ gems: Dict[str, Gem]
+ gem_size: float
+
+ has: Dict[str, Gem]
+ at: Dict[str, Tuple[float, float]]
+
+ obstacles: Set[Tuple[float, float]]
+ obstacle_size: float
+
+ agent_size: float
+ x: float
+ y: float
+ angle: float
+
+ def __str__(self) -> str:
+ """Records the current state of the system as a string
+ Returns:
+ state_str: A string representation of the state
+
+ """
+ state_str = "Current State of Continuous Gems Problem\n”"
+ state_str += "Holding\n”"
+ state_str += str(list(self.has.keys()))
+ state_str += "\n"
+ state_str += "On Ground\n"
+ state_str += str(list(self.at.keys()))
+ state_str += "\n"
+ state_str += "X Position"
+ state_str += str(round(self.x * 4.0) / 4.0)
+ state_str += "\n"
+ state_str += "Y Position"
+ state_str += str(round(self.y * 4.0) / 4.0)
+ state_str += "\n"
+ state_str += "Angle"
+ state_str += str(round(self.angle, -1))
+ return state_str
+
+ def __hash__(self):
+ """Computes a hash of the state based on the string representation
+ Returns:
+ hash: The computed hash of the state
+ """
+ return hash(str(self))
+
+ def __eq__(self, other: CGemState) -> bool:
+ """Modifies the equality comparision by discretizing continuous variables
+
+ Arguments:
+ other: The State to compare with
+
+ Returns:
+ is_equal: Whether the two states are equal
+
+ """
+ if not isinstance(other, CGemState):
+ raise (RuntimeError("Tried to compare a CGemState with another object!"))
+ x_position = round(self.x * 4.0) / 4.0 == round(other.x * 4.0) / 4.0
+ y_position = round(self.y * 4.0) / 4.0 == round(other.y * 4.0) / 4.0
+ angle = round(self.angle, -1) == round(other.angle, -1)
+ has = self.has.keys() == other.has.keys()
+ return x_position and y_position and angle and has
+
+
+class CGemStateNode(StateNode):
+
+ """
+ Defines CGem nodes for graph-based representation of relationship between states.
+
+ Arguments/Attributes:
+ executed: Previous operation to get to this point in format [action_name,*args]
+ parent_node: Parent to this node
+ state: current State
+
+ """
+
+ def __init__(
+ self,
+ state: CGemState,
+ parent_node: Optional[CGemStateNode],
+ executed: List[str],
+ ):
+ self.executed: List[str] = executed
+ self.parent_node: Optional[CGemStateNode] = parent_node
+ self.state: CGemState = state
diff --git a/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_definitions_test.py b/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_definitions_test.py
new file mode 100644
index 0000000000..bc66c8351c
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_definitions_test.py
@@ -0,0 +1,57 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import dataclasses
+
+from beanmachine.facebook.goal_inference.continuous_gems.cgem_definitions import (
+ CGemState,
+ Gem,
+)
+
+
+def test_initialize_gem():
+ gem1 = Gem("gem1")
+ gem2 = Gem("gem2")
+ assert gem1.name == "gem1"
+ assert gem1.name != gem2.name
+
+
+def test_initialize_cgem_state():
+ state_one = CGemState(
+ ("has", "gem1"),
+ 5.0,
+ 5.0,
+ {},
+ 0.5,
+ {},
+ {},
+ set(),
+ 0.5,
+ 0.5,
+ 2.0,
+ 2.0,
+ 50.0,
+ )
+ assert state_one.x == 2.0
+ assert state_one.y == 2.0
+
+
+def test_compare_cgem_state():
+ state_one = CGemState(
+ ("has", "gem1"),
+ 5.0,
+ 5.0,
+ {},
+ 0.5,
+ {},
+ {},
+ set(),
+ 0.5,
+ 0.5,
+ 2.0,
+ 2.0,
+ 50.0,
+ )
+ state_two = dataclasses.replace(state_one, x=state_one.x)
+ state_three = dataclasses.replace(state_one, x=state_one.x + 1)
+ assert state_one == state_two
+ assert state_one != state_three
diff --git a/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_domain.py b/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_domain.py
new file mode 100644
index 0000000000..69bca49684
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_domain.py
@@ -0,0 +1,267 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import dataclasses
+import math
+
+from typing import Any, List
+
+import numpy as np
+
+from beanmachine.facebook.goal_inference.continuous_gems.cgem_definitions import (
+ CGemState,
+)
+from beanmachine.facebook.goal_inference.continuous_gems.cgem_utils import (
+ check_intersection,
+)
+from beanmachine.facebook.goal_inference.environment import Action, Domain
+
+from beanmachine.facebook.goal_inference.utils import manhattan_distance
+
+
+class CGemDomain(Domain):
+ """A hard-coded Domain of a continuous gems problem defining predicates (statements that evaluate to True or False) and possible actions
+
+ Atrributes:
+
+ name: Name specifying the domain is a Continuous Gems domain
+
+ Predicates -> True or False (Boolean) statements based on the current state
+
+ obstacle(x: int, y:int) -> Is there an obstacle at position x,y
+ has(name: str) -> Is the agent holding the object referred to by name
+ at(name: str, x:float, y:float) -> Is the object referred to by name on the ground at position x,y
+
+ Actions (Precondition) -> Modify the existing state given that a precondition is True
+
+ rotate(angle) -> rotate the direction the agent is facing angle degrees
+ move(distance) -> move forward distance in the direction the agent is facing
+ pickup(gem_name) -> pickup gem_name
+
+ """
+
+ def __init__(self):
+ self.name = "Continuous Gems"
+
+ self.predicates = {}
+
+ self.predicates["obstacle"] = self._obstacle
+ self.predicates["has"] = self._has
+ self.predicates["at"] = self._at
+
+ self.actions = {}
+
+ self.actions["rotate"] = Action(
+ "rotate", self._rotate_precondition, self._rotate
+ )
+ self.actions["move"] = Action("move", self._move_precondition, self._move)
+ self.actions["pickup"] = Action(
+ "pickup", self._pickup_precondition, self._pickup
+ )
+
+ def _obstacle(self, state: CGemState, x: float, y: float) -> bool:
+ """Determines if there is an obstacle at position (x,y)
+
+ Arguments:
+ state: State to analyze
+ x: X-position to analyze
+ y: Y-position to analyze
+
+ Returns:
+ _obstacle: Whether there is an obstacle at position (x,y)
+ """
+ for obstacle_position in state.obstacles:
+ if manhattan_distance(obstacle_position, (x, y)) < state.obstacle_size:
+ return True
+ return False
+
+ def _has(self, state: CGemState, name: str) -> bool:
+ """Determines if the agent is holding the object name
+
+ Arguments:
+ state: State to analyze
+ name: Name of the object to look for
+
+ Returns:
+ _has: Whether the agent is holding the object name
+ """
+ return name in state.has
+
+ def _at(self, state: CGemState, name: str, x: float, y: float) -> bool:
+ """Determins if there is the object name is a location (x,y)
+
+ Arguments:
+ state: State to analyze
+ name: Name of the object to look for
+ x: X-Position to analyze
+ y: Y-position to analyze
+
+ Returns:
+ _at: Whether there is the object name is a location (x,y)
+
+ """
+
+ return (
+ name in state.at
+ and manhattan_distance(state.at[name], (x, y)) < state.gem_size
+ )
+
+ def _rotate_precondition(self, state: CGemState, rotation_angle: float) -> bool:
+ """Determines whether a rotation is feasible in the current state
+
+ Arguments:
+ state: The current state
+ rotation_angle: The size of the rotation in degrees
+
+ Returns:
+ true: Rotations are always allowed
+
+ """
+ return True
+
+ def _rotate(self, state: CGemState, rotation_angle: float) -> CGemState:
+ """Rotates an agent by rotation_angle degrees
+
+ Arguments:
+ state: Current State
+ rotation_angle: How far to rotate the agent's orientation
+
+ Returns:
+ new_state: A new state with a modified angle
+
+ """
+ return dataclasses.replace(state, angle=(state.angle + rotation_angle) % 360.0)
+
+ def _move_precondition(self, state: CGemState, distance: float) -> bool:
+ """Determines whether a movement is feasible in the current state
+ The move is discretized into 10 substeps. Each substep is checked to ensure it does not collide with obstacles
+
+ Arguments:
+ state: Current State
+ distance: The size of the step forward
+
+ Returns:
+ can_move: True if the movement does not collide with obstacles
+
+ """
+ curr_x = state.x
+ curr_y = state.y
+ # Check for collisions with obstacles along the possible path
+ for _step in range(10):
+ # Move forward based on agent's direction
+ curr_x += 0.1 * distance * math.cos(math.radians(state.angle))
+ curr_y += 0.1 * distance * math.sin(math.radians(state.angle))
+ # Check for collisions with obstacles
+ for obstacle in state.obstacles:
+ if check_intersection(
+ obstacle, state.obstacle_size, (curr_x, curr_y), state.agent_size
+ ):
+ return False
+ if (
+ curr_x - state.agent_size < 0.0
+ or curr_x + state.agent_size > state.width
+ or curr_y - state.agent_size < 0.0
+ or curr_y + state.agent_size > state.height
+ ):
+ return False
+ return True
+
+ def _move(self, state: CGemState, distance: float) -> CGemState:
+ """Moves an agent forward by distance
+
+ Arguments:
+ state: Current State
+ distance: How far to move the agent forward
+
+ Returns:
+ new_state: A new state with a modified location
+
+ """
+ new_x = state.x + distance * math.cos(math.radians(state.angle))
+ new_y = state.y + distance * math.sin(math.radians(state.angle))
+ return dataclasses.replace(state, x=new_x, y=new_y)
+
+ def _pickup_precondition(self, state: CGemState, gem_name: str):
+ """Determines whether picking up gem_name is feasible in the current state
+ A gem can be pickup if the agent's rectangle overlaps with the gem's rectangle
+
+ Arguments:
+ state: Current State
+ gem_name: Gem to try and pickup
+
+ Returns:
+ _pickup_precondition: Whether the gem can be picked up
+
+ """
+ return gem_name in state.at and check_intersection(
+ state.at[gem_name], state.gem_size, (state.x, state.y), state.agent_size
+ )
+
+ def _pickup(self, state: CGemState, gem_name: str) -> CGemState:
+ """Picks up a gem with name gem_name
+
+ Arguments:
+ state: Current State
+ gem_name: Gem to pickup
+
+ Returns:
+ new_state: A new state holding the specified gem
+
+ """
+ new_has = state.has.copy()
+ new_at = state.at.copy()
+ new_has[gem_name] = state.gems[gem_name]
+ new_at.pop(gem_name)
+ return dataclasses.replace(state, has=new_has, at=new_at)
+
+ def get_possible_actions(self, state: CGemState) -> List[List[Any]]:
+ """Determines list of actions whose preconditions are met and will execute
+
+ Next possible actions include:
+ (1) A rotation sample from a Uniform distribution [0.0,360.0)
+ (2) A forward move with distance drawn from Uniform(0,1) (If possible)
+ (3) Any possible pickups
+
+ Arguments:
+ state: Current state
+ Returns:
+ possible_actions: A list of possible actions for the next time step
+ """
+ possible_actions = []
+ rotation = 360 * np.random.rand()
+ if self.is_action_possible(state, "rotate", rotation):
+ possible_actions.append(["rotate", rotation])
+ step = np.random.rand()
+ if self.is_action_possible(state, "move", step):
+ possible_actions.append(["move", step])
+
+ for name in state.at:
+ if self.is_action_possible(state, "pickup", name):
+ possible_actions.append(["pickup", name])
+
+ return possible_actions
+
+ def is_action_possible(self, state: CGemState, action_name: str, *args) -> bool:
+ """Evaluates whether the predicate of the action is satisfied
+
+ Arguments:
+ state: Current State to analyze
+ action_name: Action being attempted
+ *args: Parameters of the action
+
+ Returns:
+ is_action_possible: Whether the predicate of the action is satisfied
+
+ """
+ return self.actions[action_name].check_precondition(state, *args)
+
+ def evaluate_goal(self, state: CGemState) -> bool:
+ """Evaluates whether the current goal is achieved
+
+ Arguments:
+ state: Current State to analyze
+
+ Returns:
+ is_goal_achieved: Whether the current goal is achieved
+
+ """
+ return self.predicates[state.goal[0]](state, state.goal[1])
diff --git a/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_domain_test.py b/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_domain_test.py
new file mode 100644
index 0000000000..d032c31498
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_domain_test.py
@@ -0,0 +1,85 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import math
+
+import pytest
+from beanmachine.facebook.goal_inference.continuous_gems.cgem_domain import CGemDomain
+from beanmachine.facebook.goal_inference.continuous_gems.cgem_parse import parse
+
+
+@pytest.fixture(scope="function")
+def cgem_domain():
+ return CGemDomain()
+
+
+@pytest.fixture(scope="function")
+def state_one():
+ return parse(
+ "beanmachine/facebook/goal_inference/continuous_gems/test_problems/problem-1.json"
+ )
+
+
+def test_domain_predicates(cgem_domain, state_one):
+ assert not cgem_domain.predicates["has"](state_one, "gem1")
+ assert cgem_domain.predicates["at"](state_one, "gem1", 4.0, 0.5)
+ assert cgem_domain.predicates["at"](state_one, "gem1", 4.1, 0.6)
+ assert not cgem_domain.predicates["at"](state_one, "gem1", 4.6, 0.6)
+ assert cgem_domain.predicates["obstacle"](state_one, 2.0, 2.0)
+ assert cgem_domain.predicates["obstacle"](state_one, 2.1, 2.1)
+ assert not cgem_domain.predicates["obstacle"](state_one, 0.01, 0.01)
+
+
+def test_domain_rotate(cgem_domain, state_one):
+ assert cgem_domain.is_action_possible(state_one, "rotate", 10.0)
+ assert cgem_domain.is_action_possible(state_one, "rotate", -10.0)
+ new_state = cgem_domain.execute(state_one, "rotate", -10.0)
+ assert math.isclose(new_state.angle, 350.0, abs_tol=0.1)
+ new_state = cgem_domain.execute(new_state, "rotate", 15.0)
+ assert math.isclose(new_state.angle, 5.0, abs_tol=0.1)
+ new_state = cgem_domain.execute(new_state, "rotate", 15.0)
+ assert math.isclose(new_state.angle, 20.0, abs_tol=0.1)
+
+
+def test_domain_move(cgem_domain, state_one):
+ new_state = cgem_domain.execute(state_one, "rotate", 180.0)
+ assert not cgem_domain.is_action_possible(new_state, "move", 0.8)
+ assert not cgem_domain.is_action_possible(new_state, "move", 10.0)
+ assert cgem_domain.is_action_possible(new_state, "move", 0.1)
+ new_state = cgem_domain.execute(new_state, "move", 0.1)
+ assert math.isclose(new_state.x, state_one.x - 0.1, abs_tol=0.01)
+ assert math.isclose(new_state.y, state_one.y, abs_tol=0.01)
+ new_state_two = cgem_domain.execute(new_state, "rotate", -135.0)
+ new_state_two = cgem_domain.execute(new_state_two, "move", 0.1)
+ assert math.isclose(
+ new_state_two.x, new_state.x + 0.1 * math.sqrt(2.0) / 2.0, abs_tol=0.01
+ )
+ assert math.isclose(
+ new_state_two.y, new_state.y + 0.1 * math.sqrt(2.0) / 2.0, abs_tol=0.01
+ )
+
+
+def test_domain_pickup(cgem_domain, state_one):
+ assert not cgem_domain.evaluate_goal(state_one)
+ new_state = cgem_domain.execute(state_one, "rotate", 270.0)
+ new_state = cgem_domain.execute(new_state, "move", 0.5)
+ new_state = cgem_domain.execute(new_state, "rotate", 90.0)
+ new_state = cgem_domain.execute(new_state, "move", 2.9)
+ assert not cgem_domain.is_action_possible(new_state, "pickup", "gem2")
+ new_state = cgem_domain.execute(new_state, "pickup", "gem1")
+ assert cgem_domain.evaluate_goal(new_state)
+
+
+def test_domain_next_possible_actions(cgem_domain, state_one):
+ possible_actions = cgem_domain.get_possible_actions(state_one)
+ assert len(possible_actions) == 2
+ assert possible_actions[0][0] == "rotate"
+ assert possible_actions[1][0] == "move"
+ new_state = cgem_domain.execute(state_one, "move", 2.9)
+ possible_actions = cgem_domain.get_possible_actions(new_state)
+ assert possible_actions[0][0] == "rotate"
+ assert possible_actions[-1] == ["pickup", "gem1"]
+ new_state_two = cgem_domain.execute(state_one, "rotate", 270.0)
+ new_state_two = cgem_domain.execute(new_state_two, "move", 0.74999)
+ possible_actions = cgem_domain.get_possible_actions(new_state_two)
+ assert len(possible_actions) == 1
+ assert possible_actions[0][0] == "rotate"
diff --git a/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_observation_model.py b/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_observation_model.py
new file mode 100644
index 0000000000..41773b8f87
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_observation_model.py
@@ -0,0 +1,111 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import copy
+import dataclasses
+
+import torch
+from beanmachine.facebook.goal_inference.agent.observation_model import ObservationModel
+from beanmachine.facebook.goal_inference.continuous_gems.cgem_definitions import (
+ CGemState,
+)
+from beanmachine.facebook.goal_inference.environment import State
+from torch.distributions.bernoulli import Bernoulli
+from torch.distributions.normal import Normal
+
+
+class CGemObservation(ObservationModel):
+ """Defines a probability distribution for observing states for a continuous gems problem.
+
+ Agent positions (x,y) and angles are modified with Gaussian noise
+ Held gems are modified with bernoulli noise
+
+ Arguments/Attributes:
+ position_noise: Scale of the noise applied when observing positions
+ bernoulli_noise: Chance of gem being flipped from held->unheld or unheld -> held
+ angle_noise: Scale of the noise applied when observing angles
+ """
+
+ def __init__(
+ self,
+ position_noise: float = 0.5,
+ bernoulli_noise: float = 0.05,
+ angle_noise=120.0,
+ ):
+ self.position_noise: Normal = Normal(0.0, position_noise)
+ self.bernoulli_noise: Bernoulli = Bernoulli(bernoulli_noise)
+ self.angle_noise: Normal = Normal(0.0, angle_noise)
+
+ def apply_noise(self, state: CGemState) -> State:
+ """Applies noise to a state to obtain an observation
+
+ Arguments:
+ state: The state to apply noise to
+
+ Returns:
+ noisy_state: The state with noise applied
+
+ """
+
+ new_at = copy.copy(state.at)
+ new_has = copy.copy(state.has)
+
+ # Apply Noise to gems
+ for gem_id in state.gems:
+ if gem_id in new_at:
+ # Chance that gem at (x,y) is not observed
+ if self.bernoulli_noise.sample():
+ new_at.pop(gem_id)
+
+ else:
+ # Chance that held gem is not observed
+ if self.bernoulli_noise.sample():
+ new_has.pop(gem_id)
+
+ # Apply Gaussian noise to positions / angles
+ return dataclasses.replace(
+ state,
+ has=new_has,
+ at=new_at,
+ x=state.x + self.position_noise.sample().item(),
+ y=state.y + self.position_noise.sample().item(),
+ angle=(state.angle + self.angle_noise.sample().item()) % 360.0,
+ )
+
+ def get_log_prob(self, state: CGemState, observation: CGemState) -> torch.Tensor:
+ """Gets the log probability of a observation given a state
+
+ Arguments:
+ state: The reference state
+ observation: The noisy observation
+
+ Returns:
+ log_prob: The log of P(observation|state)
+
+ """
+
+ log_prob_gems = 0.0
+ # Evaluate Probability of Item positions
+ for gem_id in state.gems:
+ # If gem is not flipped
+ if (gem_id in state.has and gem_id in observation.has) or (
+ gem_id in state.at and gem_id in observation.at
+ ):
+ log_prob_gems += self.bernoulli_noise.log_prob(torch.tensor(0.0))
+ # If gem is flipped
+ else:
+ log_prob_gems += self.bernoulli_noise.log_prob(torch.tensor(1.0))
+
+ # Evaluate probability of positions
+ log_prob_x = self.position_noise.log_prob(torch.tensor(state.x - observation.x))
+ log_prob_y = self.position_noise.log_prob(torch.tensor(state.y - observation.y))
+
+ # Evaluate probability of angles
+ difference = torch.tensor(state.angle - observation.angle)
+ if difference > 180.0:
+ difference = 360.0 - difference
+ elif difference < -180.0:
+ difference = -(difference + 360.0)
+
+ log_prob_angle = self.angle_noise.log_prob(difference)
+
+ return log_prob_x + log_prob_y + log_prob_angle + log_prob_gems
diff --git a/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_observation_test.py b/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_observation_test.py
new file mode 100644
index 0000000000..3e2005f162
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_observation_test.py
@@ -0,0 +1,64 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import dataclasses
+import math
+
+import torch
+from beanmachine.facebook.goal_inference.continuous_gems.cgem_observation_model import (
+ CGemObservation,
+)
+from beanmachine.facebook.goal_inference.continuous_gems.cgem_parse import parse
+from torch.distributions.normal import Normal
+
+
+def test_cgem_observation_noise_positions_and_angles():
+ state = parse(
+ "beanmachine/facebook/goal_inference/continuous_gems/test_problems/problem-2.json"
+ )
+ noise_model = CGemObservation(bernoulli_noise=0.0)
+ noisy_state = noise_model.apply_noise(state)
+ assert state.x != noisy_state.x
+ assert state.y != noisy_state.y
+ assert state.angle != noisy_state.angle
+ assert state.has == noisy_state.has
+ assert state.at == noisy_state.at
+
+
+def test_cgem_observation_noise_gems():
+ state = parse(
+ "beanmachine/facebook/goal_inference/continuous_gems/test_problems/problem-2.json"
+ )
+ noise_model = CGemObservation(
+ position_noise=0.01, angle_noise=0.01, bernoulli_noise=1.0
+ )
+ noisy_state = noise_model.apply_noise(state)
+ assert math.isclose(state.x, noisy_state.x, abs_tol=0.25)
+ assert math.isclose(state.y, noisy_state.y, abs_tol=0.25)
+ assert not noisy_state.at.keys()
+ assert not noisy_state.has.keys()
+
+
+def test_cgem_observation_log_prob():
+ state = parse(
+ "beanmachine/facebook/goal_inference/continuous_gems/test_problems/problem-2.json"
+ )
+ noise_model = CGemObservation()
+ new_state = dataclasses.replace(state, x=state.x + 1.0)
+ log_prob = noise_model.get_log_prob(state, new_state)
+
+ calc_log_prob = torch.tensor(0.0)
+ calc_log_prob += Normal(torch.tensor(state.x), torch.tensor(0.5)).log_prob(
+ torch.tensor(state.x + 1)
+ )
+
+ calc_log_prob += Normal(torch.tensor(state.y), torch.tensor(0.5)).log_prob(
+ torch.tensor(state.y)
+ )
+
+ calc_log_prob += Normal(torch.tensor(state.angle), torch.tensor(120.0)).log_prob(
+ torch.tensor(state.angle)
+ )
+
+ calc_log_prob += torch.log(torch.tensor(0.95)) * (len(state.gems.keys()))
+
+ assert torch.isclose(calc_log_prob, log_prob, atol=0.01)
diff --git a/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_parse.py b/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_parse.py
new file mode 100644
index 0000000000..7078303422
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_parse.py
@@ -0,0 +1,45 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import json
+
+from beanmachine.facebook.goal_inference.continuous_gems.cgem_definitions import (
+ CGemState,
+ Gem,
+)
+
+
+def parse(file_path: str) -> CGemState:
+ """Reads in selected continuous gems problem. Intializes state by parsing file for objects, rules, and goal.
+
+ Arguments:
+ file_path: Path pointing to the selected problem
+
+ Returns:
+ initial_state: The initial state of the continuous gems problem
+ """
+ with open(file_path) as problem_file:
+ cgem_problem_data = json.load(problem_file)
+
+ at = {}
+ gems = {}
+ for gem_id in cgem_problem_data["gem_locations"]:
+ gems[gem_id] = Gem(gem_id)
+ at[gem_id] = tuple(cgem_problem_data["gem_locations"][gem_id])
+ has = {}
+ obstacles = [tuple(obstacle) for obstacle in cgem_problem_data["obstacles"]]
+
+ return CGemState(
+ tuple(cgem_problem_data["goal"]),
+ cgem_problem_data["width"],
+ cgem_problem_data["height"],
+ gems,
+ cgem_problem_data["gem_size"],
+ has,
+ at,
+ set(obstacles),
+ cgem_problem_data["obstacle_size"],
+ cgem_problem_data["agent_size"],
+ cgem_problem_data["x"],
+ cgem_problem_data["y"],
+ cgem_problem_data["angle"],
+ )
diff --git a/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_parse_test.py b/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_parse_test.py
new file mode 100644
index 0000000000..156af86378
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_parse_test.py
@@ -0,0 +1,67 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from beanmachine.facebook.goal_inference.continuous_gems.cgem_parse import parse
+
+
+def test_cgem_parse_problem_one():
+ problem_one = parse(
+ "beanmachine/facebook/goal_inference/continuous_gems/test_problems/problem-1.json"
+ )
+ assert problem_one.goal == ("has", "gem1")
+ assert problem_one.width == 5.0
+ assert problem_one.height == 5.0
+ assert problem_one.gem_size == 0.25
+ assert list(problem_one.at.keys()) == ["gem1", "gem2"]
+ assert problem_one.at["gem1"] == (4.0, 0.5)
+ assert problem_one.at["gem2"] == (0.5, 4.0)
+ assert (2.0, 2.0) in problem_one.obstacles
+ assert (2.0, 2.5) in problem_one.obstacles
+ assert (4.0, 4.0) in problem_one.obstacles
+ assert (0.5, 4.0) not in problem_one.obstacles
+ assert problem_one.obstacle_size == 0.25
+ assert problem_one.agent_size == 0.25
+ assert problem_one.x == 1.0
+ assert problem_one.y == 1.0
+ assert problem_one.angle == 0.0
+
+
+def test_cgem_parse_problem_two():
+ problem_one = parse(
+ "beanmachine/facebook/goal_inference/continuous_gems/test_problems/problem-2.json"
+ )
+ assert problem_one.goal == ("has", "gem1")
+ assert problem_one.width == 5.0
+ assert problem_one.height == 5.0
+ assert problem_one.gem_size == 0.25
+ assert list(problem_one.at.keys()) == ["gem1", "gem2"]
+ assert problem_one.at["gem1"] == (0.5, 4.0)
+ assert problem_one.at["gem2"] == (4.0, 4.0)
+ assert (1.5, 0.5) in problem_one.obstacles
+ assert (4.5, 0.5) in problem_one.obstacles
+ assert (4.0, 4.0) not in problem_one.obstacles
+ assert problem_one.obstacle_size == 0.5
+ assert problem_one.agent_size == 0.25
+ assert problem_one.x == 1.5
+ assert problem_one.y == 1.5
+ assert problem_one.angle == 0.0
+
+
+def test_cgem_parse_problem_three():
+ problem_one = parse(
+ "beanmachine/facebook/goal_inference/continuous_gems/test_problems/problem-3.json"
+ )
+ assert problem_one.goal == ("has", "gem1")
+ assert problem_one.width == 5.0
+ assert problem_one.height == 5.0
+ assert problem_one.gem_size == 0.25
+ assert list(problem_one.at.keys()) == ["gem1", "gem2"]
+ assert problem_one.at["gem1"] == (0.5, 4.5)
+ assert problem_one.at["gem2"] == (4.5, 0.5)
+ assert (0.25, 1.5) in problem_one.obstacles
+ assert (2.0, 1.5) in problem_one.obstacles
+ assert (0.321, 0.87) not in problem_one.obstacles
+ assert problem_one.obstacle_size == 0.25
+ assert problem_one.agent_size == 0.25
+ assert problem_one.x == 2.5
+ assert problem_one.y == 2.5
+ assert problem_one.angle == 0.0
diff --git a/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_plot.py b/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_plot.py
new file mode 100644
index 0000000000..877ac21647
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_plot.py
@@ -0,0 +1,180 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from typing import Dict, List, Optional
+
+import matplotlib
+
+import matplotlib.pyplot as plt
+import numpy as np
+
+from beanmachine.facebook.goal_inference.continuous_gems.cgem_definitions import (
+ CGemState,
+)
+
+from beanmachine.facebook.goal_inference.plotting.utils import (
+ create_gif,
+ format_gem_data,
+ get_gem_figure,
+ get_gem_inference_plot,
+)
+
+from matplotlib import colors
+from matplotlib.patches import Rectangle
+
+
+""" Set Plot Settings.
+Colors are defined as follows:
+Empty -> White
+Obstacle -> Black
+Agent -> Red
+Gem -> blue, green, or purple
+"""
+
+CMAP = colors.ListedColormap(["white", "black", "red", "blue", "green", "purple"])
+BOUNDS = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
+NORM = colors.BoundaryNorm(BOUNDS, CMAP.N)
+plt.rcParams["axes.edgecolor"] = "black"
+plt.rcParams["axes.linewidth"] = 2.50
+
+
+def plot(state: CGemState):
+
+ """Creates graphic for current state
+
+ Arguments:
+ state: State to plot
+ """
+
+ fig, ax = get_gem_figure(state)
+ hold_data = get_data_matrix(state)
+ add_data_to_axes(ax, state, hold_data)
+ plt.show()
+ plt.close()
+
+
+def plot_gif(
+ states: List[CGemState],
+ inference_data: Optional[List[Dict[str, int]]] = None,
+ file_path: Optional[str] = None,
+) -> None:
+ """Creates a gif from a list of states and inference data (if available)
+
+ Arguments:
+ states: Series of states to turn into a gif
+ inference_data: Computation of the posterior P(goal|observations) at each time step
+ file_path: Path to location to save the gif
+ """
+
+ fig, ax = get_gem_figure(states[0], inference_data)
+
+ def animation_function(frame):
+ state = states[frame]
+ hold_data = get_data_matrix(state)
+ add_data_to_axes(ax, state, hold_data)
+ if inference_data is not None:
+ prob_goal = get_gem_inference_plot(inference_data, frame)
+ for goal in prob_goal:
+ ax[2].plot(prob_goal[goal], color=CMAP(NORM(2.5 + float(goal[3]))))
+
+ create_gif(fig, animation_function, states, file_path)
+
+ plt.close()
+
+
+def get_data_matrix(state: CGemState) -> np.ndarray:
+ """Computes formatted holding data
+
+ Arguments:
+ state: The current state
+
+ Returns:
+ data_hold: Correctly formatted data array of the held gems
+ """
+
+ data_hold = get_hold_data(state)
+
+ data_hold = format_gem_data(
+ data_hold,
+ )
+
+ return data_hold
+
+
+def get_hold_data(state: CGemState) -> np.ndarray:
+ """Computes holding data matrix (defining colors) based on objects agent currently holds
+
+ Arguments:
+ state: The current state
+
+ Returns:
+ data_hold: Data array containing identities of the held gems
+ """
+
+ data_hold = np.zeros((1, 8))
+
+ count = 0
+
+ for item_id in state.gems:
+ if item_id in state.has:
+ data_hold[0, count] = 2.0 + int(item_id[3])
+ count += 1
+
+ return data_hold
+
+
+def add_data_to_axes(
+ ax: List[matplotlib.axes.Axes], state: CGemState, hold_data: np.ndarray
+) -> None:
+ """Adds Environment and held data to subplots
+
+ Arguments:
+ ax: List of axes objects in the current figure
+ state: Current state to plot
+ hold_data: Correctly formmatted data array for held gems
+
+ """
+ # Plot Agent
+ ax[0].add_patch(
+ Rectangle(
+ (state.x - state.agent_size, state.y - state.agent_size),
+ state.agent_size * 2.0,
+ state.agent_size * 2.0,
+ color="red",
+ )
+ )
+
+ # Plot Obstacles
+ for obstacle in state.obstacles:
+ ax[0].add_patch(
+ Rectangle(
+ (obstacle[0] - state.obstacle_size, obstacle[1] - state.obstacle_size),
+ state.obstacle_size * 2.0,
+ state.obstacle_size * 2.0,
+ color="black",
+ )
+ )
+
+ # Plot Gems
+ for gem_id in state.gems:
+ if gem_id in state.at:
+ ax[0].add_patch(
+ Rectangle(
+ (
+ state.at[gem_id][0] - state.gem_size,
+ state.at[gem_id][1] - state.gem_size,
+ ),
+ state.gem_size * 2.0,
+ state.gem_size * 2.0,
+ color=CMAP(NORM(2.5 + float(gem_id[3]))),
+ )
+ )
+
+ # Plot Held Objects
+ ax[1].imshow(
+ hold_data,
+ cmap=CMAP,
+ norm=NORM,
+ origin="lower",
+ interpolation="none",
+ extent=[0.5, 1.5, 0.5, 8.5],
+ )
diff --git a/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_utils.py b/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_utils.py
new file mode 100644
index 0000000000..7ca9a91ef9
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_utils.py
@@ -0,0 +1,28 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from typing import Tuple
+
+
+def check_intersection(
+ obstacle_position: Tuple[float, float],
+ obstacle_size: float,
+ agent_position: Tuple[float, float],
+ agent_size: float,
+) -> bool:
+ """Determines whether the agent intersects an obstacle by computing whether to two rectangles intersect
+
+ Arguments:
+ obstacle_position: Center of the obstacle
+ obstacle_size: Size of the obstacle
+ agent_position: Center of the agent
+ agent_size: Size of the agent
+
+ Returns:
+ check_intersection: Whether the agent intersects with the object
+ """
+ return not (
+ obstacle_position[0] + obstacle_size < agent_position[0] - agent_size
+ or obstacle_position[0] - obstacle_size > agent_position[0] + agent_size
+ or obstacle_position[1] + obstacle_size < agent_position[1] - agent_size
+ or obstacle_position[1] - obstacle_size > agent_position[1] + agent_size
+ )
diff --git a/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_utils_test.py b/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_utils_test.py
new file mode 100644
index 0000000000..724aa69240
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/cgem_utils_test.py
@@ -0,0 +1,13 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from beanmachine.facebook.goal_inference.continuous_gems.cgem_utils import (
+ check_intersection,
+)
+
+
+def test_intersection():
+ assert not check_intersection((0.0, 0.0), 1.0, (2.0, 2.0), 0.1)
+ assert not check_intersection((0.0, 0.0), 1.0, (2.0, 2.0), 0.9)
+ assert check_intersection((0.0, 0.0), 1.0, (2.0, 2.0), 1.0)
+ assert check_intersection((0.0, 0.0), 0.1, (0.0, 0.0), 0.1)
+ assert check_intersection((0.0, 0.0), 1.0, (2.0, 0.0), 1.0)
diff --git a/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/test_problems/problem-1.json b/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/test_problems/problem-1.json
new file mode 100644
index 0000000000..afc5a0389e
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/test_problems/problem-1.json
@@ -0,0 +1,75 @@
+{
+ "goal": [
+ "has",
+ "gem1"
+ ],
+ "width": 5.0,
+ "height": 5.0,
+ "gem_size": 0.25,
+ "gem_locations": {
+ "gem1": [
+ 4.0,
+ 0.5
+ ],
+ "gem2": [
+ 0.5,
+ 4.0
+ ]
+ },
+ "obstacles": [
+ [
+ 2.0,
+ 2.0
+ ],
+ [
+ 2.0,
+ 2.5
+ ],
+ [
+ 3.0,
+ 3.5
+ ],
+ [
+ 4.0,
+ 4.5
+ ],
+ [
+ 2.5,
+ 2.5
+ ],
+ [
+ 3.5,
+ 2.5
+ ],
+ [
+ 3.0,
+ 2.5
+ ],
+ [
+ 3.0,
+ 3.0
+ ],
+ [
+ 3.0,
+ 4.0
+ ],
+ [
+ 3.5,
+ 4.0
+ ],
+ [
+ 4.0,
+ 4.0
+ ],
+ [
+ 4.0,
+ 5.0
+ ]
+
+ ],
+ "obstacle_size": 0.25,
+ "agent_size": 0.25,
+ "x": 1.0,
+ "y": 1.0,
+ "angle": 0.0
+}
diff --git a/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/test_problems/problem-2.json b/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/test_problems/problem-2.json
new file mode 100644
index 0000000000..9c08466201
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/test_problems/problem-2.json
@@ -0,0 +1,74 @@
+{
+ "goal": [
+ "has",
+ "gem1"
+ ],
+ "width": 5.0,
+ "height": 5.0,
+ "gem_size": 0.25,
+ "gem_locations": {
+ "gem1": [
+ 0.5,
+ 4.0
+ ],
+ "gem2": [
+ 4.0,
+ 4.0
+ ]
+ },
+ "obstacles": [
+ [
+ 0.5,
+ 0.5
+ ],
+ [
+ 1.5,
+ 0.5
+ ],
+ [
+ 2.5,
+ 0.5
+ ],
+ [
+ 3.5,
+ 0.5
+ ],
+ [
+ 4.5,
+ 0.5
+ ],
+ [
+ 1.0,
+ 0.5
+ ],
+ [
+ 2.5,
+ 1.5
+ ],
+ [
+ 3.5,
+ 1.5
+ ],
+ [
+ 4.5,
+ 1.5
+ ],
+ [
+ 2.5,
+ 2.5
+ ],
+ [
+ 3.5,
+ 2.5
+ ],
+ [
+ 4.5,
+ 2.5
+ ]
+ ],
+ "obstacle_size": 0.5,
+ "agent_size": 0.25,
+ "x": 1.5,
+ "y": 1.5,
+ "angle": 0.0
+}
diff --git a/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/test_problems/problem-3.json b/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/test_problems/problem-3.json
new file mode 100644
index 0000000000..f45537043a
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/continuous_gems/test_problems/problem-3.json
@@ -0,0 +1,90 @@
+{
+ "goal": [
+ "has",
+ "gem1"
+ ],
+ "width": 5.0,
+ "height": 5.0,
+ "gem_size": 0.25,
+ "gem_locations": {
+ "gem1": [
+ 0.5,
+ 4.5
+ ],
+ "gem2": [
+ 4.5,
+ 0.5
+ ]
+ },
+ "obstacles": [
+ [
+ 0.25,
+ 1.5
+ ],
+ [
+ 0.5,
+ 1.5
+ ],
+ [
+ 1.0,
+ 1.5
+ ],
+ [
+ 1.5,
+ 1.5
+ ],
+ [
+ 2.0,
+ 1.5
+ ],
+ [
+ 2.5,
+ 1.5
+ ],
+ [
+ 3.0,
+ 1.5
+ ],
+ [
+ 3.5,
+ 1.5
+ ],
+ [
+ 4.75,
+ 3.5
+ ],
+ [
+ 4.5,
+ 3.5
+ ],
+ [
+ 4.0,
+ 3.5
+ ],
+ [
+ 3.5,
+ 3.5
+ ],
+ [
+ 3.0,
+ 3.5
+ ],
+ [
+ 2.5,
+ 3.5
+ ],
+ [
+ 2.0,
+ 3.5
+ ],
+ [
+ 1.5,
+ 3.5
+ ]
+ ],
+ "obstacle_size": 0.25,
+ "agent_size": 0.25,
+ "x": 2.5,
+ "y": 2.5,
+ "angle": 0.0
+}
diff --git a/src/beanmachine/ppl/experimental/goal_inference/docs/README.rst b/src/beanmachine/ppl/experimental/goal_inference/docs/README.rst
new file mode 100644
index 0000000000..e92469d024
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/docs/README.rst
@@ -0,0 +1,4 @@
+Sequential Monte Carlo for Goal Inference
+##################
+
+**Author: James Damewood**
diff --git a/src/beanmachine/ppl/experimental/goal_inference/docs/TARGETS b/src/beanmachine/ppl/experimental/goal_inference/docs/TARGETS
new file mode 100644
index 0000000000..53f6dffa20
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/docs/TARGETS
@@ -0,0 +1,17 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+load("@fbcode_macros//build_defs:sphinx_wiki.bzl", "sphinx_wiki")
+
+oncall("hackppl")
+
+sphinx_wiki(
+ name = "docs",
+ srcs = ["README.rst"],
+ apidoc_modules = {
+ "beanmachine.facebook.goal_inference": "api",
+ },
+ python_library_deps = [
+ "//beanmachine/facebook/goal_inference:goal_inference",
+ ],
+ wiki_root_path = "Users/jkdamewo/goal_inference_api",
+)
diff --git a/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/definitions_test.py b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/definitions_test.py
new file mode 100644
index 0000000000..4addead020
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/definitions_test.py
@@ -0,0 +1,70 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import pytest
+
+from beanmachine.facebook.goal_inference.doors_keys_gems.dkg_definitions import (
+ Direction,
+ Gem,
+ Item,
+ Key,
+)
+
+from beanmachine.facebook.goal_inference.doors_keys_gems.parser import parse
+
+####### Test Definition
+
+
+@pytest.fixture
+def key():
+ k1 = Key("key1")
+ return k1
+
+
+@pytest.fixture
+def gem():
+ g1 = Gem("gem1")
+ return g1
+
+
+@pytest.fixture
+def state():
+ state = parse(
+ "beanmachine/facebook/goal_inference/doors_keys_gems/test_problems/problem-1.pddl"
+ )
+ return state
+
+
+@pytest.fixture
+def right_direction():
+ right_direction = Direction("right")
+ return right_direction
+
+
+def test_gem_name(gem):
+ assert gem.name == "gem1"
+
+
+def test_gem_class(gem):
+ assert isinstance(gem, Gem) and isinstance(gem, Item)
+
+
+def test_key_name(key):
+ assert key.name == "key1"
+
+
+def test_key_class(key):
+ assert isinstance(key, Key) and isinstance(key, Item)
+
+
+def test_direction_name(right_direction):
+ assert right_direction.name == "right"
+
+
+def test_direction_class(right_direction):
+ assert isinstance(right_direction, Direction) and not isinstance(
+ right_direction, Item
+ )
+
+
+def test_str(state):
+ assert isinstance(str(state), str)
diff --git a/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/dkg_definitions.py b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/dkg_definitions.py
new file mode 100644
index 0000000000..a1dd9bfd25
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/dkg_definitions.py
@@ -0,0 +1,155 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from __future__ import annotations
+
+from dataclasses import dataclass
+from typing import Dict, List, Optional, Set, Tuple
+
+from beanmachine.facebook.goal_inference.environment import State
+
+from beanmachine.facebook.goal_inference.planner.planner import StateNode
+
+
+class Item:
+ """An Item object can be held by the agent
+
+ Arguments/Attributes:
+ name: The name of the Item
+ """
+
+ __slots__ = "name"
+
+ def __init__(self, name: str):
+ self.name: str = name
+
+
+class Key(Item):
+ """A Key is an Item that can open doors
+
+ Arguments/Attributes:
+ name: The name of the Key
+ """
+
+ pass
+
+
+class Gem(Item):
+ """A Gem is an Item that can be the goal
+
+ Arguments/Attributes:
+ name: The name of the Gem
+ """
+
+ pass
+
+
+class Direction:
+ """A Direction determines the possible interactions with the environment [e.g. movement, unlocking doors]
+
+ Arguments/Attributes:
+ name: The name of the Direction
+ """
+
+ __slots__ = "name"
+
+ def __init__(self, name: str):
+ self.name: str = name
+
+
+@dataclass(frozen=True, eq=True)
+class DKGState(State):
+ """A State of a doors, keys, and gems game is defined by the properties of the environment and the Agent
+
+ Arguments/Attributes:
+
+ width: The width of the environment
+ height: The height of the environment
+ xdiff: Movement/Interaction along x-axis when given a direction
+ ydiff: Movement/Interaction along y-axis when given a direction
+
+ doors: Positions of doors
+ walls: Positions of walls
+
+ items: Map from name to Item for all Items remaining in game
+ directions: Map from name to Direction
+ keys: Map from name to Key for all Keys remaining in game
+ gems: Map from name to Gem for all Gems remaining in game
+
+ has: Map from name to Item for all Items held by Agent
+ at: Map from name to Location for all Items not held by the Agent
+
+ x: X-position of Agent
+ y: Y-position of Agent
+
+ """
+
+ goal: Tuple[str, str]
+
+ width: int
+ height: int
+ xdiff: Dict[str, int]
+ ydiff: Dict[str, int]
+
+ doors: Set[(Tuple[int, int])]
+ walls: Set[(Tuple[int, int])]
+
+ items: Dict[str, Item]
+ directions: Dict[str, Direction]
+ keys: Dict[str, Key]
+ gems: Dict[str, Gem]
+
+ has: Dict[str, Item]
+ at: Dict[str, Tuple[int, int]]
+
+ x: int
+ y: int
+
+ def __str__(self) -> str:
+ """Records the current state of the system as a string
+ Returns:
+ state_str: A string representation of the state
+ """
+ state_str = "Current State of DKG Problem\n”"
+ state_str += "Holding\n”"
+ state_str += str(list(self.has.keys()))
+ state_str += "\n"
+ state_str += "On Ground\n"
+ state_str += str(list(self.at.keys()))
+ state_str += "\n"
+ state_str += "X Position"
+ state_str += str(self.x)
+ state_str += "\n"
+ state_str += "Y Position"
+ state_str += str(self.y)
+ return state_str
+
+ def __hash__(self):
+ """Computes a hash of the state based on the string representation
+ Returns:
+ hash: The computed hash of the state
+ """
+ return hash(str(self))
+
+
+class DKGStateNode(StateNode):
+
+ """
+ Defines DKG nodes for graph-based representation of relationship between states.
+
+ Arguments/Attributes:
+
+ executed: Previous operation to get to this point in format [action_name,*args]
+ parent_node: Parent to this node
+ state: current State
+
+ """
+
+ def __init__(
+ self,
+ state: DKGState,
+ parent_node: Optional[DKGStateNode],
+ executed: List[str],
+ ):
+ self.executed: List[str] = executed
+ self.parent_node: Optional[DKGStateNode] = parent_node
+ self.state: DKGState = state
diff --git a/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/dkg_domain.py b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/dkg_domain.py
new file mode 100644
index 0000000000..41487068d4
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/dkg_domain.py
@@ -0,0 +1,359 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import dataclasses
+
+from typing import List
+
+from beanmachine.facebook.goal_inference.doors_keys_gems.dkg_definitions import DKGState
+from beanmachine.facebook.goal_inference.environment import Action, Domain
+
+
+class DKGDomain(Domain):
+ """A hard-coded Domain of a doors, keys, and gems game defining predicates (statements that evaluate to True or False) and possible Actions
+
+ Atrributes:
+
+ name: Name specifying the domain is a DKG domain
+
+ Predicates -> True or False (Boolean) statement based on the current state
+
+ wall(x: int,y: int) -> Is there a wall at position x,y
+ door(x: int,y: int) -> Is there a door at position x,y
+ obstacle(x: int, y:int) -> Is there a door or wall at position x,y
+ has(name: str) -> Is the agent holding the object name
+ at(name: str, x:int, y:int) -> Is the object name on the ground at position x,y
+
+ Actions (Precondition) -> Modify the existing state given that a precondition is True
+
+ down (If not blocked by boundary or obstacle) -> move state down
+ up (If not blocked by boundary or obstacle) -> move state up
+ left (If not blocked by boundary or obstacle) -> move state left
+ right (If not blocked by boundary or obstacle) -> move state right
+ pickup (If Agent is at x,y and item is at x,y) -> Pickup Item
+ unlock (If Agent has a key and there is a door in specified direction) -> Unlock Door (losing key)
+ """
+
+ def __init__(self):
+ self.name = "DKG"
+
+ self.predicates = {}
+
+ self.predicates["wall"] = self._wall
+ self.predicates["door"] = self._door
+ self.predicates["obstacle"] = self._obstacle
+ self.predicates["has"] = self._has
+ self.predicates["at"] = self._at
+
+ self.actions = {}
+
+ self.actions["down"] = Action("down", self._down_precondition, self._down)
+ self.actions["up"] = Action("up", self._up_precondition, self._up)
+ self.actions["right"] = Action("right", self._right_precondition, self._right)
+ self.actions["left"] = Action("left", self._left_precondition, self._left)
+ self.actions["pickup"] = Action(
+ "pickup", self._pickup_precondition, self._pickup
+ )
+ self.actions["unlock"] = Action(
+ "unlock", self._unlock_precondition, self._unlock
+ )
+
+ def _wall(self, state: DKGState, x: int, y: int) -> bool:
+ """Determines if there is a wall at position (x,y)
+
+ Arguments:
+ state: Current state
+ x: X-position to test
+ y: Y-position to test
+
+ Returns:
+ _wall: Whether there is a wall at (x,y)
+ """
+ return (x, y) in state.walls
+
+ def _door(self, state: DKGState, x: int, y: int) -> bool:
+ """Determines if there is a door at position (x,y)
+
+ Arguments:
+ state: Current state
+ x: X-position to test
+ y: Y-position to test
+
+ Returns:
+ _door: Whether there is a door at (x,y)
+ """
+ return (x, y) in state.doors
+
+ def _obstacle(self, state: DKGState, x: int, y: int) -> bool:
+ """Determines if there is a door or wall at position (x,y)
+
+ Arguments:
+ state: Current state
+ x: X-position to test
+ y: Y-position to test
+
+ Returns:
+ _obstalce: Whether there is a door or wall at (x,y)
+ """
+ return self._wall(state, x, y) or self._door(state, x, y)
+
+ def _has(self, state: DKGState, name: str) -> bool:
+ """Determines if the agent is holding the object name
+
+ Arguments:
+ state: State to analyze
+ name: Name of the object to look for
+
+ Returns:
+ _has: Whether the agent is holding the object name
+ """
+ return name in state.has
+
+ def _at(self, state: DKGState, name: str, x: int, y: int) -> bool:
+ """Determins if there is the object name is a location (x,y)
+
+ Arguments:
+ state: State to analyze
+ name: Name of the object to look for
+ x: X-Position to analyze
+ y: Y-position to analyze
+
+ Returns:
+ _at: Whether there is the object name is a location (x,y)
+ """
+ return name in state.at and state.at[name] == (x, y)
+
+ def _down_precondition(self, state: DKGState) -> bool:
+ """Determines if agent can move down without colliding with a wall, door, or world boundary
+
+ Arguments:
+ state: Current state
+
+ Returns:
+ can_mode_down: True if agent can move down
+ """
+
+ return state.y > 1 and not self._obstacle(state, state.x, state.y - 1)
+
+ def _down(self, state: DKGState) -> DKGState:
+ """Moves an agent downward one
+
+ Arguments:
+ state: Current State
+
+ Returns:
+ new_state: A new state after moving downward
+ """
+
+ return dataclasses.replace(state, y=state.y - 1)
+
+ def _up_precondition(self, state: DKGState) -> bool:
+ """Determines if agent can move up without colliding with a wall, door, or world boundary
+
+ Arguments:
+ state: Current state
+
+ Returns:
+ can_mode_up: True if agent can move up
+ """
+ return state.y < state.height and not self._obstacle(
+ state, state.x, state.y + 1
+ )
+
+ def _up(self, state: DKGState) -> DKGState:
+ """Moves an agent upward one
+
+ Arguments:
+ state: Current State
+
+ Returns:
+ new_state: A new state after moving upward
+ """
+ return dataclasses.replace(state, y=state.y + 1)
+
+ def _left_precondition(self, state: DKGState) -> bool:
+ """Determines if agent can move left without colliding with a wall, door, or world boundary
+
+ Arguments:
+ state: Current state
+
+ Returns:
+ can_mode_left: True if agent can move left
+ """
+ return state.x > 1 and not self._obstacle(state, state.x - 1, state.y)
+
+ def _left(self, state: DKGState) -> DKGState:
+ """Moves an agent left one
+
+ Arguments:
+ state: Current State
+
+ Returns:
+ new_state: A new state after moving left
+ """
+ return dataclasses.replace(state, x=state.x - 1)
+
+ def _right_precondition(self, state: DKGState) -> bool:
+ """Determines if agent can move right without colliding with a wall, door, or world boundary
+
+ Arguments:
+ state: Current state
+
+ Returns:
+ can_mode_right: True if agent can move right
+ """
+ return state.x < state.width and not self._obstacle(state, state.x + 1, state.y)
+
+ def _right(self, state: DKGState) -> DKGState:
+ """Moves an agent right one
+
+ Arguments:
+ state: Current State
+
+ Returns:
+ new_state: A new state after moving right
+ """
+ return dataclasses.replace(state, x=state.x + 1)
+
+ def _pickup_precondition(self, state: DKGState, item_name: str) -> bool:
+ """Determines whether picking up item_name is feasible in the current state
+ The item can be picked up if it is on the ground at the same location as the agent
+
+ Arguments:
+ state: Current State
+ item_name: Item to try and pickup
+
+ Returns:
+ _pickup_precondition: Whether the item can be picked up
+
+ """
+ return self._at(state, item_name, state.x, state.y) and (
+ item_name in state.items
+ )
+
+ def _pickup(self, state: DKGState, item_name: str) -> DKGState:
+ """Picks up an item with name item_name
+
+ Arguments:
+ state: Current State
+ item_name: Item to pickup
+
+ Returns:
+ new_state: A new state holding the specified item
+
+ """
+ new_has = state.has.copy()
+ new_at = state.at.copy()
+ new_has[item_name] = state.items[item_name]
+ new_at.pop(item_name)
+ return dataclasses.replace(state, has=new_has, at=new_at)
+
+ def _unlock_precondition(
+ self, state: DKGState, key_name: str, direction_name: str
+ ) -> bool:
+ """Determines whether a door in direction direction_name can be unlocked with key key_name
+ The agent must be holding the key key_name
+ The door must also be at a location specified by the direction
+
+ Arguments:
+ state: Current State
+ key_name: Key to use to unlock door
+ direction_name: Direction of door
+
+ Returns:
+ _unlock_precondition: Whether the door can be unlocked
+
+ """
+ return (
+ key_name in state.has
+ and key_name in state.keys
+ and self._door(
+ state,
+ state.x + state.xdiff[direction_name],
+ state.y + state.ydiff[direction_name],
+ )
+ )
+
+ def _unlock(self, state: DKGState, key_name: str, direction_name: str) -> DKGState:
+ """Unlocks a door with key key_name
+ Removes the door from the game
+ Removes the used key from the game
+
+ Arguments:
+ state: Current State
+ key_name: Key to use to unlock door
+ direction_name: Direction of the door to unlock
+
+ Returns:
+ new_state: A new state with the door unlocked and the key removed
+
+ """
+ new_items = state.items.copy()
+ new_keys = state.keys.copy()
+ new_has = state.has.copy()
+ new_doors = state.doors.copy()
+ new_items.pop(key_name)
+ new_keys.pop(key_name)
+ new_has.pop(key_name)
+ new_doors.remove(
+ (
+ state.x + state.xdiff[direction_name],
+ state.y + state.ydiff[direction_name],
+ )
+ )
+ return dataclasses.replace(
+ state, items=new_items, keys=new_keys, has=new_has, doors=new_doors
+ )
+
+ def get_possible_actions(self, state: DKGState) -> List[List[str]]:
+ """Determines list of actions whose preconditions are met and will execute
+
+ Arguments:
+ state: Current state
+ Returns:
+ possible_actions: A list of possible actions for the next time step
+ """
+ possible_actions = []
+ if self.is_action_possible(state, "right"):
+ possible_actions.append(["right"])
+ if self.is_action_possible(state, "up"):
+ possible_actions.append(["up"])
+ if self.is_action_possible(state, "left"):
+ possible_actions.append(["left"])
+ if self.is_action_possible(state, "down"):
+ possible_actions.append(["down"])
+
+ for name in state.at:
+ if self.is_action_possible(state, "pickup", name):
+ possible_actions.append(["pickup", name])
+
+ for name in state.has:
+ for direction in state.directions:
+ if self.is_action_possible(state, "unlock", name, direction):
+ possible_actions.append(["unlock", name, direction])
+
+ return possible_actions
+
+ def is_action_possible(self, state: DKGState, action_name: str, *args) -> bool:
+ """Evaluates whether the predicate of the action is satisfied
+
+ Arguments:
+ state: Current State to analyze
+ action_name: Action being attempted
+ *args: Parameters of the action
+
+ Returns:
+ is_action_possible: Whether the predicate of the action is satisfied
+
+ """
+ return self.actions[action_name].check_precondition(state, *args)
+
+ def evaluate_goal(self, state: DKGState) -> bool:
+ """Evaluates whether the current goal is achieved
+
+ Arguments:
+ state: Current State to analyze
+
+ Returns:
+ is_goal_achieved: Whether the current goal is achieved
+ """
+ return self.predicates[state.goal[0]](state, state.goal[1])
diff --git a/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/dkg_observation_model.py b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/dkg_observation_model.py
new file mode 100644
index 0000000000..924414e7ed
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/dkg_observation_model.py
@@ -0,0 +1,106 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import copy
+import dataclasses
+
+import torch
+from beanmachine.facebook.goal_inference.agent.observation_model import ObservationModel
+from beanmachine.facebook.goal_inference.doors_keys_gems.dkg_definitions import DKGState
+from beanmachine.facebook.goal_inference.environment import State
+from torch.distributions.bernoulli import Bernoulli
+from torch.distributions.normal import Normal
+
+
+class DKGObservation(ObservationModel):
+ """Defines a probability distribution for observing states for Doors, Keys, and Gems problem.
+ Agent positions (x,y) are modified with Gaussian noise
+ Presence of held Items, Doors, and Items on the ground is modified with bernoulli noise
+
+ Arguments/Attributes:
+ gaussian_noise: Scale of the noise applied when observing positions
+ bernoulli_noise: Chance of a held Item, Door, or Item on the ground not being observed
+
+ """
+
+ def __init__(self, gaussian_noise: float = 0.25, bernoulli_noise: float = 0.05):
+ self.gaussian_noise: Normal = Normal(0.0, gaussian_noise)
+ self.bernoulli_noise: Bernoulli = Bernoulli(bernoulli_noise)
+
+ def apply_noise(self, state: DKGState) -> State:
+ """Applies noise to a state to obtain an observation
+
+ Arguments:
+ state: The state to apply noise to
+
+ Returns:
+ noisy_state: The state with noise applied
+ """
+ new_at = copy.copy(state.at)
+ new_has = copy.copy(state.has)
+ new_doors = copy.copy(state.doors)
+
+ # Apply Noise to items
+ for item_id in state.items:
+ if item_id in new_at:
+ # Chance that item at (x,y) is not observed
+ if self.bernoulli_noise.sample():
+ new_at.pop(item_id)
+
+ else:
+ # Chance that held item is not observed
+ if self.bernoulli_noise.sample():
+ new_has.pop(item_id)
+
+ # Apply Noise to doors
+ for doorloc in state.doors:
+ # Change door is not observed
+ if self.bernoulli_noise.sample():
+ new_doors.remove(doorloc)
+
+ # Apply Gaussian noise to positions
+ return dataclasses.replace(
+ state,
+ at=new_at,
+ has=new_has,
+ doors=new_doors,
+ x=state.x + self.gaussian_noise.sample().item(),
+ y=state.y + self.gaussian_noise.sample().item(),
+ )
+
+ def get_log_prob(self, state: DKGState, observation: DKGState) -> torch.Tensor:
+ """Gets the log probability of a observation given a state
+
+ Arguments:
+ state: The reference state
+ observation: The noisy observation
+
+ Returns:
+ log_prob: The log of P(observation|state)
+
+ """
+ log_prob_items = 0.0
+ # Evaluate Probability of Item positions
+ for item_id in state.items:
+ # If Item is not flipped
+ if (item_id in state.has and item_id in observation.has) or (
+ item_id in state.at and item_id in observation.at
+ ):
+ log_prob_items += self.bernoulli_noise.log_prob(torch.tensor(0.0))
+ # If Item is flipped
+ else:
+ log_prob_items += self.bernoulli_noise.log_prob(torch.tensor(1.0))
+
+ # Evaluate Probability of door positions
+ log_prob_doors = 0.0
+ for doorloc in state.doors:
+ # If Door is not flipped
+ if doorloc in observation.doors:
+ log_prob_doors += self.bernoulli_noise.log_prob(torch.tensor(0.0))
+ # If Door is flipped
+ else:
+ log_prob_doors += self.bernoulli_noise.log_prob(torch.tensor(1.0))
+
+ # Evaluate probability of positions
+ log_prob_x = self.gaussian_noise.log_prob(torch.tensor(state.x - observation.x))
+ log_prob_y = self.gaussian_noise.log_prob(torch.tensor(state.y - observation.y))
+ return log_prob_x + log_prob_y + log_prob_items + log_prob_doors
diff --git a/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/dkg_observation_model_test.py b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/dkg_observation_model_test.py
new file mode 100644
index 0000000000..f68af42944
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/dkg_observation_model_test.py
@@ -0,0 +1,49 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import dataclasses
+
+import math
+
+import torch
+
+from beanmachine.facebook.goal_inference.doors_keys_gems.dkg_observation_model import (
+ DKGObservation,
+)
+from torch.distributions.normal import Normal
+
+
+def test_dkg_gaussian_noise(dkg_state_two):
+ noise_model_bern = DKGObservation(gaussian_noise=0.001, bernoulli_noise=1.0)
+ new_state = noise_model_bern.apply_noise(dkg_state_two)
+ assert not new_state.at.keys()
+ assert not new_state.has.keys()
+ assert not new_state.doors
+ assert math.isclose(new_state.x, dkg_state_two.x, abs_tol=0.1)
+ assert math.isclose(new_state.y, dkg_state_two.y, abs_tol=0.1)
+
+ noise_model_gaus = DKGObservation(gaussian_noise=0.25, bernoulli_noise=0.0)
+ new_state = noise_model_gaus.apply_noise(dkg_state_two)
+ assert new_state.at.keys() == dkg_state_two.at.keys()
+ assert new_state.has.keys() == dkg_state_two.has.keys()
+ assert new_state.doors == dkg_state_two.doors
+ assert new_state.x != dkg_state_two.x
+ assert new_state.y != dkg_state_two.y
+
+ noise_model_mixed = DKGObservation(gaussian_noise=0.25, bernoulli_noise=0.05)
+ new_state_two = dataclasses.replace(dkg_state_two, x=dkg_state_two.x + 1)
+ new_prob = Normal(torch.tensor(dkg_state_two.x), torch.tensor(0.25)).log_prob(
+ torch.tensor(dkg_state_two.x + 1)
+ )
+
+ new_prob += Normal(torch.tensor(dkg_state_two.y), torch.tensor(0.25)).log_prob(
+ torch.tensor(dkg_state_two.y)
+ )
+
+ new_prob += torch.log(torch.tensor(0.95)) * (
+ len(dkg_state_two.doors) + len(dkg_state_two.items.keys())
+ )
+ assert torch.isclose(
+ noise_model_mixed.get_log_prob(dkg_state_two, new_state_two),
+ new_prob,
+ atol=0.01,
+ )
diff --git a/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/dkg_plot.py b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/dkg_plot.py
new file mode 100644
index 0000000000..ea0b54b96f
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/dkg_plot.py
@@ -0,0 +1,190 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from typing import Dict, List, Optional, Tuple
+
+import matplotlib.pyplot as plt
+import numpy as np
+
+from beanmachine.facebook.goal_inference.doors_keys_gems.dkg_definitions import DKGState
+
+from beanmachine.facebook.goal_inference.plotting.utils import (
+ create_gif,
+ format_gem_data,
+ get_gem_figure,
+ get_gem_inference_plot,
+)
+
+from matplotlib import colors
+
+
+""" Set Plot Settings.
+Colors are defined as follows:
+Empty -> White
+Wall -> Black
+Door -> Grey
+Key -> Gold
+Agent -> Red
+Gem -> blue, green, or purple
+ """
+
+CMAP = colors.ListedColormap(
+ ["white", "black", "grey", "gold", "red", "blue", "green", "purple"]
+)
+BOUNDS = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]
+NORM = colors.BoundaryNorm(BOUNDS, CMAP.N)
+
+
+def plot(state: DKGState):
+ """Creates graphic for current state in a Doors, Keys, and Gems problem
+
+ Arguments:
+ state: State to plot
+ """
+ fig, ax = get_gem_figure(state, is_doors_keys_gems=True)
+ env_data, hold_data = get_data_matrix(state)
+
+ ax[0].imshow(
+ env_data,
+ cmap=CMAP,
+ norm=NORM,
+ origin="lower",
+ interpolation="none",
+ extent=[0.5, state.width + 0.5, 0.5, state.height + 0.5],
+ )
+ ax[1].imshow(
+ hold_data,
+ cmap=CMAP,
+ norm=NORM,
+ origin="lower",
+ interpolation="none",
+ extent=[0.5, 1.5, 0.5, 8.5],
+ )
+
+ plt.show()
+ plt.close()
+
+
+def plot_gif(
+ states: List[DKGState],
+ inference_data: Optional[List[Dict[str, int]]] = None,
+ file_path: Optional[str] = None,
+) -> None:
+ """Creates a gif from a list of states and inference data (if available)
+
+ Arguments:
+ states: Series of states to turn into a gif
+ inference_data: Computation of the posterior P(goal|observations) at each time step
+ file_path: Path to location to save the gif
+ """
+
+ fig, ax = get_gem_figure(states[0], inference_data, is_doors_keys_gems=True)
+
+ def animation_function(frame):
+ env_data, hold_data = get_data_matrix(states[frame])
+ ax[0].imshow(
+ env_data,
+ cmap=CMAP,
+ norm=NORM,
+ origin="lower",
+ interpolation="none",
+ extent=[0.5, states[frame].width + 0.5, 0.5, states[frame].height + 0.5],
+ )
+ ax[1].imshow(
+ hold_data,
+ cmap=CMAP,
+ norm=NORM,
+ origin="lower",
+ interpolation="none",
+ extent=[0.5, 1.5, 0.5, 8.5],
+ )
+ if inference_data is not None:
+ prob_goal = get_gem_inference_plot(inference_data, frame)
+ for goal in prob_goal:
+ ax[2].plot(prob_goal[goal], color=CMAP((4.0 + int(goal[3])) / 8.0))
+
+ create_gif(fig, animation_function, states, file_path)
+
+ plt.close()
+
+
+def get_data_matrix(state: DKGState) -> Tuple[np.ndarray, np.ndarray]:
+ """Computes formatted environment and holding data
+
+ Arguments:
+ state: The current state
+
+ Returns:
+ data_env: Correctly formatted data array of the environment
+ data_hold: Correctly formatted data array of the held gems
+ """
+
+ data_env = get_env_data(state)
+
+ data_env = format_gem_data(data_env)
+
+ data_hold = get_hold_data(state)
+
+ data_hold = format_gem_data(data_hold)
+
+ return data_env, data_hold
+
+
+def get_env_data(state: DKGState) -> np.ndarray:
+
+ """Computes environment data matrix (defining colors) based on current environment.
+
+ Arguments:
+ state: The current state
+
+ Returns:
+ data_env: Data array describing environment (positions of agent/Items/doors/walls etc)
+ """
+
+ data_env = np.zeros((state.width, state.height))
+ for i in range(1, state.width + 1):
+ for j in range(1, state.height + 1):
+ if (i, j) in state.walls:
+ data_env[i - 1, j - 1] = 1.0
+ elif (i, j) in state.doors:
+ data_env[i - 1, j - 1] = 2.0
+
+ for k in state.keys:
+ if k in state.at:
+ x_pos, y_pos = state.at[k]
+ data_env[x_pos - 1, y_pos - 1] = 3.0
+
+ data_env[state.x - 1, state.y - 1] = 4.0
+
+ for g in state.gems:
+ if g in state.at:
+ x_pos, y_pos = state.at[g]
+ # Make sure that each gem is a different color ("gem1" -> blue, "gem2" -> green, "gem3" -> purple)
+ data_env[x_pos - 1, y_pos - 1] = 4.0 + int(g[3])
+
+ return data_env
+
+
+def get_hold_data(state: DKGState) -> np.ndarray:
+ """Computes holding data matrix (defining colors) based on objects agent currently holds
+
+ Arguments:
+ state: The current state
+
+ Returns:
+ data_hold: Data array containing identities of the held gems
+ """
+ data_hold = np.zeros((1, 8))
+
+ count = 0
+
+ for item_id in state.keys:
+ if item_id in state.has:
+ data_hold[0, count] = 3.0
+ count += 1
+
+ for item_id in state.gems:
+ if item_id in state.has:
+ data_hold[0, count] = 4.0 + int(item_id[3])
+ count += 1
+
+ return data_hold
diff --git a/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/domain_test.py b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/domain_test.py
new file mode 100644
index 0000000000..ab9e2d5f5c
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/domain_test.py
@@ -0,0 +1,222 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import dataclasses
+
+import pytest
+
+from beanmachine.facebook.goal_inference.doors_keys_gems.dkg_domain import DKGDomain
+
+from beanmachine.facebook.goal_inference.doors_keys_gems.parser import parse
+
+
+@pytest.fixture
+def state():
+ dkg_state = parse(
+ "beanmachine/facebook/goal_inference/doors_keys_gems/test_problems/problem-1.pddl"
+ )
+ return dkg_state
+
+
+@pytest.fixture
+def domain():
+ dkg_domain = DKGDomain()
+ return dkg_domain
+
+
+def test_wall(state, domain):
+
+ for i in range(state.width):
+ for j in range(state.height):
+ assert domain.predicates["wall"](state, i + 1, j + 1) == (
+ (i + 1, j + 1) in state.walls
+ )
+
+
+def test_door(state, domain):
+ for i in range(state.width):
+ for j in range(state.height):
+ assert domain.predicates["door"](state, i + 1, j + 1) == (
+ (i + 1, j + 1) in state.doors
+ )
+
+
+def test_obstacle(state, domain):
+ for i in range(state.width):
+ for j in range(state.height):
+ assert domain.predicates["obstacle"](state, i + 1, j + 1) == (
+ (i + 1, j + 1) in state.doors or (i + 1, j + 1) in state.walls
+ )
+
+
+def test_has(state, domain):
+
+ for name in state.items:
+ assert (name in state.has) == domain.predicates["has"](state, name)
+
+ ### Assert No directions are held
+
+ for direction in state.directions:
+ assert not domain.predicates["has"](state, direction)
+
+ ### items on ground are not held
+
+ for name in state.at:
+ assert not domain.predicates["has"](state, name)
+
+
+def test_at(state, domain):
+
+ for name in state.at:
+ x_init = state.at[name][0]
+ y_init = state.at[name][1]
+ for i in range(state.width):
+ for j in range(state.height):
+ if i == x_init and j == y_init:
+ assert domain.predicates["at"](state, name, i, j)
+ else:
+ assert not domain.predicates["at"](state, name, i, j)
+
+
+#### Test Execution
+
+
+def test_action_up(state, domain):
+
+ state_two = domain.actions["up"].execute(state)
+
+ assert state_two == state
+
+ state_three = dataclasses.replace(state, y=state.y - 1)
+ state_four = domain.actions["up"].execute(state_three)
+
+ assert state_four.x == state_three.x
+ assert state_four.y == state_three.y + 1
+
+
+def test_action_down(state, domain):
+
+ state_two = domain.execute(state, "down")
+
+ assert state_two.x == state.x
+ assert state_two.y == state.y - 1
+
+ state_three = domain.execute(state_two, "down")
+
+ assert state_three.x == state_two.x
+ assert state_three.y == state_two.y - 1
+
+ state_four = domain.execute(state_three, "down")
+
+ assert state_four == state_three
+
+
+def test_action_left(state, domain):
+
+ state_two = domain.execute(state, "left")
+
+ assert state_two == state
+
+ state.walls.remove((2, 3))
+ state_three = dataclasses.replace(state, x=2)
+
+ state_four = domain.execute(state_three, "left")
+
+ assert state_four.x == state_three.x - 1
+ assert state_four.y == state_three.y
+
+
+def test_action_right(state, domain):
+
+ state_two = domain.execute(state, "right")
+
+ assert state_two == state
+
+ state.walls.remove((2, 3))
+ state_three = dataclasses.replace(state, x=1)
+ state_four = domain.execute(state_three, "right")
+
+ assert state_four.x == state_three.x + 1
+ assert state_four.y == state_three.y
+
+
+def test_action_pickup(state, domain):
+
+ state_two = domain.execute(state, "pickup", "key2")
+ assert state_two == state
+
+ state_three = dataclasses.replace(state, y=2)
+ state_four = domain.execute(state_three, "pickup", "key2")
+ assert state_four == state_three
+
+ state_five = domain.execute(state_four, "pickup", "key1")
+ assert "key1" in state_five.has
+
+
+def test_action_unlock(state, domain):
+
+ assert (2, 1) in state.doors
+
+ state_two = dataclasses.replace(state, x=1, y=1)
+
+ state_three = domain.execute(state_two, "unlock", "key1", "up")
+ assert state_three == state_two
+
+ state_four = domain.execute(state_three, "unlock", "key1", "left")
+ assert state_four == state_three
+
+ state_five = domain.execute(state_four, "unlock", "key1", "right")
+ assert state_five == state_four
+
+ state_six = dataclasses.replace(state_five, has={"key1": None})
+
+ state_seven = domain.execute(state_six, "unlock", "key1", "up")
+ assert state_seven == state_six
+
+ state_eight = domain.execute(state_seven, "unlock", "key1", "left")
+ assert state_eight == state_seven
+
+ state_nine = domain.execute(state_eight, "unlock", "key1", "right")
+ assert (2, 1) not in state_nine.doors
+
+
+def test_get_possible_actions(state, domain):
+ poss_actions = domain.get_possible_actions(state)
+ assert poss_actions[0] == ["down"]
+ assert len(poss_actions) == 1
+
+ state = domain.execute(state, "down")
+ poss_actions = domain.get_possible_actions(state)
+ assert poss_actions[0] == ["up"]
+ assert poss_actions[1] == ["down"]
+ assert poss_actions[2] == ["pickup", "key1"]
+ assert len(poss_actions) == 3
+
+ state = domain.execute(state, "pickup", "key1")
+ state = domain.execute(state, "down")
+ poss_actions = domain.get_possible_actions(state)
+ assert poss_actions[0] == ["up"]
+ assert poss_actions[1] == ["unlock", "key1", "right"]
+ assert len(poss_actions) == 2
+
+ state = domain.execute(state, "unlock", "key1", "right")
+ poss_actions = domain.get_possible_actions(state)
+ assert poss_actions[0] == ["right"]
+ assert poss_actions[1] == ["up"]
+ assert len(poss_actions) == 2
+
+
+def test_evaluate_goal(state, domain):
+ assert not domain.evaluate_goal(state)
+ state_two = dataclasses.replace(state, has={"key1": state.keys["key1"]})
+ assert not domain.evaluate_goal(state_two)
+ state_three = dataclasses.replace(state, has={"gem2": None})
+ assert not domain.evaluate_goal(state_three)
+ state_four = dataclasses.replace(state, has={"gem1": state.gems["gem1"]})
+ assert domain.evaluate_goal(state_four)
+
+
+def test_is_action_possible(state, domain):
+ assert not domain.is_action_possible(state, "pickup", "gem1")
+ assert domain.is_action_possible(state, "down")
+ state = domain.execute(state, "down")
+ assert domain.is_action_possible(state, "pickup", "key1")
diff --git a/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/parser.py b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/parser.py
new file mode 100644
index 0000000000..089a40d8c3
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/parser.py
@@ -0,0 +1,312 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from typing import Any, Dict, List, Set, Tuple
+
+from beanmachine.facebook.goal_inference.doors_keys_gems.dkg_definitions import (
+ Direction,
+ DKGState,
+ Gem,
+ Item,
+ Key,
+)
+
+
+def parse(file_path: str) -> DKGState:
+ """Reads in selected problem. Intializes state by parsing file for objects, conditions, and goal.
+
+ Arguments:
+ file_path: path to the selected problem
+
+ Returns:
+ dkg_state: Initial state of the doors, keys, and gems problem
+ """
+ full_file = open(file_path, "r")
+ full_problem = full_file.read()
+ full_file.close()
+
+ data_parse = full_problem.split(":")
+ objs_data = ""
+ condition_data = ""
+ goal_data = ""
+
+ for data_type in data_parse:
+ if data_type[:7] == "objects":
+ objs_data = data_type
+
+ elif data_type[:4] == "init":
+ condition_data = data_type
+
+ elif data_type[:4] == "goal":
+ goal_data = data_type
+
+ items, gems, keys, directions = parse_objects(objs_data)
+
+ width, height, xdiff, ydiff, doors, walls, x, y, at = parse_conditions(
+ condition_data
+ )
+
+ goal = parse_goal(goal_data)
+
+ has = {}
+
+ return DKGState(
+ goal,
+ width,
+ height,
+ xdiff,
+ ydiff,
+ doors,
+ walls,
+ items,
+ directions,
+ keys,
+ gems,
+ has,
+ at,
+ x,
+ y,
+ )
+
+
+def parse_objects(
+ obj_string: str,
+) -> Tuple[Dict[str, Item], Dict[str, Gem], Dict[str, Key], Dict[str, Direction]]:
+ """Sets State Objects [items,gems,keys] by parsing object substring of PDDL file.
+
+ Arguments:
+ obj_string: The substring of the PDDL file where objects are defined
+
+ Returns:
+ items: A map from Item names to the Item objects
+ gems: A map from Gem names to the Gem objects
+ keys: A map from Key names to the Key objects
+ directions: A map from Direction names to the Direction objects
+ """
+ items = {}
+ gems = {}
+ keys = {}
+ directions = {}
+
+ obj_dict = obj_parser(obj_string)
+ if "gem" in obj_dict:
+ for g in obj_dict["gem"]:
+ new_gem = Gem(g)
+ gems[g] = new_gem
+ items[g] = new_gem
+
+ if "key" in obj_dict:
+ for k in obj_dict["key"]:
+ new_key = Key(k)
+ keys[k] = new_key
+ items[k] = new_key
+
+ if "direction" in obj_dict:
+ for d in obj_dict["direction"]:
+ new_direction = Direction(d)
+ directions[d] = new_direction
+
+ return items, gems, keys, directions
+
+
+def parse_param_condition(
+ condition: List[str],
+) -> Tuple[Any, ...]:
+ """Handles condition parsing for setting of environment parameters
+
+ Arguments:
+ condition: A string in the form e.g. (= width 3) that relates to a parameter of the environment
+
+ Returns:
+ parsed_condition: The condition parsed into a more easily manipulated format (variable, *args)
+ """
+ # Parameters can appear with and without paranthesis
+ if condition[1][0] == "(":
+ condition[1] = condition[1][1:]
+ if condition[1][-1] == ")":
+ condition[1] = condition[1][:-1]
+
+ if condition[1] == "xpos":
+ return ("x", int(condition[2]))
+ elif condition[1] == "ypos":
+ return ("y", int(condition[2]))
+ elif condition[1] == "width":
+ return ("width", int(condition[2]))
+ elif condition[1] == "height":
+ return ("height", int(condition[2]))
+ elif condition[1] == "xdiff":
+ return ("xdiff", condition[2][:-1], int(condition[-1]))
+ elif condition[1] == "ydiff":
+ return ("ydiff", condition[2][:-1], int(condition[-1]))
+ else:
+ raise ValueError("Unknown Parameter")
+
+
+def parse_conditions(
+ condition_string: str,
+) -> Tuple[
+ int,
+ int,
+ Dict[str, int],
+ Dict[str, int],
+ Set[Tuple[int, int]],
+ Set[Tuple[int, int]],
+ int,
+ int,
+ Dict[str, Tuple[int, int]],
+]:
+ """Sets parameters [x,y,width,height,xdiff,ydiff] and locations of doors/walls/items
+
+ Arguments:
+ condition_string: The substring of the PDDL file where conditions are defined
+
+ Returns:
+ width: Width of environment
+ height: Height of environment
+ xdiff: Movement/Interaction along x-axis when given a direction
+ ydiff: Movement/Interaction along y-axis when given a direction
+ doors: Positions of doors
+ walls: Positions of walls
+ x: X-position of Agent
+ y: Y-position of Agent
+ at: Map from name to location for all Items not held by the Agent
+
+ """
+ params = {}
+ params["xdiff"] = {}
+ params["ydiff"] = {}
+ doors = set()
+ walls = set()
+ at = {}
+
+ # Separate conditions
+ conditions = condition_parser(condition_string)
+ for condition in conditions:
+ condition_splt = condition.split()
+ # Identify if condition relates to an environment variable
+ if condition_splt[0] == "=":
+ condition_parsed = parse_param_condition(condition_splt)
+ if len(condition_parsed) == 3:
+ params[condition_parsed[0]][condition_parsed[1]] = condition_parsed[2]
+ else:
+ params[condition_parsed[0]] = condition_parsed[1]
+
+ elif condition_splt[0] == "wall":
+ walls.add((int(condition_splt[1]), int(condition_splt[2])))
+
+ elif condition_splt[0] == "at":
+ at[condition_splt[1]] = (int(condition_splt[2]), int(condition_splt[3]))
+
+ elif condition_splt[0] == "doorloc":
+ doors.add((int(condition_splt[1]), int(condition_splt[2])))
+
+ elif condition_splt[0] == "itemloc" or condition_splt[0] == "door":
+ pass
+
+ else:
+ raise ValueError("Unknown Rule")
+
+ return (
+ params["width"],
+ params["height"],
+ params["xdiff"],
+ params["ydiff"],
+ doors,
+ walls,
+ params["x"],
+ params["y"],
+ at,
+ )
+
+
+def parse_goal(goal_string: str) -> Tuple[str, str]:
+ """Parses goal into predicate and argument
+ e.g. "has gem1" -> ("has","gem1")
+
+ Arguments:
+ goal_string: Substring of PDDL file related to the goal. Example: "goal (has gem3)"
+
+ Returns:
+ new_goal: Goal in the format ("has","gem1")
+
+ """
+ # Clean text around goal
+ goal = goal_parser(goal_string)
+ splt = goal.split()
+ new_goal = (splt[0], splt[1:][0])
+ return new_goal
+
+
+def obj_parser(obj_string: str) -> Dict[str, List]:
+ """Parses Objects listed in PDDL file into Dictionary e.g obj_dict["key"] = ["key1","key2","key3"...]"""
+ # Cleaning Input
+ obj_string = obj_string[7:]
+ obj_string = obj_string.replace("\n", "")
+ obj_string = obj_string.replace(")", "")
+ obj_string = obj_string.replace("(", "")
+ obj_split = obj_string.split()
+
+ # Create Dict
+ obj_dict = {}
+
+ active_names = []
+ index = 0
+ while index < len(obj_split):
+ if obj_split[index] == "-":
+ index += 1
+ obj_type = obj_split[index]
+ obj_dict[obj_type] = active_names
+ active_names = []
+
+ else:
+ active_names.append(obj_split[index])
+
+ index += 1
+
+ return obj_dict
+
+
+def condition_parser(condition_string: str) -> List[str]:
+ """Parses text stream of initial conditions into list of single conditions
+ e.g. "(wall 2 7)
+ (wall 4 7)
+ (at key1 5 7)
+ (itemloc 5 7)"
+
+ -> ["wall 2 7","wall 4 7","at key1 5 7","itemloc 5 7"]
+
+ Arguments:
+ condition_string: Substring of PDDL file related to starting conditions
+
+ Returns:
+ condition_split: List of separate conditions
+ """
+
+ # Cleaning Object
+ condition_string = condition_string[4:]
+ condition_string = condition_string.replace("\n", "")
+
+ # Get separate rules
+ condition_string = " ".join(condition_string.split())
+ condition_split = condition_string.split(") (")
+
+ # Fix off by one
+ condition_split = condition_split[:-1]
+ condition_split[0] = condition_split[0][1:]
+ last_pos = len(condition_split[-1]) - 1
+ while not condition_split[-1][last_pos].isalnum():
+ last_pos -= 1
+ condition_split[-1] = condition_split[-1][: last_pos + 1]
+
+ return condition_split
+
+
+def goal_parser(goal_string: str) -> str:
+ """Cleans text around goal phrase e.g. "goal (has gem3)" -> "has gem3"
+
+ Arguments:
+ goal_string: goal in format "goal (has gem3)"
+ Returns:
+ goal: goal in format "has gem3"
+
+ """
+ return goal_string[goal_string.find("(") + 1 : goal_string.find(")")]
diff --git a/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/parser_test.py b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/parser_test.py
new file mode 100644
index 0000000000..75801ea680
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/parser_test.py
@@ -0,0 +1,212 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from beanmachine.facebook.goal_inference.doors_keys_gems.parser import parse
+
+
+def test_state_load_problem_1():
+ state = parse(
+ "beanmachine/facebook/goal_inference/doors_keys_gems/test_problems/problem-1.pddl"
+ )
+ ### walls
+ assert len(state.has) == 0
+ assert (2, 3) in state.walls
+ assert (2, 2) in state.walls
+ ### doors
+ assert (2, 1) in state.doors
+ ### items
+ assert "key1" in state.at and state.at[("key1")] == (1, 2)
+ assert "gem1" in state.at and state.at[("gem1")] == (3, 3)
+
+ ### boundaries
+ assert state.width == 3
+ assert state.height == 3
+ ### agent
+ assert state.x == 1
+ assert state.y == 3
+
+ ### xdiff / ydiff
+ assert state.xdiff["right"] == 1
+ assert state.xdiff["left"] == -1
+ assert state.xdiff["up"] == 0
+ assert state.xdiff["down"] == 0
+ assert state.ydiff["right"] == 0
+ assert state.ydiff["left"] == 0
+ assert state.ydiff["up"] == 1
+ assert state.ydiff["down"] == -1
+
+ assert state.goal == ("has", "gem1")
+
+
+def test_state_load_problem_2():
+ state = parse(
+ "beanmachine/facebook/goal_inference/doors_keys_gems/test_problems/problem-2.pddl"
+ )
+
+ ### walls
+ assert len(state.has) == 0
+ assert (2, 2) in state.walls
+ assert (2, 3) in state.walls
+ assert (2, 4) in state.walls
+ assert (4, 2) in state.walls
+ assert (4, 3) in state.walls
+ assert (4, 4) in state.walls
+ ### doors
+ assert (4, 1) in state.doors
+ assert (4, 5) in state.doors
+
+ ### items
+ assert "key1" in state.at and state.at[("key1")] == (3, 3)
+ assert "gem1" in state.at and state.at[("gem1")] == (5, 2)
+ assert "gem2" in state.at and state.at[("gem2")] == (5, 4)
+
+ ### boundaries
+ assert state.width == 5
+ assert state.height == 5
+ ### agent
+ assert state.x == 1
+ assert state.y == 3
+
+ ### xdiff / ydiff
+ assert state.xdiff["right"] == 1
+ assert state.xdiff["left"] == -1
+ assert state.xdiff["up"] == 0
+ assert state.xdiff["down"] == 0
+ assert state.ydiff["right"] == 0
+ assert state.ydiff["left"] == 0
+ assert state.ydiff["up"] == 1
+ assert state.ydiff["down"] == -1
+
+ assert state.goal == ("has", "gem1")
+
+
+def test_state_load_problem_3():
+ state = parse(
+ "beanmachine/facebook/goal_inference/doors_keys_gems/test_problems/problem-3.pddl"
+ )
+
+ ### walls
+ assert len(state.has) == 0
+ assert (1, 2) in state.walls
+ assert (2, 2) in state.walls
+ assert (3, 2) in state.walls
+ assert (5, 1) in state.walls
+ assert (5, 2) in state.walls
+ assert (5, 3) in state.walls
+
+ assert (5, 4) in state.walls
+ assert (7, 2) in state.walls
+ assert (7, 3) in state.walls
+ assert (7, 4) in state.walls
+ assert (7, 5) in state.walls
+ assert (7, 6) in state.walls
+ assert (2, 4) in state.walls
+ assert (2, 5) in state.walls
+ assert (2, 6) in state.walls
+ assert (3, 6) in state.walls
+ assert (4, 6) in state.walls
+ assert (5, 6) in state.walls
+ assert (6, 6) in state.walls
+ assert (7, 6) in state.walls
+ assert (4, 8) in state.walls
+ assert (6, 7) in state.walls
+ ### doors
+ assert (4, 7) in state.doors
+ assert (5, 5) in state.doors
+ assert (8, 6) in state.doors
+
+ ### items
+ assert "key1" in state.at and state.at[("key1")] == (1, 7)
+ assert "key2" in state.at and state.at[("key2")] == (7, 7)
+ assert "gem1" in state.at and state.at[("gem1")] == (1, 8)
+ assert "gem2" in state.at and state.at[("gem2")] == (8, 8)
+ assert "gem3" in state.at and state.at[("gem3")] == (8, 1)
+
+ ### boundaries
+ assert state.width == 8
+ assert state.height == 8
+ ### agent
+ assert state.x == 1
+ assert state.y == 1
+
+ ### xdiff / ydiff
+ assert state.xdiff["right"] == 1
+ assert state.xdiff["left"] == -1
+ assert state.xdiff["up"] == 0
+ assert state.xdiff["down"] == 0
+ assert state.ydiff["right"] == 0
+ assert state.ydiff["left"] == 0
+ assert state.ydiff["up"] == 1
+ assert state.ydiff["down"] == -1
+
+ assert state.goal == ("has", "gem3")
+
+
+def test_state_load_problem_4():
+ state = parse(
+ "beanmachine/facebook/goal_inference/doors_keys_gems/test_problems/problem-4.pddl"
+ )
+
+ ### walls
+ assert len(state.has) == 0
+ assert (4, 1) in state.walls
+ assert (5, 1) in state.walls
+ assert (6, 1) in state.walls
+ assert (2, 2) in state.walls
+ assert (3, 2) in state.walls
+ assert (4, 2) in state.walls
+ assert (6, 2) in state.walls
+ assert (7, 2) in state.walls
+ assert (8, 2) in state.walls
+ assert (2, 3) in state.walls
+ assert (8, 3) in state.walls
+ assert (2, 4) in state.walls
+ assert (4, 4) in state.walls
+ assert (6, 4) in state.walls
+ assert (8, 4) in state.walls
+ assert (2, 5) in state.walls
+ assert (4, 5) in state.walls
+ assert (6, 5) in state.walls
+ assert (8, 5) in state.walls
+ assert (2, 6) in state.walls
+ assert (4, 6) in state.walls
+ assert (5, 6) in state.walls
+ assert (6, 6) in state.walls
+ assert (8, 6) in state.walls
+ assert (2, 7) in state.walls
+ assert (4, 7) in state.walls
+ assert (6, 7) in state.walls
+ assert (8, 7) in state.walls
+ assert (2, 8) in state.walls
+ assert (3, 8) in state.walls
+ assert (4, 8) in state.walls
+ assert (6, 8) in state.walls
+ assert (8, 8) in state.walls
+ ### doors
+ assert (5, 4) in state.doors
+ assert (7, 8) in state.doors
+
+ ### items
+ assert "key1" in state.at and state.at[("key1")] == (5, 7)
+ assert "key2" in state.at and state.at[("key2")] == (5, 9)
+ assert "gem1" in state.at and state.at[("gem1")] == (7, 1)
+ assert "gem2" in state.at and state.at[("gem2")] == (5, 2)
+ assert "gem3" in state.at and state.at[("gem3")] == (5, 5)
+
+ ### boundaries
+ assert state.width == 9
+ assert state.height == 9
+ ### agent
+ assert state.x == 3
+ assert state.y == 1
+
+ ### xdiff / ydiff
+ assert state.xdiff["right"] == 1
+ assert state.xdiff["left"] == -1
+ assert state.xdiff["up"] == 0
+ assert state.xdiff["down"] == 0
+ assert state.ydiff["right"] == 0
+ assert state.ydiff["left"] == 0
+ assert state.ydiff["up"] == 1
+ assert state.ydiff["down"] == -1
+
+ assert state.goal == ("has", "gem3")
diff --git a/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/test_problems/problem-1.pddl b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/test_problems/problem-1.pddl
new file mode 100644
index 0000000000..1ed695866e
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/test_problems/problem-1.pddl
@@ -0,0 +1,24 @@
+;; ASCII ;;
+; W: wall, D: door, k: key, g: gem, G: goal-gem, s: start, .: empty
+; sWG
+; kW.
+; .D.
+(define (problem doors-keys-gems-1)
+ (:domain doors-keys-gems)
+ (:objects
+ up down right left - direction
+ key1 - key gem1 - gem
+ )
+ (:init
+ (= (xdiff up) 0) (= (ydiff up) 1)
+ (= (xdiff down) 0) (= (ydiff down) -1)
+ (= (xdiff right) 1) (= (ydiff right) 0)
+ (= (xdiff left) -1) (= (ydiff left) 0)
+ (= width 3) (= height 3)
+ (= xpos 1) (= ypos 3)
+ (wall 2 3) (wall 2 2) (door 2 1)
+ (at key1 1 2) (at gem1 3 3)
+ (doorloc 2 1) (itemloc 1 2) (itemloc 3 3)
+ )
+ (:goal (has gem1))
+)
diff --git a/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/test_problems/problem-2.pddl b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/test_problems/problem-2.pddl
new file mode 100644
index 0000000000..51c9f401dd
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/test_problems/problem-2.pddl
@@ -0,0 +1,28 @@
+;; ASCII ;;
+; W: wall, D: door, k: key, g: gem, G: goal-gem, s: start, .: empty
+; ...D.
+; .W.Wg
+; sWkW.
+; .W.WG
+; ...D.
+(define (problem doors-keys-gems-2)
+ (:domain doors-keys-gems)
+ (:objects
+ up down right left - direction
+ key1 - key gem1 gem2 - gem
+ )
+ (:init
+ (= (xdiff up) 0) (= (ydiff up) 1)
+ (= (xdiff down) 0) (= (ydiff down) -1)
+ (= (xdiff right) 1) (= (ydiff right) 0)
+ (= (xdiff left) -1) (= (ydiff left) 0)
+ (= width 5) (= height 5)
+ (= xpos 1) (= ypos 3)
+ (wall 2 2) (wall 2 3) (wall 2 4)
+ (door 4 1) (wall 4 2) (wall 4 3) (wall 4 4) (door 4 5)
+ (at key1 3 3) (at gem1 5 2) (at gem2 5 4)
+ (doorloc 4 1) (doorloc 4 5)
+ (itemloc 3 3) (itemloc 5 2) (itemloc 5 4)
+ )
+ (:goal (has gem1))
+)
diff --git a/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/test_problems/problem-3.pddl b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/test_problems/problem-3.pddl
new file mode 100644
index 0000000000..bb6c1e2401
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/test_problems/problem-3.pddl
@@ -0,0 +1,38 @@
+;; ASCII ;;
+; W: wall, D: door, k: key, g: gem, G: goal-gem, s: start, .: empty
+; g..W...g
+; k..D.Wk.
+; .WWWWWWD
+; .W..D.W.
+; .W..W.W.
+; ....W.W.
+; WWW.W.W.
+; s...W..G
+(define (problem doors-keys-gems-3)
+ (:domain doors-keys-gems)
+ (:objects
+ up down right left - direction
+ key1 key2 - key gem1 gem2 gem3 - gem
+ )
+ (:init
+ (= (xdiff up) 0) (= (ydiff up) 1)
+ (= (xdiff down) 0) (= (ydiff down) -1)
+ (= (xdiff right) 1) (= (ydiff right) 0)
+ (= (xdiff left) -1) (= (ydiff left) 0)
+ (= width 8) (= height 8)
+ (= xpos 1) (= ypos 1)
+ (wall 1 2) (wall 2 2) (wall 3 2)
+ (wall 5 1) (wall 5 2) (wall 5 3) (wall 5 4)
+ (wall 7 2) (wall 7 3) (wall 7 4) (wall 7 5) (wall 7 6)
+ (wall 2 4) (wall 2 5) (wall 2 6)
+ (wall 3 6) (wall 4 6) (wall 5 6) (wall 6 6) (wall 7 6)
+ (wall 4 8) (wall 6 7)
+ (door 4 7) (door 5 5) (door 8 6)
+ (doorloc 4 7) (doorloc 5 5) (doorloc 8 6)
+ (at key1 1 7) (at key2 7 7)
+ (at gem1 1 8) (at gem2 8 8) (at gem3 8 1)
+ (itemloc 1 7) (itemloc 7 7)
+ (itemloc 1 8) (itemloc 8 8) (itemloc 8 1)
+ )
+ (:goal (has gem3))
+)
diff --git a/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/test_problems/problem-4.pddl b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/test_problems/problem-4.pddl
new file mode 100644
index 0000000000..a20e9da7e9
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/test_problems/problem-4.pddl
@@ -0,0 +1,68 @@
+;; ASCII ;;
+; W: wall, D: door, k: key, g: gem, G: goal-gem, s: start, .: empty
+; ....k....
+; .WWW.WDW.
+; .W.WkW.W.
+; .W.WWW.W.
+; .W.WGW.W.
+; .W.WDW.W.
+; .W.....W.
+; .WWWgWWW.
+; ..sWWWg..
+(define (problem doors-keys-gems-4)
+ (:domain doors-keys-gems)
+ (:objects up down left right - direction key1 key2 - key gem1 gem2 gem3 - gem)
+ (:init (= (xdiff up) 0) (= (ydiff up) 1)
+ (= (xdiff down) 0) (= (ydiff down) -1)
+ (= (xdiff right) 1) (= (ydiff right) 0)
+ (= (xdiff left) -1) (= (ydiff left) 0)
+ (= (width) 9) (= (height) 9) (= (xpos) 3) (= (ypos) 1)
+ (wall 4 1)
+ (wall 5 1)
+ (wall 6 1)
+ (at gem1 7 1)
+ (itemloc 7 1)
+ (wall 2 2)
+ (wall 3 2)
+ (wall 4 2)
+ (at gem2 5 2)
+ (itemloc 5 2)
+ (wall 6 2)
+ (wall 7 2)
+ (wall 8 2)
+ (wall 2 3)
+ (wall 8 3)
+ (wall 2 4)
+ (wall 4 4)
+ (door 5 4)
+ (doorloc 5 4)
+ (wall 6 4)
+ (wall 8 4)
+ (wall 2 5)
+ (wall 4 5)
+ (at gem3 5 5)
+ (itemloc 5 5)
+ (wall 6 5)
+ (wall 8 5)
+ (wall 2 6)
+ (wall 4 6)
+ (wall 5 6)
+ (wall 6 6)
+ (wall 8 6)
+ (wall 2 7)
+ (wall 4 7)
+ (at key1 5 7)
+ (itemloc 5 7)
+ (wall 6 7)
+ (wall 8 7)
+ (wall 2 8)
+ (wall 3 8)
+ (wall 4 8)
+ (wall 6 8)
+ (door 7 8)
+ (doorloc 7 8)
+ (wall 8 8)
+ (at key2 5 9)
+ (itemloc 5 9))
+ (:goal (has gem3))
+)
diff --git a/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/test_problems/problem-5.pddl b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/test_problems/problem-5.pddl
new file mode 100644
index 0000000000..a3ce0bd7ae
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/test_problems/problem-5.pddl
@@ -0,0 +1,91 @@
+;; ASCII ;;
+; W: wall, D: door, k: key, g: gem, G: goal-gem, s: start, .: empty
+; k.......k
+; WWWWDWWWW
+; WWWW.WWWW
+; WWWW.WWWW
+; .D..k..D.
+; .WWW.WWW.
+; .WWWsWWWD
+; .WWW.WWW.
+; gWWWgWWWG
+(define (problem doors-keys-gems-5)
+ (:domain doors-keys-gems)
+ (:objects up down left right - direction
+ key1 key2 key3 - key
+ gem1 gem2 gem3 - gem)
+ (:init (= (xdiff up) 0) (= (ydiff up) 1)
+ (= (xdiff down) 0) (= (ydiff down) -1)
+ (= (xdiff right) 1) (= (ydiff right) 0)
+ (= (xdiff left) -1) (= (ydiff left) 0)
+ (= (width) 9) (= (height) 9) (= (xpos) 5) (= (ypos) 3)
+ (at gem1 1 1)
+ (itemloc 1 1)
+ (wall 2 1)
+ (wall 3 1)
+ (wall 4 1)
+ (at gem2 5 1)
+ (itemloc 5 1)
+ (wall 6 1)
+ (wall 7 1)
+ (wall 8 1)
+ (at gem3 9 1)
+ (itemloc 9 1)
+ (wall 2 2)
+ (wall 3 2)
+ (wall 4 2)
+ (wall 6 2)
+ (wall 7 2)
+ (wall 8 2)
+ (wall 2 3)
+ (wall 3 3)
+ (wall 4 3)
+ (wall 6 3)
+ (wall 7 3)
+ (wall 8 3)
+ (door 9 3)
+ (doorloc 9 3)
+ (wall 2 4)
+ (wall 3 4)
+ (wall 4 4)
+ (wall 6 4)
+ (wall 7 4)
+ (wall 8 4)
+ (door 2 5)
+ (doorloc 2 5)
+ (at key1 5 5)
+ (itemloc 5 5)
+ (door 8 5)
+ (doorloc 8 5)
+ (wall 1 6)
+ (wall 2 6)
+ (wall 3 6)
+ (wall 4 6)
+ (wall 6 6)
+ (wall 7 6)
+ (wall 8 6)
+ (wall 9 6)
+ (wall 1 7)
+ (wall 2 7)
+ (wall 3 7)
+ (wall 4 7)
+ (wall 6 7)
+ (wall 7 7)
+ (wall 8 7)
+ (wall 9 7)
+ (wall 1 8)
+ (wall 2 8)
+ (wall 3 8)
+ (wall 4 8)
+ (door 5 8)
+ (doorloc 5 8)
+ (wall 6 8)
+ (wall 7 8)
+ (wall 8 8)
+ (wall 9 8)
+ (at key2 1 9)
+ (itemloc 1 9)
+ (at key3 9 9)
+ (itemloc 9 9))
+ (:goal (has gem3))
+)
diff --git a/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/test_problems/problem-6.pddl b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/test_problems/problem-6.pddl
new file mode 100644
index 0000000000..408e5ae457
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/test_problems/problem-6.pddl
@@ -0,0 +1,83 @@
+;; ASCII ;;
+; W: wall, D: door, k: key, g: gem, G: goal-gem, s: start, .: empty
+; WW.W.W.WW
+; WW.WGW.WW
+; WW.WDW.WW
+; WW.....WW
+; sWgWWW.D.
+; .WWWkWWW.
+; .........
+; WWWW.WWWW
+; WWWk.gWWW
+(define (problem doors-keys-gems-6)
+ (:domain doors-keys-gems)
+ (:objects up down left right - direction
+ key1 key2 - key
+ gem1 gem2 gem3 - gem)
+ (:init (= (xdiff up) 0) (= (ydiff up) 1)
+ (= (xdiff down) 0) (= (ydiff down) -1)
+ (= (xdiff right) 1) (= (ydiff right) 0)
+ (= (xdiff left) -1) (= (ydiff left) 0)
+ (= (width) 9) (= (height) 9) (= (xpos) 1) (= (ypos) 5)
+ (wall 1 1)
+ (wall 2 1)
+ (wall 3 1)
+ (at key1 4 1)
+ (itemloc 4 1)
+ (at gem1 6 1)
+ (itemloc 6 1)
+ (wall 7 1)
+ (wall 8 1)
+ (wall 9 1)
+ (wall 1 2)
+ (wall 2 2)
+ (wall 3 2)
+ (wall 4 2)
+ (wall 6 2)
+ (wall 7 2)
+ (wall 8 2)
+ (wall 9 2)
+ (wall 2 4)
+ (wall 3 4)
+ (wall 4 4)
+ (at key2 5 4)
+ (itemloc 5 4)
+ (wall 6 4)
+ (wall 7 4)
+ (wall 8 4)
+ (wall 2 5)
+ (at gem2 3 5)
+ (itemloc 3 5)
+ (wall 4 5)
+ (wall 5 5)
+ (wall 6 5)
+ (door 8 5)
+ (doorloc 8 5)
+ (wall 1 6)
+ (wall 2 6)
+ (wall 8 6)
+ (wall 9 6)
+ (wall 1 7)
+ (wall 2 7)
+ (wall 4 7)
+ (door 5 7)
+ (doorloc 5 7)
+ (wall 6 7)
+ (wall 8 7)
+ (wall 9 7)
+ (wall 1 8)
+ (wall 2 8)
+ (wall 4 8)
+ (at gem3 5 8)
+ (itemloc 5 8)
+ (wall 6 8)
+ (wall 8 8)
+ (wall 9 8)
+ (wall 1 9)
+ (wall 2 9)
+ (wall 4 9)
+ (wall 6 9)
+ (wall 8 9)
+ (wall 9 9))
+ (:goal (has gem3))
+)
diff --git a/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/test_problems/problem-7.pddl b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/test_problems/problem-7.pddl
new file mode 100644
index 0000000000..4323ae04e6
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/doors_keys_gems/test_problems/problem-7.pddl
@@ -0,0 +1,91 @@
+;; ASCII ;;
+; W: wall, D: door, k: key, g: gem, G: goal-gem, s: start, .: empty
+; WgWWkWWgW
+; W.WW.WWDW
+; W..D.D..W
+; WWWW.WWWW
+; .......D.
+; .WWW.WWW.
+; .WWW.WWWD
+; .WWWDWWW.
+; sWWk.kWWG
+(define (problem doors-keys-gems-7)
+ (:domain doors-keys-gems)
+ (:objects up down left right - direction
+ key1 key2 key3 - key
+ gem1 gem2 gem3 - gem)
+ (:init (= (xdiff up) 0) (= (ydiff up) 1)
+ (= (xdiff down) 0) (= (ydiff down) -1)
+ (= (xdiff right) 1) (= (ydiff right) 0)
+ (= (xdiff left) -1) (= (ydiff left) 0)
+ (= (width) 9) (= (height) 9) (= (xpos) 1) (= (ypos) 1)
+ (wall 2 1)
+ (wall 3 1)
+ (at key1 4 1)
+ (itemloc 4 1)
+ (at key2 6 1)
+ (itemloc 6 1)
+ (wall 7 1)
+ (wall 8 1)
+ (at gem3 9 1)
+ (itemloc 9 1)
+ (wall 2 2)
+ (wall 3 2)
+ (wall 4 2)
+ (door 5 2)
+ (doorloc 5 2)
+ (wall 6 2)
+ (wall 7 2)
+ (wall 8 2)
+ (wall 2 3)
+ (wall 3 3)
+ (wall 4 3)
+ (wall 6 3)
+ (wall 7 3)
+ (wall 8 3)
+ (door 9 3)
+ (doorloc 9 3)
+ (wall 2 4)
+ (wall 3 4)
+ (wall 4 4)
+ (wall 6 4)
+ (wall 7 4)
+ (wall 8 4)
+ (door 8 5)
+ (doorloc 8 5)
+ (wall 1 6)
+ (wall 2 6)
+ (wall 3 6)
+ (wall 4 6)
+ (wall 6 6)
+ (wall 7 6)
+ (wall 8 6)
+ (wall 9 6)
+ (wall 1 7)
+ (door 4 7)
+ (doorloc 4 7)
+ (door 6 7)
+ (doorloc 6 7)
+ (wall 9 7)
+ (wall 1 8)
+ (wall 3 8)
+ (wall 4 8)
+ (wall 6 8)
+ (wall 7 8)
+ (door 8 8)
+ (doorloc 8 8)
+ (wall 9 8)
+ (wall 1 9)
+ (at gem1 2 9)
+ (itemloc 2 9)
+ (wall 3 9)
+ (wall 4 9)
+ (at key3 5 9)
+ (itemloc 5 9)
+ (wall 6 9)
+ (wall 7 9)
+ (at gem2 8 9)
+ (itemloc 8 9)
+ (wall 9 9))
+ (:goal (has gem3))
+)
diff --git a/src/beanmachine/ppl/experimental/goal_inference/environment.py b/src/beanmachine/ppl/experimental/goal_inference/environment.py
new file mode 100644
index 0000000000..8d37406999
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/environment.py
@@ -0,0 +1,68 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from __future__ import annotations
+
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+
+from typing import Any, Callable, Dict, List, Tuple
+
+
+class Action:
+ """An Action has a precondition that must be true before being executed on a state.
+
+ Public Atrributes:
+
+ name: The name of the action
+ precondition: Evaluates whether a state meets criteria for effect to execute
+ effect: Defines change in state when the action is performed
+
+ """
+
+ def __init__(self, name: str, precondition: Callable, effect: Callable):
+ self.name: str = name
+ self.precondition: Callable = precondition
+ self.effect: Callable = effect
+
+ def check_precondition(self, state: State, *args) -> bool:
+ """Checks if the precondition evaluates to true"""
+ return self.precondition(state, *args)
+
+ def execute(self, state: State, *args) -> State:
+ """execute: Changes the state according to the effect if the precondition is met"""
+ if self.check_precondition(state, *args):
+ return self.effect(state, *args)
+ else:
+ return state
+
+
+@dataclass(frozen=True, eq=True)
+class State(ABC):
+ goal: Tuple[str, ...]
+
+
+class Domain(ABC):
+
+ __slots__ = "actions", "predicates"
+
+ def __init__(self):
+ self.actions: Dict[str, Action]
+ self.predicates: Dict[str, Callable]
+
+ def execute(self, state: State, action_name: str, *args):
+ return self.actions[action_name].execute(state, *args)
+
+ @abstractmethod
+ def get_possible_actions(self, state) -> List[List[Any]]:
+ """Gets All Possible Next Actions"""
+ pass
+
+ @abstractmethod
+ def is_action_possible(self, state, action_name, *args) -> bool:
+ """Determines if an action is possible"""
+ pass
+
+ @abstractmethod
+ def evaluate_goal(self, state) -> bool:
+ """Evaluates if the current goal has been achieved"""
+ pass
diff --git a/src/beanmachine/ppl/experimental/goal_inference/inference/kernels.py b/src/beanmachine/ppl/experimental/goal_inference/inference/kernels.py
new file mode 100644
index 0000000000..af327eb5ec
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/inference/kernels.py
@@ -0,0 +1,332 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import copy
+
+from abc import ABC, abstractmethod
+from random import randint
+from typing import Callable, List, Tuple
+
+import torch
+from beanmachine.facebook.goal_inference.agent.boundedly_rational_agent import (
+ BoundedRationalAgent,
+)
+from beanmachine.facebook.goal_inference.agent.observation_model import ObservationModel
+
+from beanmachine.facebook.goal_inference.environment import State
+from beanmachine.facebook.goal_inference.planner.planner import get_execution_path
+
+from beanmachine.facebook.goal_inference.planner.stoch_astar import null_heuristic
+
+from torch.distributions.categorical import Categorical
+
+
+class DeviateTimeRejuvenateProposal:
+ """Defines a probability distribution for proposing t*
+ where t* is the time step where a proposed path deviates from the
+ previous case.
+
+ The (unnormalized) proability distribution is uniform (1.0) expect for the
+ value where the P(Observation[i]|State[i]) decreases the most which has a
+ value of max_prob
+
+ The intuition is that the point with the greatest drop in P(Observation[i]|State[i])
+ should be close to the point where this particle-agent deviates from the trajectory
+ we are inferring
+
+ Attributes/Arguments:
+
+ max_prob: Weight of point with greatest decrease in P(Observation[i]|State[i])
+ """
+
+ def __init__(self, max_prob: float = 10.0):
+ self.max_prob: float = max_prob
+
+ def propose(
+ self,
+ agent: BoundedRationalAgent,
+ observations: List[State],
+ noise_model: ObservationModel,
+ ) -> Tuple[int, torch.Tensor]:
+ """Proposes a new time*, which will be used as the break point for the new agent-trajectory
+
+ Arguments:
+ agent: BoundedRationalAgent from whom a new path can be proposed
+ observations: List of observations being inferred
+ noise_model: Model for P(observation|state)
+
+ Returns:
+ time_deviate: Time step t* from which to propose new path
+ log_prob: Log probability of proposed t*
+
+ """
+ proposal_distribution = self._get_prob(agent, observations, noise_model)
+ time_deviate = Categorical(probs=proposal_distribution).sample().long()
+ return time_deviate.item(), torch.log(proposal_distribution[time_deviate])
+
+ def get_log_prob(
+ self,
+ agent: BoundedRationalAgent,
+ observations: List[State],
+ noise_model: ObservationModel,
+ time_deviate: int,
+ ) -> torch.Tensor:
+ """Returns the log probability of a t* from the proposal distribution
+
+ Arguments:
+ agent: BoundedRationalAgent from whom a new path can be proposed
+ observations: List of observations being inferred
+ noise_model: Model for P(observation|state)
+ time_deviate: Time step t* from which to propose new path
+
+ Returns:
+ log_prob: Log probability of proposed t*
+
+ """
+ return torch.log(self._get_prob(agent, observations, noise_model)[time_deviate])
+
+ def _get_prob(
+ self,
+ agent: BoundedRationalAgent,
+ observations: List[State],
+ noise_model: ObservationModel,
+ ) -> torch.Tensor:
+ """Get Normalized Proposal Distribution P(t*|observations,states)
+
+ Arguments:
+ agent: BoundedRationalAgent from whom a new path can be proposed
+ observations: List of observations being inferred
+ noise_model: Model for P(observation|state)
+
+ Returns:
+
+ distribution: Normalized P(t*|observations,states)
+
+ """
+ agent_path = get_execution_path(agent.curr_node)[0]
+ probs = torch.zeros(len(agent_path))
+ # Compute P(observation|state) at each time step
+ for time_step in range(len(agent_path)):
+ probs[time_step] = torch.exp(
+ noise_model.get_log_prob(agent_path[time_step], observations[time_step])
+ )
+ probs = torch.nan_to_num(probs, nan=0.0, neginf=0.0)
+ prob_differences = probs[1:] - probs[0:-1]
+ distribution = torch.ones(len(agent_path) - 1)
+ # Sets probability of maximum probability decrease
+ distribution[torch.argmin(prob_differences)] = self.max_prob
+ distribution = distribution / torch.sum(distribution)
+ return distribution
+
+
+class PathRejuvenateProposal:
+ """Defines a probability distribution for proposing new plans and states that
+ deviate from an original trajectory
+
+ During planning, Nodes are biased by an additional weight associated with the
+ probability of that path given the observations.
+
+ """
+
+ def propose(
+ self,
+ agent: BoundedRationalAgent,
+ observations: List[State],
+ proposal_time_deviate: int,
+ noise_model: ObservationModel,
+ ) -> Tuple[BoundedRationalAgent, torch.Tensor]:
+ """Proposes an agent with a new trajectory and the log probability of that agent
+
+ Arguments:
+ agent: BoundedRationalAgent from whom a new path can be proposed
+ observations: List of observations being inferred
+ proposal_time_deviate: Time step t* from which to propose new path
+ noise_model: Model for P(observation|state)
+
+ Returns:
+
+ proposed_agent: An Agent with a modified path
+ proposed_prob: The log probability of that proposed path
+
+ """
+ proposed_agent = copy.copy(agent)
+ proposed_agent.propose_path(observations, proposal_time_deviate, noise_model)
+ return proposed_agent, self.get_log_prob(
+ proposed_agent, observations, proposal_time_deviate, noise_model
+ )
+
+ def get_log_prob(
+ self,
+ agent: BoundedRationalAgent,
+ observations: List[State],
+ proposal_time_deviate: int,
+ noise_model: ObservationModel,
+ ) -> torch.Tensor:
+ """Evaluates the log probability of the new agent trajectory
+
+ Arguments:
+ agent: BoundedRationalAgent from whom a new path can be proposed
+ observations: List of observations being inferred
+ proposal_time_deviate: Time step t* from which to propose new path
+ noise_model: Model for P(observation|state)
+
+ Returns:
+ log_prob: The log probability of that proposed path
+
+ """
+ return agent.get_log_prob(observations, proposal_time_deviate, noise_model)
+
+
+class HeuristicGoalProposal:
+ """Defines a goal proposal distribution using a given heuristic
+ the proposal probability of each goal is
+ proportional to ~exp(-heuristic/scale)
+
+ Attributes/Arguments:
+
+ heuristic: The heuristic on which the distribution is based
+ scale: Determines the sharpness of the proposal distribution
+ """
+
+ def __init__(self, heuristic: Callable = null_heuristic, scale: float = 10.0):
+ self.heuristic = heuristic
+ self.scale = scale
+
+ def propose(
+ self,
+ agent: BoundedRationalAgent,
+ possible_goals: List[Tuple[str, ...]],
+ ) -> Tuple[Tuple[str, ...], torch.Tensor]:
+ """Proposes an new goal for an agent
+
+ Arguments:
+ agent: Agent whose goal can be modified
+ possible_goals: Goals the agent can have
+
+ Returns:
+ possible_goal: New goal for the agent
+ log_prob: Log Probability of the proposed goal
+
+ """
+ proposal_distribution = self._get_goal_log_probs(agent, possible_goals)
+ goal_index = Categorical(logits=proposal_distribution).sample().long().item()
+ return possible_goals[goal_index], proposal_distribution[goal_index]
+
+ def get_log_prob(
+ self,
+ agent: BoundedRationalAgent,
+ possible_goals: List[Tuple[str, ...]],
+ goal: Tuple[str, ...],
+ ) -> torch.Tensor:
+ """Evaluates the log probability of a goal
+
+ Arguments:
+ agent: Agent whose goal can be modified
+ possible_goals: Goals the agent can have
+ goal: Target goal to evaluate probability of
+
+ Returns:
+ log_prob: Log Probability of the target goal
+
+ """
+ proposal_distribution = self._get_goal_log_probs(agent, possible_goals)
+ target_goal_id = possible_goals.index(goal)
+ return proposal_distribution[target_goal_id]
+
+ def _get_goal_log_probs(
+ self,
+ agent: BoundedRationalAgent,
+ possible_goals: List[Tuple[str, ...]],
+ ) -> torch.Tensor:
+ """Computes Log Proposal Distribution P(goal|state)
+
+ Arguments:
+ agent: Agent whose goal can be modified
+ possible_goals: Goals the agent can have
+
+ Returns:
+ log_probs: Normalized Log P(goal|state)
+
+ """
+ curr_node = agent.curr_node
+ heuristic_values = []
+ for goal in possible_goals:
+ heuristic_values.append(self.heuristic(curr_node, goal))
+ heuristic_values = torch.tensor(heuristic_values)
+ log_probs = -heuristic_values / self.scale
+ log_probs -= torch.logsumexp(log_probs, dim=0)
+ return log_probs
+
+
+class GoalPrior(ABC):
+ """Defines a distribution for sampling the prior distribution of goals of particle-agents"""
+
+ @abstractmethod
+ def sample_prior(self, possible_goals: List[Tuple[str, ...]]) -> Tuple[str, ...]:
+ """Samples from the possible goals according to the prior
+
+ Arguments:
+ possible_goals: The possible goals to sample from
+
+ Returns:
+ sample_goal: The goal that was sampled
+
+ """
+ pass
+
+
+class UniformGoalPrior(GoalPrior):
+
+ """Defines a Uniform distribution for sampling the prior distribution of goals
+ of particle-agents"""
+
+ def sample_prior(self, possible_goals: List[Tuple[str, ...]]) -> Tuple[str, ...]:
+ """Uniformly samples from possible goals
+
+ Arguments:
+ possible_goals: Goals that can be sampled
+
+ Returns:
+ goal: A possible goal drawn from a uniform distribution
+
+ """
+ number_of_goals = len(possible_goals)
+ return possible_goals[randint(0, number_of_goals - 1)]
+
+
+class StratifiedGoalPrior(GoalPrior):
+ """Defines a (Stratified) Uniform distribution for sampling the prior distribution
+ of goals of particle-agents
+
+ Example - 300 particles with 3 goals -> exactly 100 particles / goal
+
+ Arguments:
+ number_of_samples: Total number of samples to draw from prior
+
+ Attributes:
+ number_of_samples: Total number of samples to draw from prior
+ current_sample: Identifier for the nth sample out of number_of_samples
+
+ """
+
+ def __init__(self, number_of_samples: int):
+ self.number_of_samples: int = number_of_samples
+ self.current_sample: int = 0
+
+ def sample_prior(self, possible_goals: List[Tuple[str, ...]]) -> Tuple[str, ...]:
+ """Samples from Stratified Prior
+
+ Arguments:
+ possible_goals: Goals that can be sampled
+
+ Returns:
+ goal: A possible goal drawn from a stratified distribution
+
+ """
+ if self.current_sample < self.number_of_samples:
+ current_goal = int(
+ self.current_sample * len(possible_goals) / self.number_of_samples
+ )
+ self.current_sample += 1
+ return possible_goals[current_goal]
+ else:
+ raise (RuntimeError("Too many samples drawn from stratified prior"))
diff --git a/src/beanmachine/ppl/experimental/goal_inference/inference/kernels_test.py b/src/beanmachine/ppl/experimental/goal_inference/inference/kernels_test.py
new file mode 100644
index 0000000000..9593da2237
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/inference/kernels_test.py
@@ -0,0 +1,205 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import math
+
+import pytest
+
+import torch
+
+from beanmachine.facebook.goal_inference.agent.boundedly_rational_agent import (
+ BoundedRationalAgent,
+)
+
+from beanmachine.facebook.goal_inference.agent.observation_model import (
+ DeterministicObservation,
+)
+
+from beanmachine.facebook.goal_inference.doors_keys_gems.dkg_observation_model import (
+ DKGObservation,
+)
+from beanmachine.facebook.goal_inference.inference.kernels import (
+ DeviateTimeRejuvenateProposal,
+ HeuristicGoalProposal,
+ PathRejuvenateProposal,
+ StratifiedGoalPrior,
+ UniformGoalPrior,
+)
+
+from beanmachine.facebook.goal_inference.planner.planner import (
+ get_execution_path,
+ get_plan_from_actions,
+)
+from beanmachine.facebook.goal_inference.utils import manhattan_gem_heuristic
+
+
+@pytest.fixture(scope="function")
+def dkg_agent(dkg_state_three, dkg_astar_planner):
+ agent = BoundedRationalAgent(dkg_astar_planner, dkg_state_three)
+ agent_actions = [
+ ["right"],
+ ["right"],
+ ["right"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["left"],
+ ["down"],
+ ["down"],
+ ["right"],
+ ["down"],
+ ]
+ plan = get_plan_from_actions(
+ dkg_astar_planner.domain, dkg_state_three, agent_actions
+ )
+ agent.plan_history.append(plan)
+ agent.plan_index += 1
+ agent.execute_plan()
+ return agent
+
+
+def test_time_proposal_distribution_noise(dkg_observation_set, dkg_agent):
+ proposal = DeviateTimeRejuvenateProposal()
+ noise_model = DKGObservation()
+ prob_dist = proposal._get_prob(dkg_agent, dkg_observation_set, noise_model)
+ assert prob_dist.shape[0] == 12
+ assert torch.isclose(torch.argmax(prob_dist), torch.tensor(5))
+ assert torch.isclose(prob_dist[5], torch.tensor(10.0 / 21.0))
+ assert torch.isclose(prob_dist[0], torch.tensor(1.0 / 21.0))
+ assert torch.isclose(prob_dist[-1], torch.tensor(1.0 / 21.0))
+
+
+def test_time_proposal_distribution_no_noise(dkg_observation_set, dkg_agent):
+ proposal = DeviateTimeRejuvenateProposal()
+ noise_model = DeterministicObservation()
+ prob_dist = proposal._get_prob(dkg_agent, dkg_observation_set, noise_model)
+ assert prob_dist.shape[0] == 12
+ assert torch.isclose(torch.argmax(prob_dist), torch.tensor(5))
+ assert torch.isclose(prob_dist[5], torch.tensor(10.0 / 21.0))
+ assert torch.isclose(prob_dist[0], torch.tensor(1.0 / 21.0))
+ assert torch.isclose(prob_dist[-1], torch.tensor(1.0 / 21.0))
+
+
+def test_time_proposal_log_prob_noise(dkg_observation_set, dkg_agent):
+ proposal = DeviateTimeRejuvenateProposal()
+ noise_model = DKGObservation()
+ prob_max = proposal.get_log_prob(dkg_agent, dkg_observation_set, noise_model, 5)
+ prob_min = proposal.get_log_prob(dkg_agent, dkg_observation_set, noise_model, 1)
+ assert torch.isclose(prob_max, torch.log(torch.tensor(10.0 / 21.0)))
+ assert torch.isclose(prob_min, torch.log(torch.tensor(1.0 / 21.0)))
+
+
+def test_time_proposal_log_prob_no_noise(dkg_observation_set, dkg_agent):
+ proposal = DeviateTimeRejuvenateProposal()
+ noise_model = DeterministicObservation()
+ prob_max = proposal.get_log_prob(dkg_agent, dkg_observation_set, noise_model, 5)
+ prob_min = proposal.get_log_prob(dkg_agent, dkg_observation_set, noise_model, 1)
+ assert torch.isclose(prob_max, torch.log(torch.tensor(10.0 / 21.0)))
+ assert torch.isclose(prob_min, torch.log(torch.tensor(1.0 / 21.0)))
+
+
+def test_time_proposal_propose(dkg_observation_set, dkg_agent):
+ proposal = DeviateTimeRejuvenateProposal()
+ noise_model = DKGObservation()
+ proposed_time, log_prob_proposed_time = proposal.propose(
+ dkg_agent, dkg_observation_set, noise_model
+ )
+ assert proposed_time < len(dkg_observation_set)
+ assert torch.isclose(
+ log_prob_proposed_time,
+ torch.log(
+ proposal._get_prob(dkg_agent, dkg_observation_set, noise_model)[
+ proposed_time
+ ]
+ ),
+ )
+
+
+def test_path_propose(dkg_astar_planner, dkg_state_three, dkg_observation_set):
+ agent = BoundedRationalAgent(dkg_astar_planner, dkg_state_three, r=1, p=0.9999)
+ agent_actions = [
+ ["right"],
+ ["right"],
+ ["right"],
+ ["up"],
+ ["up"],
+ ]
+ plan = get_plan_from_actions(
+ dkg_astar_planner.domain, dkg_state_three, agent_actions
+ )
+ agent.plan_history.append(plan)
+ agent.plan_index += 1
+ agent.execute_plan()
+ agent_actions = [
+ ["up"],
+ ["up"],
+ ["left"],
+ ["down"],
+ ["down"],
+ ["right"],
+ ["down"],
+ ]
+ plan = get_plan_from_actions(
+ dkg_astar_planner.domain, agent.curr_node.state, agent_actions
+ )
+ agent.action_step = 0
+ agent.plan_history.append(plan)
+ agent.plan_index += 1
+ agent.execute_plan()
+
+ proposal = PathRejuvenateProposal()
+ noise_model = DeterministicObservation()
+ new_agent, prob = proposal.propose(agent, dkg_observation_set[:13], 5, noise_model)
+ new_path = get_execution_path(new_agent.curr_node)[0]
+ assert new_path == dkg_observation_set[:13]
+ assert prob < 0.0
+
+
+def test_uniform_prior_goal_prob():
+ prior = UniformGoalPrior()
+ goal_record = {("goal1"): 0, ("goal2"): 0, ("goal3"): 0}
+ for _ in range(100):
+ new_goal = prior.sample_prior(list(goal_record.keys()))
+ goal_record[new_goal] += 1
+ assert math.isclose(goal_record[("goal1")], 33, abs_tol=10)
+ assert math.isclose(goal_record[("goal1")], 33, abs_tol=10)
+ assert math.isclose(goal_record[("goal1")], 33, abs_tol=10)
+
+
+def test_heuristic_goal_proposal(dkg_agent):
+ goals = [("has", "gem1"), ("has", "gem2"), ("has", "gem3")]
+ proposal = HeuristicGoalProposal(heuristic=dkg_agent.planner.heuristic)
+ prop_dist = proposal._get_goal_log_probs(dkg_agent, goals)
+
+ dist_goal_1 = float(manhattan_gem_heuristic(dkg_agent.curr_node, ("has", "gem1")))
+ dist_goal_2 = float(manhattan_gem_heuristic(dkg_agent.curr_node, ("has", "gem2")))
+ dist_goal_3 = float(manhattan_gem_heuristic(dkg_agent.curr_node, ("has", "gem3")))
+
+ log_probs = torch.tensor([dist_goal_1, dist_goal_2, dist_goal_3])
+ log_probs = -log_probs / 10.0
+ log_probs -= torch.logsumexp(log_probs, dim=0)
+
+ assert torch.isclose(log_probs[0], prop_dist[0], atol=0.1)
+ assert torch.isclose(log_probs[1], prop_dist[1], atol=0.1)
+ assert torch.isclose(log_probs[2], prop_dist[2], atol=0.1)
+
+ assert torch.isclose(
+ prop_dist[0], proposal.get_log_prob(dkg_agent, goals, ("has", "gem1")), atol=0.1
+ )
+ assert torch.isclose(
+ prop_dist[1], proposal.get_log_prob(dkg_agent, goals, ("has", "gem2")), atol=0.1
+ )
+ assert torch.isclose(
+ prop_dist[2], proposal.get_log_prob(dkg_agent, goals, ("has", "gem3")), atol=0.1
+ )
+
+
+def test_stratified_prior_goal_prob():
+ prior = StratifiedGoalPrior(100)
+ goal_record = {("goal1"): 0, ("goal2"): 0, ("goal3"): 0}
+ for _ in range(100):
+ new_goal = prior.sample_prior(list(goal_record.keys()))
+ goal_record[new_goal] += 1
+ assert math.isclose(goal_record[("goal1")], 33, abs_tol=2)
+ assert math.isclose(goal_record[("goal1")], 33, abs_tol=2)
+ assert math.isclose(goal_record[("goal1")], 33, abs_tol=2)
diff --git a/src/beanmachine/ppl/experimental/goal_inference/inference/sequential_inverse_plan_search.py b/src/beanmachine/ppl/experimental/goal_inference/inference/sequential_inverse_plan_search.py
new file mode 100644
index 0000000000..68c1ab06ac
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/inference/sequential_inverse_plan_search.py
@@ -0,0 +1,528 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import copy
+import dataclasses
+
+from typing import Any, Dict, List, Tuple
+
+import torch
+
+from beanmachine.facebook.goal_inference.agent.boundedly_rational_agent import (
+ BoundedRationalAgent,
+)
+
+from beanmachine.facebook.goal_inference.agent.observation_model import (
+ DeterministicObservation,
+ ObservationModel,
+)
+
+from beanmachine.facebook.goal_inference.environment import State
+
+from beanmachine.facebook.goal_inference.inference.kernels import (
+ DeviateTimeRejuvenateProposal,
+ HeuristicGoalProposal,
+ PathRejuvenateProposal,
+ StratifiedGoalPrior,
+)
+
+from beanmachine.facebook.goal_inference.planner.planner import (
+ get_execution_path,
+ Planner,
+)
+from beanmachine.facebook.goal_inference.planner.stoch_astar import (
+ null_heuristic,
+ StochasticAstarPlanner,
+)
+from torch.distributions.categorical import Categorical
+
+
+EPS = 10e-20
+
+DEFAULT_NOISE_MODEL = DeterministicObservation()
+
+
+class SIPS:
+
+ """
+ Peforms Sequential Inverse Planning Search algorithm for goal inference
+ Full details can be found here: https://papers.nips.cc/paper/2020/file/df3aebc649f9e3b674eeb790a4da224e-Paper.pdf
+
+ Summary of Algorithm:
+
+ SIPS is a particle filtering scheme used to estimate the goal posterior P(g|obs) from observations
+ where observations are obtained from an agent that does not necessarily make optimal choices.
+
+ "Particles" are each associated with an agent trajectory generated assuming a particular goal.
+ The particle-trajectory set is initialized with a uniform prior over possible goals.
+ At each time step, each particle-trajectory is advanced one time step using a model agent.
+ Each particle-trajectory receives a weight given the similarity to the target observations.
+ Intuition: particle-trajectories with similar paths to the target observations are more likely
+ to correspond to the target goal and thus receive higher weight.
+
+ The posterior P(g|obs) at each time step can be obtained by summing the normalized weights associated
+ with goal g.
+
+ In order to ensure a good particle-trajectory distribution, if the effective sample size of the
+ distribution decreases below a threshold, particles are resampled using multinomial sampling.
+
+ In addition, the goals/trajectories of the particle-trajectories can be changed through goal/path rejuventation.
+ This process involves a Metroplis Hastings steps with a proposal defined by the user
+
+ Arguments:
+
+ planner: The short-term strategy for particle-trajectories
+ noise_model: Defines a probability distribution for observing states
+ agent_args: Arguments for the boundedly-rational agents used for particle-trajectories
+
+ Attributes:
+
+ planner: The short-term strategy for particle-trajectories
+ agent_args: Arguments for the boundedly-rational agents used for particle-trajectories
+ noise_model: Defines a probability distribution for observing states
+ path_proposal: Proposal that defines distribution for rejuvenating paths
+ time_proposal: Proposal that defines distribution for t*, time step where to start path rejuvenation
+ goal_prior: function that initialzes the goals of the particle-agents based on a prior
+ goal_proposal: Proposal for proposing changes to the goal state
+
+ """
+
+ def __init__(
+ self,
+ planner: Planner,
+ noise_model: ObservationModel = DEFAULT_NOISE_MODEL,
+ **kwargs: Dict[str, Any],
+ ):
+ self.planner: Planner = planner
+ self.agent_args: Dict[str, Any] = kwargs
+ # Fall back on deterministic observations if no noise model is provided
+ self.noise_model: ObservationModel = noise_model
+ self.path_proposal: PathRejuvenateProposal = PathRejuvenateProposal()
+ self.time_proposal: DeviateTimeRejuvenateProposal = (
+ DeviateTimeRejuvenateProposal()
+ )
+ if isinstance(self.planner, StochasticAstarPlanner):
+ self.goal_proposal: HeuristicGoalProposal = HeuristicGoalProposal(
+ heuristic=self.planner.heuristic
+ )
+ else:
+ self.goal_proposal: HeuristicGoalProposal = HeuristicGoalProposal(
+ heuristic=null_heuristic
+ )
+
+ def _initialize_filter(
+ self,
+ num_particles: int,
+ initial_state: State,
+ possible_goals: List[Tuple[str, ...]],
+ ) -> Tuple[torch.Tensor, List[BoundedRationalAgent]]:
+ """Initializes the particle-agent distribution
+
+ Arguments:
+ num_particles: The total number of agents to initialize
+ initial_state: The initial state of the problem
+ possible_goals: The possible goals of the initial agents
+
+ Returns:
+ initialized_weights: Uniform weights for the agents
+ agents: The initialized set of BoundedRational agents
+
+ """
+ agents = []
+ goal_prior = StratifiedGoalPrior(num_particles)
+ for _part_idx in range(num_particles):
+ # Draw from P(g)
+ sampled_goal = goal_prior.sample_prior(possible_goals)
+ new_state = dataclasses.replace(initial_state, goal=sampled_goal)
+ agents.append(
+ BoundedRationalAgent(self.planner, new_state, **self.agent_args)
+ )
+ return torch.zeros(len(agents)), agents
+
+ def infer(
+ self,
+ num_particles: int,
+ initial_state: State,
+ possible_goals: List[Tuple[str, ...]],
+ observations: List[State],
+ resample_threshold: float = 0.25,
+ rejuvenate: bool = True,
+ goal_rejuvenation_prob: float = 0.5,
+ ) -> List[Dict[str, float]]:
+ """Computes the normalized posterior P(g|obs) over time
+
+ Arguments:
+ num_particles: The number of particle-agents used in the filter
+ initial_state: The initial state of the problem
+ possible_goals: The possible goals that could be infered
+ observations: The trajectory from which the goal will be inferred
+ resample_threshold: Value for comparison with Effective_Sample_Size/num_particles.
+ If Effective_Sample_Size/num_particles falls below this value,
+ the particle distribution is resampled.
+ rejuvenate: Whether to perform goal/path rejuvenation
+ goal_rejuvenation_prob: Probability that goals are rejuvenated after resampling
+
+ Returns:
+ infered_goal: List of records of posterior. infered_goal[i] is the posterior at time_step i
+ """
+ # Initialize particle-trajectories. Goals are drawn from P(g)
+ log_weights, agents = self._initialize_filter(
+ num_particles, initial_state, possible_goals
+ )
+ infered_goal = []
+ infered_goal.append(get_posterior(log_weights, agents, possible_goals))
+ # Use observations to update particle-trajectory weights based on likelihood of observations
+ for obs_step in range(1, len(observations)):
+ agents, log_weights = self._update_filter(
+ agents,
+ log_weights,
+ obs_step,
+ observations[: obs_step + 1],
+ initial_state,
+ possible_goals,
+ resample_threshold,
+ rejuvenate,
+ goal_rejuvenation_prob,
+ )
+ # Adjust weights for numerical stability
+
+ log_weights -= torch.logsumexp(log_weights, dim=0)
+ # Get posterior up until this time step
+ infered_goal.append(get_posterior(log_weights, agents, possible_goals))
+
+ return infered_goal
+
+ def _update_filter(
+ self,
+ agents: List[BoundedRationalAgent],
+ log_weights: torch.Tensor,
+ obs_step: int,
+ observations: List[State],
+ initial_state: State,
+ possible_goals: List[Tuple[str, ...]],
+ resample_threshold: float,
+ rejuvenate: bool,
+ goal_rejuvenation_prob: float,
+ ) -> Tuple[List[BoundedRationalAgent], torch.Tensor]:
+ """Updates particle-agents with new observation
+
+ Arguments:
+ agents: Current set of BoundedRational Agents
+ log_weights: Current agent weights
+ obs_step: Current time_step of inference
+ observations: Trajectory from which the goal will be inferred
+ initial_state: Initial state of the problem
+ possible_goals: The possible goals that can be infered
+ resample_threshold: Value for comparison with Effective_Sample_Size/num_particles.
+ If Effective_Sample_Size/num_particles falls below this value,
+ the particle distribution is resampled.
+ rejuvenate: Whether to perform goal/path rejuvenation
+ goal_rejuvenation_prob: Probability that goals are rejuvenated after resampling
+
+ Returns:
+ agents: Updated BoundedRational Agents
+ log_weights: Updated agent weights
+
+ """
+ # Test the effective sample size - resample if too low
+ if (
+ self._effective_sample_size(log_weights) / log_weights.shape[0]
+ < resample_threshold
+ ):
+ log_weights, agent_idx = self._residual_resample(log_weights)
+
+ for i in range(len(agents)):
+ new_agent = copy.copy(agents[agent_idx[i]])
+ if rejuvenate:
+ agents[i] = self._rejuvenate(
+ new_agent,
+ initial_state,
+ possible_goals,
+ observations,
+ goal_rejuvenation_prob,
+ )
+ else:
+ agents[i] = new_agent
+
+ for part_idx in range(len(log_weights)):
+ # Update particle-trajectory using model agent
+ agents[part_idx].step()
+ # Update weight of this particle-trajectory P({observations}|{states}) with P(observation_i|state_i)
+ log_weights[part_idx] += self.noise_model.get_log_prob(
+ agents[part_idx].curr_node.state, observations[obs_step]
+ )
+ return agents, log_weights
+
+ def _effective_sample_size(self, log_weights: torch.Tensor) -> torch.Tensor:
+ """Computes the effective sample size of the current particles
+
+ Arguments:
+ log_weights: Current weights of the agents
+
+ Returns:
+ eff_sample_size: Effective sample size of the current distribution of agents
+
+ """
+ part_weights = get_real_weights(log_weights)
+ sum_weights_sqrd = torch.square(torch.sum(part_weights))
+ sum_sqrd_weights = torch.sum(torch.square(part_weights))
+ eff_sample_size = sum_weights_sqrd / sum_sqrd_weights
+ return eff_sample_size
+
+ def _multinomial_resample(
+ self, log_weights: torch.Tensor
+ ) -> Tuple[torch.Tensor, torch.Tensor]:
+ """Resamples the particle distribution with multinomial resampling.
+
+ New Agents are drawn from previous distribution in proportion to the weights
+
+ Arguments:
+ log_weights: Current weights of the agents
+
+ Returns:
+ uniform_weights: New Uniform weights
+ sampled_indexes: Indexes of sampled agents
+ """
+ return (
+ torch.zeros(log_weights.shape),
+ Categorical(logits=log_weights).sample_n(log_weights.shape[0]).long(),
+ )
+
+ def _residual_resample(
+ self, log_weights: torch.Tensor
+ ) -> Tuple[torch.Tensor, torch.Tensor]:
+ """Resamples the particle distribution with residual resampling.
+
+ Let the number of agents be N
+
+ Previous Agents are sampled at least int(weight*N) times
+
+ Remaining Agents are drawn in proportion to residual weights
+ residual weight = [weight*N - int(weight*N)]
+
+ Arguments:
+ log_weights: Current weights of the agents
+
+ Returns:
+ uniform_weights: New Uniform weights
+ sampled_indexes: Indexes of sampled agents
+ """
+ part_weights = get_real_weights(log_weights)
+ N = part_weights.shape[0]
+ num_copies = (N * part_weights).int()
+ # Ensure each particle-agent is sampled at least int(N*part_weight) times
+ agent_idx = torch.repeat_interleave(torch.arange(N), num_copies)
+ k = torch.sum(num_copies)
+ # Sample remaining agents based on decimal part of N*part_weight
+ residual = N * part_weights - num_copies
+ if torch.sum(residual) != 0.0 and N - k > 0:
+ residual /= torch.sum(residual)
+ agent_idx = torch.cat(
+ (agent_idx, Categorical(probs=residual).sample_n(N - k)), dim=0
+ )
+ return torch.zeros(part_weights.shape), agent_idx.long()
+
+ def _rejuvenate(
+ self,
+ agent: BoundedRationalAgent,
+ initial_state: State,
+ possible_goals: List[Tuple[str, ...]],
+ observations: List[State],
+ goal_rejuvenation_prob: float,
+ ) -> BoundedRationalAgent:
+ """Rejuvenates Agents by changing paths / goals
+
+ Arguments:
+ agent: The agent to modify
+ initial_state: The initial state of the problem
+ possible_goals: The possible goals to infer
+ observations: Trajectory from which the goal will be inferred
+ goal_rejuvenation_prob: Probability that goals are rejuvenated after resampling
+
+ Returns:
+ agent: The modified agent is return if the MC move is accepted. Otherwise the initial agent is returned.
+
+ """
+ # Determine whether to rejuventate goals or paths
+ if torch.bernoulli(torch.tensor(goal_rejuvenation_prob)):
+ alpha, proposed_agent = self._goal_rejuvenation(
+ agent, initial_state, possible_goals
+ )
+ else:
+ alpha, proposed_agent = self._path_rejuvenation(
+ agent, initial_state, observations
+ )
+ # Evaluate Likelihood of path given observations P(states|Observations)
+ old_path_log_prob = self._get_path_log_prob(agent, observations)
+ proposed_path_log_prob = self._get_path_log_prob(proposed_agent, observations)
+ # Accept/Reject Step
+ alpha += proposed_path_log_prob - old_path_log_prob
+ if torch.log(torch.rand(1)) < alpha:
+ return proposed_agent
+ else:
+ return agent
+
+ def _goal_rejuvenation(
+ self,
+ agent: BoundedRationalAgent,
+ initial_state: State,
+ possible_goals: List[Tuple[str, ...]],
+ ) -> Tuple[torch.Tensor, BoundedRationalAgent]:
+ """Rejuventates the goal of a particle-agent
+
+ Proposes a new goal for a boundedrational agent
+ The strategy for the proposal is determined by self.goal_proposal
+
+ Currently, by default goals are
+
+ Arguments:
+ agent: The BoundedRational Agent to modify
+ initial_state: The initial state of the problem
+ possible_goals: The possible goals to infer
+
+ Returns:
+ log_proposal_prob: The proposal portion of the acceptance/rejection log probability
+ proposed_agent: The modified agent
+ """
+
+ # Get proposed goal and log probability of goal
+ proposed_goal, proposal_log_prob_new_goal = self.goal_proposal.propose(
+ agent, possible_goals
+ )
+ # Get log probability of old goal
+ proposal_log_prob_old_goal = self.goal_proposal.get_log_prob(
+ agent, possible_goals, agent.curr_node.state.goal
+ )
+ # Propose new agent with sampled goal
+ proposed_agent = BoundedRationalAgent(
+ self.planner,
+ dataclasses.replace(initial_state, goal=proposed_goal),
+ **self.agent_args,
+ )
+ # Advance timestep of proposed agent to same time as previous agent
+ proposed_agent.step(num_steps=agent.agent_step)
+ return proposal_log_prob_old_goal - proposal_log_prob_new_goal, proposed_agent
+
+ def _path_rejuvenation(
+ self,
+ agent: BoundedRationalAgent,
+ initial_state: State,
+ observations: List[State],
+ ) -> Tuple[torch.Tensor, BoundedRationalAgent]:
+ """Rejuventates the path of a paricle-agent
+
+ (1) Proposes a time t* from which a new path can be proposed
+ (2) Proposes a new path following time t*
+
+ Arguments:
+ agent: The BoundedRational Agent to modify
+ initial_state: The initial state of the problem
+ observations: Trajectory from which the goal will be inferred
+
+ Returns:
+ alpha: The proposal portion of the acceptance/rejection log probability
+ proposed_agent: The modified agent
+
+ """
+
+ # Get t* and P(t*|state,observations)
+ (
+ proposal_time_deviate,
+ proposal_log_prob_old_time_deviate,
+ ) = self.time_proposal.propose(agent, observations, self.noise_model)
+
+ # Get Proposed Agent and P(Agent|observations,t*)
+ proposed_agent, proposal_log_prob_new_path = self.path_proposal.propose(
+ agent, observations, proposal_time_deviate, self.noise_model
+ )
+
+ # Get P(Old_Agent|observations,t*)
+ proposal_log_prob_old_path = self.path_proposal.get_log_prob(
+ agent, observations, proposal_time_deviate, self.noise_model
+ )
+
+ # Get P(t*|new_states,observations)
+ proposal_log_prob_new_time_deviate = self.time_proposal.get_log_prob(
+ proposed_agent, observations, self.noise_model, proposal_time_deviate
+ )
+
+ alpha = proposal_log_prob_old_path - proposal_log_prob_new_path
+ alpha += proposal_log_prob_new_time_deviate - proposal_log_prob_old_time_deviate
+
+ return alpha, proposed_agent
+
+ def _get_path_log_prob(
+ self, agent: BoundedRationalAgent, observations: List[State]
+ ) -> torch.Tensor:
+ """Computes Log P(observations|states) for a trajectory
+
+ Arguments:
+ agent: The agent to compare with the observations
+ observations: Trajectory from which the goal will be inferred
+
+ Returns:
+ log_prob: Log P(observations|states)
+
+ """
+ log_prob = torch.tensor(0.0)
+ agent_path = get_execution_path(agent.curr_node)[0]
+ # Evaluates Log P(observations|states) = Log P(observation_1|State_1)+ Log P(observation_2|State_2)...
+ for time_step in range(len(observations)):
+ ### If the agent path has reached the goal just repeat the final state
+ if time_step == len(agent_path):
+ agent_path.append(agent_path[-1])
+ # Computes Log P(observation_i|State_i)
+ log_prob += self.noise_model.get_log_prob(
+ agent_path[time_step], observations[time_step]
+ )
+ return log_prob
+
+
+def get_real_weights(log_weights: torch.Tensor) -> torch.Tensor:
+ """Computes weights from log weights in a numerically stable way
+
+ Arguments:
+ log_weights: Weights to convert to non-log scale
+
+ Return:
+ part_weights: Weights in non-log scale
+
+ """
+ log_weights -= torch.logsumexp(log_weights, dim=0)
+ part_weights = torch.exp(log_weights)
+ part_weights = torch.nan_to_num(part_weights, nan=0.0, neginf=0.0)
+ return part_weights
+
+
+def get_posterior(
+ log_weights: torch.Tensor,
+ agents: List[BoundedRationalAgent],
+ possible_goals: List[Tuple[str, ...]],
+) -> Dict[Tuple[str, ...], float]:
+ """Computes the normalized posterior P(g|obs) at one time step
+
+ Arguments:
+ log_weights: Current weights of the agents
+ agents: The current set of BoundedRational agents
+ possible_goals: The possible goals to infer
+ Returns:
+ curr_infer: posterior at the current time_step
+ """
+ part_weights = get_real_weights(log_weights)
+ curr_infer = {}
+ for goal in possible_goals:
+ curr_infer[goal] = 0.0
+ norm = 0
+ # Sum all weights associated with each goal
+ for part_idx in range(len(agents)):
+ norm += part_weights[part_idx].item()
+ curr_infer[agents[part_idx].curr_node.state.goal] += part_weights[
+ part_idx
+ ].item()
+ if norm == 0:
+ return curr_infer
+
+ # Normalize the posterior
+ for goal_id in curr_infer:
+ curr_infer[goal_id] /= norm
+
+ return curr_infer
diff --git a/src/beanmachine/ppl/experimental/goal_inference/inference/sequential_inverse_plan_search_test.py b/src/beanmachine/ppl/experimental/goal_inference/inference/sequential_inverse_plan_search_test.py
new file mode 100644
index 0000000000..914b42330e
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/inference/sequential_inverse_plan_search_test.py
@@ -0,0 +1,454 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import dataclasses
+import math
+
+from typing import Dict, List
+
+import pytest
+
+import torch
+
+from beanmachine.facebook.goal_inference.agent.boundedly_rational_agent import (
+ BoundedRationalAgent,
+)
+
+from beanmachine.facebook.goal_inference.agent.observation_model import (
+ apply_noise_to_states,
+)
+from beanmachine.facebook.goal_inference.continuous_gems.cgem_domain import CGemDomain
+from beanmachine.facebook.goal_inference.continuous_gems.cgem_observation_model import (
+ CGemObservation,
+)
+
+from beanmachine.facebook.goal_inference.continuous_gems.cgem_parse import parse
+
+from beanmachine.facebook.goal_inference.doors_keys_gems.dkg_observation_model import (
+ DKGObservation,
+)
+
+from beanmachine.facebook.goal_inference.inference.sequential_inverse_plan_search import (
+ SIPS,
+)
+from beanmachine.facebook.goal_inference.planner.stoch_astar import (
+ StochasticAstarPlanner,
+)
+from beanmachine.facebook.goal_inference.utils import manhattan_gem_heuristic
+
+
+@pytest.fixture(scope="function")
+def dkg_SIPS_no_noise(dkg_stoch_astar_planner):
+ return SIPS(
+ dkg_stoch_astar_planner,
+ r=1000,
+ p=0.5,
+ )
+
+
+@pytest.fixture(scope="function")
+def dkg_SIPS_noise(dkg_stoch_astar_planner):
+ return SIPS(
+ dkg_stoch_astar_planner,
+ DKGObservation(),
+ r=1000,
+ p=0.5,
+ )
+
+
+def get_last_inference_prediction(infer_data: List[Dict[str, float]]):
+ """Returns the time step of posterior with nonzero weights"""
+ time_step = len(infer_data) - 1
+ while time_step > 0:
+ for goal_id in infer_data[time_step]:
+ if infer_data[time_step][goal_id] != 0:
+ return infer_data[time_step]
+ time_step -= 1
+ return infer_data[0]
+
+
+def test_dkg_problem_one_SIPS_no_noise(
+ dkg_astar_planner, dkg_state_one, dkg_SIPS_no_noise
+):
+ (
+ plan,
+ solved,
+ ) = dkg_astar_planner.generate_plan(dkg_state_one)
+ observations = plan.states
+ infered_goal = dkg_SIPS_no_noise.infer(
+ 100,
+ plan.states[0],
+ [("has", "gem1")],
+ observations,
+ resample_threshold=0.0,
+ goal_rejuvenation_prob=1.0,
+ )
+ assert math.isclose(infered_goal[0][("has", "gem1")], 1.0, abs_tol=0.2)
+ assert math.isclose(
+ get_last_inference_prediction(infered_goal)[("has", "gem1")], 1.0, abs_tol=0.2
+ )
+
+
+def test_dkg_problem_two_SIPS_no_noise(
+ dkg_astar_planner, dkg_state_two, dkg_SIPS_no_noise
+):
+ (
+ plan,
+ solved,
+ ) = dkg_astar_planner.generate_plan(dkg_state_two)
+ observations = plan.states
+ infered_goal = dkg_SIPS_no_noise.infer(
+ 100,
+ plan.states[0],
+ [("has", "gem1"), ("has", "gem2")],
+ observations,
+ resample_threshold=0.0,
+ goal_rejuvenation_prob=1.0,
+ )
+ assert math.isclose(infered_goal[0][("has", "gem1")], 0.5, abs_tol=0.2)
+ assert math.isclose(infered_goal[0][("has", "gem2")], 0.5, abs_tol=0.2)
+ assert math.isclose(
+ get_last_inference_prediction(infered_goal)[("has", "gem1")], 1.0, abs_tol=0.2
+ )
+
+
+def test_dkg_problem_three_SIPS_no_noise(
+ dkg_astar_planner, dkg_state_three, dkg_SIPS_no_noise
+):
+ (
+ plan,
+ solved,
+ ) = dkg_astar_planner.generate_plan(dkg_state_three)
+ observations = plan.states
+ infered_goal = dkg_SIPS_no_noise.infer(
+ 100,
+ plan.states[0],
+ [("has", "gem1"), ("has", "gem2"), ("has", "gem3")],
+ observations,
+ resample_threshold=0.0,
+ goal_rejuvenation_prob=1.0,
+ )
+ assert math.isclose(infered_goal[0][("has", "gem1")], 0.333, abs_tol=0.2)
+ assert math.isclose(infered_goal[0][("has", "gem2")], 0.333, abs_tol=0.2)
+ assert math.isclose(infered_goal[0][("has", "gem3")], 0.333, abs_tol=0.2)
+ assert math.isclose(
+ get_last_inference_prediction(infered_goal)[("has", "gem3")], 1.0, abs_tol=0.2
+ )
+
+
+def test_dkg_problem_four_SIPS_no_noise(
+ dkg_astar_planner, dkg_state_four, dkg_SIPS_no_noise
+):
+ (
+ plan,
+ solved,
+ ) = dkg_astar_planner.generate_plan(dkg_state_four)
+ observations = plan.states
+ infered_goal = dkg_SIPS_no_noise.infer(
+ 100,
+ plan.states[0],
+ [("has", "gem1"), ("has", "gem2"), ("has", "gem3")],
+ observations,
+ resample_threshold=0.0,
+ goal_rejuvenation_prob=1.0,
+ )
+ assert math.isclose(infered_goal[0][("has", "gem1")], 0.333, abs_tol=0.2)
+ assert math.isclose(infered_goal[0][("has", "gem2")], 0.333, abs_tol=0.2)
+ assert math.isclose(infered_goal[0][("has", "gem3")], 0.333, abs_tol=0.2)
+ assert math.isclose(
+ get_last_inference_prediction(infered_goal)[("has", "gem3")], 1.0, abs_tol=0.2
+ )
+
+
+def test_dkg_problem_one_SIPS_noise(dkg_astar_planner, dkg_state_one, dkg_SIPS_noise):
+ agent = BoundedRationalAgent(dkg_astar_planner, dkg_state_one, r=1000, p=0.5)
+ plan, solved = agent.execute_search()
+ observations = apply_noise_to_states(plan.states, DKGObservation())
+ infered_goal = dkg_SIPS_noise.infer(
+ 100,
+ plan.states[0],
+ [("has", "gem1")],
+ observations,
+ resample_threshold=0.0,
+ goal_rejuvenation_prob=1.0,
+ )
+ assert math.isclose(infered_goal[0][("has", "gem1")], 1.0, abs_tol=0.2)
+ assert math.isclose(
+ get_last_inference_prediction(infered_goal)[("has", "gem1")], 1.0, abs_tol=0.2
+ )
+
+
+def test_dkg_problem_two_SIPS_noise(dkg_astar_planner, dkg_state_two, dkg_SIPS_noise):
+ agent = BoundedRationalAgent(dkg_astar_planner, dkg_state_two, r=1000, p=0.5)
+ plan, solved = agent.execute_search()
+ observations = apply_noise_to_states(plan.states, DKGObservation())
+ infered_goal = dkg_SIPS_noise.infer(
+ 100,
+ plan.states[0],
+ [("has", "gem1"), ("has", "gem2")],
+ observations,
+ resample_threshold=0.0,
+ goal_rejuvenation_prob=1.0,
+ )
+ assert math.isclose(infered_goal[0][("has", "gem1")], 0.5, abs_tol=0.2)
+ assert math.isclose(infered_goal[0][("has", "gem2")], 0.5, abs_tol=0.2)
+ assert math.isclose(
+ get_last_inference_prediction(infered_goal)[("has", "gem1")], 1.0, abs_tol=0.2
+ )
+
+
+def test_dkg_problem_three_SIPS_noise(
+ dkg_astar_planner, dkg_state_three, dkg_SIPS_noise
+):
+ agent = BoundedRationalAgent(dkg_astar_planner, dkg_state_three, r=1000, p=0.5)
+ (
+ plan,
+ solved,
+ ) = agent.execute_search()
+ observations = apply_noise_to_states(plan.states, DKGObservation())
+ infered_goal = dkg_SIPS_noise.infer(
+ 100,
+ plan.states[0],
+ [("has", "gem1"), ("has", "gem2"), ("has", "gem3")],
+ observations,
+ resample_threshold=0.0,
+ goal_rejuvenation_prob=1.0,
+ )
+ assert math.isclose(infered_goal[0][("has", "gem1")], 0.333, abs_tol=0.2)
+ assert math.isclose(infered_goal[0][("has", "gem2")], 0.333, abs_tol=0.2)
+ assert math.isclose(infered_goal[0][("has", "gem3")], 0.333, abs_tol=0.2)
+ assert math.isclose(
+ get_last_inference_prediction(infered_goal)[("has", "gem3")], 1.0, abs_tol=0.2
+ )
+
+
+def test_dkg_problem_four_SIPS_noise(dkg_astar_planner, dkg_state_four, dkg_SIPS_noise):
+ agent = BoundedRationalAgent(dkg_astar_planner, dkg_state_four, r=1000, p=0.5)
+ plan, solved = agent.execute_search()
+ observations = apply_noise_to_states(plan.states, DKGObservation())
+ infered_goal = dkg_SIPS_noise.infer(
+ 100,
+ plan.states[0],
+ [("has", "gem1"), ("has", "gem2"), ("has", "gem3")],
+ observations,
+ resample_threshold=0.0,
+ goal_rejuvenation_prob=1.0,
+ )
+ assert math.isclose(infered_goal[0][("has", "gem1")], 0.333, abs_tol=0.2)
+ assert math.isclose(infered_goal[0][("has", "gem2")], 0.333, abs_tol=0.2)
+ assert math.isclose(infered_goal[0][("has", "gem3")], 0.333, abs_tol=0.2)
+ assert math.isclose(
+ get_last_inference_prediction(infered_goal)[("has", "gem3")], 1.0, abs_tol=0.2
+ )
+
+
+def test_update_filter_single_agent(dkg_stoch_astar_planner, dkg_state_three):
+ infer_model = SIPS(
+ dkg_stoch_astar_planner,
+ r=1000,
+ p=0.5,
+ )
+ agent_one = BoundedRationalAgent(
+ dkg_stoch_astar_planner, dkg_state_three, r=1, p=0.5
+ )
+ agent_one.step(5)
+ while agent_one.action_step >= len(agent_one.curr_plan.actions):
+ agent_one.replan()
+ agent_two = BoundedRationalAgent(
+ dkg_stoch_astar_planner, dkg_state_three, r=1, p=0.5
+ )
+ agent_two.step(5)
+ while agent_two.action_step >= len(agent_two.curr_plan.actions):
+ agent_two.replan()
+ predicted_next_state_one = agent_one.curr_plan.states[agent_one.action_step + 1]
+ predicted_next_state_two = agent_two.curr_plan.states[agent_two.action_step + 1]
+ observation = predicted_next_state_one
+ new_agents, new_weights = infer_model._update_filter(
+ [agent_one, agent_two],
+ torch.tensor([-0.6931, -0.6931]),
+ 1,
+ [dkg_state_three, observation],
+ dkg_state_three,
+ [("has", "gem1"), ("has", "gem2"), ("has", "gem3")],
+ 0.0,
+ False,
+ 0.0,
+ )
+ assert agent_one.curr_node.state == predicted_next_state_one
+ assert agent_two.curr_node.state == predicted_next_state_two
+ assert torch.isclose(new_weights[0], torch.tensor(-0.6931), atol=0.1)
+ if predicted_next_state_one == predicted_next_state_two:
+ assert torch.isclose(new_weights[1], torch.tensor(-0.6931), atol=0.1)
+ else:
+ assert torch.isneginf(new_weights[1])
+
+
+def test_effective_sample_size_uniform(dkg_SIPS_no_noise):
+ weights_uniform = torch.zeros(100)
+ ess = dkg_SIPS_no_noise._effective_sample_size(weights_uniform)
+ assert torch.isclose(ess, torch.tensor(100.0), atol=0.0001)
+
+
+def test_effective_sample_size_peaked(dkg_SIPS_no_noise):
+ weights_peaked = torch.ones(100) * -100
+ weights_peaked[0] = 0.0
+ ess = dkg_SIPS_no_noise._effective_sample_size(weights_peaked)
+ assert torch.isclose(ess, torch.tensor(1.0), atol=0.01)
+
+
+def test_resampling_new_weights_multinomial(dkg_SIPS_no_noise):
+ weights = torch.rand(100)
+ new_weights, new_indexes = dkg_SIPS_no_noise._multinomial_resample(weights)
+ assert (new_weights == torch.zeros(100)).all()
+
+
+def test_resampling_dead_trajs_not_resampled_multinomial(dkg_SIPS_no_noise):
+ weights = torch.ones(100)
+ weights[0:50] = -100.0
+ new_weights, new_indexes = dkg_SIPS_no_noise._multinomial_resample(weights)
+ assert (new_weights == torch.zeros(100)).all()
+ assert torch.all(new_indexes >= 50)
+
+
+def test_resampling_new_weights_residual(dkg_SIPS_no_noise):
+ weights = torch.rand(100)
+ new_weights, new_indexes = dkg_SIPS_no_noise._residual_resample(weights)
+ assert (new_weights == torch.zeros(100)).all()
+
+
+def test_resampling_uniform_weights_residual(dkg_SIPS_no_noise):
+ weights = torch.ones(100)
+ new_weights, new_indexes = dkg_SIPS_no_noise._residual_resample(weights)
+ assert (new_weights == torch.zeros(100)).all()
+ assert (new_indexes == torch.arange(100)).all()
+
+
+def test_resampling_dead_trajs_not_resampled_residual(dkg_SIPS_no_noise):
+ weights = torch.zeros(100)
+ weights[0:50] = -100
+ new_weights, new_indexes = dkg_SIPS_no_noise._residual_resample(weights)
+ assert (new_weights == torch.zeros(100)).all()
+ assert torch.all(new_indexes >= 50)
+
+
+def test_goal_proposal(
+ dkg_astar_planner,
+ dkg_state_two,
+ dkg_SIPS_no_noise,
+):
+ # Move Agent so that gem1 (goal gem) is closer
+ agent = BoundedRationalAgent(dkg_astar_planner, dkg_state_two, r=1000, p=0.5)
+ agent.step(11)
+ dist_gem1 = manhattan_gem_heuristic(
+ agent.curr_node,
+ ("has", "gem1"),
+ )
+
+ dist_gem2 = manhattan_gem_heuristic(
+ agent.curr_node,
+ ("has", "gem2"),
+ )
+ assert dist_gem1 < dist_gem2
+
+ counts = {"gem1": 0, "gem2": 0, "gem3": 0}
+ for _test in range(1000):
+ alpha, new_agent = dkg_SIPS_no_noise._goal_rejuvenation(
+ agent,
+ dkg_state_two,
+ [("has", "gem1"), ("has", "gem2")],
+ )
+ counts[new_agent.curr_node.state.goal[1]] += 1
+ # Test that Rejuvenated goals are more commonly gem1 than gem2
+ assert counts["gem1"] > counts["gem2"]
+
+
+def test_problem_one_resample_and_rejuvenate(
+ dkg_state_one, dkg_stoch_astar_planner, dkg_astar_planner
+):
+ model = SIPS(dkg_stoch_astar_planner, DKGObservation())
+ (
+ plan,
+ solved,
+ ) = dkg_astar_planner.generate_plan(dkg_state_one)
+ observations = plan.states
+ infered_goal = model.infer(
+ 100,
+ plan.states[0],
+ [("has", "gem1")],
+ observations,
+ )
+ assert math.isclose(infered_goal[0][("has", "gem1")], 1.0, abs_tol=0.2)
+ assert math.isclose(
+ get_last_inference_prediction(infered_goal)[("has", "gem1")], 1.0, abs_tol=0.2
+ )
+
+
+def test_problem_two_resample_and_rejuvenate(
+ dkg_state_two, dkg_stoch_astar_planner, dkg_astar_planner
+):
+ model = SIPS(dkg_stoch_astar_planner, DKGObservation())
+ (
+ plan,
+ solved,
+ ) = dkg_astar_planner.generate_plan(dkg_state_two)
+ observations = plan.states
+ infered_goal = model.infer(
+ 100,
+ plan.states[0],
+ [("has", "gem1"), ("has", "gem2")],
+ observations,
+ )
+ assert math.isclose(infered_goal[0][("has", "gem1")], 0.5, abs_tol=0.2)
+ assert math.isclose(infered_goal[0][("has", "gem2")], 0.5, abs_tol=0.2)
+ assert math.isclose(
+ get_last_inference_prediction(infered_goal)[("has", "gem1")], 1.0, abs_tol=0.2
+ )
+
+
+def test_cgem_problem_one():
+ state = parse(
+ "beanmachine/facebook/goal_inference/continuous_gems/test_problems/problem-1.json"
+ )
+ domain = CGemDomain()
+ planner = StochasticAstarPlanner(domain, manhattan_gem_heuristic, 0.1)
+ plan, solved = planner.generate_plan(state)
+ model = SIPS(planner, r=8, p=0.95, noise_model=CGemObservation())
+ goals = [("has", "gem1"), ("has", "gem2")]
+ infered_goal = model.infer(
+ 600,
+ state,
+ goals,
+ plan.states,
+ resample_threshold=0.25,
+ rejuvenate=False,
+ goal_rejuvenation_prob=1.0,
+ )
+ assert math.isclose(infered_goal[0][("has", "gem1")], 0.5, abs_tol=0.2)
+ assert math.isclose(
+ get_last_inference_prediction(infered_goal)[("has", "gem1")], 1.0, abs_tol=0.2
+ )
+
+
+def test_cgem_problem_two():
+
+ state = parse(
+ "beanmachine/facebook/goal_inference/continuous_gems/test_problems/problem-2.json"
+ )
+ domain = CGemDomain()
+ planner = StochasticAstarPlanner(domain, manhattan_gem_heuristic, 0.1)
+ state = dataclasses.replace(state, goal=("has", "gem2"))
+ plan, solved = planner.generate_plan(state)
+ model = SIPS(planner, r=8, p=0.95, noise_model=CGemObservation())
+ goals = [("has", "gem1"), ("has", "gem2")]
+ infered_goal = model.infer(
+ 600,
+ state,
+ goals,
+ plan.states,
+ resample_threshold=0.25,
+ rejuvenate=False,
+ goal_rejuvenation_prob=1.0,
+ )
+ assert math.isclose(infered_goal[0][("has", "gem2")], 0.5, abs_tol=0.2)
+ assert math.isclose(
+ get_last_inference_prediction(infered_goal)[("has", "gem2")], 1.0, abs_tol=0.2
+ )
diff --git a/src/beanmachine/ppl/experimental/goal_inference/planner/astar.py b/src/beanmachine/ppl/experimental/goal_inference/planner/astar.py
new file mode 100644
index 0000000000..6ca5c8f6a7
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/planner/astar.py
@@ -0,0 +1,80 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from __future__ import annotations
+
+from itertools import count
+
+from queue import PriorityQueue
+
+from typing import Callable, Dict, Tuple
+
+from beanmachine.facebook.goal_inference.environment import Domain, State
+from beanmachine.facebook.goal_inference.planner.planner import Planner, StateNode
+
+
+class AstarPlanner(Planner):
+
+ """
+ Obtains an A* solution to a problem given a heuristic.
+
+ Arguments:
+ domain: Domain that encodes the rules of the world
+ heuristic: Heuristic for A* Algorithm
+
+ Attributes:
+
+ domain: Domain that encodes the rules of the world
+ visited_nodes: Record of nodes visited during planning
+ heuristic: Heuristic for A* Algorithm
+ cost: Record of cost to reach visited States
+ q: Priority queue for A* algorithm
+ unique: StateNode Id to avoid collisions in Priority Queue (StateNodes cannot be compared)
+
+ """
+
+ def __init__(self, domain: Domain, heuristic: Callable):
+ super().__init__(domain)
+ self.heuristic: Callable = heuristic
+ self.cost: Dict[State, int] = {}
+ self.q: PriorityQueue[Tuple[int, int, StateNode]] = PriorityQueue()
+ self.unique: count[int] = count()
+
+ def is_empty(self) -> bool:
+ """Determines whether the priority queue is empty
+
+ Returns:
+ is_empty: Whether the astar datastructure is empty
+ """
+ return self.q.empty()
+
+ def reset(self) -> None:
+ """Clears the datatructures associated with this AstarPlanner"""
+ self.cost = {}
+ self.q = PriorityQueue()
+ self.visited_nodes = []
+
+ def get_next_node(self) -> StateNode:
+ """Get next StateNode to evaluate
+
+ Returns:
+ The next node to evaluate
+
+ """
+ curr_prioirity, curr_count, curr_node = self.q.get()
+ return curr_node
+
+ def add_node(self, new_node) -> None:
+ """Add a node to Astar datastructure
+
+ Arguments:
+ new_node: The node to be potentially explored
+ """
+ if new_node.parent_node is None:
+ self.cost[new_node.state] = 0
+ self.q.put((0, next(self.unique), new_node))
+ else:
+ new_cost = self.cost[new_node.parent_node.state] + 1
+ if new_node.state not in self.cost or new_cost < self.cost[new_node.state]:
+ self.cost[new_node.state] = new_cost
+ priority = new_cost + self.heuristic(new_node)
+ self.q.put((priority, next(self.unique), new_node))
diff --git a/src/beanmachine/ppl/experimental/goal_inference/planner/astar_test.py b/src/beanmachine/ppl/experimental/goal_inference/planner/astar_test.py
new file mode 100644
index 0000000000..6033fc064d
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/planner/astar_test.py
@@ -0,0 +1,310 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from beanmachine.facebook.goal_inference.planner.astar import AstarPlanner
+from beanmachine.facebook.goal_inference.utils import manhattan_gem_heuristic
+
+
+def test_astar_generate_plan_dkg_problem_1(dkg_domain, dkg_state_one):
+ astar_solver = AstarPlanner(dkg_domain, manhattan_gem_heuristic)
+ plan, solved = astar_solver.generate_plan(dkg_state_one)
+ assert solved
+ assert plan.actions == [
+ ["down"],
+ ["pickup", "key1"],
+ ["down"],
+ ["unlock", "key1", "right"],
+ ["right"],
+ ["right"],
+ ["up"],
+ ["up"],
+ ["pickup", "gem1"],
+ ]
+
+
+def test_astar_generate_plan_dkg_problem_2(dkg_domain, dkg_state_two):
+ astar_solver = AstarPlanner(dkg_domain, manhattan_gem_heuristic)
+ plan, solved = astar_solver.generate_plan(dkg_state_two)
+ assert solved
+ assert plan.actions == [
+ ["down"],
+ ["down"],
+ ["right"],
+ ["right"],
+ ["up"],
+ ["up"],
+ ["pickup", "key1"],
+ ["down"],
+ ["down"],
+ ["unlock", "key1", "right"],
+ ["right"],
+ ["right"],
+ ["up"],
+ ["pickup", "gem1"],
+ ]
+
+
+def test_astar_generate_plan_dkg_problem_3(dkg_domain, dkg_state_three):
+ astar_solver = AstarPlanner(dkg_domain, manhattan_gem_heuristic)
+ plan, solved = astar_solver.generate_plan(dkg_state_three)
+ assert solved
+ soln_one = plan.actions == [
+ ["right"],
+ ["right"],
+ ["right"],
+ ["up"],
+ ["up"],
+ ["left"],
+ ["left"],
+ ["left"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["pickup", "key1"],
+ ["right"],
+ ["right"],
+ ["unlock", "key1", "right"],
+ ["right"],
+ ["right"],
+ ["up"],
+ ["right"],
+ ["right"],
+ ["down"],
+ ["pickup", "key2"],
+ ["right"],
+ ["unlock", "key2", "down"],
+ ["down"],
+ ["down"],
+ ["down"],
+ ["down"],
+ ["down"],
+ ["down"],
+ ["pickup", "gem3"],
+ ]
+ soln_two = plan.actions == [
+ ["right"],
+ ["right"],
+ ["right"],
+ ["up"],
+ ["up"],
+ ["left"],
+ ["left"],
+ ["left"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["pickup", "key1"],
+ ["down"],
+ ["down"],
+ ["down"],
+ ["down"],
+ ["right"],
+ ["right"],
+ ["right"],
+ ["up"],
+ ["up"],
+ ["unlock", "key1", "right"],
+ ["right"],
+ ["right"],
+ ["down"],
+ ["down"],
+ ["down"],
+ ["down"],
+ ["right"],
+ ["right"],
+ ["pickup", "gem3"],
+ ]
+ soln_three = plan.actions == [
+ ["right"],
+ ["right"],
+ ["right"],
+ ["up"],
+ ["up"],
+ ["left"],
+ ["left"],
+ ["left"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["pickup", "key1"],
+ ["down"],
+ ["down"],
+ ["down"],
+ ["down"],
+ ["right"],
+ ["right"],
+ ["up"],
+ ["up"],
+ ["right"],
+ ["unlock", "key1", "right"],
+ ["right"],
+ ["right"],
+ ["down"],
+ ["down"],
+ ["down"],
+ ["down"],
+ ["right"],
+ ["right"],
+ ["pickup", "gem3"],
+ ]
+ assert soln_one or soln_two or soln_three
+
+
+def test_astar_generate_plan_dkg_problem_4(dkg_domain, dkg_state_four):
+ astar_solver = AstarPlanner(dkg_domain, manhattan_gem_heuristic)
+ plan, solved = astar_solver.generate_plan(dkg_state_four)
+ assert solved
+ soln_one = plan.actions == [
+ ["left"],
+ ["left"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["right"],
+ ["right"],
+ ["right"],
+ ["right"],
+ ["down"],
+ ["down"],
+ ["pickup", "key1"],
+ ["up"],
+ ["up"],
+ ["pickup", "key2"],
+ ["right"],
+ ["right"],
+ ["unlock", "key2", "down"],
+ ["down"],
+ ["down"],
+ ["down"],
+ ["down"],
+ ["down"],
+ ["down"],
+ ["left"],
+ ["left"],
+ ["unlock", "key1", "up"],
+ ["up"],
+ ["up"],
+ ["pickup", "gem3"],
+ ]
+
+ soln_two = plan.actions == [
+ ["left"],
+ ["left"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["right"],
+ ["right"],
+ ["right"],
+ ["right"],
+ ["down"],
+ ["down"],
+ ["pickup", "key1"],
+ ["up"],
+ ["up"],
+ ["pickup", "key2"],
+ ["right"],
+ ["right"],
+ ["unlock", "key1", "down"],
+ ["down"],
+ ["down"],
+ ["down"],
+ ["down"],
+ ["down"],
+ ["down"],
+ ["left"],
+ ["left"],
+ ["unlock", "key2", "up"],
+ ["up"],
+ ["up"],
+ ["pickup", "gem3"],
+ ]
+
+ soln_three = plan.actions == [
+ ["left"],
+ ["left"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["right"],
+ ["right"],
+ ["right"],
+ ["right"],
+ ["pickup", "key2"],
+ ["down"],
+ ["down"],
+ ["pickup", "key1"],
+ ["up"],
+ ["up"],
+ ["right"],
+ ["right"],
+ ["unlock", "key2", "down"],
+ ["down"],
+ ["down"],
+ ["down"],
+ ["down"],
+ ["down"],
+ ["down"],
+ ["left"],
+ ["left"],
+ ["unlock", "key1", "up"],
+ ["up"],
+ ["up"],
+ ["pickup", "gem3"],
+ ]
+
+ soln_four = plan.actions == [
+ ["left"],
+ ["left"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["up"],
+ ["right"],
+ ["right"],
+ ["right"],
+ ["right"],
+ ["pickup", "key2"],
+ ["down"],
+ ["down"],
+ ["pickup", "key1"],
+ ["up"],
+ ["up"],
+ ["right"],
+ ["right"],
+ ["unlock", "key1", "down"],
+ ["down"],
+ ["down"],
+ ["down"],
+ ["down"],
+ ["down"],
+ ["down"],
+ ["left"],
+ ["left"],
+ ["unlock", "key2", "up"],
+ ["up"],
+ ["up"],
+ ["pickup", "gem3"],
+ ]
+ assert soln_one or soln_two or soln_three or soln_four
diff --git a/src/beanmachine/ppl/experimental/goal_inference/planner/bfs.py b/src/beanmachine/ppl/experimental/goal_inference/planner/bfs.py
new file mode 100644
index 0000000000..a8889c58eb
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/planner/bfs.py
@@ -0,0 +1,67 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from __future__ import annotations
+
+from collections import deque
+
+from typing import Deque, Set
+
+from beanmachine.facebook.goal_inference.environment import Domain, State
+from beanmachine.facebook.goal_inference.planner.planner import Planner, StateNode
+
+
+class BFSPlanner(Planner):
+
+ """
+ Obtains a Breadth First Search solution to a problem.
+
+ Arguments:
+ domain: Domain that encodes the rules of the world
+
+ Attributes:
+
+ domain: Domain that encodes the rules of the world
+ visited_nodes: Record of nodes visited during planning
+ queue: Maintains queue of StateNodes for BFS
+ visited: Maintains a record of visited states
+
+ """
+
+ def __init__(self, domain: Domain):
+ super().__init__(domain)
+ self.deque: Deque[StateNode] = deque()
+ self.visited: Set[State] = set()
+
+ def is_empty(self) -> bool:
+ """Evaluates to True if the bfs datastructure is empty
+
+ Returns:
+ is_empty: Whether the bfs datastructure is empty
+
+ """
+ return not bool(self.deque)
+
+ def reset(self) -> None:
+ """Clears the datatructures associated with this BFSPlanner"""
+ self.deque = deque()
+ self.visited_nodes = []
+
+ def get_next_node(self) -> StateNode:
+ """Get next StateNode to evaluate
+
+ Returns:
+ The next node to evaluate
+
+ """
+ return self.deque.popleft()
+
+ def add_node(self, new_node: StateNode) -> None:
+ """Add a node to BFS datastructure
+
+ Arguments:
+ new_nodes: The node to be potentially explored
+
+ """
+ if new_node.state not in self.visited:
+ self.visited.add(new_node.state)
+ self.deque.append(new_node)
diff --git a/src/beanmachine/ppl/experimental/goal_inference/planner/bfs_test.py b/src/beanmachine/ppl/experimental/goal_inference/planner/bfs_test.py
new file mode 100644
index 0000000000..fd289bb5a6
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/planner/bfs_test.py
@@ -0,0 +1,29 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from beanmachine.facebook.goal_inference.planner.bfs import BFSPlanner
+
+
+def test_bfs_generate_plan_dkg_problem_1(dkg_domain, dkg_state_one):
+
+ bfs_solver = BFSPlanner(dkg_domain)
+ plan, solved = bfs_solver.generate_plan(dkg_state_one)
+ assert solved
+ assert plan.actions == [
+ ["down"],
+ ["pickup", "key1"],
+ ["down"],
+ ["unlock", "key1", "right"],
+ ["right"],
+ ["right"],
+ ["up"],
+ ["up"],
+ ["pickup", "gem1"],
+ ]
+
+
+def test_bfs_generate_plan_dkg_problem_2(dkg_domain, dkg_state_two):
+
+ bfs_solver = BFSPlanner(dkg_domain)
+ plan, solved = bfs_solver.generate_plan(dkg_state_two)
+ assert solved
+ assert len(plan.actions) == 14
diff --git a/src/beanmachine/ppl/experimental/goal_inference/planner/planner.py b/src/beanmachine/ppl/experimental/goal_inference/planner/planner.py
new file mode 100644
index 0000000000..af18165894
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/planner/planner.py
@@ -0,0 +1,190 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from __future__ import annotations
+
+import math
+
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+from typing import List, Optional, Tuple
+
+from beanmachine.facebook.goal_inference.environment import Domain, State
+
+
+@dataclass
+class StateNode:
+
+ """
+ Defines nodes for graph-based representation of relationship between states.
+
+ Arguments/Attributes:
+ state: Current State
+ parent_node: Parent to this node
+ executed: Previous operation to get to this point in format [action_name,*args]
+ """
+
+ state: State
+ parent_node: Optional[StateNode]
+ executed: List[str]
+
+
+@dataclass()
+class Plan:
+ """
+ Defines a sequence of actions in string form (e.g. ["unlock","key1","right"]) and (expected) states
+
+ Arguments/Attributes:
+ actions: A sequence of actions to perform
+ states: Expected states following actions. e.g. states[i+1] is predicted state after actions[i]
+ visited_nodes: Nodes visited during the planning process
+ budget: The search budget for creating this plan
+ """
+
+ states: List[State]
+ actions: List[List[str]]
+ visited_nodes: List[StateNode]
+ budget: int
+
+
+class Planner(ABC):
+ """A Planner finds sequences of actions to solve a problem
+
+ Arguments:
+ domain: The domain that determines the rules of the environment.
+
+ Attributes:
+ domain: The domain that determines the rules of the environment.
+ visited_nodes: A record of the nodes visited during planning.
+ """
+
+ def __init__(self, domain: Domain):
+ self.domain: Domain = domain
+ self.visited_nodes: List[StateNode] = []
+
+ def generate_plan(
+ self, initial_state: State, budget: float = math.inf
+ ) -> Tuple[Plan, bool]:
+ """Searches for a plan to solve the problem given budgetary constraints
+ Determines whether a solution has been reached
+
+ Arguments:
+ initial_state: The initial_state of the search
+ budget: The number of nodes that can be evaluated when formulating a plan
+
+ Returns:
+ plan: The Plan found by the search
+ solved: Whether the plan reached the goal
+
+ """
+ self.reset()
+ init_node = StateNode(initial_state, None, [])
+ self.add_node(init_node)
+ search_count = 0
+ curr_node = init_node
+ goal_achieved = self.domain.evaluate_goal(init_node.state)
+ while search_count < budget:
+ curr_node = self.get_next_node()
+ self.visited_nodes.append(curr_node)
+ search_count += 1
+ goal_achieved = self.domain.evaluate_goal(curr_node.state)
+ # Goal is achieved - end planning
+ if goal_achieved:
+ break
+ poss_actions = self.domain.get_possible_actions(curr_node.state)
+ for act in poss_actions:
+ next_state = self.domain.execute(curr_node.state, *act)
+ new_node = StateNode(next_state, executed=act, parent_node=curr_node)
+ self.add_node(new_node)
+ # Hit a dead end - end planning
+ if self.is_empty():
+ break
+
+ return (
+ # pyre-fixme[19]: Expected 4 positional arguments.
+ Plan(*get_execution_path(curr_node), self.visited_nodes, search_count),
+ goal_achieved,
+ )
+
+ @abstractmethod
+ def reset(self) -> None:
+ """Clears the datatructures associated with this Planner"""
+ pass
+
+ @abstractmethod
+ def is_empty(self) -> bool:
+ """Evaluates to True if the planning datastructure is empty
+
+ Returns:
+ is_empty: Whether the planning datastructure is empty
+ """
+ pass
+
+ @abstractmethod
+ def get_next_node(self) -> StateNode:
+ """Get next StateNode to evaluate
+
+ Returns:
+ The next node to evaluate
+
+ """
+ pass
+
+ @abstractmethod
+ def add_node(self, new_node: StateNode) -> None:
+ """Add a node to potentially be explored
+
+ Arguments:
+ new_node: The node to be potentially explored
+ """
+ pass
+
+
+def get_execution_path(
+ curr_node: Optional[StateNode],
+) -> Tuple[List[State], List[List[str]]]:
+ """
+ Determines All States/Actions to reach the current node.
+ Each action is in format [action_name,*args]
+ acts[i] is the transition between state[i] and state[i+1]
+
+ Arguments:
+ curr_node: The current node whose path is being analyzed
+
+ Returns:
+ states: States on path to current node
+ actions: Actions on path to current node
+ """
+ acts = []
+ states = []
+ while curr_node.parent_node is not None:
+ acts.append(curr_node.executed)
+ states.append(curr_node.state)
+ curr_node = curr_node.parent_node
+ states.append(curr_node.state)
+ acts.reverse()
+ states.reverse()
+ return states, acts
+
+
+def get_plan_from_actions(
+ domain: Domain, state: State, actions: List[List[str]]
+) -> Plan:
+ """Determines the plan that results from a series of actions
+
+ Arguments:
+ domain: The domain of the world
+ state: Initial State
+ actions: Series of actions that will be performed
+
+ Returns:
+ Plan: The plan that results from the actions
+
+ """
+ states = []
+ states.append(state)
+ curr_state = state
+ for act in actions:
+ next_state = domain.execute(curr_state, *act)
+ states.append(next_state)
+ curr_state = next_state
+ return Plan(states, actions, [], 0)
diff --git a/src/beanmachine/ppl/experimental/goal_inference/planner/planners_test.py b/src/beanmachine/ppl/experimental/goal_inference/planner/planners_test.py
new file mode 100644
index 0000000000..0015394718
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/planner/planners_test.py
@@ -0,0 +1,16 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from beanmachine.facebook.goal_inference.planner.planner import (
+ get_execution_path,
+ StateNode,
+)
+
+
+def test_get_execution_path(dkg_domain, dkg_state_one):
+
+ first_node = StateNode(dkg_state_one, None, [""])
+ second_state = dkg_domain.execute(dkg_state_one, "down")
+ second_node = StateNode(second_state, first_node, ["down"])
+ third_state = dkg_domain.execute(second_state, "pickup", "key1")
+ third_node = StateNode(third_state, second_node, ["pickup", "key1"])
+ assert get_execution_path(third_node)[1] == [["down"], ["pickup", "key1"]]
diff --git a/src/beanmachine/ppl/experimental/goal_inference/planner/stoch_astar.py b/src/beanmachine/ppl/experimental/goal_inference/planner/stoch_astar.py
new file mode 100644
index 0000000000..50ccec5fb5
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/planner/stoch_astar.py
@@ -0,0 +1,287 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from __future__ import annotations
+
+from typing import Callable, Dict, List, Tuple
+
+import torch
+from beanmachine.facebook.goal_inference.agent.observation_model import (
+ DeterministicObservation,
+ ObservationModel,
+)
+
+from beanmachine.facebook.goal_inference.environment import Domain, State
+from beanmachine.facebook.goal_inference.planner.planner import (
+ get_execution_path,
+ Plan,
+ Planner,
+ StateNode,
+)
+
+
+class StochasticAstarPlanner(Planner):
+
+ """
+ Obtains a probabilistic A* solution to a problem given a heuristic.
+ The next node to explore is determined probabilistic sampling based on priorities
+ where priority = cost (to reach that node) + heuristic (estimating additional actions until goal)
+ and weights are proportional to exp(-priority/noise)
+
+ Arguments:
+ domain: Domain that encodes the rules of the world
+ heuristic: Heuristic for A* Algorithm
+ noise: Controls randomness of sampling process
+
+ Attributes:
+ domain: Domain that encodes the rules of the world
+ visited_nodes: Record of nodes visited during planning
+ heuristic: Heuristic for A* Algorithm
+ cost: Record of cost to reach visited States
+ weights: Proportional to probability of sampling a state
+ nodes: Current nodes that can be sampled
+ noise: Controls randomness of sampling process
+
+ """
+
+ def __init__(self, domain: Domain, heuristic: Callable, noise: float):
+ super().__init__(domain)
+ self.heuristic: Callable = heuristic
+ self.cost: Dict[State, int] = {}
+ self.weights: Dict[State, float] = {}
+ self.nodes: Dict[State, StateNode] = {}
+ self.noise: float = noise
+
+ def _sample(self) -> StateNode:
+ """Samples from nodes with probabilities proportional to weights
+
+ Returns:
+ node: Sampled StateNode
+ """
+ weight_tensor = torch.tensor(list(self.weights.values()))
+ sampled_index = torch.distributions.categorical.Categorical(
+ logits=weight_tensor
+ ).sample()
+ sampled_state = list(self.weights.keys())[sampled_index]
+ return self._sample_node(sampled_state)
+
+ def _sample_node(self, state: State) -> StateNode:
+ """Samples target node. Removes node and corresponding weight from planner
+
+ Arguments:
+ state: State being sampled
+ Returns:
+ state_node: StateNode corresponding to the sampled state
+ """
+ self.weights.pop(state)
+ return self.nodes.pop(state)
+
+ def is_empty(self) -> bool:
+ """Determines whether the prioirty queue is empty
+
+ Returns:
+ is_empty: Whether the astar datastructure is empty
+ """
+ return not self.nodes
+
+ def reset(self) -> None:
+ """Clears the datatructures associated with this StochasticAstarPlanner"""
+ self.cost = {}
+ self.weights = {}
+ self.nodes = {}
+ self.visited_nodes = []
+
+ def get_next_node(self) -> StateNode:
+ """Get next StateNode to evaluate
+
+ Returns:
+ The next node to evaluate
+ """
+ curr_node = self._sample()
+ return curr_node
+
+ def add_node(self, new_node: StateNode) -> None:
+ """Add a node to StochasticAstar datastructure
+
+ Arguments:
+ new_node: The node to be potentially explored
+ """
+ if new_node.parent_node is None:
+ self.cost[new_node.state] = 0
+ self.weights[new_node.state] = 0.0
+ self.nodes[new_node.state] = new_node
+ else:
+ new_cost = self.cost[new_node.parent_node.state] + 1
+ if new_node.state not in self.cost or new_cost < self.cost[new_node.state]:
+ self.cost[new_node.state] = new_cost
+ priority = new_cost + self.heuristic(new_node)
+ # Weight is proportional to exp[-priority/noise]
+ self.weights[new_node.state] = -priority / self.noise
+ self.nodes[new_node.state] = new_node
+
+
+class StochasticAstarProposalPlanner(StochasticAstarPlanner):
+
+ """
+ Proposes a new path using probabilistic A* algorithm.
+ The next node to explore is determined probabilistic sampling based on priorities
+ where priority = cost (to reach that node) + heuristic (estimating additional actions until goal)
+ and weights are proportional to exp(-priority/noise)*P(next_observation|next_state)
+
+ P(next_observation|next_state) is an additional bias to encourage paths near future observations
+
+ Arguments:
+ agent_planner: The planning algorithm for the BoundedRationalAgent
+
+ Attributes:
+ domain: Domain that encodes the rules of the world
+ visited_nodes: Record of nodes visited during planning
+ heuristic: Heuristic for A* Algorithm. If the agent_planner was not a StochasticA*Planner, the heuristic just returns 0.0 for any state
+ noise: Controls randomness of sampling process
+ cost: Record of cost to reach visited States
+ weights: Proportional to probability of sampling a state
+ nodes: Current nodes that can be sampled
+ noise_model: A model for P(observation|state)
+ observations: List of future observations
+ """
+
+ def __init__(self, agent_planner: Planner):
+ self.heuristic = null_heuristic
+ self.noise: float = 0.1
+ if isinstance(agent_planner, StochasticAstarPlanner):
+ self.heuristic: Callable = agent_planner.heuristic
+ self.noise: float = agent_planner.noise
+ super().__init__(agent_planner.domain, self.heuristic, self.noise)
+ self.observations: List[State] = []
+ self.noise_model: ObservationModel = DeterministicObservation()
+
+ def _sample(self) -> StateNode:
+ """Samples from nodes with probabilities proportional to weights
+
+ Returns:
+ node: Sampled StateNode
+ """
+ weight_tensor = self._get_next_state_weights()
+ sampled_index = torch.distributions.categorical.Categorical(
+ logits=weight_tensor
+ ).sample()
+ sampled_state = list(self.weights.keys())[sampled_index]
+ return self._sample_node(sampled_state)
+
+ def _get_next_state_weights(self) -> torch.Tensor:
+ """Defines the biasing of the proposal distribution.
+ Probability of a node being sampled is proportional to exp[-heuristic/noise] * P(next_observation|next_state)
+
+ Returns:
+ biased_weights: Unnormalized Log weights associeated with the probability of each node being sampled
+ """
+ biased_weights = torch.tensor(list(self.weights.values()))
+ biased_weights = torch.nan_to_num(biased_weights, nan=-float("inf"))
+ biased_weights = torch.nan_to_num(biased_weights)
+ return biased_weights
+
+ def add_node(self, new_node: StateNode) -> None:
+ """Add a node to StochasticAstarProposal datastructure
+
+ Arguments:
+ new_node: The node to be potentially explored
+ """
+ if new_node.parent_node is None:
+ self.cost[new_node.state] = 0
+ self.weights[new_node.state] = 0.0
+ self.nodes[new_node.state] = new_node
+ else:
+ new_cost = self.cost[new_node.parent_node.state] + 1
+ if new_node.state not in self.cost or new_cost < self.cost[new_node.state]:
+ self.cost[new_node.state] = new_cost
+ priority = new_cost + self.heuristic(new_node)
+ bias = 0.0
+ curr_path = get_execution_path(new_node)[0]
+ if len(curr_path) - 1 < len(self.observations):
+ bias = self.noise_model.get_log_prob(
+ curr_path[-1], self.observations[len(curr_path) - 1]
+ )
+ # Naive weight is proportional to exp[-priority/noise]
+ # Adjust priority based on P(next_observation|next_state)
+ self.weights[new_node.state] = -priority / self.noise + bias
+ self.nodes[new_node.state] = new_node
+
+ def propose(
+ self,
+ state: State,
+ observations: List[State],
+ budget: int,
+ noise_model: ObservationModel,
+ ) -> Tuple[Plan, bool]:
+ """Propose a plan using the biased proposal distribution
+
+ Arguments:
+ state: The starting state of the plan
+ observations: List of future observations
+ budget: Node search limit for the planning process
+ noise_model: A model for P(observation|state)
+
+ Returns:
+ plan: A new partial plan to reach the goal
+ solved: Whether the plan reached the goal
+ """
+ self.observations = observations
+ self.noise_model = noise_model
+ return self.generate_plan(state, budget)
+
+ def get_log_prob(
+ self, plan: Plan, observations: List[State], noise_model: ObservationModel
+ ) -> torch.Tensor:
+ """Get the log probability of a specific bounded-rational agent planning sequence
+
+ Arguments:
+ plan: The planning process to compute probability of
+ observations: List of future observations
+ noise_model: A model for P(observation|state)
+
+ Returns:
+ log_prob: Log probability of the plan
+ """
+ # Initialize planning
+ self.reset()
+ self.observations = observations
+ self.noise_model = noise_model
+ init_node = StateNode(plan.states[0], None, [])
+ self.add_node(init_node)
+ log_prob = torch.tensor(0.0)
+ # Follow the planning decisions and update the probability of the
+ # planning sequence with each decision
+ for planning_step in range(len(plan.visited_nodes)):
+ # Get the probability distribution at this stage of planning
+ current_distribution = self._get_next_state_weights()
+ current_distribution -= torch.logsumexp(current_distribution, dim=0)
+ curr_visited_state = plan.visited_nodes[planning_step].state
+ # Determine which node was sampled
+ for node_idx in range(len(self.nodes)):
+ curr_node_state = list(self.nodes.keys())[node_idx]
+ if curr_node_state == curr_visited_state:
+ log_prob += current_distribution[node_idx]
+ curr_node = self._sample_node(curr_node_state)
+ # Add next possible nodes to replicate planning process
+ poss_actions = self.domain.get_possible_actions(curr_node.state)
+ for act in poss_actions:
+ next_state = self.domain.execute(curr_node.state, *act)
+ new_node = StateNode(
+ next_state, executed=act, parent_node=curr_node
+ )
+ self.add_node(new_node)
+ break
+
+ return log_prob
+
+
+def null_heuristic(state: State) -> float:
+ """Default heuristic for StochasticAstarProposalPlanner
+ Returns 0 cost for all goals for all states
+
+ Arguments:
+ state: State to predict additional cost to goal
+
+ Returns:
+ cost: =0.0 in all cases
+ """
+ return 0.0
diff --git a/src/beanmachine/ppl/experimental/goal_inference/planner/stoch_astar_test.py b/src/beanmachine/ppl/experimental/goal_inference/planner/stoch_astar_test.py
new file mode 100644
index 0000000000..70681afeeb
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/planner/stoch_astar_test.py
@@ -0,0 +1,110 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import torch
+from beanmachine.facebook.goal_inference.agent.observation_model import (
+ DeterministicObservation,
+)
+from beanmachine.facebook.goal_inference.doors_keys_gems.dkg_observation_model import (
+ DKGObservation,
+)
+
+from beanmachine.facebook.goal_inference.planner.planner import (
+ get_plan_from_actions,
+ StateNode,
+)
+
+from beanmachine.facebook.goal_inference.planner.stoch_astar import (
+ StochasticAstarPlanner,
+ StochasticAstarProposalPlanner,
+)
+from beanmachine.facebook.goal_inference.utils import manhattan_gem_heuristic
+
+
+def test_stoch_astar_generate_plan_dkg_problem_1(dkg_domain, dkg_state_one):
+ st_astar_solver = StochasticAstarPlanner(dkg_domain, manhattan_gem_heuristic, 0.5)
+ plan, solved = st_astar_solver.generate_plan(dkg_state_one)
+ assert solved
+ assert plan.actions[-1] == ["pickup", "gem1"]
+
+
+def test_stoch_astar_generate_plan_dkg_problem_2(dkg_domain, dkg_state_two):
+ st_astar_solver = StochasticAstarPlanner(dkg_domain, manhattan_gem_heuristic, 0.5)
+ plan, solved = st_astar_solver.generate_plan(dkg_state_two)
+ assert solved
+ assert plan.actions[-1] == ["pickup", "gem1"]
+
+
+def test_path_propose(dkg_domain, dkg_state_three, dkg_observation_set):
+ planner = StochasticAstarPlanner(dkg_domain, manhattan_gem_heuristic, 0.1)
+ proposal_planner = StochasticAstarProposalPlanner(planner)
+ new_plan, solved = proposal_planner.propose(
+ dkg_state_three, dkg_observation_set, 1000, DeterministicObservation()
+ )
+ for time_step in range(10):
+ assert new_plan.states[time_step] == dkg_observation_set[time_step]
+
+
+def test_get_log_prob(dkg_domain, dkg_state_three, dkg_observation_set):
+ noise_model = DKGObservation()
+ planner = StochasticAstarPlanner(dkg_domain, manhattan_gem_heuristic, 0.1)
+ proposal_planner = StochasticAstarProposalPlanner(planner)
+ new_actions = [
+ ["right"],
+ ["right"],
+ ["right"],
+ ]
+ new_plan = get_plan_from_actions(dkg_domain, dkg_state_three, new_actions)
+ new_plan.budget = 4
+ new_plan.visited_nodes = [
+ StateNode(new_plan.states[0], None, []),
+ StateNode(new_plan.states[1], None, []),
+ StateNode(new_plan.states[2], None, []),
+ StateNode(new_plan.states[3], None, []),
+ ]
+
+ computed_prob = torch.tensor(0.0)
+
+ # Step 1
+
+ # No Option Moves Right
+
+ # Step 2
+
+ # Options RR or RL
+
+ node_weights = torch.tensor([-5.0 / 0.1, -7.0 / 0.1])
+
+ # Bias
+
+ # state RR
+ # state RL
+ state_rr = dkg_domain.execute(new_plan.states[1], "right")
+ state_rl = dkg_domain.execute(new_plan.states[1], "left")
+ node_weights[0] += noise_model.get_log_prob(state_rr, dkg_observation_set[2])
+ node_weights[1] += noise_model.get_log_prob(state_rl, dkg_observation_set[2])
+
+ node_weights -= torch.logsumexp(node_weights, dim=0)
+ computed_prob += node_weights[0]
+
+ # Step 3
+
+ # Options RRR RRL RL
+
+ node_weights = torch.tensor([-4.0 / 0.1, -6.0 / 0.1, -7.0 / 0.1])
+
+ # Bias
+ state_rrr = dkg_domain.execute(new_plan.states[2], "right")
+ state_rrl = dkg_domain.execute(new_plan.states[2], "left")
+ state_rl = dkg_domain.execute(new_plan.states[1], "left")
+ node_weights[0] += noise_model.get_log_prob(state_rrr, dkg_observation_set[3])
+ node_weights[1] += noise_model.get_log_prob(state_rrl, dkg_observation_set[3])
+ node_weights[2] += noise_model.get_log_prob(state_rl, dkg_observation_set[2])
+
+ node_weights -= torch.logsumexp(node_weights, dim=0)
+ computed_prob += node_weights[0]
+
+ assert torch.isclose(
+ computed_prob,
+ proposal_planner.get_log_prob(new_plan, dkg_observation_set, noise_model),
+ atol=0.1,
+ )
diff --git a/src/beanmachine/ppl/experimental/goal_inference/plotting/utils.py b/src/beanmachine/ppl/experimental/goal_inference/plotting/utils.py
new file mode 100644
index 0000000000..53eed55c83
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/plotting/utils.py
@@ -0,0 +1,166 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import tempfile
+
+from typing import Callable, Dict, List, Optional, Tuple, Union
+
+import matplotlib.pyplot as plt
+import numpy as np
+from beanmachine.facebook.goal_inference.continuous_gems.cgem_definitions import (
+ CGemState,
+)
+
+from beanmachine.facebook.goal_inference.doors_keys_gems.dkg_definitions import DKGState
+from IPython.display import display, Image
+from matplotlib.animation import FuncAnimation
+
+
+def get_gem_inference_plot(
+ inference_data: List[Dict[str, int]], frame: int
+) -> Dict[str, List[float]]:
+ """Formats posterior P(g|obs) from inference for plotting
+ Applicable for doors, keys, and gems / continuous gems problems
+
+ Arguments:
+ inference_data: Computation of the posterior P(goal|observations) at each time step
+ frame: Time step to plot
+
+ Returns:
+ poster: P(goal|observations) for each time step until the current frame
+
+ """
+ curr_data = inference_data[: frame + 1]
+ posterior = {}
+ for goal_id in inference_data[0]:
+ posterior[goal_id[1]] = []
+
+ for time_step in range(len(curr_data)):
+ for goal_id in curr_data[time_step]:
+ posterior[goal_id[1]].append(curr_data[time_step][goal_id])
+
+ return posterior
+
+
+def get_gem_figure(
+ state: Union[DKGState, CGemState],
+ inference_data: Optional[List[Dict[str, int]]] = None,
+ is_doors_keys_gems: bool = False,
+) -> Tuple[plt.Figure, List[plt.Axes]]:
+ """Returns a figure with the current formatting
+ Applicable for doors, keys, and gems / continuous gems problems
+
+ Arguments:
+ state: State to get figure for
+ inference_data: Computation of the posterior P(goal|observations) at each time step
+ is_doors_keys_gems: Whether the problem is a doors, keys, and gems problem.
+
+ Returns:
+ fig: The figure object with the correct size/subplot settings
+ axes: A list of Matplotlib Axes objects for further modification
+ """
+
+ fig = plt.figure(figsize=(1, 1))
+
+ if inference_data is None:
+ fig = plt.figure(figsize=(10, 5))
+ ax1 = plt.subplot(1, 2, 1)
+ ax2 = plt.subplot(1, 2, 2)
+ ax3 = None
+ else:
+ fig = plt.figure(figsize=(7, 7))
+ ax1 = plt.subplot(2, 2, 1)
+ ax2 = plt.subplot(2, 2, 2)
+ ax3 = plt.subplot(2, 1, 2)
+
+ plt.sca(ax1)
+ plt.gca().set_title("Environment")
+
+ if is_doors_keys_gems:
+
+ plt.gca().set_xticks(np.arange(1, state.width + 1, 1))
+ plt.gca().set_yticks(np.arange(1, state.height + 1, 1))
+
+ plt.gca().set_xticks(np.arange(0.5, state.width + 1, 1), minor=True)
+ plt.gca().set_yticks(np.arange(0.5, state.height + 1, 1), minor=True)
+
+ plt.gca().grid(which="minor", color="k", linestyle="-", linewidth=2)
+ plt.gca().grid(which="major", visible=False)
+
+ else:
+
+ plt.gca().set_xlim(0.0, state.width)
+ plt.gca().set_ylim(0.0, state.height)
+
+ plt.sca(ax2)
+
+ plt.gca().set_title("Holding")
+ plt.gca().set_xticks([])
+ plt.gca().set_yticks(np.arange(1, 9, 1))
+
+ plt.gca().set_xticks(np.arange(0.5, 2.0, 1), minor=True)
+ plt.gca().set_yticks(np.arange(0.5, 9.0, 1), minor=True)
+
+ plt.gca().grid(which="minor", color="k", linestyle="-", linewidth=2)
+ plt.gca().grid(which="major", visible=False)
+
+ axes = [ax1, ax2]
+
+ if inference_data is not None:
+ plt.sca(ax3)
+ plt.gca().set_title("Inference")
+ plt.gca().set_xlabel("Time Step")
+ plt.gca().set_ylabel("Probability")
+ plt.gca().set_ylim(0.0, 1.0)
+ plt.gca().set_xlim(0.0, len(inference_data))
+ plt.gca().set_xticks(np.arange(0, len(inference_data), 5))
+ plt.gca().set_yticks([0.0, 0.25, 0.50, 0.75, 1.0])
+ axes.append(ax3)
+
+ return fig, axes
+
+
+def format_gem_data(data: np.ndarray) -> np.ndarray:
+ """Adjusts data matrix so it is the right orientation for imshow
+ Applicable for doors, keys, and gems / continuous gems problems
+
+ Arguments:
+ data: Input data array
+
+ Returns:
+ data: Modified data array
+ """
+ data = np.rot90(data, 1, (0, 1))
+ data = np.rot90(data, 2, (0, 1))
+ data = np.flip(data, axis=1)
+ data += 0.5
+ return data
+
+
+def create_gif(
+ fig: plt.Figure,
+ animation_function: Callable,
+ states: Union[List[DKGState], List[CGemState]],
+ file_path: Optional[str],
+):
+ """Creates a gif for a series of states
+ Applicable for doors, keys, and gems / continuous gems problems
+
+ Arguments:
+
+ fig: Base matplotlib figure
+ animation_function: Defines update of each frame of the gif
+ states: Series of states to plot
+ file_path: Optional location to save gif
+
+ """
+
+ anim_created = FuncAnimation(
+ fig, animation_function, frames=len(states), interval=200
+ )
+ if file_path is None:
+ with tempfile.TemporaryDirectory() as tmpdirname:
+ anim_created.save(tmpdirname + "/tmp.gif", fps=10)
+ display(Image(tmpdirname + "/tmp.gif", format="png"))
+ else:
+ anim_created.save(file_path, fps=10)
+ display(Image(filename=file_path, format="png"))
diff --git a/src/beanmachine/ppl/experimental/goal_inference/test_utils.py b/src/beanmachine/ppl/experimental/goal_inference/test_utils.py
new file mode 100644
index 0000000000..18793a16a2
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/test_utils.py
@@ -0,0 +1,10 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from beanmachine.facebook.goal_inference.utils import manhattan_distance
+
+
+def test_manhattan_distance():
+ assert manhattan_distance((1.0, 1.0), (1.0, 1.0)) == 0.0
+ assert manhattan_distance((1.0, 2.0), (1.0, 1.0)) == 1.0
+ assert manhattan_distance((1.0, 1.0), (2.0, 1.0)) == 1.0
+ assert manhattan_distance((1.0, 1.0), (2.0, 2.0)) == 2.0
diff --git a/src/beanmachine/ppl/experimental/goal_inference/utils.py b/src/beanmachine/ppl/experimental/goal_inference/utils.py
new file mode 100644
index 0000000000..b4e369f766
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/utils.py
@@ -0,0 +1,56 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from typing import Optional, Tuple, Union
+
+from beanmachine.facebook.goal_inference.continuous_gems.cgem_definitions import (
+ CGemStateNode,
+)
+
+from beanmachine.facebook.goal_inference.doors_keys_gems.dkg_definitions import (
+ DKGStateNode,
+)
+
+
+def manhattan_distance(
+ coordinates_one: Union[Tuple[float, float], Tuple[int, int]],
+ coordinates_two: Union[Tuple[float, float], Tuple[int, int]],
+) -> Union[int, float]:
+ """Computes the manhattan distance between two objects in 2D
+
+ Arguments:
+ coordinates_one: The position of object one
+ coordinates_two: The position of object two
+
+ Returns:
+ dist: The manhattan distance between the two objects
+
+ """
+ dist_x = coordinates_two[0] - coordinates_one[0]
+ dist_y = coordinates_two[1] - coordinates_one[1]
+ return abs(dist_x) + abs(dist_y)
+
+
+def manhattan_gem_heuristic(
+ curr_node: Union[DKGStateNode, CGemStateNode],
+ goal: Optional[Tuple[str, str]] = None,
+) -> Union[int, float]:
+ """
+ Defines a simple heuristic for solving gems problems with an A* solver.
+ Summary: Estimates additional cost as manhattan distance to goal
+ If a goal is not provided, the goal of the state is presumed
+
+ Arguments:
+ curr_node: The current node to analyze
+ goal: The targeted goal
+
+ Returns:
+ manhattan_dist: Manhattan distance of node to target goal
+ """
+ if goal is None:
+ goal = curr_node.state.goal
+ if goal[1] not in curr_node.state.at:
+ return 0
+ final_x, final_y = curr_node.state.at[goal[1]]
+ # Compute Manhattan distance to goal
+ manhattan_dist = abs(final_x - curr_node.state.x) + abs(final_y - curr_node.state.y)
+ return manhattan_dist
diff --git a/src/beanmachine/ppl/experimental/goal_inference/utils_test.py b/src/beanmachine/ppl/experimental/goal_inference/utils_test.py
new file mode 100644
index 0000000000..18793a16a2
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/goal_inference/utils_test.py
@@ -0,0 +1,10 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from beanmachine.facebook.goal_inference.utils import manhattan_distance
+
+
+def test_manhattan_distance():
+ assert manhattan_distance((1.0, 1.0), (1.0, 1.0)) == 0.0
+ assert manhattan_distance((1.0, 2.0), (1.0, 1.0)) == 1.0
+ assert manhattan_distance((1.0, 1.0), (2.0, 1.0)) == 1.0
+ assert manhattan_distance((1.0, 1.0), (2.0, 2.0)) == 2.0
diff --git a/src/beanmachine/ppl/experimental/timeseries/notebooks/GP_autoForecast_M3_month.ipynb b/src/beanmachine/ppl/experimental/timeseries/notebooks/GP_autoForecast_M3_month.ipynb
new file mode 100644
index 0000000000..c92e8722d6
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/notebooks/GP_autoForecast_M3_month.ipynb
@@ -0,0 +1,1817 @@
+{
+ "metadata": {
+ "bento_stylesheets": {
+ "bento/extensions/flow/main.css": true,
+ "bento/extensions/kernel_selector/main.css": true,
+ "bento/extensions/kernel_ui/main.css": true,
+ "bento/extensions/new_kernel/main.css": true,
+ "bento/extensions/system_usage/main.css": true,
+ "bento/extensions/theme/main.css": true
+ },
+ "kernelspec": {
+ "display_name": "bm_timeseries (local)",
+ "language": "python",
+ "name": "bm_timeseries_local",
+ "metadata": {
+ "is_prebuilt": false,
+ "kernel_name": "bm_timeseries_local"
+ }
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3"
+ },
+ "captumWidgetMessage": {},
+ "outputWidgetContext": {}
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2,
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "b70e96ce-5d06-4e59-8589-c7e336e07441",
+ "showInput": false,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "# Introduction\n",
+ "\n",
+ "In this tutorial, we implement kernels designed in Automatic forecasting using Gaussian Process [1] and test results with the M3 dataset.\n",
+ "\n",
+ ""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "4d49db74-87a3-4d8c-a986-cc9d442bc981",
+ "showInput": false,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "# Data loading and visualization\n",
+ "The data is available at the following path."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "collapsed": false,
+ "originalKey": "3090a61c-ae03-4cc9-9690-1235a343088e",
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "import matplotlib\n",
+ "import matplotlib.pyplot as plt\n",
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "import seaborn as sns\n",
+ "import torch\n",
+ "import gpytorch as gp\n",
+ "import random\n",
+ "\n",
+ "random.seed(0)\n",
+ "df = pd.read_csv('/mnt/persistent-public/zhencao/M3_monthly_TSTS.csv')\n",
+ "df"
+ ],
+ "execution_count": 89,
+ "outputs": [
+ {
+ "output_type": "execute_result",
+ "data": {
+ "text/plain": " series_id category value timestamp\n0 M1 MICRO 2640.0 1990-01\n1 M1 MICRO 2640.0 1990-02\n2 M1 MICRO 2160.0 1990-03\n3 M1 MICRO 4200.0 1990-04\n4 M1 MICRO 3360.0 1990-05\n... ... ... ... ...\n167557 M1428 OTHER 1282.5 NaN\n167558 M1428 OTHER 1261.3 NaN\n167559 M1428 OTHER 1263.4 NaN\n167560 M1428 OTHER 1257.1 NaN\n167561 M1428 OTHER 1233.7 NaN\n\n[167562 rows x 4 columns]",
+ "text/html": "
\n\n
\n \n \n | \n series_id | \n category | \n value | \n timestamp | \n
\n \n \n \n | 0 | \n M1 | \n MICRO | \n 2640.0 | \n 1990-01 | \n
\n \n | 1 | \n M1 | \n MICRO | \n 2640.0 | \n 1990-02 | \n
\n \n | 2 | \n M1 | \n MICRO | \n 2160.0 | \n 1990-03 | \n
\n \n | 3 | \n M1 | \n MICRO | \n 4200.0 | \n 1990-04 | \n
\n \n | 4 | \n M1 | \n MICRO | \n 3360.0 | \n 1990-05 | \n
\n \n | ... | \n ... | \n ... | \n ... | \n ... | \n
\n \n | 167557 | \n M1428 | \n OTHER | \n 1282.5 | \n NaN | \n
\n \n | 167558 | \n M1428 | \n OTHER | \n 1261.3 | \n NaN | \n
\n \n | 167559 | \n M1428 | \n OTHER | \n 1263.4 | \n NaN | \n
\n \n | 167560 | \n M1428 | \n OTHER | \n 1257.1 | \n NaN | \n
\n \n | 167561 | \n M1428 | \n OTHER | \n 1233.7 | \n NaN | \n
\n \n
\n
167562 rows × 4 columns
\n
",
+ "application/vnd.dataresource+json": {
+ "schema": {
+ "fields": [
+ {
+ "name": "index",
+ "type": "integer"
+ },
+ {
+ "name": "series_id",
+ "type": "string"
+ },
+ {
+ "name": "category",
+ "type": "string"
+ },
+ {
+ "name": "value",
+ "type": "number"
+ },
+ {
+ "name": "timestamp",
+ "type": "string"
+ }
+ ],
+ "primaryKey": [
+ "index"
+ ],
+ "pandas_version": "0.20.0"
+ },
+ "data": [
+ {
+ "index": 0,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 2640,
+ "timestamp": "1990-01"
+ },
+ {
+ "index": 1,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 2640,
+ "timestamp": "1990-02"
+ },
+ {
+ "index": 2,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 2160,
+ "timestamp": "1990-03"
+ },
+ {
+ "index": 3,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 4200,
+ "timestamp": "1990-04"
+ },
+ {
+ "index": 4,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 3360,
+ "timestamp": "1990-05"
+ },
+ {
+ "index": 5,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 2400,
+ "timestamp": "1990-06"
+ },
+ {
+ "index": 6,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 3600,
+ "timestamp": "1990-07"
+ },
+ {
+ "index": 7,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 1920,
+ "timestamp": "1990-08"
+ },
+ {
+ "index": 8,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 4200,
+ "timestamp": "1990-09"
+ },
+ {
+ "index": 9,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 4560,
+ "timestamp": "1990-10"
+ },
+ {
+ "index": 10,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 480,
+ "timestamp": "1990-11"
+ },
+ {
+ "index": 11,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 3720,
+ "timestamp": "1990-12"
+ },
+ {
+ "index": 12,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 5640,
+ "timestamp": "1991-01"
+ },
+ {
+ "index": 13,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 2880,
+ "timestamp": "1991-02"
+ },
+ {
+ "index": 14,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 1800,
+ "timestamp": "1991-03"
+ },
+ {
+ "index": 15,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 3120,
+ "timestamp": "1991-04"
+ },
+ {
+ "index": 16,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 2400,
+ "timestamp": "1991-05"
+ },
+ {
+ "index": 17,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 2520,
+ "timestamp": "1991-06"
+ },
+ {
+ "index": 18,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 9000,
+ "timestamp": "1991-07"
+ },
+ {
+ "index": 19,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 2640,
+ "timestamp": "1991-08"
+ },
+ {
+ "index": 20,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 3120,
+ "timestamp": "1991-09"
+ },
+ {
+ "index": 21,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 2880,
+ "timestamp": "1991-10"
+ },
+ {
+ "index": 22,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 8760,
+ "timestamp": "1991-11"
+ },
+ {
+ "index": 23,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 5160,
+ "timestamp": "1991-12"
+ },
+ {
+ "index": 24,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 2160,
+ "timestamp": "1992-01"
+ },
+ {
+ "index": 25,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 8280,
+ "timestamp": "1992-02"
+ },
+ {
+ "index": 26,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 4920,
+ "timestamp": "1992-03"
+ },
+ {
+ "index": 27,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 3120,
+ "timestamp": "1992-04"
+ },
+ {
+ "index": 28,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 6600,
+ "timestamp": "1992-05"
+ },
+ {
+ "index": 29,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 4080,
+ "timestamp": "1992-06"
+ },
+ {
+ "index": 30,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 5880,
+ "timestamp": "1992-07"
+ },
+ {
+ "index": 31,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 1680,
+ "timestamp": "1992-08"
+ },
+ {
+ "index": 32,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 6720,
+ "timestamp": "1992-09"
+ },
+ {
+ "index": 33,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 2040,
+ "timestamp": "1992-10"
+ },
+ {
+ "index": 34,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 6480,
+ "timestamp": "1992-11"
+ },
+ {
+ "index": 35,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 1920,
+ "timestamp": "1992-12"
+ },
+ {
+ "index": 36,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 3600,
+ "timestamp": "1993-01"
+ },
+ {
+ "index": 37,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 2040,
+ "timestamp": "1993-02"
+ },
+ {
+ "index": 38,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 2760,
+ "timestamp": "1993-03"
+ },
+ {
+ "index": 39,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 3840,
+ "timestamp": "1993-04"
+ },
+ {
+ "index": 40,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 960,
+ "timestamp": "1993-05"
+ },
+ {
+ "index": 41,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 2280,
+ "timestamp": "1993-06"
+ },
+ {
+ "index": 42,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 1320,
+ "timestamp": "1993-07"
+ },
+ {
+ "index": 43,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 2160,
+ "timestamp": "1993-08"
+ },
+ {
+ "index": 44,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 4800,
+ "timestamp": "1993-09"
+ },
+ {
+ "index": 45,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 3000,
+ "timestamp": "1993-10"
+ },
+ {
+ "index": 46,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 3120,
+ "timestamp": "1993-11"
+ },
+ {
+ "index": 47,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 5880,
+ "timestamp": "1993-12"
+ },
+ {
+ "index": 48,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 2640,
+ "timestamp": "1994-01"
+ },
+ {
+ "index": 49,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 2400,
+ "timestamp": "1994-02"
+ },
+ {
+ "index": 50,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 2280,
+ "timestamp": "1994-03"
+ },
+ {
+ "index": 51,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 480,
+ "timestamp": "1994-04"
+ },
+ {
+ "index": 52,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 5040,
+ "timestamp": "1994-05"
+ },
+ {
+ "index": 53,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 1920,
+ "timestamp": "1994-06"
+ },
+ {
+ "index": 54,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 840,
+ "timestamp": "1994-07"
+ },
+ {
+ "index": 55,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 2520,
+ "timestamp": "1994-08"
+ },
+ {
+ "index": 56,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 1560,
+ "timestamp": "1994-09"
+ },
+ {
+ "index": 57,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 1440,
+ "timestamp": "1994-10"
+ },
+ {
+ "index": 58,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 240,
+ "timestamp": "1994-11"
+ },
+ {
+ "index": 59,
+ "series_id": "M1",
+ "category": "MICRO",
+ "value": 1800,
+ "timestamp": "1994-12"
+ }
+ ]
+ }
+ },
+ "metadata": {
+ "bento_obj_id": "140506678605424"
+ },
+ "execution_count": 89
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "c0173071-b770-4ab8-9d3e-c1da374f000f",
+ "showInput": false,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "Select series_id for one product, and we'll fit GP as a univariate model."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "originalKey": "c9777fdf-d942-4a70-8c50-66e2959ebcef",
+ "showInput": true,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": [],
+ "collapsed": false
+ },
+ "source": [
+ "series_id = 'M10'\n",
+ "num_test = 18\n",
+ "df = df[df['series_id']==series_id]\n",
+ "df"
+ ],
+ "execution_count": 90,
+ "outputs": [
+ {
+ "output_type": "execute_result",
+ "data": {
+ "text/plain": " series_id category value timestamp\n612 M10 MICRO 4120.0 1990-01\n613 M10 MICRO 5020.0 1990-02\n614 M10 MICRO 3840.0 1990-03\n615 M10 MICRO 5720.0 1990-04\n616 M10 MICRO 4960.0 1990-05\n.. ... ... ... ...\n675 M10 MICRO 3820.0 1995-04\n676 M10 MICRO 4880.0 1995-05\n677 M10 MICRO 2800.0 1995-06\n678 M10 MICRO 3640.0 1995-07\n679 M10 MICRO 4100.0 1995-08\n\n[68 rows x 4 columns]",
+ "text/html": "\n\n
\n \n \n | \n series_id | \n category | \n value | \n timestamp | \n
\n \n \n \n | 612 | \n M10 | \n MICRO | \n 4120.0 | \n 1990-01 | \n
\n \n | 613 | \n M10 | \n MICRO | \n 5020.0 | \n 1990-02 | \n
\n \n | 614 | \n M10 | \n MICRO | \n 3840.0 | \n 1990-03 | \n
\n \n | 615 | \n M10 | \n MICRO | \n 5720.0 | \n 1990-04 | \n
\n \n | 616 | \n M10 | \n MICRO | \n 4960.0 | \n 1990-05 | \n
\n \n | ... | \n ... | \n ... | \n ... | \n ... | \n
\n \n | 675 | \n M10 | \n MICRO | \n 3820.0 | \n 1995-04 | \n
\n \n | 676 | \n M10 | \n MICRO | \n 4880.0 | \n 1995-05 | \n
\n \n | 677 | \n M10 | \n MICRO | \n 2800.0 | \n 1995-06 | \n
\n \n | 678 | \n M10 | \n MICRO | \n 3640.0 | \n 1995-07 | \n
\n \n | 679 | \n M10 | \n MICRO | \n 4100.0 | \n 1995-08 | \n
\n \n
\n
68 rows × 4 columns
\n
",
+ "application/vnd.dataresource+json": {
+ "schema": {
+ "fields": [
+ {
+ "name": "index",
+ "type": "integer"
+ },
+ {
+ "name": "series_id",
+ "type": "string"
+ },
+ {
+ "name": "category",
+ "type": "string"
+ },
+ {
+ "name": "value",
+ "type": "number"
+ },
+ {
+ "name": "timestamp",
+ "type": "string"
+ }
+ ],
+ "primaryKey": [
+ "index"
+ ],
+ "pandas_version": "0.20.0"
+ },
+ "data": [
+ {
+ "index": 612,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 4120,
+ "timestamp": "1990-01"
+ },
+ {
+ "index": 613,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 5020,
+ "timestamp": "1990-02"
+ },
+ {
+ "index": 614,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 3840,
+ "timestamp": "1990-03"
+ },
+ {
+ "index": 615,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 5720,
+ "timestamp": "1990-04"
+ },
+ {
+ "index": 616,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 4960,
+ "timestamp": "1990-05"
+ },
+ {
+ "index": 617,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 1960,
+ "timestamp": "1990-06"
+ },
+ {
+ "index": 618,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 3780,
+ "timestamp": "1990-07"
+ },
+ {
+ "index": 619,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 3620,
+ "timestamp": "1990-08"
+ },
+ {
+ "index": 620,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 6700,
+ "timestamp": "1990-09"
+ },
+ {
+ "index": 621,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 3780,
+ "timestamp": "1990-10"
+ },
+ {
+ "index": 622,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 5340,
+ "timestamp": "1990-11"
+ },
+ {
+ "index": 623,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 3280,
+ "timestamp": "1990-12"
+ },
+ {
+ "index": 624,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 4980,
+ "timestamp": "1991-01"
+ },
+ {
+ "index": 625,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 6220,
+ "timestamp": "1991-02"
+ },
+ {
+ "index": 626,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 5400,
+ "timestamp": "1991-03"
+ },
+ {
+ "index": 627,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 5180,
+ "timestamp": "1991-04"
+ },
+ {
+ "index": 628,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 5280,
+ "timestamp": "1991-05"
+ },
+ {
+ "index": 629,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 4460,
+ "timestamp": "1991-06"
+ },
+ {
+ "index": 630,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 2180,
+ "timestamp": "1991-07"
+ },
+ {
+ "index": 631,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 2560,
+ "timestamp": "1991-08"
+ },
+ {
+ "index": 632,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 5280,
+ "timestamp": "1991-09"
+ },
+ {
+ "index": 633,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 4480,
+ "timestamp": "1991-10"
+ },
+ {
+ "index": 634,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 5820,
+ "timestamp": "1991-11"
+ },
+ {
+ "index": 635,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 5720,
+ "timestamp": "1991-12"
+ },
+ {
+ "index": 636,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 8340,
+ "timestamp": "1992-01"
+ },
+ {
+ "index": 637,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 7080,
+ "timestamp": "1992-02"
+ },
+ {
+ "index": 638,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 4160,
+ "timestamp": "1992-03"
+ },
+ {
+ "index": 639,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 2460,
+ "timestamp": "1992-04"
+ },
+ {
+ "index": 640,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 3440,
+ "timestamp": "1992-05"
+ },
+ {
+ "index": 641,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 3120,
+ "timestamp": "1992-06"
+ },
+ {
+ "index": 642,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 3240,
+ "timestamp": "1992-07"
+ },
+ {
+ "index": 643,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 3560,
+ "timestamp": "1992-08"
+ },
+ {
+ "index": 644,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 3260,
+ "timestamp": "1992-09"
+ },
+ {
+ "index": 645,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 4780,
+ "timestamp": "1992-10"
+ },
+ {
+ "index": 646,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 6400,
+ "timestamp": "1992-11"
+ },
+ {
+ "index": 647,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 3880,
+ "timestamp": "1992-12"
+ },
+ {
+ "index": 648,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 5080,
+ "timestamp": "1993-01"
+ },
+ {
+ "index": 649,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 4760,
+ "timestamp": "1993-02"
+ },
+ {
+ "index": 650,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 4460,
+ "timestamp": "1993-03"
+ },
+ {
+ "index": 651,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 7580,
+ "timestamp": "1993-04"
+ },
+ {
+ "index": 652,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 5740,
+ "timestamp": "1993-05"
+ },
+ {
+ "index": 653,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 1780,
+ "timestamp": "1993-06"
+ },
+ {
+ "index": 654,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 1480,
+ "timestamp": "1993-07"
+ },
+ {
+ "index": 655,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 4600,
+ "timestamp": "1993-08"
+ },
+ {
+ "index": 656,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 5440,
+ "timestamp": "1993-09"
+ },
+ {
+ "index": 657,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 5260,
+ "timestamp": "1993-10"
+ },
+ {
+ "index": 658,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 5060,
+ "timestamp": "1993-11"
+ },
+ {
+ "index": 659,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 3460,
+ "timestamp": "1993-12"
+ },
+ {
+ "index": 660,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 6260,
+ "timestamp": "1994-01"
+ },
+ {
+ "index": 661,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 6140,
+ "timestamp": "1994-02"
+ },
+ {
+ "index": 662,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 4380,
+ "timestamp": "1994-03"
+ },
+ {
+ "index": 663,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 5080,
+ "timestamp": "1994-04"
+ },
+ {
+ "index": 664,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 4740,
+ "timestamp": "1994-05"
+ },
+ {
+ "index": 665,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 3800,
+ "timestamp": "1994-06"
+ },
+ {
+ "index": 666,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 5060,
+ "timestamp": "1994-07"
+ },
+ {
+ "index": 667,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 4260,
+ "timestamp": "1994-08"
+ },
+ {
+ "index": 668,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 4540,
+ "timestamp": "1994-09"
+ },
+ {
+ "index": 669,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 2900,
+ "timestamp": "1994-10"
+ },
+ {
+ "index": 670,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 4500,
+ "timestamp": "1994-11"
+ },
+ {
+ "index": 671,
+ "series_id": "M10",
+ "category": "MICRO",
+ "value": 3540,
+ "timestamp": "1994-12"
+ }
+ ]
+ }
+ },
+ "metadata": {
+ "bento_obj_id": "140506663654256"
+ },
+ "execution_count": 90
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "76ad70c9-a218-450b-b9a5-64db698a5ac9",
+ "showInput": false,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "## Plotting the data with time\n",
+ "We visualize the data of one product in M3 in time series."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "originalKey": "720f41b5-20af-404e-a502-cb6b3274cb55",
+ "showInput": true,
+ "customInput": null,
+ "collapsed": false,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "df['timestamp'] = pd.to_datetime(df['timestamp'])\n",
+ "plt.rcParams['figure.figsize'] = 12, 8\n",
+ "sns.lineplot(x='timestamp', y='value', data=df)\n",
+ "plt.xlabel('month')\n",
+ "plt.ylabel('value')\n",
+ ""
+ ],
+ "execution_count": 91,
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stderr",
+ "text": [
+ ":1: SettingWithCopyWarning:\n\n\nA value is trying to be set on a copy of a slice from a DataFrame.\nTry using .loc[row_indexer,col_indexer] = value instead\n\nSee the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n\n"
+ ]
+ },
+ {
+ "output_type": "execute_result",
+ "data": {
+ "text/plain": "Text(0, 0.5, 'value')"
+ },
+ "metadata": {
+ "bento_obj_id": "140506639718336"
+ },
+ "execution_count": 91
+ },
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": "",
+ "image/png": "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\n"
+ },
+ "metadata": {
+ "bento_obj_id": "140506640048240",
+ "needs_background": "light"
+ }
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "91c197e9-f13a-4108-90a0-fbe6df9b0d70",
+ "showInput": false,
+ "customInput": null
+ },
+ "source": [
+ "## Plotting the auto-correlation\n",
+ "We plot the auto correlcation function below."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "originalKey": "1827f3b2-21e8-4aaf-b2c8-f557143ff8ea",
+ "showInput": true,
+ "customInput": null,
+ "collapsed": false
+ },
+ "source": [
+ "from statsmodels.graphics.tsaplots import plot_acf\n",
+ "\n",
+ "acf = plot_acf(df['timestamp'])"
+ ],
+ "execution_count": 92,
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": "",
+ "image/png": "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ko6YmUEuNtP0yXbceyRdFPjewZW2r+d4AAAAQCtLc4z2J0xv8+OSTkl6r6SbAt87YtbvMUG53u1XWg8AAAC0rFSm92tBTXlTDB1Jplt/1bVWtFsytFsytFsytFsytFsy3dpuTR460pDp/QAAAADEELQBAACADBC0AQAAgAwQtAEAAIAMELQBAACADBC0AQAAgAwQtAEAAIAMELQBAACADBC0AQAAgAwQtAEAAIAMELQBAACADBC0AQAAgAwQtAEAAIAMELQBAACADBC0AQAAgAwQtAEAAIAMELQBAACADBC0AQAAgAwQtAEAAIAMELQBAACADBC0AQAAgAwQtAEAAIAMELQBAACADBC0AQAAgAwQtAEAAIAMELQBAACADBC0AQAAgAwQtAEAAIAMELQBAACADBC0AQAAgAwQtAEAAIAMELQBAACADBC0AQAAgAwQtAEAAIAMELQBAACADBC0AQAAgAwQtAEAAIAMELQBAACADBC0AQAAgAwQtAEAAIAMELQBAACADPSkcRDbcddLulfSrZK2SHpG0l2B7z22zD4XSPq8pPdKWm/2+dnA975q1r8kaa+kcs2uBwLfey6N6wYAAACykkrQlnS/pHdKul7SEUkfk/So7bgHAt87vMQ+fyLptKSrJZ2R9BlJj9iOe2nge8fNNrcHvvdgStfY0jb0SZvXWTo7GzX7UgAAAJCCNQ8dsR13h6TbJH0q8L1Dge9NBb53n6TvmMC92D7VXu9PBL43HPjerOnd3ijpHWu9pnbUm7d05VBO+3bkJKvZVwMAAIC1SqNH+xpznK/XLH9iqdAc+N6EpB+rWfxa83g8tuxW23E/JWlI0mFJnw1875EUrrklWZalfdstbVtv6fDJULNFercBAADa1YpB23bcHkmbltlkt3kcrVk+ImmwnoswPdxflPRo4Hv/YBY/LekFSR+VdFbSHZIeth332sD3/n65442dGlZYDus5dapKpaJGho/XseXK9vZIL09aGpnq/PtVy+WSxsdqvz5YCe2WDO2WDO2WDO2WDO2WTLe2W19PpJG+5LlvLfltYHBo2fX19GhfJylYZv3BJZZbklbskrUd92JJj0g6KelHqssD3/tAzaZ32457swneywbtHbvqyvepGxk+vmKDr8YFQ9LIZKjvjoQq1d4S2kHGx0a1dcfOZl9G26HdkqHdkqHdkqHdkqHd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\n"
+ },
+ "metadata": {
+ "bento_obj_id": "140506663587264",
+ "needs_background": "light"
+ }
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "b7d43a5c-8d9a-43e4-b682-62cd3b07ce4f",
+ "showInput": false,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "## Data transformation\n",
+ "We prepare the training set and test set data with normalizaton."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "originalKey": "967e73a4-ede4-47fe-aabf-1e04386cd7bd",
+ "showInput": true,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": [],
+ "collapsed": false
+ },
+ "source": [
+ "from sts.data import df_to_tensor\n",
+ "\n",
+ "df_convert_fns = {\n",
+ " 'timestamp': lambda x: (x - x.iloc[0]).dt.days\n",
+ "}\n",
+ "\n",
+ "df['log_value'] = np.log(df['value'])\n",
+ "df = df[['timestamp','value','log_value']]\n",
+ "\n",
+ "data = df_to_tensor(df, normalize_cols=True, df_convert_fns=df_convert_fns)\n",
+ "num_trainset = len(df)-num_test\n",
+ "x_train = data[:num_trainset, ['timestamp']]\n",
+ "y_train = data[:num_trainset, 'log_value']\n",
+ "x_test = data[num_trainset:, ['timestamp']]\n",
+ "y_test = data[num_trainset:, 'value']\n",
+ ""
+ ],
+ "execution_count": 93,
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stderr",
+ "text": [
+ ":7: SettingWithCopyWarning:\n\n\nA value is trying to be set on a copy of a slice from a DataFrame.\nTry using .loc[row_indexer,col_indexer] = value instead\n\nSee the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n\n"
+ ]
+ }
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "originalKey": "f4bbab2a-de59-4ca3-b1d1-22cfa176fea6",
+ "showInput": true,
+ "customInput": null,
+ "collapsed": false,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "from sts.gp.model import AdditiveSpectralMixtureTimeSeriesExactGPModel\n",
+ "from sts.gp.kernel import WhiteNoiseKernel\n",
+ "from gpytorch.kernels import LinearKernel, RBFKernel\n",
+ "\n",
+ "likelihood = gp.likelihoods.GaussianLikelihood()\n",
+ "model = AdditiveSpectralMixtureTimeSeriesExactGPModel(x_train, y_train, likelihood)\n",
+ "model.cov.add_seasonality(\n",
+ " time_axis=\"timestamp\", period_length=365.25, fix_period=True\n",
+ " )\n",
+ "model.cov.add_trend(\n",
+ " time_axis=\"timestamp\", kernel_cls=LinearKernel, name=\"LinearTrend\"\n",
+ ")\n",
+ "model.cov.add_trend(\n",
+ " time_axis=\"timestamp\",\n",
+ " kernel_cls=RBFKernel,\n",
+ " lengthscale=100,\n",
+ " fix_lengthscale=True,\n",
+ " name=\"RBFTrend\",\n",
+ ")\n",
+ "model.cov.add_spectral_mixture(\n",
+ " time_axis=\"timestamp\",\n",
+ " num_mixtures=2,\n",
+ " train_x=x_train.tensor,\n",
+ " train_y=y_train.tensor,\n",
+ " name=\"SM1\",\n",
+ ")\n",
+ "model.cov.add_spectral_mixture(\n",
+ " time_axis=\"timestamp\",\n",
+ " num_mixtures=2,\n",
+ " train_x=x_train.tensor,\n",
+ " train_y=y_train.tensor,\n",
+ " name=\"SM2\",\n",
+ ")\n",
+ ""
+ ],
+ "execution_count": 94,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "91e3e08a-9580-45e7-ae3d-7ea094d014e9",
+ "showInput": false,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "# Training loop\n",
+ "We train our model with our training set, and show the training time below."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "originalKey": "7b25842b-cd70-4e8b-8420-e06490104b13",
+ "showInput": true,
+ "customInput": null,
+ "collapsed": false,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "learning_rate = 0.01\n",
+ "num_epochs = 3000\n",
+ "trainer = model.train_init(torch.optim.Adam(model.trainable_params, lr=learning_rate))\n",
+ "\n",
+ "def train():\n",
+ " for epoch in range(num_epochs):\n",
+ " loss = trainer(x_train, y_train)\n",
+ " if (epoch + 1) % 200 == 1:\n",
+ " print(f'epoch {epoch+1}/{num_epochs}, loss {loss}')\n",
+ "\n",
+ "%time train()"
+ ],
+ "execution_count": 95,
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stderr",
+ "text": [
+ "/mnt/xarfuse/uid-353778/4490d57c-seed-nspid4026531836_cgpid99683980-ns-4026531840/gpytorch/utils/cholesky.py:44: NumericalWarning:\n\nA not p.d., added jitter of 1.0e-06 to the diagonal\n\n/mnt/xarfuse/uid-353778/4490d57c-seed-nspid4026531836_cgpid99683980-ns-4026531840/gpytorch/utils/cholesky.py:44: NumericalWarning:\n\nA not p.d., added jitter of 1.0e-05 to the diagonal\n\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 1/3000, loss 1.696009874343872\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 201/3000, loss 1.3974676132202148\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 401/3000, loss 1.2631440162658691\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 601/3000, loss 1.2498987913131714\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 801/3000, loss 1.247230887413025\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 1001/3000, loss 1.2462594509124756\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 1201/3000, loss 1.2457836866378784\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 1401/3000, loss 1.2451318502426147\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 1601/3000, loss 1.2099428176879883\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 1801/3000, loss 1.1965670585632324\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 2001/3000, loss 1.195930004119873\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 2201/3000, loss 1.195489764213562\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 2401/3000, loss 1.1951385736465454\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 2601/3000, loss 1.1948914527893066\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 2801/3000, loss 1.1947181224822998\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "CPU times: user 7min 44s, sys: 4min 58s, total: 12min 42s\nWall time: 35.3 s\n"
+ ]
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "a9316bc6-5cd5-4d0e-bfa4-7de704e5a5e2",
+ "showInput": false,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "# Predictions\n",
+ "We use our model to forecast the test set.\n",
+ "\n",
+ ""
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "originalKey": "6bb0f25d-a30f-4953-9eae-70b80240e9a5",
+ "showInput": true,
+ "code_folding": [],
+ "hidden_ranges": [],
+ "collapsed": false
+ },
+ "source": [
+ "from sts.data import get_mvn_stats\n",
+ "from torch.distributions import ComposeTransform, ExpTransform\n",
+ "\n",
+ "transform = ComposeTransform([y_train.transforms['log_value'].inv, ExpTransform()])\n",
+ "train_mean, train_var, train_ci = get_mvn_stats(model.predict(x_train), transform)\n",
+ "test_mean, test_var, test_ci = get_mvn_stats(model.predict(x_test), transform)\n",
+ "\n",
+ "f, ax = plt.subplots(1, 1, figsize=(12, 5))\n",
+ "ax.plot(df['timestamp'][:num_trainset], train_mean, alpha=0.8, color='blue', linewidth=1, label='train')\n",
+ "ax.plot(df['timestamp'][num_trainset:], test_mean, alpha=0.8, color='green', linewidth=1, label='test')\n",
+ "ax.plot(df['timestamp'], df['value'], 'o', markersize=1, color='black', label='actual')\n",
+ "ax.fill_between(df['timestamp'], torch.cat([train_ci[0], test_ci[0]]), torch.cat([train_ci[1], test_ci[1]]), alpha=0.2, label='ci', color='gray')\n",
+ "ax.legend()\n",
+ ""
+ ],
+ "execution_count": 96,
+ "outputs": [
+ {
+ "output_type": "execute_result",
+ "data": {
+ "text/plain": ""
+ },
+ "metadata": {
+ "bento_obj_id": "140506739301920"
+ },
+ "execution_count": 96
+ },
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": "",
+ "image/png": "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\n"
+ },
+ "metadata": {
+ "bento_obj_id": "140506678976624",
+ "needs_background": "light"
+ }
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "89198390-d8be-408c-b9e9-6945ab0ef2a3",
+ "showInput": false,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "The training set has tight credible intervals, while that of the test set is wider. This makes sense since the credible interval gets larger if we extrapolate from the data. But still, we would like to see better performance in the forecasting part.\n",
+ ""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "aa090d07-f404-49f6-b950-81155f5cb732",
+ "showInput": false,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "# Kernel Decomposition\n",
+ "We decompose additive kernels to see how each kernel functions."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "originalKey": "723c5448-ae4c-4239-afca-1da8daf35dec",
+ "showInput": true,
+ "customInput": null,
+ "collapsed": false,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "from sts.gp.graph import plot_components\n",
+ "\n",
+ "x_all = torch.cat([x_train.tensor, x_test.tensor])\n",
+ "components = model.decompose_timeseries(x_all)\n",
+ "fig, ax = plot_components(df['timestamp'], components[1], y=model.predict(x_all), transform=transform)"
+ ],
+ "execution_count": 97,
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": "",
+ "image/png": "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\n"
+ },
+ "metadata": {
+ "bento_obj_id": "140506664325952",
+ "needs_background": "light"
+ }
+ },
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": "",
+ "image/png": "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\n"
+ },
+ "metadata": {
+ "bento_obj_id": "140506869730368",
+ "needs_background": "light"
+ }
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "c208c2b1-d37b-48d9-944a-98136b2ec86e",
+ "showInput": false,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "# Evaluation\n",
+ "We measure mean absolute error (MAE), continuous-ranked probability score (CRPS), and log-likelihood (LL) using normalized values on both of the training set and the test set."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "originalKey": "9f54f0e1-82cf-4ca4-b60b-76d7ce56e567",
+ "showInput": true,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": [],
+ "collapsed": false
+ },
+ "source": [
+ "train_mean, train_var, train_ci = get_mvn_stats(model.predict(x_train))\n",
+ "test_mean, test_var, test_ci = get_mvn_stats(model.predict(x_test))\n",
+ ""
+ ],
+ "execution_count": 98,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "21572862-5c2a-4a6c-be91-a26a4b1f6d77",
+ "showInput": false,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "Here we compute MAE for both training data and test data."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "originalKey": "0904849e-2165-454b-84a2-b0da1b15004e",
+ "showInput": true,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": [],
+ "collapsed": false
+ },
+ "source": [
+ "from sts.metrics import MAE\n",
+ "MAE_train = MAE(y_train.tensor, train_mean).item()\n",
+ "MAE_test = MAE(y_test.tensor, test_mean).item()\n",
+ "print(f'Mean absolute error for training set is: {MAE_train:.3f}')\n",
+ "print(f'Mean absolute error for test set is: {MAE_test:.3f}')"
+ ],
+ "execution_count": 99,
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "Mean absolute error for training set is: 0.002\nMean absolute error for test set is: 0.813\n"
+ ]
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "9cf3aa6f-3e5f-48d8-9d0a-8523e36148e1",
+ "showInput": false,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "Here we compute CRPS for both training data and test data."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "originalKey": "c03acc57-9792-41ad-9902-1a222137644d",
+ "showInput": true,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": [],
+ "collapsed": false
+ },
+ "source": [
+ "from sts.crps import crps_gaussian\n",
+ "crps_train = crps_gaussian(y_train.tensor, train_mean, train_var.sqrt())\n",
+ "crps_test = crps_gaussian(y_test.tensor, test_mean, test_var.sqrt())\n",
+ "print(f'Continuous ranked probability score for training set is: {crps_train.mean().item():.3f}')\n",
+ "print(f'Continuous ranked probability score for test set is: {crps_test.mean().item():.3f}')"
+ ],
+ "execution_count": 100,
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "Continuous ranked probability score for training set is: 0.010\nContinuous ranked probability score for test set is: 0.596\n"
+ ]
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "9bddcd7a-e61b-41fa-9613-751e3d6df135",
+ "showInput": false,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "Here we compute log-likelihood for both training data and test data.\n",
+ "\n",
+ ""
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "originalKey": "09d02e09-3af3-4950-aa1a-3275afac405c",
+ "showInput": true,
+ "customInput": null,
+ "collapsed": false,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "from sts.metrics import log_likelihood_error\n",
+ "ll_train = log_likelihood_error(train_mean, y_train.tensor, train_var).item()\n",
+ "ll_test = log_likelihood_error(test_mean, y_test.tensor, test_var).item()\n",
+ "print(f'Log-likelihood for training set is: {ll_train:.3f}')\n",
+ "print(f'Log-likelihood for test set is: {ll_test:.3f}')"
+ ],
+ "execution_count": 101,
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "Log-likelihood for training set is: 2.231\nLog-likelihood for test set is: -1.517\n"
+ ]
+ }
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "originalKey": "38510b7b-d7a6-453e-87cf-efa1ede52d98",
+ "showInput": true,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": [],
+ "collapsed": false
+ },
+ "source": [
+ "scores = [[MAE_train, crps_train.mean().item(), ll_train], [MAE_test, crps_test.mean().item(), ll_test]]\n",
+ "df_meature = pd.DataFrame(scores, columns = ['MAE', 'CPRS', 'LL'])\n",
+ "df_meature"
+ ],
+ "execution_count": 102,
+ "outputs": [
+ {
+ "output_type": "execute_result",
+ "data": {
+ "text/plain": " MAE CPRS LL\n0 0.001731 0.010051 2.230578\n1 0.812689 0.596490 -1.516943",
+ "text/html": "\n\n
\n \n \n | \n MAE | \n CPRS | \n LL | \n
\n \n \n \n | 0 | \n 0.001731 | \n 0.010051 | \n 2.230578 | \n
\n \n | 1 | \n 0.812689 | \n 0.596490 | \n -1.516943 | \n
\n \n
\n
",
+ "application/vnd.dataresource+json": {
+ "schema": {
+ "fields": [
+ {
+ "name": "index",
+ "type": "integer"
+ },
+ {
+ "name": "MAE",
+ "type": "number"
+ },
+ {
+ "name": "CPRS",
+ "type": "number"
+ },
+ {
+ "name": "LL",
+ "type": "number"
+ }
+ ],
+ "primaryKey": [
+ "index"
+ ],
+ "pandas_version": "0.20.0"
+ },
+ "data": [
+ {
+ "index": 0,
+ "MAE": 0.0017308004,
+ "CPRS": 0.0100507997,
+ "LL": 2.2305777073
+ },
+ {
+ "index": 1,
+ "MAE": 0.8126885891,
+ "CPRS": 0.5964896083,
+ "LL": -1.5169430971
+ }
+ ]
+ }
+ },
+ "metadata": {
+ "bento_obj_id": "140506678926352"
+ },
+ "execution_count": 102
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "6d3a0ec0-caf9-4d23-8390-6763ef19f0e9",
+ "showInput": false,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "Above is the table showing the values of each metrics, where the first line is for the training set and the second line is for the test set. As a kind reminder, MAE and CRPS are better if they are lower, while LL is better when it's higher.\n",
+ "\n",
+ "\n",
+ "At the same time, we noticed the training set shows higher accuracy than the test set. To improve this, we will assign priors to the hyperparameters and use the hierarchical priors to gain joint information of univarite time series."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "fbe083b5-4875-43bc-b971-2e434f08aa29",
+ "showInput": false,
+ "customInput": null,
+ "collapsed": false,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "# References\n",
+ "\n",
+ "[1] Corani, G., Benavoli, A., Augusto, J. and Zaffalon, M., 2020. Automatic Forecasting using Gaussian Processes. arXiv preprint arXiv:2009.08102."
+ ],
+ "attachments": {}
+ }
+ ]
+}
diff --git a/src/beanmachine/ppl/experimental/timeseries/notebooks/GP_timeseries_CO2.ipynb b/src/beanmachine/ppl/experimental/timeseries/notebooks/GP_timeseries_CO2.ipynb
new file mode 100644
index 0000000000..c74abec258
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/notebooks/GP_timeseries_CO2.ipynb
@@ -0,0 +1,1250 @@
+{
+ "metadata": {
+ "bento_stylesheets": {
+ "bento/extensions/flow/main.css": true,
+ "bento/extensions/kernel_selector/main.css": true,
+ "bento/extensions/kernel_ui/main.css": true,
+ "bento/extensions/new_kernel/main.css": true,
+ "bento/extensions/system_usage/main.css": true,
+ "bento/extensions/theme/main.css": true
+ },
+ "kernelspec": {
+ "display_name": "bm_timeseries (local)",
+ "language": "python",
+ "name": "bm_timeseries_local",
+ "metadata": {
+ "is_prebuilt": false,
+ "kernel_name": "bm_timeseries_local"
+ }
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2,
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "f8ccf010-bec6-4bba-9e9f-4a0f9dfceb0e",
+ "showInput": false,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "In this tutorial, we will model CO2 with gaussian process."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "collapsed": false,
+ "originalKey": "211f80db-dd12-48b2-9a45-e3752b6ac1ad",
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "import matplotlib\n",
+ "import matplotlib.pyplot as plt \n",
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "import seaborn as sns\n",
+ "import torch\n",
+ "import gpytorch as gp"
+ ],
+ "execution_count": 472,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "2791a776-8fc9-468c-8336-c92ca7dfbe6f",
+ "showInput": false,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "# Data loading and visualization\n",
+ "The data is available at the following path."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "originalKey": "59e71900-fca1-4a77-b8a8-77795cb6d983",
+ "showInput": true,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": [],
+ "collapsed": false
+ },
+ "source": [
+ "df = pd.read_csv('/mnt/persistent-public/zhencao/co2_mm_gl.csv', comment='#', usecols=['decimal', 'average'])\n",
+ "df"
+ ],
+ "execution_count": 473,
+ "outputs": [
+ {
+ "output_type": "execute_result",
+ "data": {
+ "text/plain": " decimal average\n0 1980.042 338.55\n1 1980.125 339.27\n2 1980.208 339.60\n3 1980.292 340.00\n4 1980.375 340.43\n.. ... ...\n489 2020.792 411.71\n490 2020.875 413.25\n491 2020.958 414.18\n492 2021.042 414.95\n493 2021.125 415.88\n\n[494 rows x 2 columns]",
+ "text/html": "\n\n
\n \n \n | \n decimal | \n average | \n
\n \n \n \n | 0 | \n 1980.042 | \n 338.55 | \n
\n \n | 1 | \n 1980.125 | \n 339.27 | \n
\n \n | 2 | \n 1980.208 | \n 339.60 | \n
\n \n | 3 | \n 1980.292 | \n 340.00 | \n
\n \n | 4 | \n 1980.375 | \n 340.43 | \n
\n \n | ... | \n ... | \n ... | \n
\n \n | 489 | \n 2020.792 | \n 411.71 | \n
\n \n | 490 | \n 2020.875 | \n 413.25 | \n
\n \n | 491 | \n 2020.958 | \n 414.18 | \n
\n \n | 492 | \n 2021.042 | \n 414.95 | \n
\n \n | 493 | \n 2021.125 | \n 415.88 | \n
\n \n
\n
494 rows × 2 columns
\n
",
+ "application/vnd.dataresource+json": {
+ "schema": {
+ "fields": [
+ {
+ "name": "index",
+ "type": "integer"
+ },
+ {
+ "name": "decimal",
+ "type": "number"
+ },
+ {
+ "name": "average",
+ "type": "number"
+ }
+ ],
+ "primaryKey": [
+ "index"
+ ],
+ "pandas_version": "0.20.0"
+ },
+ "data": [
+ {
+ "index": 0,
+ "decimal": 1980.042,
+ "average": 338.55
+ },
+ {
+ "index": 1,
+ "decimal": 1980.125,
+ "average": 339.27
+ },
+ {
+ "index": 2,
+ "decimal": 1980.208,
+ "average": 339.6
+ },
+ {
+ "index": 3,
+ "decimal": 1980.292,
+ "average": 340
+ },
+ {
+ "index": 4,
+ "decimal": 1980.375,
+ "average": 340.43
+ },
+ {
+ "index": 5,
+ "decimal": 1980.458,
+ "average": 339.99
+ },
+ {
+ "index": 6,
+ "decimal": 1980.542,
+ "average": 338.45
+ },
+ {
+ "index": 7,
+ "decimal": 1980.625,
+ "average": 337.22
+ },
+ {
+ "index": 8,
+ "decimal": 1980.708,
+ "average": 337.06
+ },
+ {
+ "index": 9,
+ "decimal": 1980.792,
+ "average": 337.83
+ },
+ {
+ "index": 10,
+ "decimal": 1980.875,
+ "average": 338.93
+ },
+ {
+ "index": 11,
+ "decimal": 1980.958,
+ "average": 339.64
+ },
+ {
+ "index": 12,
+ "decimal": 1981.042,
+ "average": 340.18
+ },
+ {
+ "index": 13,
+ "decimal": 1981.125,
+ "average": 340.75
+ },
+ {
+ "index": 14,
+ "decimal": 1981.208,
+ "average": 341.38
+ },
+ {
+ "index": 15,
+ "decimal": 1981.292,
+ "average": 341.68
+ },
+ {
+ "index": 16,
+ "decimal": 1981.375,
+ "average": 341.42
+ },
+ {
+ "index": 17,
+ "decimal": 1981.458,
+ "average": 340.62
+ },
+ {
+ "index": 18,
+ "decimal": 1981.542,
+ "average": 339.22
+ },
+ {
+ "index": 19,
+ "decimal": 1981.625,
+ "average": 338.07
+ },
+ {
+ "index": 20,
+ "decimal": 1981.708,
+ "average": 337.97
+ },
+ {
+ "index": 21,
+ "decimal": 1981.792,
+ "average": 339.07
+ },
+ {
+ "index": 22,
+ "decimal": 1981.875,
+ "average": 340.17
+ },
+ {
+ "index": 23,
+ "decimal": 1981.958,
+ "average": 340.74
+ },
+ {
+ "index": 24,
+ "decimal": 1982.042,
+ "average": 341.37
+ },
+ {
+ "index": 25,
+ "decimal": 1982.125,
+ "average": 341.95
+ },
+ {
+ "index": 26,
+ "decimal": 1982.208,
+ "average": 342.23
+ },
+ {
+ "index": 27,
+ "decimal": 1982.292,
+ "average": 342.52
+ },
+ {
+ "index": 28,
+ "decimal": 1982.375,
+ "average": 342.36
+ },
+ {
+ "index": 29,
+ "decimal": 1982.458,
+ "average": 341.49
+ },
+ {
+ "index": 30,
+ "decimal": 1982.542,
+ "average": 339.75
+ },
+ {
+ "index": 31,
+ "decimal": 1982.625,
+ "average": 338.11
+ },
+ {
+ "index": 32,
+ "decimal": 1982.708,
+ "average": 338.16
+ },
+ {
+ "index": 33,
+ "decimal": 1982.792,
+ "average": 339.62
+ },
+ {
+ "index": 34,
+ "decimal": 1982.875,
+ "average": 340.95
+ },
+ {
+ "index": 35,
+ "decimal": 1982.958,
+ "average": 341.77
+ },
+ {
+ "index": 36,
+ "decimal": 1983.042,
+ "average": 342.36
+ },
+ {
+ "index": 37,
+ "decimal": 1983.125,
+ "average": 342.74
+ },
+ {
+ "index": 38,
+ "decimal": 1983.208,
+ "average": 343.04
+ },
+ {
+ "index": 39,
+ "decimal": 1983.292,
+ "average": 343.51
+ },
+ {
+ "index": 40,
+ "decimal": 1983.375,
+ "average": 343.83
+ },
+ {
+ "index": 41,
+ "decimal": 1983.458,
+ "average": 343.5
+ },
+ {
+ "index": 42,
+ "decimal": 1983.542,
+ "average": 342.13
+ },
+ {
+ "index": 43,
+ "decimal": 1983.625,
+ "average": 340.62
+ },
+ {
+ "index": 44,
+ "decimal": 1983.708,
+ "average": 340.54
+ },
+ {
+ "index": 45,
+ "decimal": 1983.792,
+ "average": 341.75
+ },
+ {
+ "index": 46,
+ "decimal": 1983.875,
+ "average": 342.81
+ },
+ {
+ "index": 47,
+ "decimal": 1983.958,
+ "average": 343.48
+ },
+ {
+ "index": 48,
+ "decimal": 1984.042,
+ "average": 344.32
+ },
+ {
+ "index": 49,
+ "decimal": 1984.125,
+ "average": 344.83
+ },
+ {
+ "index": 50,
+ "decimal": 1984.208,
+ "average": 344.96
+ },
+ {
+ "index": 51,
+ "decimal": 1984.292,
+ "average": 345.19
+ },
+ {
+ "index": 52,
+ "decimal": 1984.375,
+ "average": 345.34
+ },
+ {
+ "index": 53,
+ "decimal": 1984.458,
+ "average": 344.57
+ },
+ {
+ "index": 54,
+ "decimal": 1984.542,
+ "average": 343.2
+ },
+ {
+ "index": 55,
+ "decimal": 1984.625,
+ "average": 342.21
+ },
+ {
+ "index": 56,
+ "decimal": 1984.708,
+ "average": 342.13
+ },
+ {
+ "index": 57,
+ "decimal": 1984.792,
+ "average": 342.99
+ },
+ {
+ "index": 58,
+ "decimal": 1984.875,
+ "average": 344.16
+ },
+ {
+ "index": 59,
+ "decimal": 1984.958,
+ "average": 345.01
+ }
+ ]
+ }
+ },
+ "metadata": {
+ "bento_obj_id": "139728170765856"
+ },
+ "execution_count": 473
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "a5e27ea9-0a84-4fc0-815b-b2991e807aeb",
+ "showInput": false,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "## Plotting the data with time\n",
+ "We visualize the data of CO2 in time series. We can identify the data has some periodicity and the trend of going up with time."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "originalKey": "c0b5b261-288e-40e3-9fbe-500c8c0eb09c",
+ "showInput": true,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": [],
+ "collapsed": false
+ },
+ "source": [
+ "plt.rcParams['figure.figsize'] = 16, 8\n",
+ "sns.lineplot(x='decimal', y='average', data=df)\n",
+ "plt.xlabel('Month')\n",
+ "plt.ylabel('Average CO2')"
+ ],
+ "execution_count": 474,
+ "outputs": [
+ {
+ "output_type": "execute_result",
+ "data": {
+ "text/plain": "Text(0, 0.5, 'Average CO2')"
+ },
+ "metadata": {
+ "bento_obj_id": "139727917684336"
+ },
+ "execution_count": 474
+ },
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": "",
+ "image/png": "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\n"
+ },
+ "metadata": {
+ "bento_obj_id": "139729207122624",
+ "needs_background": "light"
+ }
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "d41aac36-ff79-4f7c-bffb-0ebae16f5eb4",
+ "showInput": false,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "## Plotting the auto-correlation\n",
+ "We plot the auto correlcation function below."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "originalKey": "1707a8c6-2776-49d4-a0b3-9069edb68271",
+ "showInput": true,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": [],
+ "collapsed": false
+ },
+ "source": [
+ "from statsmodels.graphics.tsaplots import plot_acf\n",
+ "_ = plot_acf(df['average'], lags=100)\n",
+ ""
+ ],
+ "execution_count": 475,
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": "",
+ "image/png": "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\n"
+ },
+ "metadata": {
+ "bento_obj_id": "139729206060752",
+ "needs_background": "light"
+ }
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "ea52f23f-93cf-4380-8d51-1b1a9de52d61",
+ "showInput": false,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "We prepare the training set and test set data with normalizaton."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "originalKey": "4050feb7-82cf-444d-88d6-dbc1210c249a",
+ "showInput": true,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": [],
+ "collapsed": false
+ },
+ "source": [
+ "from sts.data import df_to_tensor\n",
+ "\n",
+ "df_convert_fns = {\n",
+ " 'decimal': lambda x: (x - x.iloc[0])\n",
+ "}\n",
+ "df['log_average'] = np.log(df['average'])\n",
+ "data = df_to_tensor(df, normalize_cols=True, df_convert_fns=df_convert_fns)\n",
+ ""
+ ],
+ "execution_count": 476,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "originalKey": "39af729f-66d1-4a11-bc48-0f1f667e2752",
+ "showInput": true,
+ "customInput": null,
+ "collapsed": false,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "num_trainset = 400\n",
+ "train_x = data[:num_trainset, ['decimal']]\n",
+ "train_y = data[:num_trainset, 'log_average']\n",
+ "test_x = data[num_trainset:, ['decimal']]\n",
+ "test_y = data[num_trainset:, 'log_average']\n",
+ "print(train_x.shape, train_y.shape, test_x.shape, test_y.shape)"
+ ],
+ "execution_count": 477,
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "torch.Size([400, 1]) torch.Size([400]) torch.Size([94, 1]) torch.Size([94])\n"
+ ]
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "1944d04a-2456-4319-855f-ad4454a98e1f",
+ "showInput": false,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "# Model Defining\n",
+ "We define the model as the addition of kernels of seasonality (periordic) and trend (RBF)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "originalKey": "bacb1f70-f962-42c3-96fe-b80036aabc31",
+ "showInput": true,
+ "customInput": null,
+ "collapsed": false,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "from sts.gp.model import TimeSeriesExactGPModel\n",
+ "likelihood = gp.likelihoods.GaussianLikelihood()\n",
+ "model = TimeSeriesExactGPModel(train_x, train_y, likelihood)\n",
+ "model.cov.add_seasonality(time_axis='decimal', period_length=1, fix_period=True)\n",
+ "model.cov.add_trend(time_axis='decimal', lengthscale=100, fix_lengthscale=True)"
+ ],
+ "execution_count": 478,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "c6c6c830-8b19-4ccb-a568-3eee3a9db99a",
+ "showInput": false,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "# Training loop\n",
+ "We train our model with our training set."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "originalKey": "4cec3eba-1081-49d5-a2fc-083ec9a145b1",
+ "showInput": true,
+ "customInput": null,
+ "collapsed": false,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "learning_rate = 0.01\n",
+ "num_epochs = 1000\n",
+ "trainer = model.train_init(torch.optim.Adam(model.trainable_params, lr=learning_rate))"
+ ],
+ "execution_count": 479,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "originalKey": "b6d06144-29af-424b-8520-1eaff34f293f",
+ "showInput": true,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": [],
+ "collapsed": false
+ },
+ "source": [
+ "for epoch in range(num_epochs):\n",
+ " loss = trainer(train_x, train_y)\n",
+ " if (epoch + 1) % 100 == 1:\n",
+ " print(f'epoch {epoch+1}/{num_epochs}, loss {loss}')"
+ ],
+ "execution_count": 480,
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 1/1000, loss 0.8648936748504639\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 101/1000, loss 0.4206523895263672\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 201/1000, loss -0.08528365939855576\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 301/1000, loss -0.6039102673530579\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 401/1000, loss -1.0966287851333618\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 501/1000, loss -1.5163153409957886\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 601/1000, loss -1.79926335811615\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 701/1000, loss -1.9237152338027954\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 801/1000, loss -1.95598566532135\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 901/1000, loss -1.9616998434066772\n"
+ ]
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "d5253afa-730e-4e31-a29d-0b98982d861e",
+ "showInput": false,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "# Predictions\n",
+ "We use our model to forecast the test set.\n",
+ "\n",
+ "As we can see, the mean of our model is lower than the actual observations, while still in the credible interval."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "originalKey": "ebe4dec5-5e93-47f0-90f1-77308ba825b0",
+ "showInput": true,
+ "customInput": null,
+ "collapsed": false,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "from sts.data import get_mvn_stats\n",
+ "from torch.distributions import ComposeTransform, ExpTransform\n",
+ "\n",
+ "transform = ComposeTransform([train_y.transforms['log_average'].inv, ExpTransform()])\n",
+ "train_mean, train_var, train_ci = get_mvn_stats(model.predict(train_x), transform)\n",
+ "test_mean, test_var, test_ci = get_mvn_stats(model.predict(test_x), transform)\n",
+ ""
+ ],
+ "execution_count": 481,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "originalKey": "afabce35-24ab-465d-b886-c383e734a23f",
+ "showInput": true,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": [],
+ "collapsed": false
+ },
+ "source": [
+ "f, ax = plt.subplots(1, 1, figsize=(12, 5))\n",
+ "ax.plot(df['decimal'][:num_trainset], train_mean, alpha=0.8, color='blue', linewidth=0.5, label='train')\n",
+ "ax.plot(df['decimal'][num_trainset:], test_mean, alpha=0.8, color='green', linewidth=0.5, label='test')\n",
+ "ax.plot(df['decimal'], df['average'], 'o', markersize=0.2, color='black', label='actual')\n",
+ "ax.fill_between(df['decimal'], torch.cat([train_ci[0], test_ci[0]]), torch.cat([train_ci[1], test_ci[1]]), alpha=0.2, label='ci', color='gray')\n",
+ "ax.legend()"
+ ],
+ "execution_count": 482,
+ "outputs": [
+ {
+ "output_type": "execute_result",
+ "data": {
+ "text/plain": ""
+ },
+ "metadata": {
+ "bento_obj_id": "139727447014800"
+ },
+ "execution_count": 482
+ },
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": "",
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAswAAAEyCAYAAADuoYbuAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8li6FKAAAgAElEQVR4nOzdeXxU5dXA8d+dfc1kmWwk4IKKiqDV1v1ttRqXVKupS9VKRUDAfatWrdbauuCGVgXUal3autS+xmpN65sKdau7FhSURWUz20wmmcyWmbnL+0cmU0K2CSYkwPl+Pnwg9z73znPxgocn5zlHMQwDIYQQQgghRN9Moz0BIYQQQgghxjIJmIUQQgghhBiABMxCCCGEEEIMQAJmIYQQQgghBiABsxBCCCGEEAOQgFkIIYQQQogBWEZ7AjkYlbp3oUAThcVlo/HRYjsk75MYTvI+ieEk75MYTtv4+6T0d0JWmPuha/poT0FsR+R9EsNJ3icxnOR9EsNpe32fJGAWQgghhBBiABIwCyGEEEIIMQAJmIUQQgghhBjAtrDprxfDMAiFQuj6yOXJdKZUAoHAiN1/S5hMJgoLC1GUfnPShRBCCCHEMNsmA+ZQKITb7cbhcIzYZ6TTKaxW24jdf0t0dnYSCoUoKioa7akIIYQQQuwwtsmUDF3XRzRYHqscDseIrqoLIYQQQojetsmAWQghhBBCiK1FAuYt9Mabb+c0buFDj9LY1Dzi8xFCCCGEECNDAuYt0NTcwpLX3sh+PVCaxAVzZlJeVrqVZiaEEEIIIYbbNrnpb7Tdv/BhVq5czTE/+BHfP+K7NDU3c8dtv2b+vQtoaQmQTKWYdtbpHHzQd7jy59dz0fnn8fnK1az4bCXt4TAbNmzkjNN/xHHHHD3ajyKEEEIIMabEYjHcbvdoT6MHWWHeAqefcjJTp0zm7DNPR9M17r3rNmKxGFP22Zv5d97CDdddxZN/eqbHNSaTibVr1/Gr63/OTb+8lhderBu1+QshhBBCjEWxWIz58+cTi8VGeyo9yArzNzRp990AcLvdrPniSy6/6joAOjoivcbutdckzGYzJcX+MfciCCGEEEKMNrfbzRVXXDHmVpi3i4D5pZegsXH47ldeDscdl9tYi9UKwOIlrxOJRJl/xy20t4e5+PKre401m83ZXxuGMXwTFkIIIYTYDozFdAy2l4D5xBOH/57pdP/nFEVB07QexyLRKOXlZSiKwmtv/pu0qg7/pIQQQgghtlPd6RhjcYVZcpi3wIQJlaz+4ksSnZ3ZY9897BDee/9Dfn7dr/C4XZSVlvCnZ54b1XkKIYQQQmwr3G43l19+ea9FybFA2QZSA3pNMBAIUFxcPKIfOhZbY7OVnl0Mv2BTA/6ycaM9DbGdkPdJDCd5n8Rw2tL3qTsVIxgMkk6nKS8vH5H5DULp74SsMAshhBBCiBETi8UGLHbQnYoRDAaJxWKYTGMvPN0ucpiFEEIIIcTY0h0kz5s3D4Brrrmm39zkyy+/nPb2dgyTgW703xButIy9EF4IIYQQQmzTWlpamD9/PqlUinPPPZc5c+b0GSx3ry53dHSg6zpPrXyKcDI8KnMeiATMQgghhBBi2MRiMR566CFmzZpFJBLB4XCgaRqRSO8eFd11lwHeaX6HvQr2osBRMAqzHpgEzEIIIYQQYlhdfvnlsEkPimQyyW233dZnLrPdbqc12sqqtlUcVH7QVp9rLiRgFkIIIYQQwyIWjzN//nza29tRVZWklqQx1ojb7ebcc8/tMy2jo6ODl9e/zCm7nzIqc86FBMxb6I033x7S+H+/8x7pgbqhCCGEEEJsBy688EI0TaM91c7DnzzMkg1L+KDlA2w2W68ay7FYjEBHALvZjs/uG7U5D0YC5i3Q1NzCktfeGNI1/1v7Iqp0/xNCCCHENmiw0nDdYxYuepBgMIhhMnh21bPMmTqHMyedydLAUhRFIZlM9hh/1113Ufd5Hd+r/B4Aqqri9XpH/HmGashl5aqqaw4DXgd+U19X+6tNju8CPAZ8D9ilvq527SbnnMCdwGlAHrAcuLq+rnbxcD7M1nL/wodZuXI1f/jTs6xdt56Ojg40Xeei889j1112ZsGDj7Bq9RqSyRQnVB+L3W7ns89Xcd0vf8Mdt96E1Wod7UcQQgghhMhJLBbLqTSc2+3mJ2edidPp5E8r/8Qpu5+C3WwHoNJTSUO8Ab1FZ+edd86Ov+CCC1j44ULK3GVomobH48Hlcm3Fp8vNkFaYM4HvY0B0s+M1wDvAun4uXQgcDRwJ+IGngZerqmt2/0azHyWnn3IyU6dMxmQy8e0DvsWd837DJRfO4eFHn6AjEuGd9z7gt3fP4757bkfTNKqOOoLCgnxu/fUNEiwLIYQQYptiGAbnn38+559/fr/BciwWQ9M0DODd5nfZLX83Sl2l2fOHjjuUt9a9xYIFC3qsVDfFmqjwVmS/LigYexUy2IIV5luBz4GGzY4XAt8FxgM/3fREVXVNIXA2cGp9Xe2KzOG7q6prfgLMBa78Zo8welauXk0wGOKfi/8FQCqVJs/rpbyslBt/fRuHH3YIxx1z1GhPUwghhBBiyLoD29/85jfMmDEDh8NBOBzG5/P1Gjd//nymT59OhxpmVXgV0/eeDoCmaei6jtvsJmlOMmPGjB4ryO99/R77l+yPqqr4/X4Upd/u1KMq54C5qrrmcGAaMCWzQpxVX1f7aGbM+D4u3T/zOe9vdvw94OAtnfimXlr5Eo3RxuG4FQDlnnKO2/XYnMZeMGcm+0zeq8ex22/5FZ+vXM2rS17jxb/9nfvvuX3Y5iaEEEIIMdK6g+BZs2YxY8YMvF4v0WiUefPmcf311/dYaXa73dlOfS9tqGPOt8+HzMq02WymsrKSYDAIBrhcLhKJBC6Xi46ODhqjjRy/y/EYhjEmUzG65RQwV1XXuDKpGJfV19U2VlXXDOUzSjI/t252PAiUDeVG/Tlx0onDcZse0ulUv+cURUHTNPactAdvv/Me+0zei3XrN/DBhx9z2KEH8857H3DyidXssftETv/JuWiahmIyoWljr9WjEEIIIURfLrroIjo6OvB6vRiGgdvt5pxzzukzsDWZTLzd8DZTCvbBaXFCZnW5srISRVEoKCig1FlKc2czzqiTaDTKvffei/Vga9cKdD+pHmNFrivMtwIr6utq/ziMn60AxmCDQoEm9M0Czc6UOmBAOywMo9/PGFdeyuo1X1BaWkxzS4DLfnYtmqYx97xzyfN6+PTT5Sz51+vous7pp5yErmtMmbwXV1x9Hbf+5gZ8eXlbPK3ORIJg0+YZMWKsU9W0/HcTw0beJzGc5H0Sm4vF4yxc9CCn/OhHuNxOnvriGUyKiTJnKf9T/D80bVzfY09WLB4nmUzy4cb3+cmuP6a9NYCqqhQVFhJqacqO28lWyfvr3oE2leefr2W/I/ejw9pBKNCMVSklmEyM0hN38ZeN6/fcoAFzJhXjLGDqFn5+9+9UMbBxk+Mlm5zrV2Fx70XoQCCA1WrbwunkJp1O9fsZfr+fp558pN9rr7/2ql7Hrr7y0mGZl8PpxF9cPCz3EltPsKlhwD+IQgyFvE9iOMn7tOOIxWI5reQ6YzHmXnAhVquVZ1c9ywl7ncTOeTvzyKePUFhcgtPrJT8/P3vPRb97lIOOP4h9KqZiNlvw5hfi8Xh6beD7ltXOux9+QGl5BRdefAnPr3meY3Y+Bp/dR+m4sf0O5lIlY2amFNynVdU1warqmiBwGHB1VXXNRzlc/yGQAg7Z7PihwFtbOG8hhBBCCJGjlpYW5s+fT0tLy4DjYrEYt99+O8lkkg9aPmC8dzw753WVgduveD/+E/wPoVAoO97tdnPppZfyfuv7HD7u8GzecndAvSmPx4NhGJjMJhRFIabGyLPlYbfbR+CJh1cuAfMVwG7Afpv8+AB4EKge7OL6utow8ChwW1V1zeSq6hpPVXXNjcBOmXJzQgghhBBihMRiMR566CFOP/107r///gEbkLjdbqZNm0bammZF6woOrzg8e+6AkgP4aONHvUrDoYCBgc3c1cmvuLi4z2oXNpuNib6JfBH+gqSexGlxoqrqmM9fJpeUjPq62jagbdNjVdU1SaCjvq62KfP1ykwA3B2Ar6yqrjGAP9TX1Z4HXA7cDiwBvMB/gGPq62r7q9sshBBCCCG+oe40jDlz5hCPxznjjDNIJpP9Bqmtra1YrBae/exZZkyeAZlqF6qqoigKNqeNWbNm9VgVXt64nN0KdkPXdVwuV789JxRF4cBxB/LXL/5KMBFkv+L9UBRlm1hhHnKnP7qC6CM2+3rSIOOTwGWZH0IIIYQQYoR1l4a7+OKLSSQS2Gw20uk08+bN48Ybb+wVNHenY1QcXcHxOx+Pw+KATLWLioqKruDb4gZ711ifz0csFuODhg84aqej0DQNr2fgttZ5zjwMw2BjdCMHlx+M2WQes7WXN7VFAbMQQgghhBj7uusjWyxdIZ/b7ebcc8/F4XD0Gut0OvnhGT/k3fZ32cW3CwDpdJqysjIsFgter5dJ+ZP4vO1z8p35JJNJFi5ciP4tnXx7PiaTCTMDl9D1er2ctttpWCwWdF3vcx5j0ZBaYwshhBBCiLGve3U5GAwC8I+1/+DJFU/y3Krn8Hg8xOPxXtckEgneCL7BybudDJmV5by8/27KM5lMTCmbwur21bS3t7No0SJO+/FpuN1u0uk0eTmUzd00/ULTNLzegVekxwoJmEfQsk+W09bePuTrzp4+m0RidGsRCiGEEGLb5Xa7mT17NiaTiXeb38VhcfDTvX9Kp9ZJykj1GWeEOkIoJgWnxdlvtYsCXwEpNYXb7WbmzJl81fkVexftDZkV6sEoioLN1lW212w2Z1e+xzoJmEfQP+pfpb09PNrTEEIIIcR2IhaLDVjlolskEiGZTNLc2cxX4a84cvyRABw1/ijq19WTTqd73CcWi7Fk7ZJsVQxN0ygtLe2VX2y32/FavUS1KLquszy0nCn+KdhstpxzkV0uF8lkcptJx0BymLdMLB7nttvnk+jsJJVMceH5s0gkOnn8D0+jaxpHHvE/7DRhPP9++13WrdvAjb+4mvMvuZL/feZJAH59yx2cdGI1u+22a6/77Dlpj9F+PCGEEEKMQS0tLdx7771omsYNN9yAx+Ppc1wsFuPmm29m2vRp/HXtX5k9ZXb23DjPOELrQ3R0dPDII4/ws5/9DIC77rqL9L5pjt7paFRVpbCwELPZ3OveJpOJg8YdxIfNH3LUhKPQDA2LYhlS8Ov1enE6ndvM6jISMG+ZtrZ2jv7+ERzxvcNZuuxTnn2ulnUbNjD/jlvwejzc+OvbqD7uGCbuugsXnX8eJSV9d+br6z43Xv/zrf48QgghhBjbWlpaWLBgAaeccgpOpxNd1/vt3Od0Opk+fTp/a/wbP9rtR1hMXeGeqqoYhoHNZMPqsHLBBRdkr58xawZ/WvEnACwWS7/BOMAuBbuweONiAvEAfocfTdMGHL85RVH6LT03Vu1QAXOuLSEHk5fn5e133+fFv/2dZCpFOp3GbDKR7/MBcPNN12/RfRyOsV+HUAghhBBbVywWY9GiRZx00kmUlZUB0NTUxLPPPssVV1zRK7ZpbGzkq86vKHOVUebuGp9OpykuLsZkMrFry658GfmSb3m+lb3ms9Bn7O3fG1VVKSkpGXA+LpeLQlshL699mZN2PQmTybTNBcBDtcPkMHfvFs0l72cwtX/9G/6iQubfeQsXnX8eALpu5Hy9pmn93kcIIYQQolv3Yt+0adN6BLIOh6PHCvGm4++efzevr3ud74//PmSC5aKiIlwuFw6HgynFU/gs9BnJZBKAaDTK0ualTC6ajMlkGjS9wuVycdyE45i+93QKHAXZTXzbsx0mYHa73X3+K2xLRCJRxo0rB+D1N/+N0+lA13WCrSEMw+D6G28mGo1hUhQ0raseodlsJpVOo2kaX65d1+d9VFX9xnMTQgghxPahe7GvsbERq9XKhy0f8uinj/K7T36H2WzGMHov1tntdnY5ZhdO3vNkFEVB0zTcbnePlInSwlKiqSiapvH1119zxx13EIlFsJvsOcVJZrM5GyRvK62tv6kdJmAmEzQPh2OO/j7Pv/AS11x/E1OnTKa9PcxZZ5zKTTffziWX/5x9p+6Dx+Nm6pR9uGXeXaxdt54Tjj+Wa677FfcvfJidxlei63qf96l/dcmwzFEIIYQQ276LLrqIVCrF2shavgx/ycx9ZrJz3s6s7VhLKpXqNT4ejxMyQkzIm4BhGCiKQlFRUY8xbrcbBYVYIsb999/P8ScdT5GvaEh1ke12O4ZhYBgGLpdr2J53rFL6+tfJGNNrgoFAgOLivjfSDZd0OoXVOva+xbA1nl0Mv2BTA/6ycaM9DbGdkPdJDCd5n7a+7jSLgfZWxWIx7r77bs466yywwpOfPcnsKbMxKSZSWoqnPn+Kn+zxEyZMmNCjnNvbK99mTdsajppwFOl0mvLy8j5TJv764V9xWB1MsE7go/BHTMibwC55u1BZWZnTMySTSb7++mucTifl5eXZ49v4+9RvXbwdaoVZCCGEEGI0tbS0cNddd/Hll19y55139ru3yu12M2vWLGw2G0+tfIozJp2BSekK22xmG2aTGU3XCIVCPa57ddWrHDbusGyXvv7yiw8YdwBLA0vx+Xysi65jV9+uQ9q4Z7fbqayszG5C3N5JwCyEEEIIsRV0V7s48cQTsVgsnHPOOQOO1XWdJV8v4cDSA8m3d3XcU1WVdDrNzt6dWR1czV133ZUNutvb21ny3BL0lI6iKL269G3K6/KS0lLoho5CV67zUFMrhtKsZFsnAbMQQgghxFZgGAZnnXUWpaWlWCwWOjs7ewS83WKxGLfffjtfNn9JMBFkavFUyFS7yM/PZ/z48eyZvydfdn7JzJkzs2kd7Z3tHHfmcV3d+LzeAYNZl8vFxLyJPLHiCb5b8V10Xd8hcpG3lATMQgghhBAjrLv7nq53Vc9K62m8Xm+PgLeb2+1m+vTp/DPwT360+48gU5LW4/GQl5eHyWRiXME42jvbsVqt2Xu+t+E9DtrpIAzDGHTzntVq5fCKwzl38rns4tsFm83WZ2c/0UUCZiGEEEKIERaPx5k+fToN6QYWLl3I/A/nk9JTfQaphmGwMrySqf6p2M12dF3HYrFQWFiYHZOfn4+md/V1CAQCRCIRVoVWsatvVxwOBybT4CGe3W7Pfl73r0XfdqhOf0IIIYQQW1tHRwfz5s3j1HNO5a2mt7hg3wtoiDWweMNijhl/TLb8W7e2tjY+aP6A6ftMB0DXdcaNG9djjNVqpcJTwbq2dTz/+POYzWZc33WhazqegtzaVHs8HoLBIIZhDKm19Y5IVpiHwfsffMRLL/9jtKchhBBCiDEokUgwc/ZMXv76Zc7e62wURaHCU0FDrAFN12hra8uOjcVi3DzvZiy6BbPJjKqq+P3+PleMD6k8hE87PmXu3Lkcd8ZxTCqbhGEYg3bq6+ZwdDVeM5lMO0S3vm9iu1hhbm1t7bN495ay2Wzk5eVWuBvgO9/ef9g+WwghhBBjXzqdJhKJ4HQ6cTqd/Y4LBAIkk0le/vplTp54MjbzfwPTib6JfBH8gsUPL+YXv/gFbrcbt9vNpOMmsX/l/ui6jtPp7HczXpmvjLbONvLy8vi8+XOqdqrCarXmlI4BYDKZqKysxGw27zDVLrbUdhEwp1KpPttDfpP7DSSdTnPPfQtpbglgUhT2228q0WiMObOmD9schBBCCDE26bpOU1MTJpOJeDxORUVFnwFnLBbjjjvu4ICTD2CCdwLjPF0NPVRVxWw2s2f+nnwc/JhZs2ZlN/7puk4gHWCcexyapvXq0rcpl8uF3WQnno4TSUXwWr1DzkW2WLaLUHDEDfl3qaq65jDgdeA39XW1v8occwJ3AqcBecBy4Or6utrFuZzf1vzr9TfJy8vj6isvZclrbxCJRIlG+y48LoQQQojth2EYNDc3oygKiUQCm81GIpHocxXYbrdz2tmn8X/N/8eMXWZAJlj2+Xz4fD6UBoVXNryCxWLBMAzi8Xh2AdAwDNxu94CrxVarlYPLD+aJFU9weMXhqKrab+dA8c0MKYc5E/g+BkQ3O7UQOBo4EvADTwMvV1XX7J7j+W3KqtVfsPdekwA48nv/IztLhRBCiB1Ee3s7qqqysW0jt957K21tbYTD4T7HhsNh/q/5/zhtj9MgUxrO6XTi8/kAyMvLA70rON6wYQPz58/n/TXvM7FgIpqmZcf1R1EUdivajfP3PZ8p/ikoiiIxyQgZ6qa/W4HPgY+7D1RV1xQCZwM/r6+rXVFfVxurr6u9G/gMmDvY+eF/pK3D0IcvBUQIIYQQY18ikSASibC0cSmvNr3Kzt/fmXsevodwONxnaujKjSvxO/14bV4Mw8BkMuH3+7Pn3W43hY5CGsONLFiwgDlz5vBp+6fsW7wvVqs1p3QJl8uFpnWVl9uROu9tbTkHzFXVNYcD04A5m53aP5Pa8f5mx98DDs7h/DZnj90nsvSTTwF45933Cba2jvaUhBBCCDGCdF0nEAiwpmEN9yy4h9N3Pp0ZB81g/LHjMQwDVVV7jO/o6OCme27ioKKDILO6XFJS0iOgVRSFA8oPYFV8FbNmzcJmsxFOhsmz5g24kXBTbrcbXdclHWOE5ZTDXFVd48qkYlxWX1fbWFVds+npkszPm0eNQaAsh/MDCgWa0DW9x7HOlEo6/d+NeZv+etgYRr/3PeyQg/jgw4+5/KrrUBSFfafug65rIzOPzXQmEgSbGkb8c8TwUtW0/HcTw0beJzGc5H3KTaitjda2Vq6/7xfcPOcm0p1x0p1xnJqdO++5nSsvvJTS0tLs+I5IlKnHTMaumQg2N5Hv8xFuDfS6b4HuZVXTZ+zvnMKqNS0oKY1QoBmzUUwwmchpbtFwG7pu4LCYSMYiw/rcQ7Utv0/+snH9nst109+twIr6uto/DuFzFWCgvIXBzgNQWNw7pg4EAlit/y3L4nZ7hr2sHIrS4zM2ZbXauPbqK4bt84bC4XTiLy4elc8WWy7Y1DDgH0QhhkLeJzGcduT3SdM0gsEgFotlwGoUqVSKaGeKJV/+lXnX3M5uJbtlzx3nqObdvHfxl43Dv0nAvLT1VQ7f63v4Cv1YLJYewfSmvAVFuNZ58RYV8lnTGg7b9XsU5JVQPn58zs9RVFo+ZlIxttf3adCAOZOKcRYwtZ8hTZmfi4GNmxwvyZwb7Pw3NtBLvqW2xmqxEEIIIUaHrus0NjaiKAqdnZ34fL5+c4bb29t59+t3+fjFjzn9qtMhU2LW6XRSZCuizWjrtXD3cfPH1OxWg6qqlJX1/w11m83GPkX7sDSwlM9Cn3HI5EOwWqxDepaxEixvz3LJYZ6ZKQX3aVV1TbCquiYIHAZcXVVd8xHwIZACDtnsukOBt3I4L4QQQgix1XSXhiMTbKZSqR7d9jal6zqhSIhlwWXcdtVtuFwuVFWlqKiIkpISvF4vhm6g6zrpdBoywXRHpAOH2YHD4cBsNvc7F0VR2Ld0X5a3LuegsoMwdKPfRiVi9OSSknEFcMNmx54D3gbuqK+rDVdV1zwK3FZVXbMCWAdcCewELBzs/Ag9lxBCCCFEn7pLw60Jr+HtL96m4V8NXDTnIvx+f6/V2kgkwl9W/IXwv8IwuSuNw+Px4PF4APD5fBTYC2hob8Dr9VJYWMgXG77g/Rfe58w9zmSXXXYZdD557jym7TkNk8lEKpWSgHkMGjRgrq+rbQN6/LOrqromCXTU19V2p1RcDtwOLAG8wH+AY+rratfleF4IIYQQYsR1dnbS0dHB0qalfB76nA1LNlD23TKcTieqqmK19kyHCIaDONwOLrvwMpxOJ4qiUFBQkD1vNpuZ5J3E/IXzue2q2ygsLOTT0KdccsEleL1eHA7HoHPyer10dHRgMpmw2WwDrkiL0bFF/RDr62qP2OzrJHBZ5kdf4wc8P1Qmk4nOzs6cXsLtSWdnZ8794YUQQgjRU7Y0XOMa7lt0H4uuX4Syu8Jza5+jPdaOL+YjPz8/O94wDF767CWO3PVIXC4X6XSaysrKXqvQ++28H3v/YG8sFguBQIDPWz9n+j7TsfVTPGBzFosl2+1vR4ttthXbZAPxwsJCQqEQkcjIlU7pTCRw5FgDcWsxmUwUFhaO9jSEEEKIMccwjEE3v7W2ttIUaOLXC37N3Vfcna1bfEjRIdx0z03cde1dPQLmtrY2/vrHv3LCjSdk85b7Wv31uD1Y7VbMFjOdyU5MZhO6puMp8OQ8f5fLRSKR6Or+J8acbTJgVhRlRCpjbCrY1CDl24QQQogxLpVK0dTUhGEYjB8/vt/vxKqqSjAY5Bf3/YLrL7yecaVdpc80TWOifyJTfzi1VzpGY7SRU885FafTicViyeYtb85ms7FHwR4sa1iGx+2h0lYJMKTV4oKCgh6pHmJske/vCyGEEGKbpGkaTU1NpFKpbG5yf8LhMMtCyzhrxllMnjAZMtUsfD4fVqsVm8OW7ZjX7Z0N73DITodkV5f7oygKe/v25s4H7uS5/zzHx3/9mFQqJWmU25FtcoVZCCGEEDu27tJwyWSSBx54AEVRuOCCC/D5fL1SMwzDYF3DOh586EF+98vfQSZY9vv9uN1uHA4HRfYiWpOt5EXyKCgoQNM0GqONHL/L8SiK0m+N5m7jisdx6fmXsmvxrji/45QUyu2M/NNHCCGEENuc1tZWdF3n1Vcd/Pin57LXD/fCbrf32fk3kUjwavOr3HH1HbhcLjRNw+v1ZnOYbTYbU0um8lHDRyQSXe2oo7EoalJFVdWc8oq9Xi/7j9ufYlcxdrsdr9c7Ak8tRosEzEIIIYTYpkSjUWKxGO++q/LKKwsp8XloSjeR6EwQj8d7jW8Nt5JIJKgorMAwDCwWS6984fGe8Tz92NOEw2F0XeftVW/zWd1nxGKxnOoiW63W7IZAk8nUKx9abNskYBZCCCHENkPTNFpbW1m/XmPlynzuvHMmLpeL/Xz78at7ftVnx75/fPYP1v/feuLxOJqmUVJS0itto7S0lENrDsXlctHY2Mgn7Z9w/WXXk5+fn3PrabvdjmEY2O32YXteMTZIwBAu+tAAACAASURBVCyEEEKIUZdKpYhEIhiGMeC41tZW2ttTXH/9o9TUBLOrv98e/232rN6z18qupmk0pBq45tJrsFqt+P3+PkvDWSwWJpVOYn1sPYqiEEvEKPAU4BxCiVmfz4fD4ZBqF9shCZiFEEIIMapisRgNDQ2EQiGi0Wi/4zRNIxqN88wzbu66awY+nwvDMEin06iqis1lQ9M00ul09ppgOIjH6sHpdOJwOPpNr1AUhYMrDuajlo9YuWElH77wIZFIpN9Scn2x2WwUFRVJOsZ2SAJmIYQQQoyaVCpFMBjEZrNhtVoHLQ33yisKTU2/paCgayVa0zQqKyspLi6m1FFKc2czgUAge82Sz5ewb8m+qKo66MpvoaeQ9a3r+eX9v+Ty8y7H6/UOWh1D7BgkYBZCCCHEqNB1nebmZsxmK+vWmQkGTaiqSjKZ7DXWMAy+/jpBIGDhF784L9uquqysDLPZjMvlYmrxVP7T8B/uueceYrEY0WiURx56hPH28V21lm0Dt6p2u93M/dZcfn/j75k0ftKg48WOQwJmIYQQQoyKlpYWQOHxx90sX57kT3/SsVgsxGKxXmNTqRQvvqjS2novZDr3FRQU9Ahqdy/dnaAaZMaMGTidTkwmE4f+6FBcTldOpeHsdjsOqwO3242maUNKxxDbNwmYhRBCCLHVhcNhUqkUtbVuJk/eyCef3M3q1Xfx0UepPmsph0JR0mkLF188B7vdjtPp7BUEezwedF3H5XIRi8VY3bSa8UXjs8dysWmFi6Fs+BPbN0nMEUIIIcRWpaoq7e3t/Oc/bqzWZv7978eZOXMmdruL554rZN99wxiG0aOc29//HmP9+gXAeZhMJvx+f6/7WiwWdvbtzMb4RmKxGIvXL+ao3Y/CarXm3Kba4/HQ3NyMy+XKuZyc2P5JwCyEEEKIYREIBOjs7KSoqGjAFd1gMEggYGPZsiQdHY8ybdo0/H5/pqmIQSQSI5VKZVd7dV2nocHNddedly0N118we0jlITz/6fN8/Y+vWRZcxgm/OgGHw5HzMzidTioqKqTShehBUjKEEEII8Y2FQiE6Ozsxm82Ew+F+x6mqSjSa5M9/hp/+VGHOnDkUFhZCplteWVkbd9/9WI9KF5FIArNZwel04nQ6B2wM4vf6SZlTnDPnHI49+1hsNlu2BXYuFEXBZrPJ6rLoQQJmIYQQQnwj0WiUSCSSbQiSSvWdh0wmd/n5502Ew/eQTsdxOp0oikJ5eTnFxcUccICNKVMu6ZFC8cEHney9t4aqquTn5w84F7fbzR6+PfhX8784cdKJ2QBYiG9CUjKEEEIIscVSqRStra20ttqprdVxOAymT7cQDocpLi7uMdYwDL78MonZrHDVVbNxuVyoqkpFRUV2Rbey0kU8Dul0B7quoygK774b54wzzDmVhrNarRwy7pBs8G42m2W1WHxjssIshBBCiC2i6zotLS3EYlaefDJGe/vtvPfefJYvT/bottdNVVXq6lQ2bvwtAOl0mpKSkh6tqvPy8jAMHcNQiMfjtLW18eqrC0mnc++6Z7fbMQwDVVWHlI4hRH9khVkIIYQQW6S1tRVdh4cfTgAPct55M7FaXTz/fCGTJoXRdb1HakUgEMFm83LhhV2l4Xw+X68NeWazmT320Fm71oHZ3EZ7u5kf/OACHA495+DX4/EQDAYxDCPncnJCDCSngLmqumYKcCtwCGADVgK31NfVvpA5XwnMA74P+ICPgcvq62o/yJx3AncCpwF5wHLg6vq62sUj/YBCCCGEyF06nSaRSOB0OgesFJFIJEgkEjzxRCex2CNcfPG0bKk3ux3a2hKUlqZ6BMSvvmpw4IHt2aYi/TUTOfBAg6efTrHHHmY++MDB//xPCotF67ESPRCn04nFYsl+jhDf1KBvUVV1jQdYAqwBdgGKgReAv1RV1+xdVV1jBv4GlAPfzpxfAtRXVdeUZG6zEDgaOBLwA08DL1dV1+w+8o8ohBBCiFxomkZTUxPhcJhgMDjg2Pb2dt5+W2fp0se4+OKz8fv9qKqKqqrstFOIu+9+LNPJr4thGKxeHeMf/1hER0cHJSUl/d7b4dD55z8XEo/HaWw0MW6cNqSNe4qiMG7cOAoKCnK+RoiB5LLC7ASuAZ6qr6uN0xVE3w/cDOwDGMC+wKH1dbUNmfO/BKYB51RV1zwKnA2cWl9XuyJzz7urqmt+AswFrhzRJxRCCCHEoAzDoKmpCZPJhKIo2UoXfQWqqqqybl2YNWvKmDdvZnbzXn5+Pl6vl2RyI2vWXIzF8t91uWg0gcPhYdq02eTn5w+4Wuz3+/nhD2fz0ks+LJYomqZLm2oxqgZdYa6vqw3U19U+skmw7AduBDYCi4HuraemTa4xgBbgO8D+mcD8/c1u/R5w8HA/kBBCCCGGLhgMous6n36aYsUKC6lUivb29j7Hbty4keuue5ITTmjF5XKhaRoej4e8vDwURcHv92AYbtLpNJqmAfDee51MnqxhtVoHXfm1WCycdJKVww8PEQj8lng8PqTmI0IMtyFt+quqrklmcpg/BKrq62qDVdU1bcAK4Jaq6pppQAcwE5gMxIDu77m0bna7IFA22GeGAk3omj6khxoOqpom2NSw1T9XbJ/kfRLDSd4nMZxUNc3aL1bT0RHhX6+lqPv7n9l36jQam37PRReehUlXe13z8QcBfnD8T7CaorQFIyiKgsNiyr6Xuq7TmdBobWnFUFN43G7efC3NMcc0Eo+6aA+29DGTnlKJMGhhfnzqKRhamtbmxhF5fjG8tuW/n/xl4/o9N6SAub6u1p5ZYb4E+HdVdc3B9XW1q6qqa34I3AsszQTJjwH/AgbqK6lk0jkGVFg8aEw9IoJNDQP+xgkxFPI+ieEk75MYTo0b1qFYbKzbaOPvr/yFO+6cTl6en8cfv4bScpWC4tIe6RPhcJgHFj3PfffNJL+gIFtHefMUiwO+HSAQcjFuvIbb50M1AvzvC3/hiiuuyOn9Vax2HvzdI8yZM4dx48bh9XpH5PnF8Npe/34aclm5+rraIPDLquqa0zI5yFfU19V+AZy46biq6pqPMyvRTZlDxZk0jm4lm5wTQgghxDAyjK41qYGadhiGQVtbO/GUm7vvfpp77z0jW+mioMBFU1MLRUWJHvnD8TgcccSFFBSYSKfTlJWV9ZmP/O1vw+9/n2SvvXRWrAhSUeHhe9+bOeBmv00VFhZy3nnnYbfbpTScGHW5VMn4QVV1zYaq6prNix8qgJoZc2pVdc1em1wzIbMRcHEmaE5lStJt6lDgreF6ECGEEEJ0aW9vZ/369TQ1DbwuFY1GSSY1XnihhPvum0FJiT/b8GOvvdq4667HCQQCPa554w2N733Piq53bcSz2+193ttmgyVLFpBMpli2zM0BB6Twer1YLLmt1SmKwq677sr48eNzLicnxEjJ5a19J5O3fH9Vdc2VQAKYA+wGPJ8ZMwPwVlXX1AA6sCiT1/xcfV1tOlMp47aq6poVwLpMZYydMuXmhBBCCDFMIpEIHR0dWK1WUqkUyWSy36C2o6ODl14u5thjg/j9TgzDQNd1CgsLmTSpjSlTLmLTIhldpeEUDj1Uy47rT1FREaefPptg0MXGjWaOOUbDas29NByZjn1CjAW5VMloBaoyKRSrgGbgLKCmvq72ncywczOb+tYAXwFx4Jj6utruvpiXZ2o1LwECwHGZ8+tG9vGEEEKIHUcqlSIUCmGxWIjH41gsln4rXSSTSZYtU/B6w7z44iLi8TiaplFeXp6peOHBYnGRTqdR1a6Nf4lEJ8lkFOjqujdQuofJZOLIIx3U1zvYe++2bCUNIbZFOX1fpL6udhlwwgDnm4GTBzifBC7L/BBCCCHEMNN1nebmZiKRNE8+aePttx/jiivO4oADvBiG0Su4DYc7eO01mHaWht01B6vVSnFxcTZlwufz4fG0EotZiUQiFBQU8P77LXz66SIikXMoLy8fdE5+v42TTlrLH//4RyZPnonT6Ryx5xdiJEm/SCGEEGI70NzcTCDQysUXP8appya4774fc//9TxGLxUilUr3Gv/lmhHXr7iORSGCz2fD5fD0CWpPJxH77wYcfqiQSCQCWLfNw7bXnDdp4pJuiKDzxxBNMmzYNn8834Iq0EGOZBMxCCCHENi4cDtPU1MT11/+Zyy47i8pKB6Wlfn74w7nEYj7i8XiP8aqqsnSpj5tumoXDYcfhcJCfn9/rvjvvnOSJJx4iHA7T0NBAOGyivNyecxORwsJC5s6dS0FBgVS6ENs0CZiFEEKIMUjTNJqammhpGbjJh6ZpNDQ0cOutf6amZhrf+c5/u+gde6yF11/Xe60wNzXFcDhieDwuDMPIlpLbXGlpMYcdNhev10c4rOBwxIaci1xSUoLdbpc6ymKbJgGzEEIIMcZ0B8GRSIRQKJRNiehLOBymubmAAw+8kB/8wAeZFWSTyYSihKmrW0hbW1u2LjPAkiUdrF79AB0dHeTn52My9R0O2Gw2pkyx8/nnFt54I82qVfeRTCaxWgfqS9ZTfn4+JSUl/X6GENsCeXuFEEKIMcQwDJqbmwmFQjzwwAM8+OCDNDT03Wq4q/FIjLo6gzPP7PpfuqqqeL1eysrKKC8v5/DDz8dud2ZXmQ3DYN06N9dcMxuPx4NzgPQKRVE48ECDZ54xaGjwcfXVs/tM3RBieycBsxBCCDGGbNy4kUgkwm9+8wxu90V8//uXYrFY0DSt19hEIsFf/qLT0XEPnZ1xdF3H4XBQUNCVluH1etl9dzsbN9qJRqMAxOMJDAOcztzSJCwWDZ/vTs4+O4DNZpPScGKHJAGzEEIIMUY0NTVxzz338PHHDo477nwuvNDNxx8Xkkgk6Ozs7DW+tTWKrvv42c9mZytcFBcXZ8+bTCYOOEBh+XJb9vrlyxOUl0fRdT2ngLm0tJSZM2dkN+1JaTixI5KAWQghhBgDVFWlra2N44+/iIaGPKqrLSgKVFSEueOOx3q1qAb4298SHHFEEpfLhaqqlJeX9yrdVlnpJBDoun84HGbx4hiffHJ/Ns95MBaLBZ+vKzfaZrNJaTixQ5KAWQghhBghhmEQCoUIBAI9Nt31Ze3atSxY8HsWL3Zw+un/3eR3zDEWdt75kl4b7cLhMH/+84MUF0dIp9MUFxf3WRvZ6XRiMkVIpy2Ew2F0PY8LLzyPoqKinJ/D4XCQTqclHUPssCRgFkIIIUZIIBAgHo/T2dmZzSHuSzKZJBpN43RewaxZYDJ1de7rakmtYrG4UVUVXdez14RCcMIJ5+NwOHA6nf3WOe7s7GTNmgW8/bZKR4eVggIdu90+pOC3sLCQCRMmSMAsdlgSMAshhBAjoK2tjWQySWdnJ8lkko6Ojn7Hfv311/z853/gRz9K4HSSXY2urKyksLAQt1sjGjX1KC/31lsahx9uR9M0CgsL+7232+3mhhvO5/PPC3juORcHHpjCbDZnW2DnQlEUScUQOzQJmIUQQohhlkgkiEQiLFsWZs6cB7n++oV0dHSQTCZ7jdV1nS+/dHDyyeez005dJd40TaO8vByTyYTb7WaffdL85z96dpVa13XWrjWorNSw2+2DBr+lpSUcdVSUk05KkJcXwW63j9CTC7F9koBZCCGEGEbpdJqWlha++irMXXc9zd13/5SJE3+G2+0lFov1Gh+LxViyROPEE83Z60tLS7P5yIqiMHFimscffyjbgCQajZNKxVHVdHZD3kCcTicTJ6axWFpYtGiRNBERYojkT4wQQggxTAzDoKWlhUgkxQ03PMO8eT+mpMTP4YdbeestrVeLaoDly1tZtmwhnZ1x0uk0hYWFvVaAy8tLOPjguTidThKJBK+/HmTVqgUkEgkcAzQe6WYymVBVlT/84Q+cffbZA6ZwCCF6k4BZCCGEGEQ8HicUCvXYdNeXcDhMJBLlf/+3hDvumMn48X4AdtstzCOPPER7e3uPahmGYfD663nccsssHA4HLperz9rINpuNykonwaCNQCDA8uVerr9+Fvn5+TnnFhcVFXHuuedSUVEh+chCDJEEzEIIIcQAotEo69atIxgM0t7e3u84wzBoamriiiue4KCDQkyY0LXyq6oqVquFI464AJvNSTqdzl6TSqVIJg38fie6rvdb6k1RFA4/XOe99+yk02kSiU58Pnu/lTH6kpeXx0477dSjsYkQIjcSMAshhBD96OzsZOXKlTz44IMsXLiQlpaWfuspd23ys3HqqXOZOrUrpaK7PnJZWRl77GFh7Vp7jzzm1avjlJcbqKpKQUHBgLnF5eVWGhvj3HjjAj76aD7RaBS3253zs3RvIJT8ZSGGLveaMkIIIcQORNM0VqxYwR/+8AwTJlzA+PF2XC4T0Wi0z7SJr75qYdGix3j44XMBC6qq4vf7s62k99vPoL7ewZ57JigoKABgyZIo3/1uV0OSwWocu91uDjggSUXF5Rx2WAqfz9VnoxIhxPCTf2YKIYQQmzEMgy+//JInn3wKw5jLkUf6WLMmn3TaSjAY7DVeVVVee83HbbfNxO12oWkaXq+3xwpwRYWX9naDcDiMpml0dHRQW7sQp7MDt9s9aF6xzWZj//1VTjzRQkGBU0rDCbEVScAshBBCbGbDhg3YbA6cziuYPdtFWZnOccd18tJLKgsWLOhVHq6jI0pLS4oJExzoelcnve5V5G4ulwtVjfK73z1CS0sLiYTGkUdeiN1uJy8vb9A5KYqC3W7HMLpSOKTrnhBbT04pGVXVNVOAW4FDABuwErilvq72hcz5PYE7gEMBK/A58Ov6utqXM+edwJ3AaUAesBy4ur6udvFIP6AQQghBJp84Ho/jcrmwWq39jgsGg9x7771UVl7BccdZKChQASgr04lE8pg5c2avUm6vvNLB+vULiMfPw+Fw9LmxzmQy8e1vO0gmLyaVSvHeewoHH2zDZEoOOJ9NeTwegsEgJpNJVpiF2IoGXWGuqq7xAEuANcAuQDHwAvCXquqavauqaxTgFSACTAT8wJ+AFzKBNMBC4GjgyMz5p4GXq6prdh/5RxRCCLGjS6VSNDQ0EIlECIVCg4496KBLKC52svvuXcGyqqqkUinKytJEo3nE4/HseMMw+OILDzfccB5Wq5Xi4uJ+0ysOOEBh9WofVquV5cs19tpLxWaz5fwcTqcTt9uN3+/P+RohxDeXS0qGE7gG+EV9XW2kvq42CdwPmIF9gBJgAvBUfV1tuL6uNg08mlm93requqYQOBv4eX1d7Yr6utpYfV3t3cBnwNyt8IxCCCF2YKqq0tTURDqdxmQyEQqFUFW1z7GpVIq1a6N88UU+Rx3V1cY6ne7qpldRUcHkyZ2sWOHoETAnEl3jXC4nTufAucV5eS7SaYOGhiBvvrmAaLRjSJUuFEWhqKgou5FQCLF1DBow19fVBurrah+pr6uN07Xi7AduBDYCi+vrapuB14AZVdU1/qrqGjswB2gF/gXsnwme39/s1u8BB4/YkwkhhNjhdddGTiSSXHvto/ztb2EeffRRGhoa+hy/cePXXHfdE5x4YtfGPk3TyMvLw+frWhWeONHG11+bezQg+eijGBMmdKCqKvn5+QPOx+l0MnlyiGuvfYarrjoLp9M5pFrKQojRMaSyclXVNclMDvOHQFV9XW33VuHTgb8DAcAAgsCp9XW1zVXVNUdlxrRudrsgUDbYZ4YCTejawJ2VRoKqpgk29f0XqhBDJe+TGE7yPuWuNRQimUzzhz96qDnpdBoaXHz3sDNpafgal63n/wINw+Dtfyc5+yenYyZGKBDBYrHgtJoJNiUA0NJpQq0h7rv3Xi675GLy8/P55ysdNDY/wN57TMNtHzwXec/dY9x28w9xuTRiHWFCLbnlL48UeZ/EcNqW3yd/2bh+zw0pYK6vq7VnVpgvAf5dVV1zMLA2k8P8OXA8EAXOAV6qqq45ZIDbKZngekCFxYPG1CMi2NQw4G+cEEMh75MYTvI+5aajowNnSqX2RROh9vs48ODZWCxWHn+8jH+9cTc33XRTj3rKyWSS5St0LrggD0UxMAyDcePG9Wr0scekIJMnX0W+P4+8vDzMNgdXXHkJ5eXlOVW7MNudxGIxDMPIrl6PJnmfxHDaXt+nIZeVq6+rDdbX1f4SaM7kIB8N7AdcXl9X21JfVxuvr6tdBHwFzACaMpduvmW4ZJNzQgghxKDS6TShUIhEIjHouLa2Nt5+20Vlpca1187G5XJhs4HP5+LMM+f0avqxdGkLn3yykM7OOJqmUVpa2mdXvMMOM/jkkwISiQTLl7fg9ys4HI6cc5G9Xi+apqFpmpSGE2IbkUuVjB9UVddsqKqu2fxvAgVQN/t6U5bMCvKHQCpTkm5ThwJvbfnUhRBC7EjS6TSNjY0kEgmCwWC/LaoB2traaGmx89lnbSxd+gBk8pHT6TRTpiRZv76wVy3l997z8KtfzcJms5Gfn99vqbfKShvBoILFYuHf/4aDD05hsVhy7rpnsVhwu90UFhZKpz4hthG5pGS8k8lbvr+quuZKIJHZ1Lcb8HwmFaMJmFdVXXMZEMtUxZgEzKmvqw1XVdc8CtxWVV2zAlgHXAnslCk3J4QQQgxI13Wampowm80kEgk0TSMWi/W5QqvrOuFwguees6FpD3POOdOw2+04nU7y8/MxjCb+/GcHhxzy30oXmqbR3q5TXu7Mpkr0x+1243a3s3ZtKy+88DTHHnsuDkfhkJ5HysIJsW3JpUpGK1CVSaFYlUnFOAuoqa+rfae+rrYdOBYoypwPAOcDp9XX1b6Ruc3lwN8y9ZwDwHHAMfV1tetG/hGFEEJsy7orXcTjCV5+WWPu3Ad54IFFNDX1ndUXDod55hkzZ5yhcP75cygsLMRut+P3+7FYLOTne0in/9uiGqClJYrJFM9WxRiIxWLhgAPa+MUvnmHmzLOx2WxDKg0nhNj2KAN9S2uMGJUJbq9J62J0yPskhtOO9j4Fg0E2btzItdf+mblzZ+Px6KxebeX443UmTJjQq0nIW299ybx5v+Oee2bidHatGFdUVGTH6brOHXdspLHxPq6++nIqKip4+un1vPLKAq69dgZ77LFHv41HurW0tBAOh3G73WiaRmVl5aDXjFU72vskRtY2/j71+4d4SFUyhBBCiK0pHo8TDAa56aZnOfvsaXznO11d8d5800002kAymezRplrXdd54w8fNN8/C5XKiqmqPYJlMi+oDD3TS1HQxiqKg6zpffOHm2mtnUViYn1Pg6/F46OzsBMBut2+zwbIQIjdDrpIhhBBCfBPpdJqWlhba2toGHKfrOq2traxc6eDooy/gyCP/2xRk6tQ2br31cVpaWnpc09oao7MzTnGxk3Q6TXFxcZ8b6/bd18JXX+Whqirr129EUUw4nfacUyu6O+2pqiqVLoTYAUjALIQQYqvRNI3GxkbS6TQdHR2k0+l+x4bDYdauTXL//Q9zzDFd7ad1XSedTjN1qpm9976kVyWLxYvb+eqrB4hEIni93n5bSHs8LgxDJ5FIsWqVg91264BNAuHBKIqC1+vF7XZLm2ohdgASMAshhNgqDMOgsbExW+kilUr1u8psGAbhcJSXXnJz//0zcLtd6LqOzWZjwoQJeDw2FMVNKpVC1/XsNWvWuLnuuvNwuVwUFBT0OxebzcbEiWFuueV3vPZamHfffYB0Oj2k1IqCggKKiookHUOIHYAEzEIIIUacYRg0NzcD8OKLOrNmPcStty4kFAr1WU85Fovxl78YtLffg9XatbJsNpspLi5GURQKCgqwWlWSSVO2iUlnZxJdN3C7u5qIDBTIKorCYYc52WmnS9lvvwLmzj2PoqKiEfwdEEJsy2TTnxBCiBHX1tZGOp2mrs5g3DgnixbN4amnXBhGuNfGPYB161rQ9UKuvnp2ttJFaWlpNgi22WxMnWqwbJmGzxfF7Xbz2WcxSktjaJqRU7tpn8/F7NkdmM0p0ml7jzbZQgixKVlhFkIIMaISiQTRaJR//jPKK68sYvLkMD6fC79f47e//T2BQKDH+Gg0ys9//jCHHhrC5XKhqmqfbap3372Thx9+mFAohKZpLF4cY9my+1FVNacOeh6PJ1uH2Wq1Stc9IUS/ZIVZCCHEkKVSKQKBQK8ax5szDINgMMinn2o899wfmDfvTFwuFwAnnGAhHr8Ui6VnoGqxWJk69UJ23dVMOp3G7/f32aa6oqKEgw6ai9drYuPGjXR25nHJJbmnVpjNZmw2G7quS+MRIcSAZIVZCCHEkKTTaRobG1EUJbM5L9zv2EgkQlOTiXfftfHb387A7/ejaRq6rmO1pjEMD+l0ukce8/Llcfbc04mu67hc/8/encfHVVeNH//c2e5smex79wZaWuCRRZYiIEt8MIKan6BQaKFNFygFV0TxEVAffVREgUIXpa1t2UHDIsE6bIJCCxQRyl6wLU0zyWSZzL7c5fdHJmPT7NLS7bxfr760me/3zr3zmlc8np7vOe5Bg1mHw8GkSU527LATiTgoKurpiTyaNm/5+fm43e4RlXAIIQ5dEjALIYQYMcMwCAQC2Gw9/0BptVqJRCIDHtwD6O6O8OCDFiKRW1CUnrZyqqpSXV1NQUEBdrtBKmWSSqVye555Jsrxx2fQdX3IbHHPwT2DZ57J8NRTTv7rv7qwWq25exsJj8dDUVFRv3IPIYTYlfyGEEIIMSK9nS5MU2HdOg/r1rl57DEnhmH0CXh7pVIpHn3UwTnnJFi0aCFOpxObzZbrdJGXl8fUqRk2bzaIRCKQ7b3c1LQUuz2Ky+UaNpB1uTK89NLt5OUFaGxciqZpe+35hRCHLgmYhRBCjEhPpwuNu+/2cuqpKWbNitPRYUHTbMTj8X7rQ6EogUCaJ55Yhmma/TpdKIrClCkpVqz4Xa4fcyRicPbZi3A4HBQUFPS75u4qKir42c8u5Zxz8mloaKCiomIvPLkQ4lAnh/6EEOIQpmlabiDIUBKJBJFIhD//x287lQAAIABJREFUOY/jjkszcaJOPB7nM59J8tRTBZx3Xv8M81NPmZx1lp0xYxbicDioqKjolzEeN66MT3/6clTVJBaL8dxzGp/5jAObTRv2nsh2t+htB+f1elFVddSfgRBCDEcCZiGEOETF43Ha2tpymd/e7hW76+108dprbpxOkyOP1Ghvb2flypUoikJBwTVkMjqmaeayx7qu8957Fk44IYTdbqe4uHjATheqqlJe7iYczgDtvPOOldNOU0YULPdyOp0kEglUVZWpe0KIvUJKMoQQ4hCUSqUIBoM4HA5UVSUUCg26Nh6Ps3OnhXfftXPKKV3E43HWrFnD/PnzufLKK3E4eg7updPp3J5AIIaqRlm+fPmQbdt6Du7pbNyoEgx2s2HDUiKR8KiGiOTn5+Pz+WRSnxBir5GAWQghDjG6rtPa2oqm2dm0yU5zc0+/44EO7gF0dnbz2GN5nHXWdlasWIGu61x99dUceeSRlJeXs3nzbWzebBCNRnN7/va3DKecotLQ0MDYsWOHvJ9x42xs2ZLkuuvuY/78i/F4PKMqrbDb7eTn58vgESHEXiMBsxBCHEJM06SlpYV02sqqVV4cDnjkERcWi61PwNtL0zQef9zGGWe0c99967j44ospKChg/PjxAPh8Pn74w0V8+GEByWQSsq3n3n8fJk/WKSwsHLbNm9frpa7O5H/+Zx6nnFKIw+GQ0gohxH5FapiFEOIQEgwGMQxYu9bLzJkxVDVGNGpj0yYvJ56Y7rc+HI7S2urg7LMNFixYgMvloqysrM+aiRMrSSRiaJqGpmnEYgnS6TiaZlBcXD7sPTkcDiZONLBanWiaRlFR0R59ZiGE+LgkwyyEEAe4cDhMIBAYtKSiVzQaJZlMct99Xurqkuh6kCVLlvD887ewaVOadDrdbwDJ889rHH10KFeKUVlZ2S/7q6oqbjfE4zaCwSBPPx3k/ffvyB3EG46iKKiqmms9N9jhQyGE2FckYBZCiANYKBQiFAphGEaul/FATNOkq6uLp5/2cMQRGdzuVtatW8ell17KwoULKShwkUzSJ+g2DIPXX1c44QQHDQ0NjBs3bsA6YUVRmDFD5+9/7xl5/d57Rfzwh/MoKCgYcWmF1+sllUqhqqpM3RNC7HdGVJJRW1d/FPAz4GTAAbwL/NTf1PhwbV39acBfBthmB9b6mxrn1NbVu4CbgAsAH/Am8F1/U+PTe/6RhBDi0BCNRgmHw7ka4VQqRSaTGbB9Wzwe5733rCQSCkcc0c2KFeu46KKLmDx5Mg6HgylTQrz+ukFJSQyn0wlAJJLAZlOIx2MUFRUNmfmtrEzygx8s5/TT56JpHvLy1EE7YwzE5XIxduzYUY21FkKIT8qw/ze+tq7eCzwDbAEmAqXAw8BDtXX10/xNjc/5mxqdu/4BJgFdwO+zl1kKnA2cAZQA9wKP19bVH7b3H1EIIQ4+qVSKjo4OgkEHK1d6WLPGjc1mIxwOD7i+ra2bZ5/1cNZZnbjdbhoaGqipqSE/Px+Xy8XkyXHuvPN3dHZ25vZs3JikpibMsmXLBgzCd1VeXsaZZy7kvvtKmTq1J+M9mtIKRVGw2+1y2E8IsV8ayb97uYDvAT/wNzVG/E2NKWAJYAWOHGTPb4EH/U2Nf62tqy8CLgGu9Tc1vuVvaoz5mxpvBt4GLt/DzyOEEAe93rZwoZDKI4+4uOCCINXV3bz9tn3AOmZd11m/3k5tbQe/+90KIpEIZWVl+Hy+3Jrx4ys58cTLsdvtaJqGaZq8+ip8+tMOrrzySgoLC4e8J1VVufhihS9+cRsbNtxBJpORNm9CiIPGsP/25W9qDAJ39v69tq6+BPg+sAPoV1JRW1dfD5yQDZIBjs2+z8u7LX0JOGlPPIQQQhzoTNNE13UsFsuQNbymadLe2YldLeWBB9zU129l2bKVgML773+Xww7LYBhGn2tEo3ECARtnn20wf/58fD5fv04ULpeL/HwPqVSSSCSCw6GSTitYLBqlpRXD3r+iKBiGxl139bSeKykp+ZifiBBC7D9GVSxWW1efytYwbwJq/U2N7bu9bgN+DvzY39TYOzaqt/9Qx26XaweG/S3cGQxg6MZobnOP0LQM7YGdn/j7ioOTfJ/EUEzTJNjeQSaTxqk6KS4evK1aJBIhEU+zahWcfdarrFn9AF+94AJcLhf+JzV2bu/CYuq4snXIAP4nE0yaEOHW3/yWWZdcQoHXPeD3cdqUMM8+7WDGSQE+2uHA54VQRwanzUIi0j3sc9gVk/Prv4xi6qRiEdqT8Y/xqYhPivx+EnvSgfx9KqmoGvS1UQXM/qZGNZthvhp4obau/iR/U+N7uyz5SrZGedUILqcA5nCLikaQ2dgb2gM7h/zghBgN+T6JwZimSSAQwKY6KSguobu7m8LS8gHLGUzTJKkZPPqYh8+d08mTTz7O/IWXU1BQgN1u59MnmnywrYCaqR5KSktzez7c1sUFF5h8+sSrmDRp0qCt3k442cmLL8UpLq/k8fUGLS234s5bSFnVmBE/CzYHTqeT0uz7i/2f/H4Se9LB+n0ade8ef1Nju7+p8XqgdYAa5NnAA/6mxl3TCoHsf+7+27Nsl9eEEOKQ1N7eTiAQ4Oab7+Tll7tYuXIlO3bsGHBtLBbD788wblwnTz65hlmzZpGfn095eTmVlZWMGRNjzZrfEgqFcnuSyRSpVJTf/nY5TqdzyL7IigIvvHAHHR1xNC2PK6+cT3Fx8YifRVEUxo4dK8GyEOKgM5IuGV+orav/qLaufvf+QAqg7bLOA5wJ/Hm3dZuAdLYl3a5mAH//WHcvhBAHsFAoREdHB//7vw8wYcI83n23mv/+70WDtlb78MNW7r77d3zqv+LZ3skFlJWV5YLgMWMqOfnkK3IH9wBeey3GtGk9XTGqq6uHvJ/CwkKuvXYujz1Wwmmn9fRE9nq9e+HJhRDiwDKSkowN2brlJbV19d8GEsBCoAb44y7rjgScwD933exvauyuratfCfxfbV39W8A24NvA+Gy7OSGEOOQkEgm6u7vZtMnFOedcwRe+YCOTibNuXTFjxuykoqKiT1mGYRj89a8+fvzjebjdERwOB0VFRbhcrtwaj8dDcXGSeDxFJBKhoKCADRvgC1/IkJdXgMPhGPKeFEXh6KN9TJzYczzFZnMN205OCCEOBcNmmP1NjR1AbbaE4r1sKcZMoN7f1Lhhl6W9qYvgAJf5JvCnbD/nIHAO8Dl/U+O2PfcoQgixbyWTSVpaWoacuEe2zVswGOTVV6PcffcKzjgjDYDdDh5PhNtuW0l7e58z1USjCQKBJBMmONF1nby8vH7ZX0VROOkkeOEFnUQiQSgUIhJRMM3wiIeIKIrCbbfdxpIlS9B1fdSfgRBCHIxGdOjP39T4OnDuMGv+mC3TGOi1FPCN7B8hhDjoJJNJWltbsdvthMNhfD7foH2IQ6EQ27alWbLkHn7zmwtxu90YhoGu65xyigO3++p+AzyefLKT7dtvJxabh9VmG7QvcnV1iuuuW86pp15KczMUF+usWLGCG2+8cUTPUVJSwqJFi9B1nYqKfXPoWggh9jcyg1QIIT6mdDqdC5YBrFYroVBowANzpmnS3Bxk/foqbr99DgUFPcGy1WqlrKwMi6WNp57ykU5H++x5910PP/jBfBwOOz63q991e5WXl3H66ZfjcNjYuNHFGWck+e//XtRnSMlQLBYLVVVVWCyWYUs4hBDiUDHqLhlCCCH+Tdd1AoEAum5n1SoPS5d62b7dTjw+cA/ilpYWrrlmDZ//fHsuWLZYLFRUVOBwOCgoyMc0DTIZjUwmA9lOF5pmkpfnwu12Y7UO/qvbbrczY4aD1as9tLVZKCgwhp3StzufzyeH/YQQYheSYRZCiP+QaZq0trai61ZWrfJy4YUxvF6TVaugocEgk8n0OzTX2WmltvZKJk609PQtBioqKnIlGF6vl/Lydj76SCc/P0JRURGbN0epqIihaVBeXk6ovW3I+zrySAWvt4PiYgNNs5OXl7cXPwUhhDj4SYZZCCF2YZomkUhk0Azxrrq6ushkdNau9fLVr8YpKjIJh9t59dXb+eijDLFYrM96wzB45JEk553XU9us6zqVlZV9xlgrisKRR8a5+eY76ezsxDRNnnkmzuuv346maYO2nNuVxaJwzz23cMcdt5NKpaS0QgghPibJMAshRJZpmrS1tZFOpzEMg+rq6kED1HQ6TSQS4Q9/8HHmmUlKSgzi8Tjr1q3je9+bzcaNTg47LNVnT0tLO08/vZyvfa0BTXNQWlo64MHAadOKOProRTgcJs3NzaRSeVx11ciHiJSWlrJo0SKsVitFRYOP2RZCCDEykmEWQoisYDBIOp3GarVis9mGbA8XCoV47jkPkydrTJ6sE4/HcTgcLFq0iJISO088sZSurq5c2QXA669bWbx4YW4gyK49lHfldrvJz3eRStkJBm2Ul5ujGiKiKApFRUWoqirlGEIIsQdIwCyEEEBnZyepVIrXX3dy111udu60kUgkMAyj31pd19myJU0waOXTn87Q3t7OsmXLUFWViRMnUl1dzamnXoHD4SKd7umxbJomL70U57jjesojhjqIZ7VaOekkjeefz/DCCyqf+lQXNpttROUYvUpLSxk3bpyUYwghxB4gAbMQ4pAXjUaJRqNs2OCipcXKV78a589/dgKQSqX6rQ+Hw6xf7+X88xO0t7ezZs0aFi1aRHl5OWQP7k2frvKvfzkJh8MAdHR08te/LiWZjOLxePr1Wd5dVVWCe+9djqa18cADy0Y9RGS46wshhBg5qWEWQhyUejPDux6oG0gmk6Gjo4N33nHT0WHhi19MAlBWphMIOPB44v1KJ95+O83EiTZCoZ5gecGCBUyePDn3uqIoHH+8lQceiDNlSk/gunWryUUXXY6qQkFBwbD3X1VVyW23zSI/P4/u7oZcMC6EEOKTJxlmIcRBJx6P89FHH7Ft27ZcScRggsEgO3eqvPaanfPOS+b2n3JKJ88+6+yXYTYMg6eesnHCCV2sXbuWOXPmMGXKlH7X9XpN/vznpUQiETo7O3n+eYXTTnPgcDiGDeIBVFXNjbPOy8tDVdVRfgpCCCH2FMkwCyEOKolEgmAwiN1uxzRNurq6Bs3OxuNxgkGdJ57wsGBBDEWBtrY2Vq1aBUBR0bVomp4bLgLQ3Z3AboeCAjfz58/nsMMOG/DaRUVF1NUtRNedxONxQiEFj8fE5Rr5wT1VVclkMhIsCyHEPiYBsxDioJHJZGhrayOTcfDuu1aqq3W83uSg/Yu7ukL84Q8+Lr00jsXSU8t89913c91116EoCvffbyUcTpJIJHLZ3r//PcUxxxhomsbYsWMHzRZbLBbOPtvFCy/YGT++nddfv5tweBYVFRUjfp6CggLi8fiIx1oLIYTYO6QkQwhxUNB1nZaWFuJxO6tXe0inFR54wI3FYuk3QIRscL1+vY3TT0/hcpnEYjHcbjfXX389FRUVlJWVMWVKmDffdBKNRiHb6eKf/4QJE7qxWq243e4h72nsWBvvvJPkf//3Xr7znZnk5+ePqtOFqqoUFhYO2KtZCCHEJ0cCZiHEAa93RHU6beWuu7zMmRNj6tRuxo/vZssWlWQy2W9Pd3eE7dsdHHGERjAYZPny5fh8vlzf4ng8zrPP3snbbydJpVKYpkk8niCZjPHb3y4bURDr9Xr5+tczrF49h/HjC3E6nXvl+YUQQuxdUpIhhNgvGYZBS0sLmqZRVlY26JAPskNE0mmdtWt9zJwZIx4PsnLlSkDhvfcWU1PTvwb46acNPvMZjXg8ztq1a/nWt77Vp/TB4/Fw7bXf5bbbdEwzRiwWY9OmBNOnu/jUp+aPqGuFqqpYrVbsdjuZTEZKK4QQ4gAlGWYhxH7HMAx27twJgN1uJxQKDbm2uzvMPffkce65SXQ9yLp167j00kuZPXsWmzatIhyOkslkcnt0Xeftty1Mm6aRyWS49tprqa6u7nftgoICJk/W2b5dpaOjgw0bLHz602kKCgpG3OdYVVVM08Rms2G32/+jz0MIIcS+JQGzEGK/YpomgUAA04RQyEIy2VNvPNAAEbLZ5Wef9TB1aoiiogjr1q3jwgsvZOrUqUydOpWLL55Ha2thnzrmYDCO1wuxWIzf//73uQN9A5kxw+Tllx3YbHY0zYrDoQ9bu7wrn8+HoiiSXRZCiAOYBMxCiP2GaZoEg0F03eD++70884yT5cu9KIqVSCQy4PoPPkgSCCR58cU7AGhoaGDatGm43W48Hg8nn+xi82aVeDye2/fcc2mOP15D0zSuu+66IQPm4mIX7e0xHn3UyeTJOpFIZMj1u1NVlaqqqlxttBBCiAOPBMxCiP1GV1cXqVSKBx/0cOyxac45p4NTTunkpZfUAQeQpFIp1q9XOffcJAsXLsThcDBmzJg+9c5jxvgIh026u7vR9Z6eyu+9p1BZ2c3q1atH1LWis/M3TJ8e4rjjuli9evWAhwiFEEIcvCRgFkLsNb0Z4x07dgyYId5VIpEgEonwxBMeDj9cY9y4MEuWLOGZZ27h1VfTZDKZ3LjrXh99FMNmS7BmzQo0TcPn8+H19h0M4nK5MM0oK1bcSVtbG+FwLDsUxMG11147bLbY5/Pxne9cQU2NE5fLyTe+8Y1RZZiFEEIc+EbUJaO2rv4o4GfAyYADeBf4qb+p8eFd1swFrgXGAzuBJf6mxt9kX3MBNwEXAD7gTeC7/qbGp/fmwwkh9q1gMEgqlcJqtRIKhfB6vYMeluvs7OTFFz3k5Zkce2yGeBwWLVqEYRg884yT7m6DkpJEn2D18ccVvvhFKzbbfAoKCigoKOh3XYvFwowZTlpbryadTrNxY5RPfcqGoigUFRWN6DmKi4uJxWLous6YMWM+xicihBDiQDRshrm2rt4LPANsASYCpcDDwEO1dfXTsmu+BlwPzAbygauAy2vr6j+dvcxS4GzgDKAEuBd4vLaufuCZskKIA15nZ2e2f7EVXe/52UADRMhmlz/4QKG11crpp6dob29n2bJluFwuxo8fz/TpCV55Re+zP5PJEA6DwxHD5XJRUlIy6L0cfbSVrVvzsdvtvPWWi5qablRVHXGni7y8PDKZDA6HQ4aICCHEIWgkJRku4HvAD/xNjRF/U2MKWAJYgSOza24ArvE3NW70NzWm/E2Nj/ubGqf4mxpfrq2rLwIuAa71NzW+5W9qjPmbGm8G3gYu38vPJ4TYB0KhENFolFdfdbJypYebb84jlbLlJubtrq0txF/+4uXzn+8gHo+zZs0aFixYwLhx43C73Ywdm+Kee1b0aS/37rtRiooiLFu2DJvNNuiIaoC8PA+GoRMIWEinewaPjIbNZqOkpEQ6XQghxCFq2JIMf1NjELiz9++1dfUlwPeBHcDTtXX1lcARgLW2rv4VYArwYbZk4wHg2Oz7vLzbpV8CTtorTyWE2Gfi8TjhcJi333axfbuNhQtjtLVZWL/eyXnnRTBNs09m1zAM/H4rn/1sO7/73QrmzZvH1Vdfzfjx43NrqqurmTHjclTVJJVKoaoqzz5rcsYZDmprF1BRUTHkPamqyllndbBhg8H559uxWudRWlo64meKxWL88pe/BOB73/ue1DALIcQhZlST/mrr6lPZGuZNQK2/qbG9tq7+xOzLlwMXZeuX5wH319bVtwJl2dc7drtcOzD0/8oBncEAhm4Mt2yP07QM7YGdn/j7ioPTgf59CocjxBMJnKpKQUH+oOt03aA12MbWrW5ee03hK/+vk50fJXC7XWzb6qItEMWGgcPhyO2JRBK8966DTx3VxgVfqcfU0rgd3n6fV3GhxgfvJcgkPsDr9dL8EaB3YrWpdLS2DPsMqm0Hb7+5hqOmXUBJSTGdbYFRfQbz5lwKQCLSTSLSPaq9e9qB/n0S+xf5Pok96UD+PpVUVA362qgCZn9To5rNMF8NvFBbV3/SLtf4kb+p8f3sf7+1tq7+YmAO8JdBLqcA5nDvWVQ6bEy9V7QHdg75wQkxGgfy96mrqwubU6PI21PHW1haPmgdbzAYJBqvYvNbThrmx+noULjvwYeYOXMmzTtX8lHzQibV+Pocttu4qZMTTwpz34MPsWDBAg477LABa4v/+/NBnn66kJopEVo7rFSPdWKxxxg/qWZEE/ScXh9zGuZx9913c80111AyTFZ6d4NXSH/yDuTvk9j/yPdJ7EkH6/dp1G3l/E2N7f6mxuuB1mxWuT37UtduSz8EKoHeNM7u//5ZtstrQoj9UDgcJhKJYBg2Egly3S4Gous6wWCCJ55wMXt2nI6OdtasWcOll17K1KlTueaaufzrX4V9JvaZpslrr8EJJzhoaGhgwoQJgx7Eq6520tISw2azsXGji2OP7WblypUD9mceiNvtprCwkIaGBsrKykawQwghhOgxbIa5tq7+C8ByYKq/qXHXI+4KoGW7Z7QDJwKv7fJ6DfBKtnwjnW1J9+Aur88A/rRnH0cIsafE43G6urrYscNJU5ML04TPfz7BxImJAdeHQiH+8Ic8LrooTjIZZ+3atcyZM4fp06ejKArjxpXS3R0jne4ZHmKxWIjHExgGJJMxSkpK+pRq7M40TV59dQnbty+ktdXDF76gsnjx4hHXE1ssFqqqqrBarUMeEBRCCCF2N5KSjA3ZuuUltXX13wYSwMJsQPxHf1OjXltX/2vghtq6+n8ArwPzgWOA+f6mxu7auvqVwP/V1tW/BWwDvp3t17z0E3hGIcQopdNpgsEgbW1Onn7ayRVXRIlG49x9t5t583Q0Tes3Ie+ttzKMHWunoMAkGjVYuHAhNTU1uYyx3W5nw4Y7qK+/jKKiGHl5ebz2WoJx46IsW7aMG264Ych78vl83HDDAp58sogZM1JomjbsYb/dqar6H3waQgghDnXDpln8TY0dQG22hOK9bCnGTKDe39S4Ibvs58AdwEPZw32XAef5mxr/kX39m9ls8jNAEDgH+Jy/qXHb3n08IUSvcDjM9u3bCQSGroQyTZO2tjY6Ox089piTr341SDIZZ9myJWzadDPbtmX69VPWNI2nnnJw4oldxGIxVqxYQUVFRZ/yiry8PBYvvpxt23qGgJimyQsvwCmnOFi8eDH5+YMfJuw1eXIBl14aY/z4MBaLRQJgIYQQnwjFNIc9d7ev7ZMbPFiL1sW+sa+/T+FwmFAoRDqdRtM0xo8fj8vlGnBtKBTio49i3H9/Hl/+8lbuv38dCxYsQNM0wmEbmzaV8JWvpCkvL8/tef/9EI88Eqa1dQlz586lqqpqwAC4o6OL5cth1qwIVquNlStdzJkTpaCggLy8vGGfI5VKsXnzZu69914WL17MhAkTPuYnc2Da198ncXCR75PYkw7w79Og06xG1SVDCLHvxWKxUfUBjsVi7Ny5k2TSztKlt+N2w+LFi6mpqem31jRNQqEI992Xz4UXtrF27Touvvji3CS9zs5OnngiTiql9+mn/Ne/Gpx1lgO3ex7V1dV4vd4B78XrdZNKtaIoNv71LyuTJxtEo1Gqqkb2y1XTNO655x4uvPDCUZdjCCGEEP8pOfkixAEkFovx61//mra2thGtTyQSvPPOO9x66yruucfNlCnf4YgjvoXdbkfvnVe9i2g0SmOjmy9+MYHLBQsWLKCkpISqqiqcTid2u52//e12wuFYrtuFrusEAiZ5eVG8Xu+gwTLZcdZbttzOyy+n2bhR5eijQ6xatYpkMjmi5/F4PHz/+9/nqKOOwul0jmiPEEII8XFJwCzEAWb+/PksW7asXx3x7jRNY+vWraxadT8u1wKuvNLkoossBAL5RKMJEon+3S527oxjmhZcrlaWL1+OYRhUVlbmukqUlpYyZ85CAoEiIpEIAK2tESyWOMuWLRu2H7LX6+XGGy/nrbcKqazUKSxU+frXvz6qjHlJSYkEy0IIIT5REjALcYCIxWL87Gc/o6uriwsuuGDIoNE0TVpbW4lE7Hg83+Tqq930xrInnNDJjTeuIRgM9tvz+OM2Tj21k3Xr1jFz5kwmTZrUb0jJqafm8cYbjlyG+W9/05gxQ2XhwoUj6m9cVVXG7NndfPazKXRdl9IKIYQQ+z0JmIU4AMRiMXRdZ9asWeTn5+Pz+Whubh5y/QcftHHNNauZNSuGw9ETEGcyGaZPtzF9+uJ+2eBoNEFXV5zqahdz585l+vTpA2aMy8o8RCImhmGwc+dO3nnHQk1NhsLCwhE9i9vtzmXHM5lMv/Z0QgghxP5GAmYh9nNtbW38/Oc/zx7cK+CFFxw0N6e59dZbc2URu2tubuH66x/i5z+/kOJiN6Zp5sornE4Vu92NpvX0U+717LMdfPDB7UQiESoqKgZt2aaqKoWFYdraHCQS4HZbiETCI+pyQbauevXq1bS0tLBq1aphS0uEEEKIfU0CZiH2gVgsNqJAMRaLcfvtt/PlL3+ZYLCQRx91UVZmsH59MfPnzx9wYl0qleKZZwr43vfmMX58cS5YrqqqwuFwUFxczNixaXbscOQCbtM0efNND//zP/Nxu90UFBQMek/xeJz33lvKX/+q8dJLKkcd1cWdd97ZJ/geSu/BvSOOOILrrrtuVPXLQgghxL4gAbMQn7C2tjZ+8pOf8OMf/5hoNDrkWl3XmTlzJpo2hueeU5k7N0ZNjUZVlU5XVwHxeLzfnvb2MM3NaY4+Ws1do6KiIleLbLVaOfFEC6+8ouUO/iUSSdJpyMtT8Xq9fQaO7M7j8fDd716Fy+Wiq8vCkUeqXHnllUN2x9hdYWEhbrd7VHuEEEKIfUUCZiE+QW1tbdxyyy1ccMEFXHbZZUOujcVi/OQnPyEUsvP4405mz47Tm1A+++wkzz7rJJ1O99v3yCNxAoFbicfjZDIZKioq+tUiFxaaPProUrq7u9F1nc2bY1RWRjAMY0QT9yorK/nCF6J8+csJdH30I6qFEEKIA4kEzEL8h0ZTexuLx4nFYtxyyy25N6LjAAAgAElEQVScf/75VFZWkp+fTygUGjTLnEwm+drXGnjssVLmzo1htf774J6iZDBNyGQ0wuFwbk8mkyEYzOPaaxdgt9spKyvD4XD0u3ZJSQlnnXU5FouPnTt34vfHefPN29E0bcAyj93ZbLZcsB6PxwedGiiEEEIcDCRgFuI/0NbWNuIBIrFYjGXLVxAOh5k9ezbR6BjWrHGzYYODaDTKL37xi37BdywW4+c//zl/+IMv1+XCMAxM02TMmDGUlZVRXp5h69YMv/zlL3P7//GPVqqqDJxOJx6PZ9BA1mKxcMYZTl5+2YnFYsU087niinmUlJSM6PljsRirVq2ipaWF1atXD1gaIoQQQhwsJGAWYpRisRgrVqzgkksuYcWKFSPKNM+57FIymQxbtxbzyit2Zs+O8+67Nmw2Hw0NDf0OvqmqyuTJi6itteHzmZhmz5+qqiqsVisul4tjjtHYsqWIuXPn4vF4iMVi/OhHd3DMMT1lFkVFRUPe0+GH2/jwQyt/+1uamhoNp9M54ppij8fDddddxxFHHMEPfvADObgnhBDioCYBsxD/gW9961sUFBRw8cUXDzndLhaL8atf/Yqu7m4+/NDJm2/aufDCBIoC55yTZP1614D7w+EogUAhU6dqmKaJrutUVVX1KZc47DAvgUDPIT7DMHA4HBxzzCIqKlTcbvewpRVer4cpUzp44IEV1NQ0Y7fb+w0pGUpeXh5utxufzzfiPUIIIcSBSAJmIUahtxQjGAwSjUZxOp10dHQMmWW+5JJLCIcK+fvfHVx44b9LF8rLDbq6LGQyGrqu534ei8V46imNGTN6aoQ1TaOysrJfMOt2u1EUE11XaG1t5b33wowd60bX9RENEVFVlRkzHNxww0Xcd99aDMP4Dz8VIYQQ4uAmAbMQI9RbinH++edjtVpzAWwoFOpTR7zr+l/+8pcEgxn8TxYwe3YcRempRe4NkCsr07S22nJjqnsz0v/8Z4Lp0zUymQylpaUDZqGtVivHHKPzyisGN910E4880sYpp/RMzhvJ9DxFUVBVleLiYubOnUtlZeUe+qSEEEKIg4sEzEKMoONFLBbD4/Fw2WWX4fF4ePFFF7/7nYclS7x4vb7cz3fl8XiYPftS/vSnSr761Q6s1p5g2WKxUF1dTUVFBUcfneKVVwx+/etf595j9uyF+HxuTNPA7XbjdrsHva/jjlPYsqWAyy67jKeeWoeqRnA6nSN+bp/PRyqVorCwcFTlGEIIIcShRAJmcUiLRqOEw2FuvvnmQYPmWCzGr3/9awKBAIZh8NxzHlIphfnzY5x1VpIXXlAHbN1mGAYbNng4/fQUHreRC5YrKyuxWCxYLBZqajyEQl7mzp2bC4w3bbJzwgn6iA7u5eV5ME2DV1+t5rzzrsDhcIxqGIiqqowdO1b6KAshhBBDkIBZHLICgQA/+tGPaG5uZtasWYOu83g8LF68mFQqxcsve9B1OOusFADTpmm8/ba9Xx0yQFtbkHfecTB9es/BPYCKioo+U/R8Ph+maeB0ukkkEkQiEd55B2pqMrhcrmGzvi6Xiy9/Ocb06Rrnn99TJqKq6og/A0VRsNvtQ072E0IIIQ51EjCLQ1IgEOBXv/oVF198Mfn5+SSTSW666aYBs8yxWIxkMsm//uVi504rtbU9wXJvLfKECRotLf+uQ+7d853v3MJRR3UDoOtGLrO8K6vVyhFHGGzZ4uSDDz7gRz/6X3Q9jq5rI+o+oSgKxcV2qqt1FMWUASJCCCHEXjD8ySCgtq7+KOBnwMmAA3gX+Km/qfHh7OtbgWpA323r0f6mxvdq6+pdwE3ABYAPeBP4rr+p8em98lRCDCEajXLzzTdz8cWXsG1bNR9+qHDCCQPXIfce3DvrrJk891wFDQ09AbWu6zgcDtxuN0ceGeLFF6Gx8VZuuOEGPB4PbrebyZOvZMYMC5qmUVRYMGi2+KSTYNWqNKHQ7zniiLlMmKCiKMkRZ4q9Xi+dnZ2YpkleXt4e+ISEEEIIsathM8y1dfVe4BlgCzARKAUeBh6qrauftsvS+f6mRuduf97LvrYUOBs4AygB7gUer62rP2zvPZoQ/ZmmSWtrK3PnzueJJyZgmgrd3RY2b3YM2FnC4/Ewa9al/PnPFcyeHUNReoJlp9NJWVkZeXl5jBunEonk9alDjsUS2O09bd+cTueQB/EKCz2Am8svv4K2tmqOOEJDVdURl0n0BvkOh2PAWmohhBBCfDwjKclwAd8DfuBvaoz4mxpTwBLAChw53Obauvoi4BLgWn9T41v+psaYv6nxZuBt4PI98xjiUJZKpWhtbSUcDg+7dvv27SxdupT77vNw5pkpTjghTW1tkhdfdKDrOpqm9VkfjUZ58UUvtbUpHI6eYFlVVUpKSnIBbVFREYaho6ouUqkUsViMDRsSHHVUz/WGO7jndDqZMiXNunWlFBUZ6Lo2qkyxoiiMGzdO2sIJIYQQe8mwJRn+psYgcGfv32vr6kuA7wM7gF1LKi6orau/FqgC3gdu9Dc1/gk4Nvs+L+926ZeAk/bo04hDTiKRoK2tDbvdTnNzMx6PZ9DSh3g8TiwWp6joW5x6qp1x43qCY4sFamo0tm93YLe3UVVVBdlyjF/84hek0ws56ywLhmFgs9koLS3tk/212WwcfrjJ1q1O4vEPeOihh1CUOcyebUNV1WF7IlssFk491eQzn+kp99A0pBZZCCGE2I+M6tBfbV19CggCpwO1/qbG9uxLrwPvZcsuxgKPAo/W1tWfDJRl13Tsdrl2QHpZif9YMpnMBcvt7e2sXLmS5ubmQdfv3LmTa69dy1FHpamp6QmWNa2nu8UxxyR4+WWdW265JXfwz+PxcOKJCzjhBDXX5aK8vHzAUokTTzR58cUMq1at4ktfqsdiycNq1UecKfZ4PLkuG6MpxxBCCCHE3qf0BgIjlc0wXw0sBk7apU5593WbsoG0H7gbcGbLOXpf/ynwNX9TY81Q79cZDJiG/smP7NW0DDZb/+lqYv+QzmRob28nElF54CEnr7yygiuv+BKTaxQmTZjQL+BMJpM89WyG7q4MZ5/dE5hqmka+z4fH46G9vZ277y3k3HM/YtKE8SiKgmma3L5Up74+hKJkKCspGXDiHkAyleL2pTa+Ut/M1m1FpNMKRx0ZoaK8DIvFMuz3yTAMWlpbUVAoLCzANYrhI+LQI7+fxJ4k3yexJx3I36eSiqpBs1Uj6pKxq2xW+frauvoLsjXI3xpk6RagEghk/16aLePoVbbLa4MqKt03Sej2wE5KKqr2yXsfqjKZDIqiDFvCoOs6zc3NmJZqHn3c4OvfgHR6IXfd5eaVf/yK66+/noKCgj573n33Q7Ztr2DevFjuvYqLi3NDPnxFJbi9EYpLq8krLMbpdBIMtmNzKJSWW3E4HJSWlg56T6ZpMm16G8nMRN7/QOWSS+LY7V7KsnXFI/k+WVUXhmH0qY8WYiDy+0nsSfJ9EnvSwfp9GkmXjC/U1tV/VFtX79ntJQXQauvqJ9bW1S+rrasv2O316dla5k1AOtuSblczgL9//EcQBzrTNAkGgzQ3N7Njxw4MY/B/UTBNk0AgQDhs4+67TTKZ32AYcXw+N5MmOamru5Ld/9UkGo1yzTUrOPXUnqogTdMoLCzsMxHP4XAwbZrBhx+6aGlpIRaL8f3v/4oxY6K59UNRFIVTTjF4/nmVadM0FEUf1cQ9gOLi4n710UIIIYTY90aSYd6Q7b28pLau/ttAAlgI1AB/zGaJzwN8tXX1V2WD4+8AhwFf8Tc1dtfW1a8E/q+2rv4tYBvwbWB8tt2cOMS1t7eTTCZxOBwYhkEoFBq0s0Q0GqW72+Tee/OYNasNl2shbrcbXdc57bQEjz5axPTpyT57LBYb06cvZsoUK5rW04FioKEgxx9vZc2aOOvX384Pf/hDJk5cxGmn2XE4GDbrDVBS4mbWrDBWq5VMxujX01kIIYQQB6ZhM8z+psYOoDZbQvEe0ArMBOr9TY0b/E2NiexhP282o7wd+CzwWX9T47vZy3wT+FO2n3MQOAf4nL+pcdvef0SxP+sNll97zclddxls25YmGo32yxKTzS53dXVzzz0+LrggyNq1KzBNE03rmYrndJokkwqZTKbP/o0bYxx/vBPDMHA6nYNmi0tKPOi6iwULFhIKdWOaeTgc2ogzxV6vN5cdV1W131Q/IYQQQhyYRlTD7G9qfB04d4jX3wG+NMTrKeAb2T9CANDV1UU8HufJJ70YRpRt226mqcnBsmVzSaVS/YZ9JBIJHn7YSV1dAq/XZMGCBTidTqqqqrBardnBHTE6OhKUlCRwu92Ypsnzz8eZNcuaqw8ejMPhYOJEnba2fFIphWnTdAxj5Jliq9WK3W4nlUoNWe8shBBCiAOLpMDEHpNOp2lubqa5uXnIOmSypRWRSISnn/bg8xl89rNpvvnNqzj//KsJBNRca7ddtbRESSZteL2tLF++HF3Xc8Ey9PQunjIlwi9/uZrW1lYA2ts7ePbZpWQyUTwez5BZX0VRmDHD4MEH3Tz2mIvjjktjt9tHlSkuLS2lurpayjGEEEKIg4gEzGKPSKVStLS05NqxdXV1DbrWMAw6Ojp44QU3mhbjU58KsWLFCgDOPDPFz352Z7/9pmny0EMJTj+9k3Xr1jFz5kwmT57cb0jJyScXMHXqYqxWK6ZpsmULzJx5OU6ns1/njIEUF7u4/PJurrkmgsWijzrwtdvtOBwOObgnhBBCHEQkYBYfWzqdJhAIYJp2tmxJkslYiMVig2aZQ6EQb7zhpLm5g3ffXQLAvHnzcLlceL0OTjnlSux2e5/97e2drF+/nOJig7lz5zJ9+vQBeyLn53tRFDeGAYFAgOefVzjjDAd2u33QCYC78nq9eDw6FktPYD+aEdVCCCGEODiNug+zELvKZDIEAgEyGTtLliTYseNOJk1q4KqrHMRisX4Bp2EYfPBBnBdeSJDJ3MmsWbNQVRWPx0NRURGJRILy8ijt7SbFxfHcgbvNm6GhYSGqaqW0tBRVVQe8H7vdztSpGh9+6GTs2DDRqInDoeN29++KMZDeOmSyNc1ycE8IIYQQEg2IPnrLKVpbW9E0bci1hmEQCARIp22sWKGg68u55povsWXLSv75zzDxeLzfnng8zsMPmySTv2XWrFkUFhbidrtzbeRcLhfHH2/wxhsu2tracve0cSPMmOEAGLAl3K5OPhleeCHDDTfcwVtv/YpoNDqqnsh5eXkoijKiEg4hhBBCHPwkwyxyTNOktbWVTCaDxWKhs7OTsrKyQdcHg0ESCQtr1niZMyeGw9HTE/l//ucirr32HpYuvYzy8vI+e95+O8GECR7OOGMhqqridDopLi7us2bKFDePPhrijTfu4Ec/+hGKYiEajWOz/TuYHUpBgYvycgWb7dt86UtJ8vPdIyrH6JWXlyelGEIIIYTIkYBZwG7Bcm9wmUgk0HV9wGAznU4TCiVZu7aQSy6JYbfHcLvdZDIZSkryOe20K7HbNTRNyw39ME2T9eut/L//14nT6cRutw/Y5s3jcaOqaS68cAGapvHii128++5viUZnU11dPeyzeDwePve5Tux2O7quSscKIYQQQnwsUpIhcqOpNU1j/XoPv/+9myVLwGKx0t3dPeCezs4u7rsvny9+sR27Pcby5csJh8NUVFRQVlbGYYdZ+de/+raHi0YTZDIxVq9eQTweH3QMtNVq5dhjdT74oIju7m5ef72AG29soKCgYEQ1xRaLBYfDkXs2yRYLIYQQ4uOQgPkglUwmCYVCw9YhA3R0dJBKpXjwQQ+FhWHOPXc7H354G6++qpFMJvutNwyDp56Cww/fyUMPLcM0TebNm0dNTQ2qquJyuTj2WJM33lAJBoO5fX//e4ITTnAyd+5cxo4dO2Twe+yxCps320mlMui6gs83ukyx1+slnU7LwT0hhBBCfGwSSRyEotEora2tRKNR2tvbh10bj8d55BEvFRUtPPfcb1i1ahXf//5MXnutsN+YaYBIJMobb2R49dXVuS4XkydPzpVeAIwdm09HR5SlS5cSDocxDIMNG+IcdVSG/Px8XC7XkPfl83nQ9TALF66mpqZ5VBP3yAbMvdluIYQQQoiPQwLmg0w4HKazszM3oS6VSpFOpwdca5omoVCIhx9WKC3t5tVXV9PQ0MCiRYsoKiqgsFCntTXZL8v8zDNpTj1VZeHChRQUFFBRUdGvJ7LL5SIvz83s2ZdjmiaBQBvPP7+UeDxMfn7+sM/hcrm49FK49dav8fLLv0fTtFEd3FMUBafTKdllIYQQQnxsEk0cRMLhMKFQiOZmld/+tqcW2WKxEQqFBlwfiUR49tkMzz+/lOOO01i4cCH5+fkUFxdTVFTE5Mkd3HTTv8dMky3HeOMNhcMP78bhcFBaWpqrF96VoiicdJLGW28VEwqFePllkyuu6Omi4Xa7h30WRVFQVZWSkhIaGhokUyyEEEKIfUYC5v2YrutEIpFBM8S7SiQSdHV18f77Tp59VmXevBgnnJDmqae0Qfdv3x6jubmQ//u/BtxuNw6Hg4KCAoqLi/F6vRx7rI/p06/qU2rR2RkDYqxYsRzDMIYsrZg2zc6HH1qw2+28+aaLk05yjGpstNfrRdd1XC6XdLoQQgghxD4jAfN+Kp1O09zcTCgUoq2trV8d8a4ymQzBYJAPP3SxaZOD2bPjJJNxJkwIs2bNb2lp6T+ERNM0Hn/cwec+14Hb7UbTNHw+X59yiaKiAmw2F7qu54Lu555LM2OGk4aGBsaOHTvkM3i9HlRVx+/PYBgxDEMb1QARt9uNqqoUFhZKaYUQQggh9hmJQvZD6XSalpYWbDYbVqsVwzD6tGfbXWdnJ//6l8rGjQ4uvjhOR0c7y5cvxzRNZs68hKVL789Nzev10UcRdD3OPfcsJxKJkJeX12+ynaqqVFUZbN3ak+nWdZ3Nm2HMmG6Ki4uHrSl2OByceWYnTz55C62tNxGLxUZUjtFLURTKysqGnewnhBBCCLE3ScC8n+kNljXNwdq1blau9JBI2AmHw4Ou/+ijNH/9q5NZs3qC5bVr1zJr1iyKi4s5+WQP06Zd3S9Du369yZlnZpg3bx5FRUUUFhYOeP3jjovyi1/cmc1gt2CxJFixYtmIDuApisK4cYVcf/0ivv71xRQVFUmmWAghhBAHHIle9jLTNIlGo6RSqWHX6rpOIBAgHnewapWH885L8LnPdfDwwzqZTAbDMPrt6ewM0djoY/bsGB0d7axZs4bLLruMo48+mqKiIsrLXaTTHtLpdK6sQ9M0Pvooyh/+sAxFUQactterpqaUY4+9Ap/Px8svuzj9dDsLFiygqKhoRM/v8/lwOHpql2WAiBBCCCEORBIw70WGYbBz5046OzsJBAIDBry9TNOkpaWFeNzGXXd5uPDCIKoa4557bmX9+ltob+/f3s00TZ55xuS009JoWpw1a9YwZ84cpk+fnjtYV1RUhN1uEAoliMfjAGzbFqGiwsO8efOorKwc8hCey+Vi7FiVN95IsnlzikmTdIqKikZ8cE9VVWw2Gzabbdjey0IIIYQQ+yMJmPcSwzBobm6GbNmE1WodtL0bQHd3N+EwrFvn5bzztrF27XIArrrqKm68cRFvvFFCNBrtsyeRSPHWW3YmT+7G6XSyaNGiPsEy2THTU6ZE+MUvVuXawz39tMGxx3bj8XiGPYRnsVg48cQIv/nNUnbs+BWRSHhUB/cAqqurqaqqGnGQLYQQQgixP5GAeS/ozSzH40nuucfk8stX8cYbIaLR6IDdLkzTpLMzwj33+Dj33G384Q9rueSSS7Db7eTn5zN+vI2tW5NkMpk++zZujHH44WGWL19OLBZj4sSJAwalp5yST01NT3u41tZWtm6N09i4FNM0RxTEjh9fxG23LeD66xfh8XgkUyyEEEKIQ4ptBGuoras/CvgZcDLgAN4Ffupvanx4gLWnAM8BP/E3Nd6Y/ZkLuAm4APABbwLf9Tc1Pr03HmpPM02TcDiM1WodNrvaW1oRCsW56qo1/PCHDZx11oV85zv3cscdl5BOp1FVtc+ecDjMQw95OOecdv74x55gubCwkMrKSux2Ozt37uT552/nggsuoby8HJvNhmmabNyo8LWvOTj++AYmTZo06IG6/HwvdruBoqRobjYZP97Dqac2UFFRMaLnz8vLIxwOY7PZRtVHWQghhBDiYDBshrm2rt4LPANsASYCpcDDwEO1dfXTdlvrAlYD0d0usxQ4GzgDKAHuBR6vras/bI8/0R5mGAYtLS10d3fT3t4+7OG9trY20mmTu+7y8tOfNjB1qpOKihLOP/9yuroKB2wP98EHCTwehYoKI3egrrq6OjduurKykosuWkAoVEgkEgEgkUiSTkMmE6WkpKTfaOpd2Ww2/uu/Mrz2mp3nn1c59dQUPp9vyD2777fZbKTTaWnxJoQQQohDzkhKMlzA94Af+JsaI/6mxhSwBLACR+629mfAO8A/en9QW1dfBFwCXOtvanzL39QY8zc13gy8DVy+5x9pz+kNlg3DwGazkclk6OrqGnR9PB4nkUhx550Wurtvoazs34f86uqsPP203i/gNgyDpiY7p53WwYoVK9B1ncrKyj5t2xRF4bTTvPzznyqJRAKA116LMXZslOXLl/fLWO9OURSOP17hH/9Ik59vYLVGcDqdo/osKisrGT9+/LDvJYQQQghxsBk2YPY3NQb9TY13+psa4/QEwCXADcAOIFdSUVtX/xlgFrBwt0scmy39eHm3n78EnLSnHmRPMwyDQCCArps88oiHO+80uf76lXR2dvabmterqyvE/ff7+Oxnk3z72wtyE/TsdjupVIRnn72DUCjUp1tGa2sUiyVOcbGbuXPnMmnSpD6jqHuNGeOmvb1nql97ezvPP69w2ml2rrzyyhFlfa1Whe7uX3Pssc0sX758wPcYisVikR7KQgghhDgkjSoCqq2rTwFB4HSg1t/U2J79uTtbivENf1Njy27byrL/2bHbz9uBkRXR7gPhSIRMxmDNmjyOOirDzJkJJk26GkWx9etWAZBMJnn8cRtTp4b4y1+WQXZkdWlpKaWlpUyYMIFzzllAJuPLZYkB/vznEB98sIRwOMzYsWNxOBwD3o/T6cTlChOJqCSTaXTdisOhUVZWNuD63ZWWljJ//nxKSkpYtGhRnxHYQgghhBBicKNKM/qbGtVshvlq4IXauvqT/E2N72VLMd7yNzXeNYrLKUD/lhG76QwGMPTB+xfvLalUmjtXKpx9VjOK0cqtv3mQE0+8mO/+//buPzbq+o7j+POutHhcrwI9WkqhlP3Kpmw6ncnQBdzi17Gvc8vXyX4YJxmVH1tCIgN/ZJmKS+Y2zRIDEUKIugU3Y/zxnc5+t/lNxow/xtwcc0FF4ohMB6UU8KBXflyvtz/4dDsr/d63vVLa+74eSXPpfb7fT+7be/Xbdz/3+X6+Nz/O2ju/yexZs963/d597/HOnhQXXdDBN679Gj1HM6Tr68lmDpPNnJrG8cnzj/PSC33UVO0mXV9PPp9n105YsfQa+k4e53j3EY53n/6OftmeHna+cR+9ue8xp3UCc1qy/Oed/UysinEiezTUMcXyvRzo2EtdKkVXx94R+ClJWL29Of3MZcQoTzKSlCcZSeM5T+npMwZtG9rn8qeK5i7gDst2FgErLNt5ErgO+NQgu3SYx2lmGke/hqK2QU2dNvqD0H19cN+6OAvtHmbOrGHTJo8bly0nnU7z1u41TGvMU9/4/xt+FAoFHnlsIgvtDI8+/gRtbW20trZ+YJ7wvMtSvLQtw6TUBOobm9i37z1q67ppnDGDdDrNpEmTBn1NaWDtXbfy6KNJ3v53nGuu6WLz5qdYu3YtyWQy1HFNmdZIPp+nurpaK12Msq6OvYG/iCJDoTzJSFKeZCRVap7CrJJxlWU771i2M7AqiwG9QJtZKm6HZTtdlu10AZcBt1i283fgFeCkWZKu2KXAiyN7OCNnwYIO2ttPTa1YsmQJzc3NxGIxamsTHDt26mYk/U6cOMnhwzEaG/toa2ujpaVlkIvqCrzwwv1kMj10dnbS3p5h9+71HDt2LLBY7jd9+nQWLTrKDTf0cM45NaxevTp0sYy5iYmWhRMREREZmjAjzNvM2svrLdtZDRwzF/Z9BHjSrMl8+4B9HgP+DNzje27Gsp0HgJ9YtvM6sAdYDcw2y82NOfE4TEv3snz5cqqrq2lubiaRSNDX18d55+1n584EicR+WlpaANi+PcusWUfZuHEjq1atGrT4raurY+XKZezeXUt9fY6OjincdttSJk+eHOp1VVdXv+9ivbDzl0VERERk+MKsknEQsMwUil3AfjMFw/E9d5vvuYd9z323+As4ARzxPbd/ysUq4BmznvMBYCFwpe+5e878IQ5dNpvloV/8klwuR0NDw//ubBePx7n44hpeffUE69atI5vNUigUeP75AvPn17Bs2TKam5sD+543r5bXXqvm0KE4U6f2MXHiRFKpVOjX1tfXRy6Xo7e3V6tWiIiIiIyCUHOYfc/9J/DlsJ36nnv5gO9PADeZrzEvmUyy9MYltLa2fuA20FOn1hGLQVtbGxMmTKCn5xiZTA81NZBOTy853SGVStLU1M0TT+S56qpDxGI1odc2zmazPPjggyxevJgtW7awZs2aIU3JEBEREZGh0xDlIKY3Nn6gWMZMi2hu7iOTmUJnZydbt+5j1677yWazoUaKE4kE8+Yd4tChe3j44fXk8/nQc4qTySRr1qyhtbVVxbKIiIjIKBnyKhkCCxYUePrpiVx9dTc7dqS5664bOffcZKgpErFYjClTprBy5UpyuRwzZgztStL+IlnFsoiIiMjo0AjzMDQ0JDh4MMuGDZs4cuQAqdTEIRWwqVSKqqoqUqnUoDcqEREREZGxQQXzMEyaNIn58+PU1S3j4MHNdHd3U1tbG3r/RPUFXgIAAAXCSURBVCJBU1MTTU1NZ/R1ioiIiEj5NCVjGKqqqpg7F+bOTdLTs4za2tohrVgRi8UGWadZRERERMYajTAPUzKZJJ/PD3lZOBEREREZX1QwD1MqlSKfz1MoFELdpU9ERERExidNyRimeDzOzJkzicfjutW0iIiISAVTwVyG4ttUi4iIiEhl0pQMEREREZEAKphFRERERAKoYBYRERERCaCCWUREREQkgApmEREREZEAKphFRERERAKoYBYRERERCaCCWUREREQkgApmEREREZEAKphFRERERALECoXC2X4NIiIiIiJjlkaYRUREREQCqGAWEREREQmggllEREREJIAKZhERERGRACqYRUREREQCqGAWEREREQkw4Wy/gDPJsp05wEPAAmCO77lvF7XNBH4KfAE4F9gO3OR77t9M+8eBe4BLgWpgJ/Aj33Pbi/pIAPcCi4A64DXgFt9z/3i2jlnOnDLzFNiO8hQplu00Aj8DFgIJ817/wPfcPxEiC2GyojxFS7mZosQ5LmwfUhlG4BwVuH+YPsaaih1htmzHAbYBe07TVgU8AzQBnwGmAVsB37KdBst2YsAfgKPAh4E08CvgN6aQ7rcBuAL4vNnmEaDdsp2Pju7RyplWZp4C24u6Up6i4ymgEbjQPD4HPGPZzgzTXioLYbKiPEVLWZkKOscVUaaio9xzVKn9w/QxplRswQxMBeYDW07T9jHgAuCHvufu9T23B7gDyACLgQagBfi177kZ33NzwANmRP4CTp1cpgLXA7f6nvu677lZ33N/DrwBrBj9w5UzrJw8lWpXniLEsp3+kZRVvud2+J573IzEJIHPlspCmKwoT9FSbqZMN0HnOGUqQkbgHBW4P+M0TxU7JcP33Ac49abMOk1zzDzGi7YvWLbTCVzie+69lu08ByyxbOcvZqR5OXAQ6P844SLz8/vrgL5f7g+EVI5y8gS0l2hHeYoO33OPAG0Dnv6QedwbIgthsqI8RcgIZKrUOQ5lKjrKzVOI/RmPearYgrmEN4HXgR9btvNtoP/NPR/Imm2+DvwOOAAUgC7gWt9z95v2/o/SDw7ouwuYPorHImdfqTyFyZvyFFFmNOYhoN333G2W7VxnmgbLQpisKE8RNoxMhaFMRVS5eRq4v3l63OWpkqdkDMr33DzwFTNy/CqwA5hsRo9zlu3UmDnMu8zcm1rgTuC3lu3MLdF9zBTYEhGl8lSqvUT3ylMFs2xnNvCi+SPxrRKbl8pCmKwoTxVuhDMVhjJVwcrN0xD3P20fY0VUR5jxPfdfwNXFz1m2sx14xUxCvxD4ku+5naZ5o2U73wWWAN8HOszz04B3i7ppKGqTiCiRp5LtylP0WLZzibkY1AVWmmslCJGFMFlRniKojEyFoUxFTLl5Ctg/dB9jSSRHmDn1Rl5r2c4nir5vMRdmFS9nEhuw24Si/3xeAU4C8wZsc6n5b0oipFSeQuRNeYoQ80nV74G7fc9dMeAPSakshMmK8hQxZWYqDGUqQsrNU4n9Q/Ux1sQKhTE58j1iLNu5AvBPs26uB6QAB+gzVwbPBj5truR8A3gWuMnMM70e2Axc7nvu86aPDcCVwFfNUjyrgZuB833PDVqaR8ap4eTJ99xcqXaUp8gwywy+DHi+594+yDaBWQiTFeUpOkYiU0XbnfYcN5Q+ZHwrN09mxDhw/1J9jMU8VeyUDMt23jQFSf8o+puW7RSALb7nLgW+A2wC3jIjyc8CV5ri5T3Ldr4I3G3mMdeYx0X9xbKxyiyVstUUQ/8wfYy5N1rKU2aeCNGO8hQZ88wV4nMt27l5QFt/nkplIUxWlKfoKDtTIc5xKFORUVaeLNv5XIj9GW95qvgRZhERERGRckR2DrOIiIiISBgqmEVEREREAqhgFhEREREJoIJZRERERCSACmYRERERkQAqmEVEREREAqhgFhEREREJoIJZRERERCSACmYRERERkQD/BWlD2neTqJorAAAAAElFTkSuQmCC\n"
+ },
+ "metadata": {
+ "bento_obj_id": "139729203451456",
+ "needs_background": "light"
+ }
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "c45c24e9-6a52-48eb-9540-8b99d7ba0095",
+ "showInput": false,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "# Evaluation\n",
+ "Here we evaluate with MSE and MAE."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "originalKey": "2885e571-c266-454c-9da0-70cc041ed181",
+ "showInput": true,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": [],
+ "collapsed": false
+ },
+ "source": [
+ "from sts.metrics import mape\n",
+ "test_y = torch.tensor(df['average'][num_trainset:].values)\n",
+ "mean_abs_perc_error = mape(test_y, test_mean)\n",
+ "MSE = torch.nn.MSELoss()\n",
+ "mean_squared_error = MSE(test_y, test_mean)\n",
+ "print(f'Mean squared error is: {mean_squared_error:.3f}')\n",
+ "print(f'Mean absolute error is: {mean_abs_perc_error:.3f}%')"
+ ],
+ "execution_count": 483,
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "Mean squared error is: 2.012\nMean absolute error is: 0.307%\n"
+ ]
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "acd83a00-70dd-44aa-9f3a-8f150104cb58",
+ "showInput": false,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "# Kernel Decomposition\n",
+ "We decompose kernels to see how each kernel functions."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "originalKey": "6245c93a-a885-4085-a19e-a7fafaa5f995",
+ "showInput": true,
+ "customInput": null,
+ "collapsed": false,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "from sts.gp.graph import plot_components\n",
+ "\n",
+ "x_all = torch.cat([train_x.tensor, test_x.tensor])\n",
+ "components = model.decompose_timeseries(x_all)\n",
+ "fig, ax = plot_components(df['decimal'], components[1], y=model.predict(x_all), transform=transform)"
+ ],
+ "execution_count": 484,
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": "",
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAA6sAAAHVCAYAAAAXVW0dAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8li6FKAAAgAElEQVR4nOzdeXRd1Znn/e+5o+ZZsmzZlo1tSbY12hjMEAwJIlgkEFEkaZIi1ZBKZ1jdKdKppgjkrUq9hIyddApCeEMnFZJ0IEUSFLKCDIgYDGEylmTLgyRbHmVLssar+Q7n3PP+wfVty5KswTaW7d9nLRZLe5+9zzkKJ/B47/08hm3biIiIiIiIiMwljvP9ACIiIiIiIiKnUrAqIiIiIiIic46CVREREREREZlzFKyKiIiIiIjInKNgVUREREREROYcBasiIiIiIiIy57jO9wNMw5yurdPb1UFaZvb5fgyROUPfhMh4+i5ExtI3ITLeJf5dGBM1amX1DIWt8Pl+BJE5Rd+EyHj6LkTG0jchMp6+i/EUrIqIiIiIiMico2BVRERERERE5hwFqyIiIiIiIjLnKFgVERERERGROUfBqoiIiIiIiMw5ClZFRERERERkzlGwKiIiIiIiInOOglURERERERGZcxSsioiIiIiIyJyjYFVERERERETmHAWrIiIiIiIiMucoWBUREREREZE5R8GqiIiIiIiIzDkKVkVERERERGTOUbAqIiIiIiIic46CVREREREREZlzFKyKiIiIiIjInKNgVURERERE5CJl2/b5foRZU7AqIiIiIiJyEbIsi6ampvP9GLOmYFVEREREROQidPDgQfx+//l+jFlTsCoiIiIiInKR8fv9dHV14XQ6z/ejzJqCVRERERERkYvMgQMHcLlc5/sxzoiCVRERERERkYvIyMgIPp8Ph+PCDvcu7KcXERERERGRMQ4cOIDH48Hv9xMOh8/348zahb0uLCIiIiIicpEyTZOOjg5CoRBLly6d1phAIMDAwABer5cf/vCH5ObmUlpaes6f9VxQsCoiIiIiIjIHNTU1MTw8jGVZpKenk5SUNOWYjo4OXC4XTU1NbNmyhT/+8Y/vy7OeC9oGLCIiIiIiMse0t7czNDSEy+XC4/HQ1tY2rXF9fX0YhsH3vvc9vvjFL04rwJ2rtLIqIiIiIiIyh4RCIQ4fPozb7QbAMAwGBgawbRvDMCYdZ5omo6OjvP766wSDQW699db38anPPq2sioiIiIiIzCH79u0bVx/VNE16e3tPO66rqwvbtnniiSf4whe+oGzAIiIiIiIicnb4fL4Jy854vV46OztPO7anp4fXX38dr9fLNddcc46f9NzTNmAREREREZE5wLZtDhw4gNfrxbZt/uM//oMDBw6watUqPvaxj+H3+087fnR0lF/96ld87nOfO+124QuFVlZFRERERETmgPb2dgKBAAC/+93v+NOf/sSiRYv48Y9/TCgUIhAIYNv2hGODwSCHDx+mvb2dq6++Oto+2fUXAgWrIiIiIiIi55llWbS2tuLxeDh06BBPPPEE3/72t7nrrrtYsmQJb731FpZlMTo6OuH4/v5+XnvtNa677rroeddgMMj8+fPf5zc5exSsioiIiIiInGdtHR0QWQn95je/yec+9zlyc3MB2LhxI5s2bcLpdNLf3z/h+L6+Pl5//XVuuOGG6Dzx8fFkZWW9j29xdilYFREREREROY9M06S3pw+Xy8ULL7yA3+/njjvuiPbfeOONvPnmm/j9fgYGBiac4+jRo7S0tHDFFVdApPxNXl7e+/YO54KCVRERERERkfPo0KFDGA6D4eFhHn30Ue67774xpWuSk5MpKyvj7bffnjDJkm3bvPzyy1x11VV4PB7C4TCpqanExMS8z29ydilYFREREREROQssy2L37t28++67k66Ansq2bXp7e3E6HPzsZz/jiiuuoLi4eNx1hYWFNDU1TZhkye/3s2PHDi6//HKIrKouWbLkLL3V+TPj0jXlFZXXAK8BD9VUV33jpPalwC+ADcDSmuqqQyf1xQLfBz4OJAG7gftqqqs2n82XEREREREROV/27t3L8PAwDoeDtrY2kpKSphzT39+PaZocaW3lT3/6E//xH/8R7bNtm2AwCEBeXh7PPPMMpmkSDAbxer3R6/r6+tizZw+f+tSnsG2blJSUC35VlZmurEaCzl8AQ6e0VwJvA4cnGfoT4EbgBiADeBp4vryicsUZPb2IiIiIiMgc0NXVhc/nw+l0YhgGAwMD0yob09HRgcfj4ceP/YR77rmHjIyMaJ9pmuTl5TF//nyWLVtGc3MzAD6fb8wcra2tHD9+nOXLlxMMBsnJyTkHb/j+m+nK6reAJqDtlPY04DpgEfCZkzvKKyrTgL8F7qiprtoTaf5BeUXlp4EvAF89s1cQERERERE5fyzL4uDBg3g8nmibaZr09fWRlpY26TjbthkcHKSuro6jx47xyU9+MtoXDAZZunQpGRkZpKSk0N7ejm3bDAwM0NfXx7x586LX1tXVkZeXh8vlwjCMaa3oXgimvbJaXlF5LXAX8PlT+2qqq35eU13VPMnQNZGg+N1T2rcC62f8xCIiIiIiInPI/v37x7V5PB46IuVoJjM0NEQwGOTxxx/nP3/mM7hc760lhsNhEhMTyc7OBsDlcpGYmEheXh7Nzc2MjIxE5wgGg+zYsYPCwkJs2yYpKQnDMM76O54P01pZLa+ojIts/723prqqvbyicib3OFHYp+eU9m4ge6rBvV0dhK3wTO73vjLNEN0dpy40i1y69E2IjKfvQmQsfRNyMRkeHubwwQN43G4ATMtidHSUxIQEBvv7yEpLmXTskSOtvPHaa/j6+rj++usY6n9ve69pmizMLhjznXhdDpYsXszOhh2sLsjn+LFWnE4nvb197GxooPzGD9HX001aUuIF931lZC+YsH2624C/Beypqa76P2fxmQxgyk3caZlTxrPnVXdH26S/XJFLkb4JkfH0XYiMpW9CLha2bXOkvp7U9Axs2+bBBx/ktddew+12s2nTJtwOB8npmbgjgeyp2jq7+fOmTdx9zz143B4SklPey+Q7fz7zF+WOuTYtK5vC4mJeffVV4hKTcMXEkZ6eTrdvgOa9e7n/a18jOTWNpSvyLpqV1Sm3AUe2/35qou2/03Ri7TvzlPask/pEREREREQuKMeOHSMYDGIYBk8//TTHjx/nL3/5C0VFRbz22msQ2eo7Edu26e7upq6ujg0bNkTbXS4XixcvHne9w+GgsLCQvXv34vF46O3thcgWZNu2mT9/PnFxcRdNoMo0z6x+NlJuZld5RWV3eUVlN3ANcF95RWXdNMbXAkHgqlParwbemOVzi4iIiIiInDeWZXHs2DHcbjctLS384he/4KGHHiImJoabb76ZF154AbfbPS5z7wl+v5833niD4uJiEhMTAQgEAixbtmzSgDM/P5++vj76+/vx+XzRmq4lJSXYtk18fPw5fef323SC1f8OLAdKT/prG/D/ARVTDa6pruoHfg58u7yicnV5RWVCeUXlvwC5kZI2IiIiIiIiF5QjR45gGAbhcJhv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mTdvHgsWLADAMAxcLtfVviwREREREZGkpDmrk8RqtZKVlRX7PhwOU1xcfFWvSUREREREJFkpWZ1Eubm5GIYB5lYz6enpV/uSREREREREkpKS1UlUXFxMKBQiEomQk5NztS9HREREREQkaWnO6iTKzMzE6XQSjUa54YYbrvbliIiIiIiIJC0lq5OssrLyal+CiIiIiIhI0tMwYBEREREREUk6SlZFREREREQk6ShZFRERERERkaSjZFVERERERESSjpJVERERERERSTpKVkVERERERCTpKFkVERERERGRpKNkVURERERERJKOklURERERERFJOkpWRUREREREJOkoWRUREREREZGko2RVREREREREko6SVREREREREUk6SlZFREREREQk6ShZFRERERERkaSjZFVERERERESSjpJVERERERERSTpKVkVERERERCTpWKLR6NW+BhEREREREZFB1LMqIiIiIiIiSUfJqoiIiIiIiCQdJasiIiIiIiKSdJSsioiIiIiISNJRsioiIiIiIiJJR8mqiIiIiIiIJB371b6AZOD2eGcArwF3ADMCft9HA8rKgG8Cq4A84LfAuoDft8csnwe8CCwH0oDfAX8X8Pu2DGgjE3gJeADIBQ4BGwJ+3ztX655F4hlnXIxYjuJCUozb4y0GXgB+D8g0n9enA37fdhJ4nhN53hUTkmrGGxfEea9JtA2RZDEB7xUj1k+kjWvNdd+z6vZ4vUADcGKYMhvwFlACfA5wAduAgNvjLXJ7vBbgV0AnMAsoBH4KvGkmsf2+B9wN3Gme8+/AFrfHO2dy71YkMeOMixHLBzSluJBU8n+BYmCR+fU3wFtuj7fULI/3PCfyvCsmJNWMKy5Geq8ZQHEhqWS87xXx6ifSxjXluk9WganASuDfhimbCywENgb8vtMBv+8S8AxwAfgjoAiYDvws4PddCPh9IeBHZo/1Qj79RTwV+CrwlwG/ryng93UH/L6XgcPAY5N/uyIJGU9cxCtXXEhKcXu8/Z9crw/4fS0Bv6/X/OR7ClAT73lO5HlXTEiqGW9cmM2M9F6juJCUMgHvFSPW5zqNiet+GHDA7/sRn/7nlw9TbDG/WgecH3V7vGeB2wJ+30tuj/c3wJ+4Pd7/NHtYHwXOAf3d9UvM1/m9IW3v7n/wRJLNeOIC2BKnHMWFpJKA33cR+NMhh2eaX08n8Dwn8rwrJiSlTEBcxHuvQXEhqWS8MZFAfa7HmLjuk9U4PgCagH9we7x/CPQ/RJVAt3nOV4BfAq1AFGgD/iDg950xy/uHPZ4b0nYbMG0S70VkosSLi0TiRnEhKcv89Ps1YEvA72twe7wPmUVXep4Ted4VE5LSxhAXiVBcSMoab0wMrW8evu5iQsOARxDw+wzgPrPH9ADQCDjNXtOQ2+N1mHNWj5jjyrOBvwE2uz3e+XGat5jJrUhKiRcX8crjNK+4kKTm9nhvBOrMPwz+Z5zT4z3PiTzviglJehMcF4lQXEhSG29MjLL+sG1cK9SzGkfA7zsG/I+Bx9we72+Bvebk5kXAPQG/76xZ/M9uj/d/AX8CPAG0mMddwMcDmikaUCaSUuLERdxyxYWkIrfHe5u5eJgP+D/mOgUk8Dwn8rwrJiQljSMuEqG4kJQz3pgYoX7CbVxL1LMah9vj/QO3x1sx4Pvp5uIxA5eHtgypZh/w6cZeIAgsG3LOcvMTE5GUEy8uEogbxYWkFHO0zFbg+YDf99iQPx7iPc+JPO+KCUk544yLRCguJKWMNybi1E+ojWuNJRq9JnuMR83t8d4NBIbZT9IP5ABeIGKuWHcjsNhcnesw8DawzpyP91Xgh8DnA37fTrON7wGrgfvN5dm/DjwJVAb8vpGWaxe5qsYSFwG/LxSvHMWFpBBzO6bdgD/g9/31Fc4Z8XlO5HlXTEgqmYi4GHDesO81o2lD5Gobb0yYPaUj1o/XxrUYE9f9MGC3x/uB+Ud0fy/zB26PNwr8W8Dv+zPgj4EfAB+aPahvA6vNP7g73B7vF4DnzXmrDvPrA/2Jqmm9ufT0NvMP+P1mG9fcAyXXhnHGBQmUo7iQFLLMXIFxvtvjfXJIWX9MxHueE3neFROSSsYdFwm816C4kBQyrphwe7y1CdTneosJ9ayKiIiIiIhI0tGcVREREREREUk6SlZFREREREQk6ShZFRERERERkaSjZFVERERERESSjpJVERERERERSTpKVkVERERERCTpKFkVERERERGRpKNkVURERERERJKOklURERERERFJOv8FbPtd9KDaN1wAAAAASUVORK5CYII=\n"
+ },
+ "metadata": {
+ "bento_obj_id": "139729203980176",
+ "needs_background": "light"
+ }
+ },
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": "",
+ "image/png": "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FStW4OabbybdSd4wDDQ1NeGss87iHernkJozq6Ojo0LN8PCw789N08SePXuEmt27dwduCwBGRkaEbcn0+fjx474aXdexf/9+YZxUKuWr0TQNBw8e9NWoqooDBw4I+5NMJoVtxeNxX42iKFKasbExX02hUJDSiPqcz+eFmlwuJ6URfRaZTAYTExO+mnQ6LaVJp9OBNalUSqiZmJhANpsVxsnlcr6aZDKJfD5PolEUxVcTj8eFcUZHR6GqqjCOSDM8PAxN03w1x48fF2qGh4eh67pQYxhGYM3x48eFZ9MeO3ZMqGEYhmHmL6qqYseOHairqyMxf4Zh4Etf+hIikQi++MUvIhqlszWGYSAWi+G8885jozrH1JRZTafT+MAHPoBCoeCpSSaTuPjii30HjMePH8dnPvMZX83Q0BA+97nP+Q4Gh4aG8IlPfMJ3gHbw4EFceumlvpr9+/fj8ssv9/w5ALz22mu48sorfTU7d+7EzTff7KvZtWsXrrnmGl/NK6+8gttuu81X87vf/Q533XWXr+all17Crbfe6qv51a9+JYzz85//HPfcc4+v5sUXX8S9997rq3nhhRewefNmX81PfvIT3H///b6a//iP/8CDDz7oq3n++efx93//976af//3f8cjjzziq/n+97+Pxx57zFfz3e9+F0888YSv5tvf/jaefvppX82zzz6LZ5991lfzzDPP4Nvf/rav5qmnnsJ3v/tdX83WrVvxve99z1fz6KOP4t/+7d98NVu2bMHzzz/vq3nooYfwox/9yFfz4IMPYmBgwFfzla98Bf/93//tq7nvvvvw05/+1FfzpS99CT/72c98NXfffTd++ctf+mruuusu/PrXv/bV3H777XjppZd8NbfccgteeeUVX82mTZuwfft2X821116LXbt2+WoYhmGY+Ymmadi+fTsikQiJ+TNNE9/4xjdw7NgxfO1rXyPL1FqxI5EIzj//fNK4THnUlFmNx+MoFAp44403PDXHjx9HoVDwzfolEglh9tBq68iRI56a4eFhTExM+GZFh4eHMTY2hkQi4asZGRnB+Pi4r2ZoaAiTk5O+fT569Khv5mt4eBj79+/3zTRZ25D7TQrE43G88cYbvob/2LFjeO2113yzNsPDw9i7d6+vmR8ZGRFqrDh+HD9+HK+99hqJRqYtkWZ4eDi0tij78/rrrweOU20aqvsj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\n"
+ },
+ "metadata": {
+ "bento_obj_id": "139729205746032",
+ "needs_background": "light"
+ }
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "39b9fa43-85c6-433d-9ff2-fda4d109caeb",
+ "showInput": false,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "\n",
+ "# Further improvement\n",
+ "As we show above, the major trend is captured by RBF kernel but deviates a little at the forecasting part. We would like to make better prediction with more proper kernels. Now we try polynomial kernel with power 2 to capture the trend, and repeat every step above. "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "e6fb79fa-2e5b-4063-87dd-e083a4a127c7",
+ "showInput": false,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "## Model Defining: polynomial kernel for trend\n",
+ "\n",
+ "This model has a periodic kernel to capture the seasonality and a polynomial kernel of power 2 to capture the long term trend."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "originalKey": "62d267f6-cdbd-4926-a7d5-061f8a063412",
+ "showInput": true,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": [],
+ "collapsed": false
+ },
+ "source": [
+ "from sts.gp.model import TimeSeriesExactGPModel\n",
+ "likelihood = gp.likelihoods.GaussianLikelihood()\n",
+ "model = TimeSeriesExactGPModel(train_x, train_y, likelihood)\n",
+ "model.cov.add_seasonality(time_axis='decimal', period_length=1, fix_period=True)\n",
+ "model.cov.add_trend(time_axis='decimal', kernel_cls=gp.kernels.PolynomialKernel, power=2, name='LongTrend')\n",
+ ""
+ ],
+ "execution_count": 485,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "4b27b84c-1f23-4e1e-a080-c579a795258c",
+ "showInput": false,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "## Traning loop"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "originalKey": "5cae7ad1-564d-4803-a5a7-2bfa4d604dc0",
+ "showInput": true,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": [],
+ "collapsed": false
+ },
+ "source": [
+ "trainer = model.train_init(torch.optim.Adam(model.trainable_params, lr=learning_rate))\n",
+ "for epoch in range(num_epochs):\n",
+ " loss = trainer(train_x, train_y)\n",
+ " if (epoch + 1) % 100 == 1:\n",
+ " print(f'epoch {epoch+1}/{num_epochs}, loss {loss}')"
+ ],
+ "execution_count": 486,
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 1/1000, loss 0.7857952117919922\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 101/1000, loss 0.37224793434143066\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 201/1000, loss -0.11693023890256882\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 301/1000, loss -0.6290424466133118\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 401/1000, loss -1.1186810731887817\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 501/1000, loss -1.5382708311080933\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 601/1000, loss -1.8263381719589233\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 701/1000, loss -1.955971121788025\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 801/1000, loss -1.9883410930633545\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "epoch 901/1000, loss -1.9929193258285522\n"
+ ]
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "3be99acf-746c-41fa-9859-f75148424fce",
+ "showInput": false,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "## Predictions\n",
+ "As we can see from the figure below, our model does better in the forecasting part."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "originalKey": "9da139aa-9b9d-4d72-80fc-b6457bf3ab07",
+ "showInput": true,
+ "customInput": null,
+ "collapsed": false,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "train_mean, train_var, train_ci = get_mvn_stats(model.predict(train_x), transform)\n",
+ "test_mean, test_var, test_ci = get_mvn_stats(model.predict(test_x), transform)\n",
+ "\n",
+ "f, ax = plt.subplots(1, 1, figsize=(12, 5))\n",
+ "ax.plot(df['decimal'][:num_trainset], train_mean, alpha=0.8, color='blue', linewidth=0.5, label='train')\n",
+ "ax.plot(df['decimal'][num_trainset:], test_mean, alpha=0.8, color='green', linewidth=0.5, label='test')\n",
+ "ax.plot(df['decimal'], df['average'], 'o', markersize=0.2, color='black', label='actual')\n",
+ "ax.fill_between(df['decimal'], torch.cat([train_ci[0], test_ci[0]]), torch.cat([train_ci[1], test_ci[1]]), alpha=0.2, label='ci', color='gray')\n",
+ "ax.legend()"
+ ],
+ "execution_count": 487,
+ "outputs": [
+ {
+ "output_type": "execute_result",
+ "data": {
+ "text/plain": ""
+ },
+ "metadata": {
+ "bento_obj_id": "139727889792640"
+ },
+ "execution_count": 487
+ },
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": "",
+ "image/png": "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\n"
+ },
+ "metadata": {
+ "bento_obj_id": "139727889790048",
+ "needs_background": "light"
+ }
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "80a3f3e2-444f-47a3-bd5a-7f2f3ee994f1",
+ "showInput": false,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "## Decompose kernels"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "originalKey": "7b4e5632-cb4d-455c-af2a-53d22a7ad47e",
+ "showInput": true,
+ "customInput": null,
+ "collapsed": false,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "components = model.decompose_timeseries(x_all)\n",
+ "fig, ax = plot_components(df['decimal'], components[1], y=model.predict(x_all), transform=transform)"
+ ],
+ "execution_count": 488,
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": "",
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAA6sAAAHVCAYAAAAXVW0dAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8li6FKAAAgAElEQVR4nOzdeXxd1X3v/c8+o+bZsmx5niRbskYbUyhDMKJBEBI1pYFCkma49CY3N2kIJVNDKYGMTfo0aaGBBAipH2iSG+UmtkIsjIEQDMaSPGu0DLY1WPMsnbPPPvv5I0fnsSzJPvIo29/36+UX1l57rbP2CTv4599av2XYto2IiIiIiIjIbOK42BMQEREREREROZmCVREREREREZl1FKyKiIiIiIjIrKNgVURERERERGYdBasiIiIiIiIy6yhYFRERERERkVnHdbEnEIFZfbZOT2c7KXMyLvY0RGYNvRMik+m9EJlI74TIZFf4e2FMdVGZ1bMUtIIXewois4reCZHJ9F6ITKR3QmQyvReTKVgVERERERGRWUfBqoiIiIiIiMw6ClZFRERERERk1lGwKiIiIiIiIrOOglURERERERGZdRSsioiIiIiIyKyjYFVERERERERmHQWrIiIiIiIiMusoWBUREREREZFZR8GqiIiIiIiIzDoKVkVERERERGTWUbAqIiIiIiIis46CVREREREREZl1FKyKiIiIiIjIrKNgVURERERERGYdBasiIiIiIiIy6yhYFRERERERkVlHwaqIiIiIiMhlyrbtiz2FM6ZgVURERERE5DIUCASoq6u72NM4YwpWRURERERELkOHDx9mbGzsYk/jjClYFRERERERucyMjIzQ2dmJ0+m82FM5YwpWRURERERELjPNzc14PJ6LPY2zomBVRERERETkMjIyMsLAwACGYVzsqZwVBasiIiIiIiKXkfGsamNjI83NzRd7OmdMwaqIiIiIiMgs5fP5GB4ejvh+v9/PwMAAtm3z9a9/nQMHDpzX+Z1Pros9AREREREREZnsnXfeoaWlBcuy2LBhA16v97R92tvbcblc/Pa3v8XlcnHbbbddkLmeD8qsioiIiIiIzDJDQ0O0tbURFRVFdHQ0LS0tEfXr7e1ldHSUxx9/nAceeACH49IN+S7dmYuIiIiIiFyGbNumvr4et9sNgMPh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\n"
+ },
+ "metadata": {
+ "bento_obj_id": "139729205844240",
+ "needs_background": "light"
+ }
+ },
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": "",
+ "image/png": "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\n"
+ },
+ "metadata": {
+ "bento_obj_id": "139727431235376",
+ "needs_background": "light"
+ }
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "originalKey": "be4e8f26-f01d-445b-8b26-6f4b02d83d95",
+ "showInput": false,
+ "customInput": null,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "## Evaluation\n",
+ "The MSE and MAE show that the model with polynomial kernel for trend performs better than RBF."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "originalKey": "9eb430f1-97f2-4e2c-8d91-f3c6576d78ea",
+ "showInput": true,
+ "customInput": null,
+ "collapsed": false,
+ "code_folding": [],
+ "hidden_ranges": []
+ },
+ "source": [
+ "from sts.metrics import mape\n",
+ "test_y = torch.tensor(df['average'][num_trainset:].values)\n",
+ "mean_abs_perc_error = mape(test_y, test_mean)\n",
+ "MSE = torch.nn.MSELoss()\n",
+ "mean_squared_error = MSE(test_y, test_mean)\n",
+ "print(f'Mean squared error is: {mean_squared_error:.3f}')\n",
+ "print(f'Mean absolute error is: {mean_abs_perc_error:.3f}%')"
+ ],
+ "execution_count": 489,
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "Mean squared error is: 1.089\nMean absolute error is: 0.221%\n"
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/src/beanmachine/ppl/experimental/timeseries/setup.py b/src/beanmachine/ppl/experimental/timeseries/setup.py
new file mode 100644
index 0000000000..d8ecbb0337
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/setup.py
@@ -0,0 +1,19 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from setuptools import find_packages, setup
+
+
+setup(
+ name="timeseries",
+ version="0.0.0",
+ description="Time series modeling using GPs and Bayesian Structural Time Series",
+ packages=find_packages(include=["sts", "sts.*"]),
+ install_requires=["gpytorch", "torch", "numpy", "pandas"],
+ extras_require={
+ "test": [
+ "flake8",
+ "pytest>=4.1",
+ ],
+ "examples": ["matplotlib", "seaborn"],
+ },
+)
diff --git a/src/beanmachine/ppl/experimental/timeseries/sts/__init__.py b/src/beanmachine/ppl/experimental/timeseries/sts/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/src/beanmachine/ppl/experimental/timeseries/sts/abcd/__init__.py b/src/beanmachine/ppl/experimental/timeseries/sts/abcd/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/src/beanmachine/ppl/experimental/timeseries/sts/abcd/expansion.py b/src/beanmachine/ppl/experimental/timeseries/sts/abcd/expansion.py
new file mode 100644
index 0000000000..4f3be6251f
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/sts/abcd/expansion.py
@@ -0,0 +1,232 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from copy import deepcopy
+from typing import List, Tuple
+
+from gpytorch.kernels import (
+ AdditiveKernel,
+ Kernel,
+ PeriodicKernel,
+ ProductKernel,
+ ScaleKernel,
+)
+from sts.abcd.expression import KernelExpression
+from sts.abcd.kernels import ChangePointABCDKernel, ChangeWindowABCDKernel
+from sts.abcd.operator_helpers import traverse_bottom_up
+from sts.abcd.operators import (
+ B_to_B1,
+ S_add_S1_to_S,
+ S_mul_S1_to_S,
+ S_to_B,
+ S_to_CP_S_S,
+ S_to_CW_S,
+ S_to_S_add_B,
+ S_to_S_mul_B,
+ S_to_S_mul_B_add_C,
+)
+from sts.abcd.utils import GRAMMAR_RULES, is_base_kernel, remove_redundancy
+from sts.gp.kernels import ConstantKernel, WhiteNoiseKernel
+
+
+def expand_kernel(
+ kernel: Kernel, grammar: List[str] = GRAMMAR_RULES["all"]
+) -> List[Kernel]:
+ """
+ Propose a list of kernels to prepare for search of next level of depth by operating all operators.
+
+ :param kernel: The current kernel to expand.
+ :return: a list of kernels that will be optimized and evaluated.
+ """
+ res = []
+ # all operatos
+
+ if "S->S+B" in grammar:
+ # S->S+B
+ res.extend(S_to_S_add_B(kernel))
+
+ if "S->S*B" in grammar:
+ # S->S*B
+ res.extend(S_to_S_mul_B(kernel))
+
+ if "B->B1" in grammar:
+ # B->B' B is any base kernel
+ # kernel is base kernel, is is redundant with S->B
+ res.extend(B_to_B1(kernel))
+
+ if "S->CP(S,S)" in grammar:
+ # change points
+ # S->CP(S,S)
+ res.extend(S_to_CP_S_S(kernel))
+
+ if "S->CW(S,S)" in grammar:
+ # S->CW(S,S)
+ res.extend(S_to_CW_S(kernel, 0))
+
+ if "S->CW(S,C)" in grammar:
+ # S->CW(S, C)
+ res.extend(S_to_CW_S(kernel, -1))
+
+ if "S->CW(C,S)" in grammar:
+ # S->CW(C, S)
+ res.extend(S_to_CW_S(kernel, 1))
+
+ if "S->S*(B+C)" in grammar:
+ # S->S*(B+C)
+ res.extend(S_to_S_mul_B_add_C(kernel))
+
+ if "S->B" in grammar:
+ # S->B
+ res.extend(S_to_B(kernel))
+
+ if "S+S1->S" in grammar:
+ # S+S1->S
+ res.extend(S_add_S1_to_S(kernel))
+ if "S*S1->S" in grammar:
+ # S*S1->S
+ res.extend(S_mul_S1_to_S(kernel))
+
+ res = remove_redundancy(res)
+ return res
+
+
+def _get_res_kernel(
+ res_kernel: Kernel, child_simp: Kernel, op: str, exclude_wn_const: bool = False
+) -> Tuple[Kernel, int, int]:
+ """
+ Operate child_simp on res_kernel. Helper function for simplify.
+ :param res_kernel: the kernel to add or multiply.
+ :param child_simp: the kernel to add or multiply.
+ :param op: operation add '+' or multiply '*'.
+ :param exclude_wn_const: if True, not add/multiply white noise kernel/constant kernel to res_kernel.
+ :return: the result kernel, the count of white noise kernel, and the count of constant kernel.
+ """
+ wn = 0
+ cons = 0
+ if isinstance(child_simp, WhiteNoiseKernel):
+ wn = 1
+ elif isinstance(child_simp, ConstantKernel):
+ cons = 1
+
+ if exclude_wn_const and (wn == 1 or cons == 1):
+ return res_kernel, wn, cons
+
+ if res_kernel is None:
+ res_kernel = child_simp
+ else:
+ if op == "+":
+ res_kernel += child_simp
+ elif op == "*":
+ res_kernel *= child_simp
+
+ return res_kernel, wn, cons
+
+
+def simplify(kernel: Kernel) -> Kernel:
+ """
+ Simplify unnecessary structure of a composite kernel.
+ WN + WN -> WN
+ WN * WN -> WN
+ Const + Const -> Const
+ Const * S -> S
+ :param kernel: The current kernel to expand.
+ :return: The simplified kernel.
+ """
+
+ if is_base_kernel(kernel):
+ return kernel
+
+ wn_cnt = 0
+ const_cnt = 0
+ res_kernel = None
+ if isinstance(kernel, AdditiveKernel):
+ for child_kernel in kernel.kernels:
+ child_simp = simplify(child_kernel)
+ res_kernel, wn, cons = _get_res_kernel(res_kernel, child_simp, "+", True)
+ wn_cnt += wn
+ const_cnt += cons
+
+ if wn_cnt > 0:
+ res_kernel, wn, cons = _get_res_kernel(
+ res_kernel, WhiteNoiseKernel(noise=1e-4), "+"
+ )
+ if const_cnt > 0:
+ res_kernel, wn, cons = _get_res_kernel(
+ res_kernel, ConstantKernel(constant=1.0), "+"
+ )
+ return res_kernel
+ elif isinstance(kernel, ProductKernel):
+ for child_kernel in kernel.kernels:
+ child_simp = simplify(child_kernel)
+ res_kernel, wn, cons = _get_res_kernel(res_kernel, child_simp, "*", True)
+ wn_cnt += wn
+ const_cnt += cons
+
+ if wn_cnt > 0:
+ res_kernel, wn, cons = _get_res_kernel(
+ res_kernel, WhiteNoiseKernel(noise=1e-4), "*"
+ )
+ if const_cnt > 0 and res_kernel is None:
+ res_kernel = ConstantKernel(constant=1.0)
+ return res_kernel
+ elif isinstance(kernel, ChangeWindowABCDKernel):
+ child_simp0 = simplify(kernel.kernels[0])
+ child_simp1 = simplify(kernel.kernels[1])
+ return ChangeWindowABCDKernel(
+ deepcopy(child_simp0),
+ deepcopy(child_simp1),
+ location=kernel.location.detach().squeeze(-1),
+ steep=kernel.steep.detach().squeeze(-1),
+ )
+ elif isinstance(kernel, ChangePointABCDKernel):
+ child_simp0 = simplify(kernel.kernels[0])
+ child_simp1 = simplify(kernel.kernels[1])
+ return ChangePointABCDKernel(
+ deepcopy(child_simp0),
+ deepcopy(child_simp1),
+ location=kernel.location.item(),
+ steep=kernel.steep.item(),
+ )
+
+
+def traverse_kernel_initialize(cur_exp: KernelExpression, value_list: Tuple[float]):
+ """
+ Update the kernel expression for each periodic kernel in a given kernel expression.
+ :param kernel: the kernel expression.
+ :parma value_list: the candidate list of period_length.
+ """
+ if is_base_kernel(cur_exp.kernel):
+ cur_exp.new_kernel_list.extend(
+ initialize_params_period(cur_exp.kernel, value_list)
+ )
+ else:
+ traverse_kernel_initialize(cur_exp.lhs, value_list)
+ traverse_kernel_initialize(cur_exp.rhs, value_list)
+
+
+def initialize_params_period(kernel: Kernel, value_list: Tuple[float]) -> List[Kernel]:
+ """
+ Initialize the period_length for a periodic kernel.
+ :param kernel: the periodic kernel.
+ :parma value_list: the candidate list of period_length.
+ :return: list of kernels with initialized period lengths.
+ """
+ kernel_list = []
+ if isinstance(kernel, ScaleKernel):
+ if isinstance(kernel.base_kernel, PeriodicKernel):
+ for value in value_list:
+ kernel.base_kernel.period_length = value
+ kernel_list.append(deepcopy(kernel))
+
+ return kernel_list
+
+
+def initialize_kernel(kernel: Kernel, value_list: Tuple[float]) -> List[Kernel]:
+ """
+ Initialize a kernel by initialize each periodic kernel in it with period_length.
+ :param kernel: the periodic kernel.
+ :parma value_list: the candidate list of period_length.
+ :return: list of kernels with periodic kernels initialized period lengths.
+ """
+ cur_exp = KernelExpression(kernel)
+ traverse_kernel_initialize(cur_exp, value_list)
+ return traverse_bottom_up(cur_exp)
diff --git a/src/beanmachine/ppl/experimental/timeseries/sts/abcd/expression.py b/src/beanmachine/ppl/experimental/timeseries/sts/abcd/expression.py
new file mode 100644
index 0000000000..eeec3507e3
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/sts/abcd/expression.py
@@ -0,0 +1,193 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import itertools
+from copy import deepcopy
+from typing import List
+
+from gpytorch.kernels import (
+ AdditiveKernel,
+ Kernel,
+ LinearKernel,
+ PeriodicKernel,
+ ProductKernel,
+ RBFKernel,
+ ScaleKernel,
+)
+from sts.abcd.kernels import ChangePointABCDKernel, ChangeWindowABCDKernel
+from sts.abcd.utils import is_base_kernel
+from sts.gp.kernels import ConstantKernel, WhiteNoiseKernel
+
+"""
+TODO: This can be reorganzied using parent node instead of new_kernel_list.
+"""
+
+
+class KernelExpression:
+ """
+ Class used to store kernel information and structure as a binary tree node.
+
+ :param kernel: class `Kernel`. This is the kernel that this `KernelExpression` would help store info.
+ :param parent: class `KernelExpression`. This is the parent of this node.
+ :param new_kernel_list: class `List[Kernel]`. This is the list to store expansion of kernel.
+ :param children: class `List[KernelExpression]`. This is the list of children of this node. List size is 2.
+ """
+
+ def __init__(self, kernel):
+ self.kernel = kernel
+ self.new_kernel_list = []
+ self.lhs = None
+ self.rhs = None
+ self.init_children()
+
+ def init_children(self):
+ """
+ Initialize the list of children.
+ :return: The list of children, if it's an internal node (composite kernel);
+ None, if it's a leaf node (base kernel).
+ """
+ if not is_base_kernel(self.kernel):
+ num_children = len(self.kernel.kernels)
+ if num_children == 2:
+ self.lhs = KernelExpression(self.kernel.kernels[0])
+ self.rhs = KernelExpression(self.kernel.kernels[1])
+ else:
+ left_kernel = self.kernel.kernels[0]
+ if type(self.kernel) == AdditiveKernel:
+ for i in range(1, num_children - 1):
+ left_kernel += self.kernel.kernels[i]
+ self.lhs = KernelExpression(left_kernel)
+ self.rhs = KernelExpression(self.kernel.kernels[num_children - 1])
+
+ else:
+ for i in range(1, num_children - 1):
+ left_kernel *= self.kernel.kernels[i]
+ self.lhs = KernelExpression(left_kernel)
+ self.rhs = KernelExpression(self.kernel.kernels[num_children - 1])
+
+ def __repr__(self):
+ if is_base_kernel(self.kernel):
+ return _get_kernel_name(self.kernel)
+ elif isinstance(self.kernel, AdditiveKernel):
+ return f"({repr(self.lhs)} + {repr(self.rhs)})"
+ elif isinstance(self.kernel, ProductKernel):
+ return f"({repr(self.lhs)} x {repr(self.rhs)})"
+ elif isinstance(self.kernel, ChangePointABCDKernel):
+ return f"CP({repr(self.lhs)}, {repr(self.rhs)})"
+ elif isinstance(self.kernel, ChangeWindowABCDKernel):
+ return f"CW({repr(self.lhs)}, {repr(self.rhs)})"
+
+ def additive_form_kernel(self) -> Kernel:
+ """
+ Get the kernel after apply distributive law to self.kernel.
+ :return: the kernel after apply distributive law.
+ """
+ return _distribute_products(self.kernel)
+
+
+def _get_kernel_name(kernel):
+ KERNEL_NAME = {
+ WhiteNoiseKernel: "WN",
+ ConstantKernel: "C",
+ RBFKernel: "RBF",
+ PeriodicKernel: "PER",
+ LinearKernel: "LIN",
+ }
+ if type(kernel) in KERNEL_NAME.keys():
+ return KERNEL_NAME[type(kernel)]
+ elif isinstance(kernel, ScaleKernel):
+ return _get_kernel_name(kernel.base_kernel)
+
+
+def _break_into_summands(kernel) -> List[Kernel]:
+ """
+ Get the summands of a kernel.
+ :param kernel: kernel to get summands.
+ :return: the list of summand kernels.
+ """
+ k = deepcopy(kernel)
+ k_dist = _distribute_products(k)
+
+ if isinstance(k_dist, AdditiveKernel):
+ return k_dist.kernels
+ else:
+ return [k_dist]
+
+
+def _distribute_products(kernel: Kernel) -> Kernel:
+ """
+ Apply the distributive law to a composite kernel.
+ :param kernel: this is kernel to apply distributive law.
+ :return: the kernel which is the same as the input kernel, but in additive form.
+ """
+ k = deepcopy(kernel)
+ if isinstance(k, ProductKernel):
+ distributed_ops = [
+ _break_into_summands(child_kernel) for child_kernel in k.kernels
+ ]
+ res_k_sum = []
+
+ for prod in itertools.product(*distributed_ops):
+ res_k_sum.append(_mul_kernels(prod))
+ return _add_kernels(res_k_sum)
+
+ elif isinstance(k, AdditiveKernel):
+ return _add_kernels(
+ [
+ subchild
+ for child in k.kernels
+ for subchild in _break_into_summands(child)
+ ]
+ )
+ elif isinstance(k, (ChangePointABCDKernel, ChangeWindowABCDKernel)):
+ if len(k.kernels) == 2:
+ summands = []
+ # the constant kernel below is zerokernel, which has no effect on the computation.
+ operands_list = [
+ [op, ConstantKernel(constant=0.0)]
+ for op in _break_into_summands(k.kernels[0])
+ ]
+ for ops in operands_list:
+ k_new = deepcopy(k)
+ k_new.kernels = ops
+ summands.append(k_new)
+ operands_list = [
+ [ConstantKernel(constant=0.0), op]
+ for op in _break_into_summands(k.kernels[1])
+ ]
+ for ops in operands_list:
+ k_new = deepcopy(k)
+ k_new.kernels = ops
+ summands.append(k_new)
+ return _add_kernels(summands)
+ else:
+ raise RuntimeError("Wrong form")
+ else:
+ return k
+
+
+def _mul_kernels(kernels: List[Kernel]) -> Kernel:
+ """
+ Multiply all kernels in the list.
+ :return: the kernel by multiplying all kernels.
+ """
+ res_k = None
+ for k in kernels:
+ if res_k is None:
+ res_k = k
+ else:
+ res_k *= k
+ return res_k
+
+
+def _add_kernels(kernels: List[Kernel]) -> Kernel:
+ """
+ Add all kernels in the list.
+ :return: the kernel by adding all kernels.
+ """
+ res_k = None
+ for k in kernels:
+ if res_k is None:
+ res_k = k
+ else:
+ res_k += k
+ return res_k
diff --git a/src/beanmachine/ppl/experimental/timeseries/sts/abcd/hill_climbing.py b/src/beanmachine/ppl/experimental/timeseries/sts/abcd/hill_climbing.py
new file mode 100644
index 0000000000..64093c5f8b
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/sts/abcd/hill_climbing.py
@@ -0,0 +1,192 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import random
+import time
+from copy import deepcopy
+from functools import partial
+from typing import Dict, List, Optional, Tuple
+
+import dill
+import torch
+import torch.multiprocessing as mp
+from gpytorch.kernels import Kernel
+from sts.abcd.expansion import expand_kernel
+from sts.abcd.expression import KernelExpression
+from sts.abcd.search import Search
+from sts.abcd.utils import BASE_KERNELS, GRAMMAR_RULES
+
+
+"""
+This file is runnable only locally if run_in_parallel is True, not using buck.
+The result is showing in notebook N1007190.
+"""
+
+
+class HillClimbingSearch(Search):
+ """
+ :param x_train: input training data.
+ :param y_train: output training data.
+ """
+
+ def __init__(self, x_train: torch.Tensor, y_train: torch.Tensor):
+ super().__init__(x_train, y_train)
+
+ def _get_random_neighbor(self, kernel: Kernel, rules: Dict) -> Kernel:
+ """
+ Get a random neighbor kernel of the current kernel
+ :param kernel: current kernel to get neighbor.
+ :param rules: the grammar rules that can be used to expand the current kernel.
+ :return: a neighbor kernel.
+ """
+ nb_kernels = []
+ while len(nb_kernels) == 0:
+ rule = random.choices(rules, k=1)
+ nb_kernels = expand_kernel(kernel, rule)
+ return random.choices(nb_kernels, k=1)[0]
+
+ def _search_one_round(
+ self,
+ kernel: Kernel,
+ score: float,
+ rules: Dict,
+ learning_rate: float,
+ num_epochs: int,
+ method: str,
+ reject: int,
+ ) -> Tuple[Kernel, int, int]:
+ """
+ One iteration of the search to get one neighbor kernel and train, decide whether or not to accept the new kernel by the scores.
+ :param kernel: current kernel to get neighbor.
+ :param score: the score of current kernel.
+ :param rules: the grammar rules that can be used to expand the current kernel.
+ :param learning_rate: learning rate of training GP model.
+ :param num_epochs: the number of epochs in traning GP model.
+ :param method: scoring method of kernels, one of 'AIC', 'BIC' or 'NLL'.
+ :param reject: the count of rejections.
+ :return: a better kernel, which is the neighbor kernel if its score is better or the current kernel otherwise,
+ the score of the returned kernel,
+ and the count of rejections.
+ """
+ nb_kernel = self._get_random_neighbor(kernel, rules)
+ score_new = self.train_model(nb_kernel, learning_rate, num_epochs, method)
+ if score_new < score:
+ return nb_kernel, score_new, reject
+ else:
+ return kernel, score, reject + 1
+
+ def _search_one_start(
+ self,
+ restart_id: int,
+ num_iters: int,
+ grammar: Dict,
+ top_k: int,
+ learning_rate: float,
+ num_epochs: int,
+ method: str,
+ ) -> Tuple[List[Tuple[Kernel, float]], str]:
+ """
+ One hill climbing search process.
+ :param restart_id: the id of this search, search with different id has different start.
+ :param num_iters: the number of iterations in this search.
+ :param grammar: the grammar rules that can be used to expand kernels.
+ :param top_k: return top k kernels.
+ :param learning_rate: learning rate of training.
+ :param num_epochs: the number of epochs in traning.
+ :param method: scoring method of kernels, one of 'AIC', 'BIC' or 'NLL'.
+ :return: the kernel, score pair of the top k kernels, and the string info to write to file.
+ """
+ kernel_list = random.choices(BASE_KERNELS, k=2)
+ best_kernel = deepcopy(kernel_list[0]) + deepcopy(kernel_list[1])
+ score = self.train_model(
+ best_kernel,
+ learning_rate=learning_rate,
+ num_epochs=num_epochs,
+ method=method,
+ )
+ best_kernels = []
+ best_kernels.append((best_kernel, score))
+ reject_cnt = 0
+
+ for _ in range(num_iters):
+ best_kernel, score, reject_cnt_new = self._search_one_round(
+ best_kernel,
+ score,
+ grammar,
+ learning_rate,
+ num_epochs,
+ method,
+ reject_cnt,
+ )
+ if reject_cnt == reject_cnt_new:
+ best_kernels.append((best_kernel, score))
+ reject_cnt = reject_cnt_new
+ if reject_cnt >= 0.6 * num_iters:
+ break
+
+ best_kernels.sort(key=lambda x: x[1])
+ lines = f"--------Round {restart_id}--------\n"
+ for best_kernel, score in best_kernels[:top_k]:
+ lines += repr(KernelExpression(best_kernel)) + ";" + str(score) + "\n"
+
+ return best_kernels[:top_k], lines
+
+ def search(
+ self,
+ num_iters: int,
+ num_restarts: int,
+ top_k: int,
+ output_file: str = "./search.txt",
+ pickle_file: Optional[str] = "./result.pkl",
+ grammar: List[str] = GRAMMAR_RULES["all"],
+ learning_rate: float = 0.01,
+ num_epochs: int = 1000,
+ method: str = "BIC",
+ run_in_parallel: bool = False,
+ ) -> List[Tuple[Kernel, float]]:
+ """
+ The search with several restarts.
+ :param num_iters: the number of iterations in this search.
+ :param num_restarts: the number of restarts, each restart is an independent search chain.
+ :param top_k: return top k kernels.
+ :param output_file: the path of the output file.
+ :param pickle_file: the path of the file to pickle the best kernels.
+ :param grammar: the grammar rules that can be used to expand kernels.
+ :param learning_rate: learning rate of training.
+ :param num_epochs: the number of epochs in traning.
+ :param method: scoring method of kernels, one of 'AIC', 'BIC' or 'NLL'.
+ :return: the kernel, score pair of the top k kernels.
+ """
+ with open(output_file, "w") as file:
+ start_time = time.time()
+
+ lines = "--------search begin---------\n"
+ all_good_kernels = []
+
+ search_partial = partial(
+ self._search_one_start,
+ num_iters=num_iters,
+ grammar=grammar,
+ top_k=top_k,
+ learning_rate=learning_rate,
+ num_epochs=num_epochs,
+ method=method,
+ )
+ if run_in_parallel:
+ with mp.Pool(num_restarts) as pool:
+ result_list = pool.map(search_partial, range(num_restarts))
+ else:
+ result_list = map(search_partial, range(num_restarts))
+ for kernels, ss in result_list:
+ all_good_kernels.extend(kernels)
+ lines += ss
+ all_good_kernels.sort(key=lambda x: x[1])
+ lines += "--------overall Result--------\n"
+ for best_kernel, score in all_good_kernels[:top_k]:
+ lines += repr(KernelExpression(best_kernel)) + ";" + str(score) + "\n"
+ lines += "--- %s seconds ---" % (time.time() - start_time)
+ file.write(lines)
+ file.close()
+ if pickle_file is not None:
+ with open(pickle_file, "wb") as handle:
+ dill.dump(all_good_kernels[:top_k], handle)
+ return all_good_kernels[:top_k]
diff --git a/src/beanmachine/ppl/experimental/timeseries/sts/abcd/kernels.py b/src/beanmachine/ppl/experimental/timeseries/sts/abcd/kernels.py
new file mode 100644
index 0000000000..6541f43a4d
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/sts/abcd/kernels.py
@@ -0,0 +1,107 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from sts.gp.kernels import ChangePointKernel
+from torch.nn import ModuleList # @manual
+
+
+class ChangeKernel(ChangePointKernel):
+ @property
+ def kernels(self):
+ return list(dict.fromkeys(self._kernels))
+
+ @kernels.setter
+ def kernels(self, kernels):
+ self._kernels = ModuleList(kernels)
+
+
+class ChangePointABCDKernel(ChangeKernel):
+ """
+ Wrapper over :class:`sts.gp.kernels.ChangePointKernel` for use with the :mod:`sts.abcd` module.
+
+ :param k1: a kernel.
+ :param k2: a kernel.
+ :param location: the location of change point.
+ :param steep: the steepness of sigmoid.
+ :param location_prior: (Prior, optional)
+ Set this if you want to apply a prior to the location parameter. Default: `None`.
+ :param location_constraint: (Constraint, optional)
+ Set this if you want to apply a constraint to the location parameter. Default: `GreaterThan(location)`.
+ :param steep_prior: (Prior, optional)
+ Set this if you want to apply a prior to the steep parameter. Default: `None`.
+ :param steep_constraint: (Constraint, optional)
+ Set this if you want to apply a constraint to the steep parameter. Default: `Positive`.
+ """
+
+ def __init__(
+ self,
+ k1,
+ k2,
+ location=0.0,
+ steep=1.0,
+ location_prior=None,
+ location_constraint=None,
+ steep_prior=None,
+ steep_constraint=None,
+ **kwargs,
+ ):
+ super().__init__(
+ [k1, k2],
+ location,
+ steep,
+ location_prior=location_prior,
+ location_constraint=location_constraint,
+ steep_prior=steep_prior,
+ steep_constraint=steep_constraint,
+ **kwargs,
+ )
+
+
+class ChangeWindowABCDKernel(ChangeKernel):
+ """
+ Wrapper over :class:`sts.gp.kernels.ChangePointKernel` for use with the :mod:`sts.abcd` module to simulate
+ a changepoint window.
+
+ :param k1: a kernel.
+ :param k2: a kernel.
+ :param location: the location of two change points location=(l1, l2). The second kernel functions in the window (l1, l2).
+ :param steep: the steepness of sigmoid.
+ :param location_prior: (Prior, optional)
+ Set this if you want to apply a prior to the location parameter. Default: `None`.
+ :param location_constraint: (Constraint, optional)
+ Set this if you want to apply a constraint to the location parameter. Default: `GreaterThan(l1)`.
+ :param steep_prior: (Prior, optional)
+ Set this if you want to apply a prior to the steep parameter. Default: `None`.
+ :param steep_constraint: (Constraint, optional)
+ Set this if you want to apply a constraint to the steep parameter. Default: `Positive`.
+ """
+
+ def __init__(
+ self,
+ k1,
+ k2,
+ location=(0.0, 3.0),
+ steep=(1.0, 2.0),
+ location_prior=None,
+ location_constraint=None,
+ steep_prior=None,
+ steep_constraint=None,
+ **kwargs,
+ ):
+ super().__init__(
+ [k1, k2, k1],
+ location,
+ steep,
+ location_prior=location_prior,
+ location_constraint=location_constraint,
+ steep_prior=steep_prior,
+ steep_constraint=steep_constraint,
+ **kwargs,
+ )
+
+ @property
+ def kernels(self):
+ return super().kernels
+
+ @kernels.setter
+ def kernels(self, kernels):
+ self._kernels = ModuleList(kernels + [kernels[0]])
diff --git a/src/beanmachine/ppl/experimental/timeseries/sts/abcd/model.py b/src/beanmachine/ppl/experimental/timeseries/sts/abcd/model.py
new file mode 100644
index 0000000000..ae3992e7f9
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/sts/abcd/model.py
@@ -0,0 +1,112 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from typing import OrderedDict, Tuple, Union
+
+import gpytorch as gp
+import torch
+from sts.abcd.expression import KernelExpression
+from sts.abcd.utils import is_base_kernel
+from sts.data import DataTensor
+from sts.gp.mean import Mean
+from sts.gp.model import ExactGPAdditiveModel
+from sts.metrics import AIC, BIC
+
+
+class ABCDExactGPModel(ExactGPAdditiveModel):
+ """
+ Univariate time series model for Automatic Bayesian Covariance Discovery (ABCD) [1].
+ Reference:
+ [1] Lloyd, James, et al. "Automatic construction and natural-language description of
+ nonparametric regression models." Proceedings of the AAAI Conference on Artificial
+ Intelligence. Vol. 28. No. 1. 2014.
+
+ :param train_inputs: a sample :class:`DataTensor` object that represents
+ the inputs of interest.
+ :param train_targets: a sample :class:`DataTensor` object that represents
+ the output from the time series model.
+ :param likelihood: a gpytorch :class:`~gp.likelihoods.Likelihood` object
+ that specifies the mapping from `f(X)` to observed data.
+ :param kernel: a gpytorch :class:`~gp.kernels.Kernel` object that specifies
+ the candidate kernel to optimize parameters and evaluate with BIC score.
+ """
+
+ def __init__(
+ self,
+ train_inputs: DataTensor,
+ train_targets: DataTensor,
+ likelihood: gp.likelihoods.Likelihood,
+ kernel: gp.kernels.Kernel,
+ ):
+ super().__init__(train_inputs, train_targets, likelihood)
+ self.mean = Mean(train_inputs)
+ self.cov = kernel
+
+ def optimize_params(self, learning_rate=0.01, num_epochs=1000):
+ """
+ Train the model to optimize parameters.
+ :param learning_rate: the learning rate of the model.
+ :param num_epochs: the number of epochs to train the model.
+ """
+ trainer = self.train_init(torch.optim.Adam(self.parameters(), lr=learning_rate))
+
+ for _ in range(num_epochs):
+ self.loss = trainer(self.train_inputs[0], self.train_targets)
+
+ def score(self, method="BIC") -> torch.Tensor:
+ """
+ Score the model with method.
+ :param method: the scoring method, can be BIC, AIC, NLL.
+ :return: the score.
+ """
+ with torch.no_grad():
+ n = self.train_inputs[0].shape[0]
+ nll = self.loss * n
+ if method == "BIC":
+ return BIC(
+ nll,
+ len(list(self.cov.parameters())),
+ n,
+ )
+ elif method == "AIC":
+ return AIC(
+ nll,
+ len(list(self.cov.parameters())),
+ )
+ elif method == "NLL":
+ return nll
+
+ def decompose_timeseries(
+ self, x: Union[torch.Tensor, DataTensor]
+ ) -> Tuple[OrderedDict, OrderedDict]:
+ """
+ Run the model to generate predictions for the given input tensor, and
+ return the decomposition over the mean and additive covariance kernels.
+
+ :param x: input data.
+ :return: tuple of mean and covariance decompositions, which are dicts
+ keyed by component names.
+ """
+ self.eval()
+ train_X = self.train_inputs[0]
+ with torch.no_grad(), gp.settings.fast_pred_var():
+ alpha = self.prediction_strategy.mean_cache
+ mean_parts = OrderedDict(
+ [(name, p(x)) for name, p in self.mean.parts.items()]
+ )
+ cov_parts = OrderedDict()
+ kern_exp = KernelExpression(self.cov)
+ kernel_additive = kern_exp.additive_form_kernel()
+ if is_base_kernel(kernel_additive):
+ kernel_list = [kernel_additive]
+ else:
+ kernel_list = list(kernel_additive.kernels)
+ for p in kernel_list:
+ mean = p(x, train_X) @ alpha
+ cov = self._component_cov(x, p)
+ name = repr(KernelExpression(p))
+ suffix = 1
+ while name in cov_parts.keys():
+ name = name + str(suffix)
+ suffix += 1
+ cov_parts[name] = gp.distributions.MultivariateNormal(mean, cov)
+ return mean_parts, cov_parts
diff --git a/src/beanmachine/ppl/experimental/timeseries/sts/abcd/operator_helpers.py b/src/beanmachine/ppl/experimental/timeseries/sts/abcd/operator_helpers.py
new file mode 100644
index 0000000000..2d74312ac7
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/sts/abcd/operator_helpers.py
@@ -0,0 +1,302 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from copy import deepcopy
+from itertools import combinations
+from typing import List
+
+from gpytorch.kernels import AdditiveKernel, Kernel, ProductKernel
+from sts.abcd.expression import KernelExpression
+from sts.abcd.kernels import ChangePointABCDKernel, ChangeWindowABCDKernel
+from sts.abcd.utils import is_base_kernel
+from sts.gp.kernels import ConstantKernel
+
+"""
+TODO: This can be reorganized by using parent pointer of KernelExpression.
+
+Each traverse_dfs.. functions are to update the new_kernel_list at each corresponding node.
+traverse_bottom_up utilize the new_kernel_list info to get expanded kernels.
+e.g:
+Suppose we have cur_exp = k0 + k1 * k2, and would like to add kernel_to_add = k4.
+The kernel expression is:
+ k0 + k1 * k2
+ / \
+ k0 k1 * k2
+ / \
+ k1 k2
+
+traverse_dfs_add: add kernel_to_add to every node in the kernel expression.
+We add k4 to it in new_kernel_list of each node in the tree.
+From top down:
+ k0 + k1 * k2
+ [k0 + k1 * k2 + k4]
+ / \
+ k0 k1 * k2
+ [k0 + k4] [k1 * k2 + k4]
+ / \
+ k1 k2
+ [k1 + k4] [k2 + k4]
+traverse_bottom_up: update the new expressions to the root.
+From bottom up:
+ k0 + k1 * k2
+ [k0 + k1 * k2 + k4, k0 + k4 + k1 * k2, k0 + k1 * k2 + k4, k0 + (k1 + k4) * k2, k0 + k1 * (k2 + k4)]
+ / \
+ k0 k1 * k2
+ [k0 + k4] [k1 * k2 + k4, (k1 + k4) * k2, k1 * (k2 + k4)]
+ / \
+ k1 k2
+ [k1 + k4] [k2 + k4]
+Therefore, it returns 5 kernels to root, which are our expanded kernels:
+[k0 + k1 * k2 + k4, k0 + k4 + k1 * k2, k0 + k1 * k2 + k4, k0 + (k1 + k4) * k2, k0 + k1 * (k2 + k4)].
+Other operators perform similarly.
+"""
+
+
+def traverse_dfs_add(cur_exp: KernelExpression, kernel_to_add: Kernel):
+ """
+ Helper function for S->S+B.
+ Update each kernel expression node from top down.
+ Update new_kernel_list to kernel + kernel_to_add.
+
+ :param cur_exp: current `KernelExpression` to update.
+ :param kernel_to_add: to add base kernel kernel_to_add with kernel.
+ """
+ cur_exp.new_kernel_list.append(deepcopy(cur_exp.kernel) + deepcopy(kernel_to_add))
+ if not is_base_kernel(cur_exp.kernel):
+ traverse_dfs_add(cur_exp.lhs, kernel_to_add)
+ traverse_dfs_add(cur_exp.rhs, kernel_to_add)
+
+
+def traverse_dfs_mul(cur_exp: KernelExpression, kernel_to_mul: Kernel):
+ """
+ Helper function for S->S*B.
+ Update each kernel expression node from top down.
+ Update new_kernel_list to kernel * kernel_to_mul
+
+ :param cur_exp: current `KernelExpression` to update.
+ :param kernel_to_mul: to multiply a base kernel kernel_to_mul with kernel.
+ """
+ cur_exp.new_kernel_list.append(deepcopy(cur_exp.kernel) * deepcopy(kernel_to_mul))
+ if not is_base_kernel(cur_exp.kernel):
+ traverse_dfs_mul(cur_exp.lhs, kernel_to_mul)
+ traverse_dfs_mul(cur_exp.rhs, kernel_to_mul)
+
+
+def traverse_dfs_replace(cur_exp: KernelExpression, base_kernel: Kernel):
+ """
+ Helper function for B->B1.
+ Update each kernel expression node from top down.
+ Replace new_kernel_list at leaf which is base kernel with base_kernel
+
+ :param cur_exp: current `KernelExpression` to update.
+ :param base_kernel: to replace kernel with base kernel base_kernel.
+ """
+ if is_base_kernel(cur_exp.kernel):
+ cur_exp.new_kernel_list.append(deepcopy(base_kernel))
+
+ else:
+ traverse_dfs_replace(cur_exp.lhs, base_kernel)
+ traverse_dfs_replace(cur_exp.rhs, base_kernel)
+
+
+def traverse_dfs_cp(cur_exp: KernelExpression):
+ """
+ Helper function for S->CP(S,S).
+ Update each kernel expression node from top down.
+ Add changepoint for new_kernel_list.
+
+ :param cur_exp: current `KernelExpression` to update.
+ """
+ cur_exp.new_kernel_list.append(
+ ChangePointABCDKernel(deepcopy(cur_exp.kernel), deepcopy(cur_exp.kernel))
+ )
+
+ if not is_base_kernel(cur_exp.kernel):
+ traverse_dfs_cp(cur_exp.lhs)
+ traverse_dfs_cp(cur_exp.rhs)
+
+
+def traverse_dfs_cw(cur_exp: KernelExpression, pos_constant_kernel: int):
+ """
+ Helper function for S->CW(S,S), S->CW(S,C), S->CW(C,S).
+ Update each kernel expression node from top down.
+ Add changewindow for new_kernel_list.
+
+ :param cur_exp: current `KernelExpression` to update.
+ :param pos_constant_kernel: if -1, S->CW(S, C);
+ else if 0, S->CW(S, S);
+ else, S->CW(C, S).
+ """
+ if pos_constant_kernel == -1:
+ cur_exp.new_kernel_list.append(
+ ChangeWindowABCDKernel(deepcopy(cur_exp.kernel), ConstantKernel(1.0))
+ )
+
+ elif pos_constant_kernel == 0:
+ cur_exp.new_kernel_list.append(
+ ChangeWindowABCDKernel(deepcopy(cur_exp.kernel), deepcopy(cur_exp.kernel))
+ )
+
+ else:
+ cur_exp.new_kernel_list.append(
+ ChangeWindowABCDKernel(ConstantKernel(1.0), deepcopy(cur_exp.kernel))
+ )
+
+ if not is_base_kernel(cur_exp.kernel):
+ traverse_dfs_cw(cur_exp.lhs, pos_constant_kernel)
+ traverse_dfs_cw(cur_exp.rhs, pos_constant_kernel)
+
+
+def traverse_dfs_mul_const(cur_exp: KernelExpression, kernel_to_mul: Kernel):
+ """
+ Helper function for S->S*(B+C).
+ Update each kernel expression node from top down.
+ Update new_kernel_list to kernel * (kernel_to_mul + C).
+
+ :param cur_exp: current `KernelExpression` to update.
+ :param kernel_to_mul: a base kernel, multiply (kernel_to_mul + C) with kernel.
+ """
+ cur_exp.new_kernel_list.append(
+ deepcopy(cur_exp.kernel) * (deepcopy(kernel_to_mul) + ConstantKernel(1.0))
+ )
+ if not is_base_kernel(cur_exp.kernel):
+ traverse_dfs_mul_const(cur_exp.lhs, kernel_to_mul)
+ traverse_dfs_mul_const(cur_exp.rhs, kernel_to_mul)
+
+
+def traverse_dfs_simplify_base(cur_exp: KernelExpression, to_kernel: Kernel):
+ """
+ Helper function for S->B.
+ Update each kernel expression node from top down.
+ Simplify new_kernel_list that are not base kernels to base kernel to_kernel.
+
+ :param cur_exp: current `KernelExpression` to update.
+ :param to_kernel: replace kernel to a base kernel to_kernel.
+ """
+ if not is_base_kernel(cur_exp.kernel):
+ cur_exp.new_kernel_list.append(deepcopy(to_kernel))
+ traverse_dfs_simplify_base(cur_exp.lhs, to_kernel)
+ traverse_dfs_simplify_base(cur_exp.rhs, to_kernel)
+
+
+def traverse_dfs_simplify_add(cur_exp: KernelExpression):
+ """
+ Helper function for S+S1->S.
+ Update each kernel expression node from top down.
+ Simplify new_kernel_list to any summands of it.
+
+ :param cur_exp: current `KernelExpression` to update.
+ """
+ cur_exp.new_kernel_list = add_combination(cur_exp.kernel)
+
+ if not is_base_kernel(cur_exp.kernel):
+ traverse_dfs_simplify_add(cur_exp.lhs)
+ traverse_dfs_simplify_add(cur_exp.rhs)
+
+
+def traverse_dfs_simplify_mul(cur_exp: KernelExpression):
+ """
+ Helper function for S*S1->S.
+ Update each kernel expression node from top down.
+ Simplify new_kernel_list to any multipliers of it.
+
+ :param cur_exp: current `KernelExpression` to update.
+ """
+ cur_exp.new_kernel_list = mul_combination(cur_exp.kernel)
+
+ if not is_base_kernel(cur_exp.kernel):
+ traverse_dfs_simplify_mul(cur_exp.lhs)
+ traverse_dfs_simplify_mul(cur_exp.rhs)
+
+
+def add_combination(kernel: Kernel):
+ """
+ Get all combination of summands of an additive kernel.
+
+ :param kernel: the additive kernel.
+ :return: all combination of summands.
+ """
+ res = []
+ if isinstance(kernel, AdditiveKernel):
+ kernel_summands = kernel.kernels
+ if len(kernel_summands) >= 2:
+ indexes = list(range(len(kernel_summands)))
+ for num_summands in range(1, len(kernel_summands)):
+ comb = combinations(indexes, num_summands)
+ for index_to_comb in list(comb):
+ kernel = None
+ for j in index_to_comb:
+ if kernel is None:
+ kernel = deepcopy(kernel_summands[j])
+ else:
+ kernel += deepcopy(kernel_summands[j])
+ res.append(kernel)
+ return res
+
+
+def mul_combination(kernel: Kernel):
+ """
+ Get all combination of multipliers of a product kernel.
+
+ :param kernel: the product kernel.
+ :return: all combination of multipliers.
+ """
+ res = []
+ if isinstance(kernel, ProductKernel):
+ kernel_multiplier = kernel.kernels
+ if len(kernel_multiplier) >= 2:
+ indexes = list(range(len(kernel_multiplier)))
+ for num_summands in range(1, len(kernel_multiplier)):
+ comb = combinations(indexes, num_summands)
+ for index_to_comb in list(comb):
+ kernel = None
+ for j in index_to_comb:
+ if kernel is None:
+ kernel = deepcopy(kernel_multiplier[j])
+ else:
+ kernel *= deepcopy(kernel_multiplier[j])
+ res.append(kernel)
+ return res
+
+
+def _compute_res_list(
+ cur_exp: KernelExpression,
+ cur_exp_child1: KernelExpression,
+ cur_exp_child2: KernelExpression,
+) -> List[Kernel]:
+ """
+ Helper function to get all new kernels from cur_exp_child1 side.
+ :param cur_exp: `KernelExpression`.
+ :param cur_exp_child1: `KernelExpression`, one of two children of cur_exp.
+ :param cur_exp_child2: `KernelExpression`, one of two children of cur_exp.
+ :return: a list of kernels collected from children for this expression.
+ """
+ res = []
+ child_reslist = traverse_bottom_up(cur_exp_child1)
+ for child_res in child_reslist:
+ value = deepcopy(child_res)
+ if type(cur_exp.kernel) == AdditiveKernel:
+ value += deepcopy(cur_exp_child2.kernel)
+ elif type(cur_exp.kernel) == ProductKernel:
+ value *= deepcopy(cur_exp_child2.kernel)
+ elif type(cur_exp.kernel) == ChangePointABCDKernel:
+ value = ChangePointABCDKernel(value, deepcopy(cur_exp_child2.kernel))
+ elif type(cur_exp.kernel) == ChangeWindowABCDKernel:
+ value = ChangeWindowABCDKernel(value, deepcopy(cur_exp_child2.kernel))
+ res.append(value)
+ return res
+
+
+def traverse_bottom_up(cur_exp: KernelExpression) -> List[Kernel]:
+ """
+ Get all possible expanded kernels for each node from bottom up by using new_kernel_list info.
+ :param cur_exp: `KernelExpression`.
+ :return: a list of kernels collected from children for this expression.
+ """
+
+ if cur_exp.lhs is None and cur_exp.rhs is None:
+ return cur_exp.new_kernel_list
+
+ res = cur_exp.new_kernel_list
+ res.extend(_compute_res_list(cur_exp, cur_exp.lhs, cur_exp.rhs))
+ res.extend(_compute_res_list(cur_exp, cur_exp.rhs, cur_exp.lhs))
+ return res
diff --git a/src/beanmachine/ppl/experimental/timeseries/sts/abcd/operators.py b/src/beanmachine/ppl/experimental/timeseries/sts/abcd/operators.py
new file mode 100644
index 0000000000..6a3a5e6b78
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/sts/abcd/operators.py
@@ -0,0 +1,164 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+"""
+Wrapper funtions for operators.
+"""
+from typing import List
+
+from gpytorch.kernels import Kernel
+from sts.abcd.expression import KernelExpression
+from sts.abcd.operator_helpers import (
+ traverse_bottom_up,
+ traverse_dfs_add,
+ traverse_dfs_cp,
+ traverse_dfs_cw,
+ traverse_dfs_mul,
+ traverse_dfs_mul_const,
+ traverse_dfs_replace,
+ traverse_dfs_simplify_add,
+ traverse_dfs_simplify_base,
+ traverse_dfs_simplify_mul,
+)
+from sts.abcd.utils import BASE_CONST_KERNELS, BASE_KERNELS, remove_redundancy
+
+
+def S_to_S_add_B(kernel: Kernel) -> List[Kernel]:
+ """
+ Operate S->S+B for any subexpression and each base kernel.
+
+ :param kernel: The kernel to expand, S is any subexpressoin of it.
+ :return: list of kernels proposed with this operator.
+ """
+ res = []
+ for base_kernel in BASE_CONST_KERNELS:
+ kernel_exp = KernelExpression(kernel)
+ traverse_dfs_add(kernel_exp, base_kernel)
+ res.extend(traverse_bottom_up(kernel_exp))
+ res = remove_redundancy(res)
+ return res
+
+
+def S_to_S_mul_B(kernel: Kernel) -> List[Kernel]:
+ """
+ Operate S->S*B for any subexpression and each base kernel.
+
+ :param kernel: The kernel to expand, S is any subexpressoin of it.
+ :return: list of kernels proposed with this operator.
+ """
+
+ res = []
+ for base_kernel in BASE_KERNELS:
+ kernel_exp = KernelExpression(kernel)
+ traverse_dfs_mul(kernel_exp, base_kernel)
+ res.extend(traverse_bottom_up(kernel_exp))
+ res = remove_redundancy(res)
+ return res
+
+
+def B_to_B1(kernel: Kernel) -> List[Kernel]:
+ """
+ Operate B->B1 for each base kernel.
+ :param kernel: The kernel to expand, B is any base kernel of it.
+ :return: list of kernels proposed with this operator.
+ """
+
+ res = []
+ for base_kernel in BASE_CONST_KERNELS:
+ kernel_exp = KernelExpression(kernel)
+ traverse_dfs_replace(kernel_exp, base_kernel)
+ res.extend(traverse_bottom_up(kernel_exp))
+ res = remove_redundancy(res)
+ return res
+
+
+def S_to_CP_S_S(kernel: Kernel) -> List[Kernel]:
+ """
+ Operate changepoint S->CP(S,S) for any subexpression.
+
+ :param kernel: The kernel to expand, S is any subexpressoin of it.
+ :return: list of kernels proposed with this operator.
+ """
+ kernel_exp = KernelExpression(kernel)
+ traverse_dfs_cp(kernel_exp)
+ res = traverse_bottom_up(kernel_exp)
+ res = remove_redundancy(res)
+ return res
+
+
+def S_to_CW_S(kernel: Kernel, pos_constant_kernel: int) -> List[Kernel]:
+ """
+ Operate changewindow S->CW for any subexpression.
+
+ :param kernel: The kernel to expand, S is any subexpressoin of it.
+ :param pos_constant_kernel: if -1, S->CW(S, C);
+ else if 0, S->CW(S, S);
+ else, S->CW(C, S).
+ :return: list of kernels proposed with this operator.
+ """
+ kernel_exp = KernelExpression(kernel)
+ traverse_dfs_cw(kernel_exp, pos_constant_kernel)
+ res = traverse_bottom_up(kernel_exp)
+ res = remove_redundancy(res)
+ return res
+
+
+def S_to_S_mul_B_add_C(kernel: Kernel) -> List[Kernel]:
+ """
+ Operate S->S*(B+C) for any subexpression and each base kernel.
+
+ :param kernel: The kernel to expand, S is any subexpressoin of it.
+ :return: list of kernels proposed with this operator.
+ """
+
+ res = []
+ for base_kernel in BASE_KERNELS:
+ kernel_exp = KernelExpression(kernel)
+ traverse_dfs_mul_const(kernel_exp, base_kernel)
+ res.extend(traverse_bottom_up(kernel_exp))
+ res = remove_redundancy(res)
+ return res
+
+
+def S_to_B(kernel: Kernel) -> List[Kernel]:
+ """
+ Simplify S->B for any subexpression and each base kernel.
+
+ :param kernel: The kernel to expand, S is any subexpressoin of it.
+ :return: list of kernels proposed with this operator.
+ """
+
+ res = []
+ for base_kernel in BASE_CONST_KERNELS:
+ kernel_exp = KernelExpression(kernel)
+ traverse_dfs_simplify_base(kernel_exp, base_kernel)
+ res.extend(traverse_bottom_up(kernel_exp))
+ res = remove_redundancy(res)
+ return res
+
+
+def S_add_S1_to_S(kernel: Kernel) -> List[Kernel]:
+ """
+ Simplify S+S1->S for any subexpression.
+
+ :param kernel: The kernel to expand, S is any subexpressoin of it.
+ :return: list of kernels proposed with this operator.
+ """
+ kernel_exp = KernelExpression(kernel)
+ traverse_dfs_simplify_add(kernel_exp)
+ res = traverse_bottom_up(kernel_exp)
+ res = remove_redundancy(res)
+ return res
+
+
+def S_mul_S1_to_S(kernel: Kernel) -> List[Kernel]:
+ """
+ Simplify S*S1->S for any subexpression.
+
+ :param kernel: The kernel to expand, S is any subexpressoin of it.
+ :return: list of kernels proposed with this operator.
+ """
+ kernel_exp = KernelExpression(kernel)
+ traverse_dfs_simplify_mul(kernel_exp)
+ res = traverse_bottom_up(kernel_exp)
+ res = remove_redundancy(res)
+ return res
diff --git a/src/beanmachine/ppl/experimental/timeseries/sts/abcd/search.py b/src/beanmachine/ppl/experimental/timeseries/sts/abcd/search.py
new file mode 100644
index 0000000000..ea23efd5ce
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/sts/abcd/search.py
@@ -0,0 +1,214 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import time
+from functools import partial
+from typing import Dict, List, Optional, Tuple
+
+import dill
+import gpytorch as gp
+import torch
+import torch.multiprocessing as mp
+from gpytorch.kernels import Kernel
+from sts.abcd.expansion import expand_kernel, initialize_kernel, simplify
+from sts.abcd.expression import KernelExpression
+from sts.abcd.model import ABCDExactGPModel
+from sts.abcd.utils import GRAMMAR_RULES, is_kernel_type_eq, remove_redundancy
+from sts.data import DataTensor
+from sts.gp.kernels import WhiteNoiseKernel
+
+
+"""
+This file is runnable only locally if run_in_parallel is True, not using buck.
+"""
+
+
+class Search(object):
+ """
+ :param x_train: input training data.
+ :param y_train: output training data.
+ """
+
+ def __init__(self, x_train: torch.Tensor, y_train: torch.Tensor):
+ self.x_train = x_train
+ self.y_train = y_train
+
+ def train_model(
+ self,
+ candidate_kernel: Kernel,
+ learning_rate: float,
+ num_epochs: int,
+ method: str,
+ ) -> float:
+ """
+ Train a model given the kernel to to optimize params and evaluate the score.
+ :param candidate_kernel: the candidate kernel.
+ :param learning_rate: learning rate for training models.
+ :param num_epochs: number of epochs for training models.
+ :param method: method for scoring, one of 'BIC', 'AIC', 'NLL'.
+ :return: the score of the trained model.
+ """
+ likelihood = gp.likelihoods.GaussianLikelihood()
+ x_train = DataTensor(self.x_train, header=["x"])
+ y_train = DataTensor(self.y_train, header=["y"])
+ model = ABCDExactGPModel(x_train, y_train, likelihood, candidate_kernel)
+ model.optimize_params(learning_rate=learning_rate, num_epochs=num_epochs)
+ score = model.score(method=method).item()
+ return score
+
+ def _get_all_candidate_kernels(
+ self,
+ best_kernels: List[Tuple[Kernel, float]],
+ grammar: Dict,
+ period_value_list: Tuple[float],
+ depth: int,
+ ) -> Tuple[List[Kernel], str]:
+ """
+ Get all candidate kernels by operating all possible operators.
+ :param best_kernels: the list of kernels to expand from.
+ :param grammar: the grammar operator rules for expanding current kernel to neighbor kernels.
+ :param peiord_value_list: the tuple of possible values of period lengths.
+ :param depth: the depth of search.
+ :return: a list of kernels and output information.
+ """
+ nb_kernels = []
+ for best_kernel, _ in best_kernels:
+ nb_kernels.extend(expand_kernel(best_kernel, grammar))
+ nb_kernels = remove_redundancy(nb_kernels)
+ lines = f"before simplify={len(nb_kernels)}\n"
+
+ # simplify kernel structures and remove redundant kernels
+ sim_kernels = []
+ for kern in nb_kernels:
+ sim_kernels.append(simplify(kern))
+ nb_kernels = remove_redundancy(sim_kernels)
+ lines += f"after simplify={len(nb_kernels)}\n"
+
+ # add heuristic restart of period length for periodic kenerls
+ restart_period_kernels = []
+ for kern in nb_kernels:
+ restart_period_kernels.extend(initialize_kernel(kern, period_value_list))
+ nb_kernels.extend(restart_period_kernels)
+
+ lines += f"after period restart={len(nb_kernels)}\n"
+
+ lines += f"number of candidate kernels at depth {depth} is {len(nb_kernels)}\n"
+ return nb_kernels, lines
+
+ def search(
+ self,
+ max_depth: int,
+ top_k: int,
+ period_value_list: Tuple[float],
+ output_file: str = "./search.txt",
+ pickle_file: Optional[str] = "./result.pkl",
+ grammar: List[str] = GRAMMAR_RULES["all"],
+ learning_rate: float = 0.01,
+ num_epochs: int = 1000,
+ method: str = "BIC",
+ run_in_parallel: bool = False,
+ pool_num: int = 4,
+ ) -> List[Tuple[Kernel, float]]:
+ """
+ Search algorithm to find the best kernel given the training dataset
+ with regard to BIC score.
+ We keep k best models in each depth and end the search when best models
+ are not updated or reach the preset maximum depth.
+ At each depth n, we do the following:
+ 1. expand the kernel of best models by our operators;
+ 2. simplify kernel structures and remove redundant kernels;
+ 3. add heuristic restart of period length for periodic kenerls;
+ 4. train each model with a kernel and evaluate with BIC score.
+ 5. update k best kernels.
+ If any of best kernels are updated or depth hasn't reach the maximum, we go back to step 1 and continue the loop for depth n+1.
+ Search method to search the kernel. This is the main function for ABCD method.
+
+ :param max_depth: maximum number of depth to search.
+ :param top_k: keep top k models in each depth.
+ :param period_value_list: the tuple of period length values.
+ :param output_file: output file path.
+ :param pickle_file: result model file path.
+ :param grammar: list of representations for operators to use.
+ :param learning_rate: learning rate for training models.
+ :param num_epochs: number of epochs for training models.
+ :param method: method for scoring, one of 'BIC', 'AIC', 'NLL'.
+ :param run_in_parallel: if true, run the training of model in parallel.
+ :param pool_num: the number of pools for multiprocessing.
+ :return: a list of kernels and their scores.
+ """
+
+ with open(output_file, "w") as file:
+ start_time = time.time()
+ # initialize
+ current_kernel = WhiteNoiseKernel(noise=1e-4)
+ model_score = self.train_model(
+ current_kernel,
+ learning_rate=learning_rate,
+ num_epochs=num_epochs,
+ method=method,
+ )
+ lines = f"score={model_score}\n"
+ best_kernels = [(current_kernel, model_score)]
+
+ lines += "--------search begin--------\n"
+
+ for depth in range(max_depth):
+ # expand the kernel of best models
+ nb_kernels, lines = self._get_all_candidate_kernels(
+ best_kernels, grammar, period_value_list, depth
+ )
+
+ # train each model with a kernel and evaluate with score
+ score_list = []
+ train_partial = partial(
+ self.train_model,
+ learning_rate=learning_rate,
+ num_epochs=num_epochs,
+ method=method,
+ )
+
+ if run_in_parallel:
+ with mp.Pool(pool_num) as pool:
+ score_list = pool.map(train_partial, nb_kernels)
+ else:
+ score_list = map(train_partial, nb_kernels)
+
+ kernel_score_list = list(zip(nb_kernels, score_list))
+
+ kernel_score_list.extend(best_kernels)
+ kernel_score_list.sort(key=lambda x: x[1])
+ best_kernels_new = kernel_score_list[:top_k]
+
+ best_fixed = True
+ for i in range(top_k):
+ if not is_kernel_type_eq(
+ best_kernels_new[i][0], best_kernels[i][0]
+ ):
+ best_fixed = False
+ break
+ if best_fixed:
+ break
+ best_kernels = best_kernels_new
+
+ lines += "--------depth=" + str(depth) + "--------\n"
+ for k, score in kernel_score_list:
+ lines += repr(KernelExpression(k)) + ";" + str(score) + "\n"
+ lines += "--------best kernel--------\n"
+ for best_kernel, score in best_kernels:
+ lines += (
+ repr(KernelExpression(best_kernel)) + ";" + str(score) + "\n"
+ )
+ file.write(lines)
+ file.flush()
+ lines = ""
+
+ lines += "--------overall depth=" + str(depth) + "--------\n"
+ for best_kernel, score in best_kernels:
+ lines += repr(KernelExpression(best_kernel)) + "\n"
+ lines += str(score) + "\n"
+ lines += "--- %s seconds ---" % (time.time() - start_time)
+ file.write(lines)
+ file.close()
+ if pickle_file is not None:
+ with open(pickle_file, "wb") as handle:
+ dill.dump(best_kernels, handle)
+ return best_kernels
diff --git a/src/beanmachine/ppl/experimental/timeseries/sts/abcd/utils.py b/src/beanmachine/ppl/experimental/timeseries/sts/abcd/utils.py
new file mode 100644
index 0000000000..666325a1af
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/sts/abcd/utils.py
@@ -0,0 +1,151 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from typing import Dict, List
+
+from gpytorch.kernels import (
+ Kernel,
+ LinearKernel,
+ PeriodicKernel,
+ RBFKernel,
+ ScaleKernel,
+)
+from sts.abcd.kernels import ChangePointABCDKernel, ChangeWindowABCDKernel
+from sts.gp.kernels import ConstantKernel, WhiteNoiseKernel
+
+
+"""
+Base kernels as specified in the paper: WN, LN, SE, PER.
+"""
+BASE_KERNELS = [
+ WhiteNoiseKernel(noise=1e-5),
+ LinearKernel(),
+ ScaleKernel(RBFKernel()),
+ ScaleKernel(PeriodicKernel()),
+]
+"""
+Base kernels and constant kernels as specified in the paper: WN, LN, SE, PER, C.
+"""
+BASE_CONST_KERNELS = BASE_KERNELS + [ConstantKernel(constant=1.0)]
+"""
+grammar rules.
+"""
+BASIC_GRAMMAR_RULES = ["S->S+B", "S->S*B", "B->B1"]
+CP_GRAMMAR_RULES = ["S->CP(S,S)", "S->CW(S,S)", "S->CW(S,C)", "S->CW(C,S)"]
+HEURISTIC_GRAMMAR_RULES = ["S->S*(B+C)", "S->B", "S+S1->S", "S*S1->S"]
+GRAMMAR_RULES = {
+ "basic": BASIC_GRAMMAR_RULES,
+ "cp": CP_GRAMMAR_RULES,
+ "heuristic": HEURISTIC_GRAMMAR_RULES,
+ "all": BASIC_GRAMMAR_RULES + CP_GRAMMAR_RULES + HEURISTIC_GRAMMAR_RULES,
+}
+
+
+def is_base_kernel(kernel: Kernel) -> bool:
+ """
+ If kernel is a base kernel, return True; else, return False.
+
+ :param kernel: kernel to check.
+ :return: True if kernel is a base kernel; False otherwise.
+ """
+ return type(kernel) in map(type, BASE_CONST_KERNELS)
+
+
+def remove_redundancy(kernel_list: List[Kernel]) -> List[Kernel]:
+ """
+ Remove duplicate kernels in kernel_list.
+
+ :param kernel_list: the kernel list to remove redundancy.
+ :return: the list of kernels without duplication.
+ """
+ kernel_set = set(kernel_list)
+ for i in range(len(kernel_list) - 1):
+ for j in range(i + 1, len(kernel_list)):
+ kernel_map = {}
+ if is_kernel_type_eq(kernel_list[i], kernel_list[j], kernel_map):
+ if kernel_list[j] in kernel_set:
+ kernel_set.remove(kernel_list[j])
+ break
+ return list(kernel_set)
+
+
+def _is_base_kernel_type_eq(kernel1: Kernel, kernel2: Kernel) -> bool:
+ """
+ Check whether two base kernels are of the same type.
+
+ :param kernel1: one base kernel.
+ :param kernel2: another base kernel.
+ :return: True if kernel1 and kernel2 are identical, False otherwise.
+ """
+ if type(kernel1) == type(kernel2) and type(kernel1) != ScaleKernel:
+ return True
+ elif type(kernel1) == type(kernel2) and type(kernel1.base_kernel) == type(
+ kernel2.base_kernel
+ ):
+ return True
+ else:
+ return False
+
+
+def _init_kernel_map(kernel_map: Dict):
+ """
+ Initiate kernel_map of None to {}.
+ """
+ if kernel_map is None:
+ return {}
+ return kernel_map
+
+
+def is_kernel_type_eq(
+ kernel1: Kernel, kernel2: Kernel, kernel_map: Dict = None
+) -> bool:
+ """
+ Check whether two kernels are of the same type. Two kernels are of the same type if they
+ have the same type and every subkernel is of the same type.
+
+ :param kernel1: one kernel.
+ :param kernel2: another kernel.
+ :param kernel_map: the dictionary of mapping every subkernel in kernel1 to kernel2.
+ :return: True if kernel1 and kernel2 are identical, False otherwise.
+ """
+ if is_base_kernel(kernel1) and is_base_kernel(kernel2):
+ return _is_base_kernel_type_eq(kernel1, kernel2)
+
+ elif is_base_kernel(kernel1) or is_base_kernel(kernel2):
+ return False
+
+ if type(kernel1) != type(kernel2) or len(kernel1.kernels) != len(kernel2.kernels):
+ return False
+
+ kernel_map = _init_kernel_map(kernel_map)
+
+ # ChangeKernel should care the order of children
+ # CW(S, C) and CW(C, S) are different
+ if isinstance(kernel1, (ChangePointABCDKernel, ChangeWindowABCDKernel)):
+ if is_kernel_type_eq(
+ kernel1.kernels[0], kernel2.kernels[0], kernel_map
+ ) and is_kernel_type_eq(kernel1.kernels[1], kernel2.kernels[1], kernel_map):
+ kernel_map[kernel1] = kernel2
+ return True
+ else:
+ return False
+ else:
+ children1 = set(kernel1.kernels)
+ children2 = set(kernel2.kernels)
+
+ for c1 in children1:
+ if c1 in kernel_map.keys():
+ if kernel_map[c1] in children2:
+ children2.remove(kernel_map[c1])
+ continue
+ else:
+ return False
+ map_node2 = None
+ for c2 in children2:
+ if is_kernel_type_eq(c1, c2, kernel_map):
+ map_node2 = c2
+ break
+ if map_node2 is None:
+ return False
+ children2.remove(map_node2)
+ kernel_map[kernel1] = kernel2
+ return True
diff --git a/src/beanmachine/ppl/experimental/timeseries/sts/changepoints.py b/src/beanmachine/ppl/experimental/timeseries/sts/changepoints.py
new file mode 100644
index 0000000000..efc87b5b83
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/sts/changepoints.py
@@ -0,0 +1,118 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import math
+from collections import defaultdict
+
+import torch
+
+
+class BinSegChangepoint:
+ """
+ Offline changepoint detection using Binary Segmentation. This method
+ greedily selects the changepoint that minimizes the negative log likelihood
+ (NLL) to iteratively segment the time series.
+
+ [1] Charles Truong, Laurent Oudre, Nicolas Vayatis, "Selective review of
+ offline change point detection methods", https://arxiv.org/abs/1801.00718.
+
+ :param int min_segment: the minimum length of a time series segment.
+ :param float regularization: Optional regularization term for least squares
+ to estimate the regression parameters.
+ :param float penalty_weight: Overfitting penalty to add to the cost function
+ when adding a changepoint. This is specified as a fraction w.r.t. the
+ NLL of the original segment.
+ :param int max_changepoints: Maximum number of changepoints to return. If
+ the number of changepoints found is larger than `max_changepoints`, then
+ `max_changepoints` number of changepoints with the lowest cost are
+ returned.
+ """
+
+ def __init__(
+ self,
+ min_segment=10,
+ regularization=0.0,
+ penalty_weight=1e-2,
+ max_changepoints=10,
+ ):
+ self.min_segment = min_segment
+ self.regularization = regularization
+ self.penalty_weight = penalty_weight
+ self.max_changepoints = max_changepoints
+ self._cost_cache = defaultdict(lambda: float("inf"))
+
+ def nll(self, x, y):
+ # MLE for penalized least squares
+ theta = torch.inverse(x.T @ x + self.regularization * torch.eye(2)) @ (x.T @ y)
+ n = len(y)
+ const_term = -n / 2 * math.log(2 * math.pi)
+ err = y - x @ theta
+ param_term = -0.5 * torch.dot(err, err)
+ return -(const_term + param_term)
+
+ def get_cost(self, x, y, i, j):
+ """
+ The cost of a segment (i, j) is given by Negative Log Likelihood of the
+ observations in (i, j), where the parameters of the regression are
+ estimated by maximizing the likelihood.
+
+ :param torch.Tensor x: 1-D torch tensor designating the independent
+ axis.
+ :param torch.Tensor y: 1-D torch tensor for the response variable over
+ which to carry out changepoint detection.
+ :param int i: lower limit (inclusive) for the changepoint search.
+ :param int j: upper limit (exclusive) for the changepoint search.
+ """
+ if (i, j) in self._cost_cache:
+ return self._cost_cache[(i, j)]
+ x_seg = x[i:j]
+ y_seg = y[i:j]
+ cost = self.nll(x_seg, y_seg)
+ self._cost_cache[(i, j)] = cost
+ return cost
+
+ def _changepoints_segment(self, x, y, i, j, penalty):
+ orig_cost = self.get_cost(x, y, i, j)
+ min_cost = orig_cost
+ min_idx = None
+ for k in range(i + self.min_segment, j - self.min_segment):
+ cost_seg_1 = self.get_cost(x, y, i, k)
+ cost_seg_2 = self.get_cost(x, y, k, j)
+ total_cost = cost_seg_1 + cost_seg_2 + penalty
+ if total_cost < min_cost:
+ min_cost = total_cost
+ min_idx = k
+ if min_idx is None:
+ return [], []
+ seg_score = orig_cost - min_cost
+ seg_lhs, score_lhs = self._changepoints_segment(x, y, i, min_idx + 1, penalty)
+ seg_rhs, score_rhs = self._changepoints_segment(x, y, min_idx + 1, j, penalty)
+ return seg_lhs + [min_idx] + seg_rhs, score_lhs + [seg_score] + score_rhs
+
+ def get_changepoints(self, x, y):
+ """
+ The cost of adding a changepoint t to a segment (i, j) is given by:
+ Cost(i, j, t) = NLL(i, t) + NLL(t, j) + penalty_weight * NLL(0, n)
+
+ where NLL = Negative Log Likelihood of the observations, where the
+ parameters of the regression are estimated by maximizing the likelihood.
+ """
+ n = len(y)
+ assert len(x) == n, "`x` and `y` should have the same length."
+ assert x.dim() == 1, "1-D tensor expected for `x`"
+ assert y.dim() == 1, "1-D tensor expected for `y`"
+ x = x.unsqueeze(-1)
+ x = torch.cat([x, torch.ones_like(x)], -1)
+ penalty = self.penalty_weight * self.get_cost(x, y, 0, n)
+ changepoints, scores = self._changepoints_segment(x, y, 0, n, penalty)
+ if len(changepoints) > self.max_changepoints:
+ filtered = list(
+ zip(
+ *(
+ sorted(zip(scores, changepoints), reverse=True)[
+ : self.max_changepoints
+ ]
+ )
+ )
+ )[1]
+ changepoints = sorted(filtered) # sort changepoints by location
+ return changepoints
diff --git a/src/beanmachine/ppl/experimental/timeseries/sts/data.py b/src/beanmachine/ppl/experimental/timeseries/sts/data.py
new file mode 100644
index 0000000000..7e3d702d96
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/sts/data.py
@@ -0,0 +1,754 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import functools
+import inspect
+import warnings
+from collections.abc import Sequence
+from typing import Any, Callable, Dict, Iterable, List, Optional, Union
+
+import pandas as pd
+import torch
+from gpytorch.distributions import MultivariateNormal
+from torch.distributions import transforms
+from torch.overrides import get_testing_overrides
+from torch.utils._pytree import PyTree, tree_flatten, tree_unflatten
+
+
+POINTWISE_OPS = [
+ torch.abs,
+ torch.absolute,
+ torch.acos,
+ torch.arccos,
+ torch.acosh,
+ torch.arccosh,
+ torch.add,
+ torch.addcdiv,
+ torch.addcmul,
+ torch.angle,
+ torch.asin,
+ torch.arcsin,
+ torch.asinh,
+ torch.arcsinh,
+ torch.atan,
+ torch.arctan,
+ torch.atanh,
+ torch.arctanh,
+ torch.atan2,
+ torch.bitwise_not,
+ torch.bitwise_and,
+ torch.bitwise_or,
+ torch.bitwise_xor,
+ torch.ceil,
+ torch.clamp,
+ torch.clip,
+ torch.conj,
+ torch.copysign,
+ torch.cos,
+ torch.cosh,
+ torch.deg2rad,
+ torch.div,
+ torch.divide,
+ torch.digamma,
+ torch.erf,
+ torch.erfc,
+ torch.erfinv,
+ torch.exp,
+ torch.exp2,
+ torch.expm1,
+ torch.fix,
+ torch.float_power,
+ torch.floor,
+ torch.fmod,
+ torch.frac,
+ torch.ldexp,
+ torch.lerp,
+ torch.lgamma,
+ torch.log,
+ torch.log10,
+ torch.log1p,
+ torch.log2,
+ torch.logaddexp,
+ torch.logaddexp2,
+ torch.logical_and,
+ torch.logical_not,
+ torch.logical_or,
+ torch.logical_xor,
+ torch.logit,
+ torch.hypot,
+ torch.i0,
+ torch.igamma,
+ torch.igammac,
+ torch.mul,
+ torch.multiply,
+ torch.nan_to_num,
+ torch.neg,
+ torch.negative,
+ torch.nextafter,
+ torch.pow,
+ torch.rad2deg,
+ torch.reciprocal,
+ torch.remainder,
+ torch.round,
+ torch.rsqrt,
+ torch.sigmoid,
+ torch.sign,
+ torch.sgn,
+ torch.signbit,
+ torch.sin,
+ torch.sinc,
+ torch.sinh,
+ torch.sqrt,
+ torch.square,
+ torch.sub,
+ torch.subtract,
+ torch.tan,
+ torch.tanh,
+ torch.true_divide,
+ torch.trunc,
+ torch.xlogy,
+]
+
+
+REDUCTION_OPS = [
+ torch.argmax,
+ torch.argmin,
+ torch.amax,
+ torch.amin,
+ torch.all,
+ torch.any,
+ torch.max,
+ torch.min,
+ torch.dist,
+ torch.logsumexp,
+ torch.mean,
+ torch.median,
+ torch.nanmedian,
+ torch.mode,
+ torch.norm,
+ torch.nansum,
+ torch.prod,
+ torch.quantile,
+ torch.nanquantile,
+ torch.std,
+ torch.std_mean,
+ torch.sum,
+ torch.unique,
+ torch.unique_consecutive,
+ torch.var,
+ torch.var_mean,
+]
+
+
+HANDLED_FNS = {}
+OVERRIDES = get_testing_overrides()
+
+
+def implements(op):
+ @functools.wraps(op)
+ def _wrapped(fn):
+ HANDLED_FNS[op] = fn
+ return fn
+
+ return _wrapped
+
+
+# TODO: This can be removed in the next PyTorch version (> 1.9)
+def tree_map(fn: Any, pytree: PyTree) -> PyTree:
+ flat_args, spec = tree_flatten(pytree)
+ return tree_unflatten([fn(i) for i in flat_args], spec)
+
+
+def _check_arg_consistency(dt_nodes):
+ check_eq = [(dt.data_dim, dt.header) for dt in dt_nodes]
+ if not all(x == check_eq[0] for x in check_eq):
+ raise ValueError(
+ f"Different headers or data_dim found - {check_eq}."
+ " Consider using underlying tensors directly."
+ )
+
+
+def _map_unwrap(args):
+ """
+ Simple unwrap mapping operation that does not work on nested PyTree.
+ """
+ unpacked, dt_nodes = [], []
+ for x in args:
+ if isinstance(x, DataTensor):
+ unpacked.append(x.tensor)
+ dt_nodes.append(x)
+ else:
+ if isinstance(x, Sequence):
+ warnings.warn("For nested unpacking, use `tree_map`")
+ unpacked.append(x)
+ # Check that args have same header/data_dim
+ _check_arg_consistency(dt_nodes)
+ return unpacked, dt_nodes
+
+
+def _handle_pointwise_ops(func, *args, **kwargs):
+ args, dt_nodes = _map_unwrap(args)
+ ret = func(*args, **kwargs)
+ return DataTensor(ret, dt_nodes[0].header, dim=dt_nodes[0].data_dim)
+
+
+def _handle_reduction_ops(func, *args, **kwargs):
+ args, dt_nodes = _map_unwrap(args)
+ prototype = dt_nodes[0]
+ func_sign = inspect.signature(OVERRIDES[func]).bind(*args, **kwargs)
+ func_sign.apply_defaults()
+ dim = func_sign.arguments.get("dim", None)
+ is_reduction = (prototype.data_dim is None) or dim in (
+ None,
+ prototype.data_dim,
+ prototype.data_dim + prototype.ndim,
+ )
+ ret = func(*args, **kwargs)
+
+ def _wrap(x):
+ if not isinstance(x, torch.Tensor):
+ return x
+ if is_reduction:
+ return DataTensor(x, header=[])
+ return DataTensor(x, prototype.header, dim=prototype.data_dim)
+
+ return tree_map(_wrap, ret)
+
+
+@implements(torch.squeeze)
+def _squeeze(input, dim):
+ new_tensor = input.tensor.squeeze(dim)
+ # Squeeze has no effect - early exit.
+ if new_tensor.ndim == input.tensor.ndim:
+ return input.new_datatensor(new_tensor)
+ dim = dim if dim < 0 else dim - input.ndim
+ if not input.data_dim:
+ header, col_dim = (), None
+ elif dim < input.data_dim:
+ header = input.header
+ col_dim = input.data_dim
+ elif dim == input.data_dim:
+ header = []
+ col_dim = None
+ else:
+ header = input.header
+ col_dim = input.data_dim + 1
+ assert col_dim < 0
+ return input.new_datatensor(new_tensor, header, dim=col_dim)
+
+
+@implements(torch.unsqueeze)
+def _unsqueeze(input, dim):
+ new_tensor = input.tensor.unsqueeze(dim)
+ dim = dim if dim < 0 else dim - input.ndim - 1
+ if not input.data_dim or dim < input.data_dim:
+ col_dim = input.data_dim
+ else:
+ col_dim = input.data_dim - 1
+ return input.new_datatensor(new_tensor, input.header, dim=col_dim)
+
+
+for _fn in POINTWISE_OPS:
+ HANDLED_FNS[_fn] = functools.partial(_handle_pointwise_ops, _fn)
+
+for _fn in REDUCTION_OPS:
+ HANDLED_FNS[_fn] = functools.partial(_handle_reduction_ops, _fn)
+
+
+class DataTensor(object):
+ """
+ Data structure used by time series model to store additional metadata with
+ :class:`torch.Tensor` objects such as header (column) information and
+ normalization. Note that the header information may be empty for scalar
+ tensor or tensors that result from a reduction op. e.g.
+
+ >>> d = DataTensor(torch.arange(4).view(2, 2), ['a', 'b'])
+ DataTensor(tensor=tensor([[0, 1],
+ [2, 3]]), header=('a', 'b'))
+ >>> d[:, ['b']]
+ DataTensor(tensor=tensor([[1],
+ [3]]), header=('b',))
+ >>> torch.sum(d, 0)
+ DataTensor(tensor=tensor([2, 4]), header=('a', 'b'))
+ >>> torch.sum(d)
+ DataTensor(tensor=6, header=())
+
+ :param tensor: a :class:`torch.Tensor` instance.
+ :param header: list of column names having the same size as the innermost dim
+ of `tensor`.
+ :param normalize_cols: list of columns to normalize by scaling to 0 mean unit
+ norm, or a dictionary of column names mapped to the corresponding
+ :class:`torch.distributions.Transform`.
+ :param dim: Dimension for column indexing. By default, it is the
+ rightmost dimension.
+ """
+
+ def __init__(
+ self,
+ tensor: torch.Tensor,
+ header: Iterable[str] = (),
+ normalize_cols: Union[Dict[str, transforms.Transform], List[str]] = None,
+ dim: int = -1,
+ ):
+ assert isinstance(tensor, torch.Tensor)
+ self.reduced = not header
+ self.scalar = tensor.ndim == 0
+ # dim should be None for scalar or reduced DataTensors.
+ if self.reduced or self.scalar:
+ self.data_dim = None
+ else:
+ if dim < -tensor.ndim or dim >= tensor.ndim:
+ raise IndexError(
+ f"dim={dim} invalid for a tensor of dim {tensor.ndim}."
+ )
+ self.data_dim = dim if dim < 0 else dim - tensor.ndim
+ if self.scalar:
+ if header:
+ raise ValueError("Scalar DataTensor must have empty header.")
+ elif (not self.reduced) and (len(header) != tensor.shape[self.data_dim]):
+ raise ValueError(
+ f"Tensor data dim size {tensor.shape[self.data_dim]} does not match header length {len(header)}."
+ )
+ self.tensor = tensor
+ self.header = tuple(header)
+ self.rev_index = {h: i for i, h in enumerate(header)}
+ # Transforms applied to the columns
+ self.transforms = {}
+ self._normalized = set()
+ if normalize_cols is not None:
+ self.normalize(normalize_cols)
+
+ def new_datatensor(self, tensor, header=None, dim=None):
+ """
+ Return a new DataTensor instance defaulting to the current instance
+ for header/data_dim information.
+
+ :param tensor: New underlying tensor data.
+ :param header: Optional header information.
+ :param dim: Dimension for column indexing. By default, we use this is
+ the same as `self.data_dim`.
+ """
+ dim = self.data_dim if dim is None else dim
+ header = self.header if header is None else header
+ data_tensor = DataTensor(tensor, header, dim=dim)
+ for h in data_tensor.header:
+ if h in self.transforms:
+ data_tensor.transforms[h] = self.transforms[h]
+ return data_tensor
+
+ def normalize(
+ self, transform_columns: Union[Dict[str, transforms.Transform], List[str]]
+ ):
+ """
+ Scale the specified columns using the transforms specified for each `column`.
+ If `transform_columns` is a list, use standard normalization - scaling the data to
+ 0 mean and unit norm. Else, we can also provide a dict of column names
+ mapped to the corresponding :class:`torch.distributions.Transform`.
+
+ :param transform_columns: List of columns (subset of `self.header`), or
+ a dictionary of column names mapped to the corresponding
+ :class:`torch.distributions.Transform`.
+ """
+ if self.tensor.ndim <= 1:
+ return
+ if isinstance(transform_columns, dict):
+ intersection = self._normalized & transform_columns.keys()
+ if intersection:
+ raise ValueError(f"Columns {intersection} already normalized.")
+ self.transforms = transform_columns
+ # Use default transform
+ elif isinstance(transform_columns, list):
+ for c in transform_columns:
+ if c in self._normalized:
+ raise ValueError(f"Column {c} already normalized.")
+ idx = self.tensor.new_full((), self.rev_index[c], dtype=torch.long)
+ selected_column = self.tensor.index_select(self.data_dim, idx)
+ mean = selected_column.mean()
+ std = selected_column.std()
+ transform = transforms.AffineTransform(mean, std).inv
+ self.transforms[c] = transform
+ else:
+ raise TypeError(f"Invalid type {type(transform_columns)} for `columns`.")
+ for c, transform in self.transforms.items():
+ if c in self._normalized:
+ continue
+ if not isinstance(transform, transforms.Transform):
+ raise TypeError(
+ f"Invalid transform type {type(transform)}. Must be an instance of "
+ f"`torch.distributions.Transform`."
+ )
+ idx = self.tensor.new_full((), self.rev_index[c], dtype=torch.long)
+ selected_column = self.tensor.index_select(self.data_dim, idx)
+ transformed_column = transform(selected_column)
+ self.tensor.index_copy_(self.data_dim, idx, transformed_column)
+ self._normalized.add(c)
+
+ def denormalize(
+ self, data: Union["DataTensor", torch.Tensor]
+ ) -> Union["DataTensor", torch.Tensor]:
+ """
+ Rescale the given tensor so that column values are in their original
+ scale using the internal normalization metadata.
+
+ :param data: a :class:`DataTensor` or :class:`torch.Tensor` instance.
+ :return: a new :class:`DataTensor` or :class:`torch.Tensor` instance
+ with rescaled columns.
+ """
+ if isinstance(data, DataTensor):
+ header = data.header
+ tensor = data.tensor.clone()
+ else:
+ tensor, header = data.clone(), None
+ if (
+ tensor.ndim != self.tensor.ndim
+ or tensor.shape[self.data_dim] != self.tensor.shape[self.data_dim]
+ ):
+ raise ValueError(
+ "Tensor's ndim and size of column dim must match the source tensor."
+ )
+ for c, transform in self.transforms.items():
+ idx = tensor.new_full((), self.rev_index[c], dtype=torch.long)
+ selected_column = tensor.index_select(self.data_dim, idx)
+ transformed_column = transform.inv(selected_column)
+ tensor.index_copy_(self.data_dim, idx, transformed_column)
+ return tensor if header is None else self.new_datatensor(tensor, header)
+
+ def get_index(self, key):
+ """Get integer indices corresponding to the column names in `key`.
+
+ :param key: A sequence, int or str values corresonding to indices in the
+ to be selected from the `data_dim`.
+ :return: Integer indices for (potential) column names referenced in `key`.
+ """
+ col_key = key
+ if isinstance(key, str):
+ if key not in self.rev_index:
+ raise IndexError(f"key={key} not in {self.header}.")
+ col_key = self.rev_index[key]
+ elif isinstance(key, Sequence) and any(isinstance(k, str) for k in key):
+ col_idxs = []
+ for c in key:
+ if c not in self.rev_index:
+ raise IndexError(f"key={c} not in {self.header}.")
+ col_idxs.append(self.rev_index[c])
+ # tensor[(0,)] doesn't behave the same as tensor[[0]]
+ col_key = tuple(col_idxs) if isinstance(key, tuple) else col_idxs
+ return col_key
+
+ def clone(self):
+ return self.new_datatensor(self.tensor.clone())
+
+ def squeeze(self, dim):
+ return torch.squeeze(self, dim)
+
+ def unsqueeze(self, dim):
+ return torch.unsqueeze(self, dim)
+
+ def float(self):
+ return self.new_datatensor(self.tensor.float())
+
+ def long(self):
+ return self.new_datatensor(self.tensor.long())
+
+ def __add__(self, other):
+ return torch.add(self, other)
+
+ def __sub__(self, other):
+ return torch.subtract(self, other)
+
+ def __mul__(self, other):
+ return torch.mul(self, other)
+
+ def __div__(self, other):
+ return torch.divide(self, other)
+
+ def __getattr__(self, name):
+ return self.tensor.__getattribute__(name)
+
+ @staticmethod
+ def _is_index_type(key, t):
+ return isinstance(key, t) or (
+ isinstance(key, Sequence) and any(isinstance(k, t) for k in key)
+ )
+
+ def _forward_parse(self, key, parsed):
+ """
+ Parse key until we reach the end or an Ellipsis is encountered, while
+ gathering the index of empty dims in the possibly reduced tensor and
+ the number of reduced dims to the right of `self.data_dim`.
+ """
+ empty_dims = []
+ data_dim = self.ndim + self.data_dim
+ nonempty_idx = 0
+ num_reduced = 0 # number of reduced dims
+ num_reduced_ddim = 0 # number of reduced dims to the right of data_dim
+ ellipsis_idx = len(key)
+ for i, k in enumerate(key):
+ if k is None:
+ empty_dims.append(i - num_reduced)
+ elif k is Ellipsis:
+ ellipsis_idx = i
+ break
+ else:
+ if self._is_index_type(k, str) and nonempty_idx != data_dim:
+ raise IndexError(
+ f"String indexing at dim {i} does not match self.data_dim={data_dim}."
+ )
+ if isinstance(k, (str, int)):
+ num_reduced += 1
+ if nonempty_idx > data_dim:
+ num_reduced_ddim += 1
+ parsed[nonempty_idx] = k
+ nonempty_idx += 1
+ return parsed, empty_dims, num_reduced_ddim, ellipsis_idx
+
+ def _reverse_parse(self, key, parsed, stop):
+ """
+ Parse key in reverse order until we hit `stop` index, while
+ gathering the index of empty dims in the possibly reduced tensor and
+ the number of reduced dims to the right of `self.data_dim`. Note that
+ indexing is done from the right starting from -1.
+ """
+ empty_dims = []
+ nonempty_idx = -1
+ num_reduced = 0 # number of reduced dims
+ num_reduced_ddim = 0 # number of reduced dims to the right of data_dim
+ for i, k in enumerate(reversed(key)):
+ j = -i - 1
+ if len(key) + j <= stop:
+ break
+ if k is None:
+ empty_dims.append(j + num_reduced)
+ elif k is Ellipsis:
+ raise NotImplementedError(
+ "More than 1 ellipsis for indexing is not supported."
+ )
+ else:
+ if self._is_index_type(k, str) and nonempty_idx != self.data_dim:
+ raise IndexError(
+ f"String indexing at dim {j} does not match self.data_dim={self.data_dim}."
+ )
+ if isinstance(k, (str, int)):
+ num_reduced += 1
+ if nonempty_idx > self.data_dim:
+ num_reduced_ddim += 1
+ parsed[nonempty_idx] = k
+ nonempty_idx -= 1
+ return parsed, empty_dims, num_reduced_ddim
+
+ def _get_normalized_dims(self, key):
+ """
+ Remove Ellipsis and return key of the same size as `self.ndim`.
+ Also returns (i) the indices for the empty (`None`) dims in the output
+ tensor (possibly of a reduced dim), and (ii) the
+ number of reduced dimensions after the `data_dim`.
+
+ e.g. for a 3-D tensor:
+ [..., "a"] --> [slice(None), slice(None), "a"]
+ """
+ if not isinstance(key, Sequence):
+ if key is None:
+ return tuple(slice(None) for _ in range(self.ndim)), [0], 0
+ elif isinstance(key, (str, int, slice)):
+ return (
+ (key,) + tuple(slice(None) for _ in range(self.ndim - 1)),
+ [],
+ 0,
+ )
+ raise ValueError(f"Unsupported type {type(key)} for key.")
+ # indexing along dim 0
+ if isinstance(key, list):
+ key = (key,) + tuple(slice(None) for _ in range(self.ndim - 1))
+ for k in key:
+ if isinstance(k, Sequence) and any(k_ is None for k_ in k):
+ raise IndexError("Nested `None` indices are disallowed.")
+ # Convert all indexing ops into multi-dim indexing with one
+ # index per dim. e.g. (slice(None, None, None), ['a'], 1) for a 3D tensor.
+ parsed = [slice(None)] * self.ndim
+ parsed, empty_dims_lhs, num_reduced_lhs, ellipsis_idx = self._forward_parse(
+ key, parsed
+ )
+ parsed, empty_dims_rhs, num_reduced_rhs = self._reverse_parse(
+ key, parsed, ellipsis_idx
+ )
+ return (
+ tuple(parsed),
+ empty_dims_lhs + empty_dims_rhs,
+ num_reduced_lhs + num_reduced_rhs,
+ )
+
+ def __getitem__(self, key):
+ header = self.header
+ # 1. If self.data_dim is None (scalar or reduced tensor),
+ # exit early.
+ if self.data_dim is None:
+ return DataTensor(self.tensor[key])
+ # 2. For boolean masked indexing or advanced indexing via LongTensor
+ # exit early
+ if self._is_index_type(key, (bool, torch.Tensor)):
+ return DataTensor(self.tensor[key])
+
+ # 3. Handle remaining cases by first getting a normalized key
+ # having an entry for each dim, determining if the `data_dim`
+ # is affected, and handling the header information appropriately.
+
+ # Positive indexed dim for column indexing.
+ data_dim = self.tensor.ndim + self.data_dim
+ # Get normalized key (with entry for each dim)
+ key_nonempty, empty_dims, num_reduced = self._get_normalized_dims(key)
+ col_idxs = self.get_index(key_nonempty[data_dim])
+ # Default
+ tensor_key = key_nonempty
+ header = self.header
+ # Column indexing has occured via string/integer indexing.
+ if self._is_index_type(col_idxs, int):
+ tensor_key = (
+ key_nonempty[:data_dim] + (col_idxs,) + key_nonempty[data_dim + 1 :]
+ )
+ header = (
+ ()
+ if isinstance(col_idxs, int)
+ else tuple(self.header[c] for c in col_idxs)
+ )
+ # If all entries are ints => advanced indexing, exit early
+ if self.ndim > 1 and all(self._is_index_type(k, int) for k in tensor_key):
+ return DataTensor(self.tensor[tensor_key])
+ # Column indexing has occured via a slice operator
+ # Only need to adjust the header
+ elif isinstance(col_idxs, slice):
+ header = tuple(self.header[col_idxs])
+ val = self.new_datatensor(
+ self.tensor[tensor_key], header, dim=self.data_dim + num_reduced
+ )
+ # Handle None dims => apply unsqueezes
+ for d in empty_dims:
+ val = val.unsqueeze(d)
+ return val
+
+ def __len__(self):
+ return len(self.tensor)
+
+ def __repr__(self):
+ return f"DataTensor(tensor={self.tensor}, header={self.header})"
+
+ @classmethod
+ def __torch_function__(cls, func, types, args=(), kwargs=None):
+ if kwargs is None:
+ kwargs = {}
+ if func in HANDLED_FNS:
+ return HANDLED_FNS[func](*args, **kwargs)
+
+ # No special handling for these operations - the result from the
+ # corresponding PyTorch ops is returned with empty header.
+ args = tree_map(lambda x: x.tensor if isinstance(x, DataTensor) else x, args)
+ ret = func(*args, **kwargs)
+ return tree_map(
+ lambda x: DataTensor(x, header=[]) if isinstance(x, torch.Tensor) else x,
+ ret,
+ )
+
+
+def df_to_tensor(
+ df: pd.DataFrame,
+ columns: Optional[Iterable] = None,
+ df_convert_fns: Dict[str, Callable] = None,
+ dtype: torch.dtype = torch.float32,
+ normalize_cols: Union[bool, Iterable] = False,
+) -> DataTensor:
+ """
+ Construct and return a :class:`DataTensor` instance from a pandas DataFrame.
+
+ :param df: Pandas DataFrame object.
+ :param columns: Subset of columns to select from `df` to construct the
+ `DataTensor` instance.
+ :param df_convert_fns: A dict of post-processing functions by column names.
+ This is useful to convert custom pandas data types such as datetime values
+ into a `torch.float` value.
+ :param dtype: default dtype for the backing `torch.Tensor` object. Defaults
+ to `torch.float32`.
+ :param normalize_cols: flag to indicate whether columns should be normalized
+ to 0 mean and unit norm. Two other possibilities are: (i) A list of columns
+ can be passed instead in which case only the specified columns will be
+ normallized. (ii) To have custom transforms per column, a dict of column names
+ with the corresponding applicable :class:`torch.distributions.Transform` instance
+ can be passed.
+ :return: `DataTensor` instance.
+ """
+ df = df.copy()
+ header = list(df.columns)
+ if df_convert_fns:
+ for name, fn in df_convert_fns.items():
+ df[name] = fn(df[name])
+ if columns is not None:
+ header = list(columns)
+ df = df[columns]
+ if normalize_cols is True:
+ normalize_cols = header
+ elif normalize_cols is False:
+ normalize_cols = []
+ return DataTensor(
+ torch.tensor(df.to_numpy(), dtype=dtype), header, normalize_cols=normalize_cols
+ )
+
+
+def _extract_transforms(transform):
+ def _extract_affine_params(t):
+ if isinstance(t, transforms.AffineTransform) or (
+ isinstance(t, transforms._InverseTransform)
+ and isinstance(t._inv, transforms.AffineTransform)
+ ):
+ return t.loc, t.scale
+ return None, None
+
+ loc, scale, exp_transform = None, None, False
+
+ if transform is None:
+ return 0.0, 1.0, False
+ elif isinstance(transform, transforms.ExpTransform):
+ return 0.0, 1.0, True
+ elif isinstance(transform, transforms.ComposeTransform):
+ if len(transform.parts) == 2:
+ loc, scale = _extract_affine_params(transform.parts[0])
+ if isinstance(transform.parts[1], transforms.ExpTransform):
+ exp_transform = True
+ else:
+ loc, scale = _extract_affine_params(transform)
+ return loc, scale, exp_transform
+
+
+def get_mvn_stats(
+ mvn: MultivariateNormal,
+ transform: Optional[torch.distributions.Transform] = None,
+ ci: int = 90,
+):
+ """
+ Get mean, variance and confidence interval from a
+ :class:`MultivariateNormal` distribution.
+
+ :param mvn: the multivariatenormal distribution of interest.
+ :param transform: any transforms to rescale the samples from `mvn` to
+ their original scale.
+ :param ci: confidence interval from 0-100 (defaults to 90)
+ :return: tuple of `(mean, variance, ci)`.
+ """
+ with torch.no_grad():
+ mean = mvn.mean
+ # XXX: calling .variance can blow up the memory due to some gpytorch
+ # broadcasting ops.
+ var = mvn.covariance_matrix.diag()
+ mean_t, scale_t, exp_transform = _extract_transforms(transform)
+ # TODO: We can draw multiple samples and compute stats when other
+ # transforms are provided.
+ if mean_t is None or scale_t is None:
+ raise NotImplementedError(f"Unsupported transform {transform}.")
+ mean = mean_t + mean * scale_t
+ var = scale_t**2 * var
+ p1, p2 = torch.tensor((100 - ci) / 200.0), torch.tensor((100 + ci) / 200.0)
+ mean_orig, var_orig = mean, var
+ q1 = mean + (2 * var).sqrt() * torch.erfinv(2 * p1 - 1)
+ q2 = mean + (2 * var).sqrt() * torch.erfinv(2 * p2 - 1)
+ if exp_transform:
+ mean_orig = torch.exp(mean + var / 2)
+ var_orig = mean_orig**2 * (var.exp() - 1)
+ q1 = torch.exp(q1)
+ q2 = torch.exp(q2)
+ return (mean_orig, var_orig, (q1, q2))
diff --git a/src/beanmachine/ppl/experimental/timeseries/sts/gp/__init__.py b/src/beanmachine/ppl/experimental/timeseries/sts/gp/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/src/beanmachine/ppl/experimental/timeseries/sts/gp/cov.py b/src/beanmachine/ppl/experimental/timeseries/sts/gp/cov.py
new file mode 100644
index 0000000000..50bc9b7808
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/sts/gp/cov.py
@@ -0,0 +1,607 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import numbers
+from collections import OrderedDict
+from typing import Iterable, List, Optional, Set, Type
+
+import gpytorch as gp
+import torch
+from gpytorch.kernels import (
+ AdditiveKernel,
+ Kernel,
+ PeriodicKernel,
+ ProductKernel,
+ RBFKernel,
+ ScaleKernel,
+ SpectralMixtureKernel,
+)
+from sts.data import DataTensor
+from sts.gp.kernels import ChangePointKernel, WhiteNoiseKernel
+from torch import nn
+
+
+class CovComponent(nn.Module):
+ def __init__(self, kernel: Kernel, name=None):
+ super().__init__()
+ self.kernel = kernel
+ self._name = name if name is not None else self._get_name()
+
+ def __add__(self, other):
+ components = []
+ components += (
+ list(self.parts.values())
+ if isinstance(self, AdditiveComponents)
+ else [self]
+ )
+ components += (
+ list(other.parts.values())
+ if isinstance(other, AdditiveComponents)
+ else [other]
+ )
+ return AdditiveComponents(*components)
+
+ def __mul__(self, other):
+ components = []
+ components += (
+ list(self.parts.values()) if isinstance(self, ProductComponents) else [self]
+ )
+ components += (
+ list(other.parts.values())
+ if isinstance(other, ProductComponents)
+ else [other]
+ )
+ return ProductComponents(*components)
+
+ @property
+ def name(self):
+ return self._name
+
+ @name.setter
+ def name(self, name):
+ self._name = name
+
+ @property
+ def lengthscale(self):
+ if isinstance(self.kernel, ScaleKernel):
+ return self.kernel.base_kernel.lengthscale * self.scale
+ return self.kernel.lengthscale * self.scale
+
+ @property
+ def scale(self):
+ return 1.0
+
+ @lengthscale.setter
+ def lengthscale(self, value):
+ if isinstance(self.kernel, ScaleKernel):
+ self.kernel.base_kernel.lengthscale = value / self.scale
+ else:
+ self.kernel.lengthscale = value / self.scale
+
+ @property
+ def fixed_params(self) -> Set[nn.Parameter]:
+ return set()
+
+ def forward(self, x1, x2, diag=False, **params):
+ return self.kernel.forward(x1, x2, diag=diag, **params)
+
+ def __call__(self, x1, x2=None, diag=False, last_dim_is_batch=False, **params):
+ if isinstance(x1, DataTensor):
+ x1 = x1.tensor
+ if isinstance(x2, DataTensor):
+ x2 = x2.tensor
+ return self.kernel(x1, x2, diag, last_dim_is_batch, **params)
+
+
+class Regression(CovComponent):
+ def __init__(
+ self,
+ sample_input: DataTensor,
+ features: Iterable[str],
+ *,
+ ard: bool = True,
+ kernel_cls: Type[Kernel] = RBFKernel,
+ outputscale_prior: gp.priors.Prior = None,
+ outputscale_constraint: gp.constraints.Interval = None,
+ name: Optional[str] = None,
+ **kernel_kwargs,
+ ):
+ if kernel_cls is ScaleKernel:
+ raise ValueError(
+ "Wrapping kernel in ScaleKernel is not required. Pass the base kernel instead."
+ )
+ self.features = features
+ regression_kernel = ScaleKernel(
+ kernel_cls(
+ active_dims=sample_input.get_index(features),
+ ard_num_dims=len(features) if ard else None,
+ **kernel_kwargs,
+ ),
+ outputscale_prior=outputscale_prior,
+ outputscale_constraint=outputscale_constraint,
+ )
+ super().__init__(regression_kernel, name=name)
+ scale = []
+ for f in features:
+ if f in sample_input.transforms:
+ scale.append(sample_input.transforms.get(f, 1.0).inv.scale)
+ else:
+ scale.append(1.0)
+ self._scale = torch.tensor(scale)
+
+ @property
+ def scale(self):
+ return self._scale
+
+
+class Trend(CovComponent):
+ """
+ Covariance component for modeling the trend.
+
+ :param sample_input: a sample :class:`DataTensor` object that represents
+ the inputs of interest.
+ :param time_axis: the name for the time axis over which to model the
+ trend.
+ :param lengthscale: optional length scale to initialize to. Note that
+ this is in the original (unnormalized) scale of the time unit.
+ :param fix_lengthscale: whether to fix the `lengthscale`, i.e. remove
+ this as a hyperparameter to be optimized.
+ :param kernel_cls: a :class:`gpytorch.kernels.Kernel` class to be used
+ for modeling trend; defaults to RBFKernel.
+ :param outputscale_prior: Optional prior for the `ScaleKernel`.
+ :param outputscale_constraint: Optional constraint for the `ScaleKernel`.
+ :param name: optional name for the component.
+ """
+
+ def __init__(
+ self,
+ sample_input: DataTensor,
+ time_axis: str,
+ *,
+ lengthscale: Optional[numbers.Real] = None,
+ fix_lengthscale: bool = False,
+ kernel_cls: Type[Kernel] = RBFKernel,
+ outputscale_prior: gp.priors.Prior = None,
+ outputscale_constraint: gp.constraints.Interval = None,
+ name: Optional[str] = None,
+ **kernel_kwargs,
+ ):
+ if kernel_cls is ScaleKernel:
+ raise ValueError(
+ "Wrapping kernel in ScaleKernel is not required. Pass the base kernel instead."
+ )
+ self.fix_lengthscale = fix_lengthscale and (lengthscale is not None)
+ super().__init__(
+ ScaleKernel(
+ kernel_cls(
+ active_dims=(sample_input.get_index(time_axis),), **kernel_kwargs
+ ),
+ outputscale_prior=outputscale_prior,
+ outputscale_constraint=outputscale_constraint,
+ ),
+ name=name,
+ )
+ # normalize lengthscale if input data is normalized
+ self._scale = 1.0
+ if lengthscale is not None:
+ if time_axis in sample_input.transforms:
+ self._scale = sample_input.transforms[time_axis].inv.scale
+ self.lengthscale = lengthscale
+
+ @property
+ def scale(self):
+ return self._scale
+
+ @property
+ def fixed_params(self) -> Set[nn.Parameter]:
+ return (
+ {self.kernel.base_kernel.raw_lengthscale} if self.fix_lengthscale else set()
+ )
+
+
+class Seasonality(CovComponent):
+ """
+ Covariance component for modeling seasonality.
+
+ :param sample_input: a sample :class:`DataTensor` object that represents
+ the inputs of interest.
+ :param time_axis: the name for the time axis over which to place the
+ seasonality kernel.
+ :param period_length: optional period length to initialize to. Note that
+ this is in the original (unnormalized) scale of the time unit.
+ :param fix_period: whether to fix the `period_length`, i.e. remove this as a
+ hyperparameter to be optimized.
+ :param outputscale_prior: Optional prior for the `ScaleKernel`.
+ :param outputscale_constraint: Optional constraint for the `ScaleKernel`.
+ :param name: optional name for the component.
+ """
+
+ def __init__(
+ self,
+ sample_input: DataTensor,
+ time_axis: str,
+ period_length: numbers.Real,
+ *,
+ lengthscale: Optional[int] = None,
+ fix_period: bool = False,
+ fix_lengthscale: bool = False,
+ outputscale_prior: gp.priors.Prior = None,
+ outputscale_constraint: gp.constraints.Interval = None,
+ name: Optional[str] = None,
+ **kernel_kwargs,
+ ):
+ self.fix_period = fix_period
+ self.fix_lengthscale = fix_lengthscale
+ super().__init__(
+ ScaleKernel(
+ PeriodicKernel(
+ active_dims=(sample_input.get_index(time_axis),), **kernel_kwargs
+ ),
+ outputscale_prior=outputscale_prior,
+ outputscale_constraint=outputscale_constraint,
+ ),
+ name=name,
+ )
+ # normalize lengthscale if input data is normalized
+ self._scale = 1.0
+ if time_axis in sample_input.transforms:
+ self._scale = sample_input.transforms[time_axis].inv.scale
+ period_length = period_length / self._scale
+ self.kernel.base_kernel.period_length = period_length
+ if lengthscale is not None:
+ self.lengthscale = lengthscale
+
+ @property
+ def period_length(self):
+ return self.kernel.base_kernel.period_length * self.scale
+
+ @property
+ def scale(self):
+ return self._scale
+
+ @property
+ def fixed_params(self) -> Set[nn.Parameter]:
+ fixed_params = set()
+ if self.fix_period:
+ fixed_params.add(self.kernel.base_kernel.raw_period_length)
+ if self.fix_lengthscale:
+ fixed_params.add(self.kernel.base_kernel.raw_lengthscale)
+ return fixed_params
+
+
+class SpectralMixture(CovComponent):
+ """
+ Covariance component for spectral mixture kernel designed in [1].
+ [1] Wilson, A., and Adams, R. 2013. Gaussian process kernels for pattern
+ discovery and extrapolation. In Proc. International Conference on
+ Machine Learning.
+
+ :param sample_input: a sample :class:`DataTensor` object that represents
+ the inputs of interest.
+ :param time_axis: the name for the time axis over which to place the
+ spectral mixture kernel.
+ :param num_mixtures: the number of mixtures in the kernel.
+ :param mixture_scales: optional mixture_scales to initialize.
+ :param mixture_means: optional mixture_means to initialize.
+ :param mixture_weights: optional mixture_weights to initialize.
+ :param outputscale_prior: Optional prior for the `ScaleKernel`.
+ :param outputscale_constraint: Optional constraint for the `ScaleKernel`.
+ :param name: optional name for the component.
+ """
+
+ def __init__(
+ self,
+ sample_input: DataTensor,
+ time_axis: str,
+ num_mixtures: int,
+ *,
+ name: Optional[str] = None,
+ sample_output: Optional[DataTensor] = None,
+ **kernel_kwargs,
+ ):
+ self.sample_input = sample_input
+
+ super().__init__(
+ SpectralMixtureKernel(
+ num_mixtures=num_mixtures,
+ active_dims=(sample_input.get_index(time_axis),),
+ **kernel_kwargs,
+ ),
+ name=name,
+ )
+ self._scale = 1.0
+ if time_axis in sample_input.transforms:
+ self._scale = sample_input.transforms[time_axis].inv.scale
+ if sample_output is not None:
+ self.kernel.initialize_from_data(sample_input.tensor, sample_output.tensor)
+
+ @property
+ def mixture_scales(self):
+ return self.kernel.mixture_scales
+
+ @property
+ def mixture_means(self):
+ return self.kernel.mixture_means
+
+ @property
+ def mixture_weights(self):
+ return self.kernel.mixture_weights
+
+ @property
+ def scale(self):
+ return self._scale
+
+
+class WhiteNoise(CovComponent):
+ """
+ Covariance component for modeling the noise.
+
+ :param sample_input: a sample :class:`DataTensor` object that represents
+ the inputs of interest.
+ :param time_axis: the name for the time axis over which to model the
+ noise.
+ :param noise: the noise to add to kernel.
+ :param fix_noise: whether to fix the `noise`, i.e. remove
+ this as a hyperparameter to be optimized.
+ :param outputscale_prior: Optional prior for the `ScaleKernel`.
+ :param outputscale_constraint: Optional constraint for the `ScaleKernel`.
+ :param name: optional name for the component.
+ """
+
+ def __init__(
+ self,
+ sample_input: DataTensor,
+ time_axis: str,
+ noise: float,
+ *,
+ fix_noise: bool = False,
+ name: Optional[str] = None,
+ **kernel_kwargs,
+ ):
+ self.fix_noise = fix_noise
+ super().__init__(
+ WhiteNoiseKernel(noise, **kernel_kwargs),
+ name=name,
+ )
+ # normalize lengthscale if input data is normalized
+ self._scale = 1.0
+ if time_axis in sample_input.transforms:
+ self._scale = sample_input.transforms[time_axis].inv.scale
+
+ @property
+ def fixed_params(self) -> Set[nn.Parameter]:
+ fixed_params = set()
+ if self.fix_noise:
+ fixed_params.add(self.kernel.raw_noise)
+ return fixed_params
+
+
+class ChangePoint(CovComponent):
+ def __init__(
+ self,
+ sample_input: DataTensor,
+ time_axis: str,
+ kernels: List[CovComponent],
+ changepoint_location: float,
+ changepoint_steep: float = 1,
+ *,
+ fix_changepoint_location: bool = False,
+ fix_changepoint_steep: bool = False,
+ name: Optional[str] = None,
+ **kernel_kwargs,
+ ):
+ self.fix_changepoint_location = fix_changepoint_location
+ self.fix_changepoint_steep = fix_changepoint_steep
+ super().__init__(
+ ChangePointKernel(
+ [k.kernel for k in kernels],
+ location=changepoint_location,
+ steep=changepoint_steep,
+ active_dims=(sample_input.get_index(time_axis),),
+ **kernel_kwargs,
+ ),
+ name=name,
+ )
+ self.kernels = kernels
+
+ @property
+ def fixed_params(self) -> Set[nn.Parameter]:
+ fixed_params = set().union(*(k.fixed_params for k in self.kernels))
+ if self.fix_changepoint_location:
+ fixed_params.add(self.kernel.raw_location)
+ if self.fix_changepoint_steep:
+ fixed_params.add(self.kernel.raw_steep)
+ return fixed_params
+
+
+class Aggregated(CovComponent):
+ def __init__(self, kernel_cls, *components, name=None):
+ if name is None and components:
+ # construct default name if components is non-empty
+ name = f"{kernel_cls.__name__}({','.join(c.name for c in components)})"
+ # Add components later so that their names are correctly populated
+ super().__init__(kernel_cls(), name)
+ self.parts = OrderedDict()
+ for c in components:
+ self.append(c)
+
+ def append(self, component: CovComponent):
+ name = component.name
+ i = 1
+ while name in self.parts:
+ name = name + f"_{i}"
+ i += 1
+ component.name = name
+ self.parts[name] = component
+ self.kernel.kernels.append(component.kernel)
+
+ @property
+ def fixed_params(self) -> Set[nn.Parameter]:
+ return set().union(*[k.fixed_params for k in self.parts.values()])
+
+
+class ProductComponents(Aggregated):
+ def __init__(self, *components, name=None):
+ super().__init__(ProductKernel, *components, name=name)
+
+
+class AdditiveComponents(Aggregated):
+ def __init__(self, *components, name=None):
+ super().__init__(AdditiveKernel, *components, name=name)
+
+
+class Covariance(AdditiveComponents):
+ """
+ Represents the covariance function of the GP.
+
+ :param sample_input: a sample :class:`DataTensor` object that represents
+ the inputs of interest.
+ """
+
+ def __init__(self, sample_input: DataTensor, sample_output: DataTensor = None):
+ self.sample_input = sample_input
+ self.sample_output = sample_output
+ super().__init__()
+
+ # Some helper methods (can also simply self.append)
+ def add_regression(
+ self,
+ features: Iterable[str],
+ *,
+ ard: bool = True,
+ kernel_cls: Type[Kernel] = RBFKernel,
+ outputscale_prior: gp.priors.Prior = None,
+ outputscale_constraint: gp.constraints.Interval = None,
+ name: Optional[str] = None,
+ **kernel_kwargs,
+ ):
+ """
+ Add a regression component to the model using an ARD kernel specified by
+ the :class:`Regression` class.
+
+ :param features: list of header names to be included as regressors.
+ :param ard: Whether to enable Automatic Relevance Determination, i.e.
+ have separate lengthscale for each of the features.
+ :param kernel_cls: a :class:`gpytorch.kernels.Kernel` class to be used
+ for regression.
+ :param outputscale_prior: Optional prior for the `ScaleKernel`.
+ :param outputscale_constraint: Optional constraint for the `ScaleKernel`.
+ :param name: optional name for the component.
+ """
+ regression_kernel = Regression(
+ self.sample_input,
+ features,
+ ard=ard,
+ kernel_cls=kernel_cls,
+ outputscale_prior=outputscale_prior,
+ outputscale_constraint=outputscale_constraint,
+ name=name,
+ **kernel_kwargs,
+ )
+ self.append(regression_kernel)
+
+ def add_seasonality(
+ self,
+ time_axis: str,
+ period_length: numbers.Real,
+ *,
+ fix_period: bool = False,
+ outputscale_prior: gp.priors.Prior = None,
+ outputscale_constraint: gp.constraints.Interval = None,
+ name: Optional[str] = None,
+ **kernel_kwargs,
+ ):
+ """
+ Add a seasonality component to the model using the :class:`Seasonality`
+ class.
+
+ :param time_axis: the name for the time axis over which to place the
+ seasonality kernel.
+ :param period_length: optional period length to initialize to. Note that
+ this is in the original (unnormalized) scale of the time unit.
+ :param fix_period: whether to fix the `period_length`, i.e. remove this
+ as a hyperparameter to be optimized.
+ :param outputscale_prior: Optional prior for the `ScaleKernel`.
+ :param outputscale_constraint: Optional constraint for the `ScaleKernel`.
+ :param name: optional name for the component.
+ """
+ seasonality_kernel = Seasonality(
+ self.sample_input,
+ time_axis,
+ period_length,
+ fix_period=fix_period,
+ outputscale_prior=outputscale_prior,
+ outputscale_constraint=outputscale_constraint,
+ name=name,
+ **kernel_kwargs,
+ )
+ self.append(seasonality_kernel)
+
+ def add_trend(
+ self,
+ time_axis: str,
+ *,
+ lengthscale: Optional[numbers.Real] = None,
+ fix_lengthscale: bool = False,
+ kernel_cls: Type[Kernel] = RBFKernel,
+ outputscale_prior: gp.priors.Prior = None,
+ outputscale_constraint: gp.constraints.Interval = None,
+ name: Optional[str] = None,
+ **kernel_kwargs,
+ ):
+ """
+ Add a trend component to the model using the :class:`Trend` class.
+
+ :param time_axis: the name for the time axis over which to model the
+ trend.
+ :param lengthscale: optional length scale to initialize to. Note that
+ this is in the original (unnormalized) scale of the time unit.
+ :param fix_lengthscale: whether to fix the `lengthscale`, i.e. remove
+ this as a hyperparameter to be optimized.
+ :param kernel_cls: a :class:`gpytorch.kernels.Kernel` class to be used
+ for modeling trend; defaults to RBFKernel.
+ :param outputscale_prior: Optional prior for the `ScaleKernel`.
+ :param outputscale_constraint: Optional constraint for the `ScaleKernel`.
+ :param name: optional name for the component.
+ """
+ trend_kernel = Trend(
+ self.sample_input,
+ time_axis,
+ lengthscale=lengthscale,
+ fix_lengthscale=fix_lengthscale,
+ kernel_cls=kernel_cls,
+ outputscale_prior=outputscale_prior,
+ outputscale_constraint=outputscale_constraint,
+ name=name,
+ **kernel_kwargs,
+ )
+ self.append(trend_kernel)
+
+ def add_spectral_mixture(
+ self,
+ time_axis: str,
+ num_mixtures: numbers.Real,
+ *,
+ train_x: Optional[torch.Tensor] = None,
+ train_y: Optional[torch.Tensor] = None,
+ name: Optional[str] = None,
+ **kernel_kwargs,
+ ):
+ """
+ Add a spectral mixture component to the model using the :class:`SpectralMixture` class.
+
+ :param time_axis: the name for the time axis over which to model the
+ spectral mixture.
+ :param num_mixtures: the number of components in the mixture.
+ :param train_x: the input training data.
+ :param train_y: the output training data.
+ :param name: optional name for the component.
+ """
+ sm_kernel = SpectralMixture(
+ self.sample_input,
+ time_axis,
+ num_mixtures,
+ name=name,
+ sample_output=self.sample_output,
+ **kernel_kwargs,
+ )
+ self.append(sm_kernel)
diff --git a/src/beanmachine/ppl/experimental/timeseries/sts/gp/graph.py b/src/beanmachine/ppl/experimental/timeseries/sts/gp/graph.py
new file mode 100644
index 0000000000..df1f889843
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/sts/gp/graph.py
@@ -0,0 +1,107 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import math
+from typing import List, Optional, OrderedDict, Tuple
+
+import matplotlib.pyplot as plt
+import torch
+from gpytorch.distributions import MultivariateNormal
+from sts.data import get_mvn_stats
+
+
+def _decouple_plot_fmt_attrs(plot_kwargs):
+ plot_kwargs = plot_kwargs.copy()
+ plot_fmt = {
+ "color": plot_kwargs.pop("color", "black"),
+ "linestyle": plot_kwargs.pop("linestyle", None),
+ "linewidth": plot_kwargs.pop("linewidth", 1),
+ "marker": plot_kwargs.pop("marker", None),
+ "markerfacecolor": plot_kwargs.pop("markerfacecolor", None),
+ "markersize": plot_kwargs.pop("markersize", None),
+ }
+ return plot_fmt, plot_kwargs
+
+
+def plot_predictions(
+ x: torch.Tensor,
+ y: MultivariateNormal,
+ transform: Optional[torch.distributions.Transform] = None,
+ axis: plt.Axes = None,
+ **plot_kwargs,
+) -> Tuple[plt.Figure, plt.Axes]:
+ """
+ Plot the predictions from the time-series model.
+
+ :param x: the x axis for the plot.
+ :param y: the multivariate normal distribution representing the prediction
+ from the model.
+ :param transform: optional transform to apply to rescale the
+ predictions from the model.
+ :param axis: optional axis
+ """
+ fig, ax = None, axis
+ if axis is None:
+ fig, ax = plt.subplots(1, 1)
+ plot_fmt, plot_kwargs = _decouple_plot_fmt_attrs(plot_kwargs)
+ mean, _, ci = get_mvn_stats(y, transform)
+ ax.plot(x, mean, label="predicted", **plot_fmt)
+ ax.fill_between(x, ci[0], ci[1], color="gray", alpha=0.4)
+ ax.set(**plot_kwargs)
+ return fig, ax
+
+
+def plot_components(
+ x: torch.Tensor,
+ components: Tuple[OrderedDict[str, MultivariateNormal]],
+ transform: Optional[torch.distributions.Transform] = None,
+ ncols: int = 2,
+ y: Optional[MultivariateNormal] = None,
+ plot_mean: Optional[bool] = False,
+ **plot_kwargs,
+) -> List[Tuple[plt.Figure, plt.Axes]]:
+ """
+ Plot the decomposition of the time series components.
+
+ :param x: the x axis for the plot
+ :param components: a dict of predictions for the individual components of
+ the model keyed by the name of the component.
+ :param transform: optional transform to apply to rescale the
+ predictions from the model.
+ :param y: the multivariate normal distribution representing the predictions
+ from the model.
+ :param bool plot_mean: Whether to plot the components of the mean function.
+ Defaults to False.
+ :param ncols: number of columns in the subplots, defaults to 2.
+ """
+ figs = []
+ if y is not None:
+ figs.append(plot_predictions(x, y, transform, **plot_kwargs))
+
+ mean_components = components[0]
+ cov_components = components[1]
+ if plot_mean:
+ num_mean = len(mean_components)
+ components = list(mean_components.items()) + list(cov_components.items())
+ num_components = num_mean + len(cov_components)
+ else:
+ num_mean = 0
+ components = list(cov_components.items())
+ num_components = len(cov_components)
+
+ nrows = math.ceil(num_components / float(ncols))
+ fig, ax = plt.subplots(nrows, ncols, squeeze=False)
+ plot_fmt, plot_attrs = _decouple_plot_fmt_attrs(plot_kwargs)
+ for i in range(nrows):
+ for j in range(ncols):
+ nplot = i * ncols + j
+ if nplot == num_components:
+ break
+ ax_c = ax[i][j]
+ name, comp = components[nplot]
+ if nplot < num_mean:
+ ax_c.plot(x, comp.detach(), **plot_fmt)
+ ax_c.set(title=name, **plot_attrs)
+ else:
+ plot_predictions(x, comp, transform, ax_c, title=name, **plot_kwargs)
+ figs.append((fig, ax))
+ return figs
diff --git a/src/beanmachine/ppl/experimental/timeseries/sts/gp/kernels.py b/src/beanmachine/ppl/experimental/timeseries/sts/gp/kernels.py
new file mode 100644
index 0000000000..61c2520860
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/sts/gp/kernels.py
@@ -0,0 +1,263 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+"""
+Reference paper:
+ Lloyd, James, et al.
+ "Automatic construction and natural-language description of nonparametric regression models."
+ Proceedings of the AAAI Conference on Artificial Intelligence. Vol. 28. No. 1. 2014.
+ link: https://arxiv.org/pdf/1402.4304.pdf
+"""
+
+import torch
+from gpytorch.constraints import Positive
+from gpytorch.kernels import Kernel
+from torch.nn import ModuleList # @manual
+
+
+class WhiteNoiseKernel(Kernel):
+ """
+ Computes a covariance matrix based on white noise.
+
+ :param noise: the noise to add to diagnal.
+ :param noise_prior: (Prior, optional)
+ Set this if you want to apply a prior to the noise parameter. Default: `None`.
+ :param noise_constraint: (Constraint, optional)
+ Set this if you want to apply a constraint to the noise parameter. Default: `Positive`.
+ """
+
+ def __init__(self, noise, noise_prior=None, noise_constraint=None, **kwargs):
+ super(WhiteNoiseKernel, self).__init__(**kwargs)
+
+ self.register_parameter(
+ name="raw_noise",
+ parameter=torch.nn.Parameter(torch.zeros(*self.batch_shape, 1, 1)),
+ )
+
+ if noise_constraint is None:
+ noise_constraint = Positive()
+
+ if noise_prior is not None:
+ self.register_prior(
+ "noise_prior",
+ noise_prior,
+ lambda m: m.noise,
+ lambda m, v: m._set_noise(v),
+ )
+ self.register_constraint("raw_noise", noise_constraint)
+ self.noise = noise
+
+ @property
+ def noise(self):
+ return self.raw_noise_constraint.transform(self.raw_noise)
+
+ @noise.setter
+ def noise(self, value):
+ self._set_noise(value)
+
+ def _set_noise(self, value):
+ if not torch.is_tensor(value):
+ value = torch.as_tensor(value).to(self.raw_noise)
+ self.initialize(raw_noise=self.raw_noise_constraint.inverse_transform(value))
+
+ def forward(self, x1, x2, **kwargs):
+ res = torch.eye(x1.shape[0], x2.shape[0]) * self.noise
+ return res
+
+
+class ConstantKernel(Kernel):
+ """
+ Computes a covariance matrix which has constant values.
+
+ :param constant: the constant to add to each element.
+ :param constant_prior: (Prior, optional)
+ Set this if you want to apply a prior to the constant parameter. Default: `None`.
+ :param constant_constraint: (Constraint, optional)
+ Set this if you want to apply a constraint to the constant parameter. Default: `Positive`.
+ """
+
+ def __init__(
+ self, constant, constant_prior=None, constant_constraint=None, **kwargs
+ ):
+ super(ConstantKernel, self).__init__(**kwargs)
+
+ self.register_parameter(
+ name="raw_constant",
+ parameter=torch.nn.Parameter(torch.zeros(*self.batch_shape, 1, 1)),
+ )
+
+ if constant_constraint is None:
+ constant_constraint = Positive()
+
+ if constant_prior is not None:
+ self.register_prior(
+ "constant_prior",
+ constant_prior,
+ lambda m: m.constant,
+ lambda m, v: m._set_constant(v),
+ )
+ self.register_constraint("raw_constant", constant_constraint)
+ self.constant = constant
+
+ @property
+ def constant(self):
+ return self.raw_constant_constraint.transform(self.raw_constant)
+
+ @constant.setter
+ def constant(self, value):
+ self._set_constant(value)
+
+ def _set_constant(self, value):
+ if not torch.is_tensor(value):
+ value = torch.as_tensor(value).to(self.raw_constant)
+ self.initialize(
+ raw_constant=self.raw_constant_constraint.inverse_transform(value)
+ )
+
+ def forward(self, x1, x2, **kwargs):
+ res = torch.ones(*self.batch_shape, x1.shape[0], x2.shape[0]) * self.constant
+ return res
+
+
+class ChangePointKernel(Kernel):
+ """
+ Computes a covariance matrix that change from one kernel to another at various changepoint locations.
+
+ :param kernels: a list of GPyTorch :class:`gpytorch.kernels.Kernel` instances. Must be one more
+ than the number of change points.
+ :param location: the location of the change points.
+ :param steep: the steepness of sigmoid.
+ :param location_prior: (Prior, optional)
+ Set this if you want to apply a prior to the location parameter. Default: `None`.
+ :param location_constraint: (Constraint, optional)
+ Set this if you want to apply a constraint to the location parameter. Default: `GreaterThan(l1)`.
+ :param steep_prior: (Prior, optional)
+ Set this if you want to apply a prior to the steep parameter. Default: `None`.
+ :param steep_constraint: (Constraint, optional)
+ Set this if you want to apply a constraint to the steep parameter. Default: `Positive`.
+ """
+
+ def __init__(
+ self,
+ kernels,
+ location,
+ steep=1.0,
+ location_prior=None,
+ location_constraint=None,
+ steep_prior=None,
+ steep_constraint=None,
+ **kwargs,
+ ):
+ location = torch.as_tensor(location)
+ steep = torch.as_tensor(steep)
+ self.num_changepoints = 1 if location.numel() == 1 else location.shape[-1]
+ if steep.shape != location.shape:
+ steep = steep.expand(location.shape)
+ assert len(kernels) == self.num_changepoints + 1
+ super().__init__(**kwargs)
+ self._kernels = ModuleList(kernels)
+
+ self.register_parameter(
+ name="raw_location",
+ parameter=torch.nn.Parameter(
+ torch.zeros(*self.batch_shape, 1, 1, self.num_changepoints)
+ ),
+ )
+
+ if location_prior is not None:
+ self.register_prior(
+ "location_prior",
+ location_prior,
+ lambda m: m.location,
+ lambda m, v: m._set_location(v),
+ )
+ if location_constraint is not None:
+ self.register_constraint("raw_location", location_constraint)
+ self.location = location
+
+ self.register_parameter(
+ name="raw_steep",
+ parameter=torch.nn.Parameter(
+ torch.ones(*self.batch_shape, 1, 1, self.num_changepoints)
+ ),
+ )
+
+ if steep_prior is not None:
+ self.register_prior(
+ "steep_prior",
+ steep_prior,
+ lambda m: m.steep,
+ lambda m, v: m._set_steep(v),
+ )
+ if steep_constraint is None:
+ steep_constraint = Positive()
+ self.register_constraint("raw_steep", steep_constraint)
+ self.steep = steep
+
+ @property
+ def location(self):
+ constraint = getattr(self, "raw_location_constraint", None)
+ if constraint:
+ return self.raw_location_constraint.transform(self.raw_location)
+ return self.raw_location
+
+ @location.setter
+ def location(self, value):
+ self._set_location(value)
+
+ def _set_location(self, value):
+ if not torch.is_tensor(value):
+ value = torch.as_tensor(value).to(self.raw_location)
+ constraint = getattr(self, "raw_location_constraint", None)
+ if constraint:
+ self.initialize(
+ raw_location=self.raw_location_constraint.inverse_transform(value)
+ )
+ else:
+ self.initialize(raw_location=value)
+
+ @property
+ def steep(self):
+ return self.raw_steep_constraint.transform(self.raw_steep)
+
+ @steep.setter
+ def steep(self, value):
+ self._set_steep(value)
+
+ def _set_steep(self, value):
+ if not torch.is_tensor(value):
+ value = torch.as_tensor(value).to(self.raw_steep)
+ self.initialize(raw_steep=self.raw_steep_constraint.inverse_transform(value))
+
+ def _sigmoid(
+ self, X: torch.Tensor, last_dim_is_batch: bool = False
+ ) -> torch.Tensor:
+ if last_dim_is_batch:
+ location = self.location.unsqueeze(-2)
+ steep = self.steep.unsqueeze(-2)
+ else:
+ location = self.location
+ steep = self.steep
+ return 0.5 + 0.5 * torch.tanh(steep * (X[..., None] - location))
+
+ def num_outputs_per_input(self, x1, x2):
+ return self._kernels[0].num_outputs_per_input(x1, x2)
+
+ def forward(self, x1, x2, diag=False, last_dim_is_batch=False, **params):
+ if last_dim_is_batch:
+ x1 = x1.transpose(-1, -2).unsqueeze(-1)
+ x2 = x2.transpose(-1, -2).unsqueeze(-1)
+ sig_x1 = self._sigmoid(x1, last_dim_is_batch)
+ sig_x2 = self._sigmoid(x2, last_dim_is_batch)
+ starters = sig_x1 * torch.transpose(sig_x2, -2, -3)
+ stoppers = (1 - sig_x1) * torch.transpose((1 - sig_x2), -2, -3)
+ ones = torch.ones(
+ starters.shape[:-1] + (1,), dtype=starters.dtype, device=starters.device
+ )
+ starters = torch.cat([ones, starters], dim=-1)
+ stoppers = torch.cat([stoppers, ones], dim=-1)
+
+ kernel_stack = torch.stack(
+ [k(x1, x2).evaluate() for k in self._kernels],
+ dim=-1,
+ )
+ return torch.sum(kernel_stack * starters * stoppers, dim=-1)
diff --git a/src/beanmachine/ppl/experimental/timeseries/sts/gp/mean.py b/src/beanmachine/ppl/experimental/timeseries/sts/gp/mean.py
new file mode 100644
index 0000000000..9679f3cef7
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/sts/gp/mean.py
@@ -0,0 +1,65 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from collections import OrderedDict
+from typing import Iterable
+
+import gpytorch as gp
+import torch
+from gpytorch.means import ConstantMean, LinearMean
+from sts.data import DataTensor
+from torch import nn
+
+
+class RegressionMean(LinearMean):
+ def __init__(self, sample_df: DataTensor, features: Iterable[str]):
+ super().__init__(len(features), bias=False)
+ self.active_dims = sample_df.get_index(features)
+
+ def forward(self, x):
+ x = x[:, self.active_dims]
+ return super().forward(x)
+
+
+class Mean(gp.means.Mean):
+ """
+ Represents the mean prediction from the model.
+
+ :param sample_input: a sample :class:`DataTensor` object that represents
+ the inputs of interest.
+ """
+
+ def __init__(self, sample_input: DataTensor):
+ super().__init__()
+ self.sample_input = sample_input
+ self.parts = OrderedDict()
+ self.means = nn.ModuleList()
+ self.append(ConstantMean())
+
+ def append(self, component: gp.means.Mean):
+ """
+ Append a :class:`gpytorch.means.Mean` module to the current model.
+
+ :param component: [description]
+ :type component: [type]
+ """
+ name = component._get_name()
+ i = 1
+ while name in self.parts:
+ name = name + f"_{i}"
+ i += 1
+ component.name = name
+ self.parts[name] = component
+ self.means.append(component)
+
+ def add_regression(self, features: Iterable[str]):
+ """
+ Add a linear regression component to the mean function of the GP.
+
+ :param features: list of header names to be included as regressors.
+ """
+ if len(features) == 0:
+ return
+ self.append(RegressionMean(self.sample_input, features))
+
+ def forward(self, input: torch.Tensor):
+ return sum(c.forward(input) for c in self.means)
diff --git a/src/beanmachine/ppl/experimental/timeseries/sts/gp/model.py b/src/beanmachine/ppl/experimental/timeseries/sts/gp/model.py
new file mode 100644
index 0000000000..34a3cd48fc
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/sts/gp/model.py
@@ -0,0 +1,400 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import warnings
+from collections import OrderedDict
+from typing import Callable, Set, Tuple, Union
+
+import gpytorch as gp
+import numpy as np
+import torch
+from gpytorch.kernels import LinearKernel, RBFKernel
+from gpytorch.models import ExactGP, GP
+from gpytorch.priors import LogNormalPrior
+from pandas.api.types import is_datetime64_any_dtype as is_datetime
+from sts.changepoints import BinSegChangepoint
+from sts.data import DataTensor, df_to_tensor
+from sts.gp.cov import ChangePoint, Covariance, Trend
+from sts.gp.mean import Mean
+from torch import nn
+from torch.distributions import transforms
+
+
+class TimeSeriesGPModel(GP):
+ @property
+ def trainable_params(self) -> Set[nn.Parameter]:
+ return set(self.parameters()) - self.cov.fixed_params
+
+
+class ExactGPAdditiveModel(ExactGP, TimeSeriesGPModel):
+ """
+ Univariate time series model using exact GP.
+
+ :param sample_input: a sample :class:`DataTensor` object that represents
+ the inputs of interest.
+ :param sample_output: a sample :class:`DataTensor` object that represents
+ the output from the time series model.
+ :param likelihood: a gpytorch :class:`~gp.likelihoods.Likelihood` object
+ that specifies the mapping from `f(X)` to observed data.
+ """
+
+ def __init__(
+ self,
+ sample_input: DataTensor,
+ sample_output: DataTensor,
+ likelihood: gp.likelihoods.Likelihood,
+ ):
+ super().__init__(sample_input.tensor, sample_output.tensor, likelihood)
+ self.mean = Mean(sample_input)
+ self.cov = Covariance(sample_input, sample_output)
+
+ def forward(self, x: Union[torch.Tensor, DataTensor]):
+ if isinstance(x, DataTensor):
+ x = x.tensor
+ mean_x = self.mean(x).squeeze(-1)
+ covar_x = self.cov(x)
+ return gp.distributions.MultivariateNormal(mean_x, covar_x)
+
+ def __call__(self, *args, **kwargs):
+ args = [x.tensor if isinstance(x, DataTensor) else x for x in args]
+ return super().__call__(*args, **kwargs)
+
+ def train_init(self, optim: torch.optim.Optimizer) -> Callable:
+ """
+ Return a callable that can be used to run training iterations for the
+ time series model.
+
+ :param optim: the :class:`~torch.optim.Optimizer` to use for minimizing
+ the loss function.
+ :return: Returns a callable which runs a single iteration for the
+ optimizer when called with the training inputs and outputs and
+ returns the loss.
+ """
+ self.train()
+ mll = gp.mlls.ExactMarginalLogLikelihood(self.likelihood, self)
+
+ def apply_fn(x, y):
+ if isinstance(x, DataTensor):
+ x = x.tensor
+ if isinstance(y, DataTensor):
+ y = y.tensor
+ optim.zero_grad()
+ with warnings.catch_warnings():
+ # ignore PyTorch warnings from GPyTorch
+ warnings.simplefilter("ignore", UserWarning)
+ loss = -mll(self(x), y)
+ loss.backward()
+ optim.step()
+ return loss.item()
+
+ return apply_fn
+
+ def predict(
+ self, x: Union[torch.Tensor, DataTensor]
+ ) -> gp.distributions.MultivariateNormal:
+ """
+ Run the model to generate predictions for the given input tensor.
+
+ :param x: input data.
+ :return: output tensor that represents the prediction from the model.
+ """
+ if isinstance(x, DataTensor):
+ x = x.tensor
+ self.eval()
+ with torch.no_grad(), gp.settings.fast_pred_var():
+ return self.likelihood(self(x))
+
+ def _component_cov(self, test_X, k):
+ # See the note on additive decomposition: https://www.cs.toronto.edu/~duvenaud/cookbook/
+ train_X = self.train_inputs[0]
+ test_train_covar = k(test_X, train_X)
+ test_test_covar = k(test_X, test_X)
+ pred_strategy = self.prediction_strategy
+ train_train_covar = pred_strategy.lik_train_train_covar
+ train_train_covar_inv_root = train_train_covar.root_inv_decomposition().root
+ covar_inv_quad_form_root = test_train_covar.matmul(train_train_covar_inv_root)
+ kxx_inv = covar_inv_quad_form_root @ covar_inv_quad_form_root.transpose(-1, -2)
+ return test_test_covar - kxx_inv
+
+ def decompose_timeseries(
+ self, x: Union[torch.Tensor, DataTensor]
+ ) -> Tuple[OrderedDict, OrderedDict]:
+ """
+ Run the model to generate predictions for the given input tensor, and
+ return the decomposition over the mean and additive covariance kernels.
+
+ :param x: input data.
+ :return: tuple of mean and covariance decompositions, which are dicts
+ keyed by component names.
+ """
+ self.eval()
+ train_X = self.train_inputs[0]
+ with torch.no_grad(), gp.settings.fast_pred_var():
+ alpha = self.prediction_strategy.mean_cache
+ mean_parts = OrderedDict(
+ [(name, p(x)) for name, p in self.mean.parts.items()]
+ )
+ cov_parts = OrderedDict()
+ for name, p in self.cov.parts.items():
+ mean = p(x, train_X) @ alpha
+ cov = self._component_cov(x, p.kernel)
+ cov_parts[name] = gp.distributions.MultivariateNormal(mean, cov)
+ return mean_parts, cov_parts
+
+
+class AutomaticForecastingGP(ExactGPAdditiveModel):
+ """
+ Variant of time series forecasting model using GP as discussed in [1].
+ K = PER1 + PER2 + LIN + RBF1 + RBF2 + SM + WN,
+ where WN is already included in `GaussianLikelihood`
+
+ :param pd.DataFrame df_train: Dataframe object for training the time series
+ model.
+ :param str time_var: The column corresponding to the time axis.
+ :param str response_var: The column responding to the response variable
+ we are looking to forecast.
+ :param changepoint_locations: List of changepoint locations. For daily forecasts,
+ these are simply the indices along the time axis where the trend changes
+ rapidly.
+ :param list linear_covariates: The mean of the GP is modeled as an affine
+ function of the linear covariates specified.
+ param list nonlinear_covariates: An ARD RBF kernel is placed over the
+ specified covariates and added to the covariance kernel.
+ :param dict priors: Priors for the length and output scale for different
+ kernels. This updates the default priors dict in `self.priors`.
+ :param bool detect_changepoints: Whether to enable automatic changepoint
+ detection.
+ :param dict changepoint_detection_params: Parameters for automatic changepoint
+ detection algorithm (currently, binary segmentation).
+ :param bool disable_linear_trend: Whether to disable linear trend in the model;
+ defaults to False
+ :param bool disable_sm_kernel: Whether to disable Spectral Mixture kernel
+ component. Defaults to `True`.
+
+ [1] Corani, G., Benavoli, A., Augusto, J. and Zaffalon, M., 2020.
+ Automatic Forecasting using Gaussian Processes. arXiv preprint arXiv:2009.08102.
+ """
+
+ def __init__(
+ self,
+ df_train,
+ time_var,
+ response_var,
+ changepoint_locations=(),
+ linear_covariates=(),
+ nonlinear_covariates=(),
+ priors=None,
+ detect_changepoints=False,
+ changepoint_detection_params=None,
+ disable_linear_trend=False,
+ disable_sm_kernel=True,
+ ):
+ self.time_var = time_var
+ if not is_datetime(df_train[self.time_var]):
+ raise ValueError(f"{self.time_var} column must have datetime64 dtype.")
+ self.time_scale = (df_train[time_var].max() - df_train[time_var].min()).days
+ if self.time_scale < 15:
+ raise ValueError(
+ "Unsuitable class for short-term time series with less than 15 days."
+ )
+ self.response_var = response_var
+ self.linear_covariates = list(linear_covariates)
+ self.nonlinear_covariates = list(nonlinear_covariates)
+ # Default priors on normalized scale
+ self.priors = {
+ "per_yearly_outputscale": LogNormalPrior(-3.0, 1.0),
+ "per_yearly_lengthscale": LogNormalPrior(0.2, 1.0),
+ "per_weekly_outputscale": LogNormalPrior(-3.0, 1.0),
+ "per_weekly_lengthscale": LogNormalPrior(-5.9, 1.0),
+ "lin_outputscale": LogNormalPrior(-3.0, 1.0),
+ "rbf_long_outputscale": LogNormalPrior(-3.0, 1.0),
+ "rbf_long_lengthscale": LogNormalPrior(
+ np.log(self.time_scale / 365.25), 0.5
+ ),
+ "rbf_short_outputscale": LogNormalPrior(-3.0, 1.0),
+ "rbf_short_lengthscale": LogNormalPrior(
+ np.log(self.time_scale / 365.25) - np.log(100.0), 0.5
+ ),
+ }
+ if priors:
+ self.priors.update(priors)
+ self._linear_trend_disabled = disable_linear_trend
+ self._sm_kernel_disabled = disable_sm_kernel
+ self.transforms = {}
+ self.train_data = self.preprocess_data(df_train)
+ x_train, y_train = (
+ self.train_data[
+ :, [time_var] + self.linear_covariates + self.nonlinear_covariates
+ ],
+ self.train_data[:, response_var],
+ )
+ if detect_changepoints:
+ params = changepoint_detection_params
+ if params is None:
+ params = {}
+ if changepoint_locations:
+ warnings.warn(
+ "`changepoint_locations` will not be used. Set `detect_changepoints`"
+ " to False when manually specifying changepoint locations."
+ )
+ x, y = self.train_data[:, time_var], self.train_data[:, response_var]
+ min_segment_length = min(len(x) // 5, 100)
+ default_params = {
+ "min_segment": min_segment_length,
+ "penalty_weight": 1e-3,
+ }
+ default_params.update(params)
+ binseg = BinSegChangepoint(**default_params)
+ self.changepoint_locations = binseg.get_changepoints(x.tensor, y.tensor)
+ else:
+ self.changepoint_locations = sorted(changepoint_locations)
+ likelihood = gp.likelihoods.GaussianLikelihood()
+ super().__init__(x_train, y_train, likelihood)
+ self._construct_model()
+
+ def preprocess_data(self, df):
+ df = df[
+ [self.time_var, self.response_var]
+ + self.linear_covariates
+ + self.nonlinear_covariates
+ ]
+ df_convert_fns = {
+ self.time_var: lambda x: (x - x.iloc[0]).dt.total_seconds() / (24 * 3600)
+ }
+ if not self.transforms:
+ self.transforms = {}
+ self.transforms[self.time_var] = transforms.AffineTransform(0.0, 365.25).inv
+ std_norm_cols = (
+ self.linear_covariates + self.nonlinear_covariates + [self.response_var]
+ )
+ for col in std_norm_cols:
+ mean = df[col].mean()
+ std = df[col].std()
+ self.transforms[col] = transforms.AffineTransform(mean, std).inv
+ return df_to_tensor(
+ df, df_convert_fns=df_convert_fns, normalize_cols=self.transforms
+ )
+
+ def _construct_model(self):
+ if self.time_scale >= 730:
+ self.cov.add_seasonality(
+ time_axis=self.time_var,
+ period_length=365.25,
+ fix_period=True,
+ outputscale_prior=self.priors["per_yearly_outputscale"],
+ lengthscale_prior=self.priors["per_yearly_lengthscale"],
+ name="Yearly Seasonality",
+ )
+ self.cov.add_seasonality(
+ time_axis=self.time_var,
+ period_length=7,
+ fix_period=True,
+ outputscale_prior=self.priors["per_weekly_outputscale"],
+ lengthscale_prior=self.priors["per_weekly_lengthscale"],
+ name="Weekly Seasonality",
+ )
+ sample_input = self.cov.sample_input
+ if not self.changepoint_locations:
+ if not self._linear_trend_disabled:
+ self.cov.add_trend(
+ time_axis=self.time_var,
+ kernel_cls=LinearKernel,
+ outputscale_prior=self.priors["lin_outputscale"],
+ name="Linear Trend",
+ )
+ self.cov.add_trend(
+ time_axis=self.time_var,
+ kernel_cls=RBFKernel,
+ lengthscale=self.time_scale,
+ outputscale_prior=self.priors["rbf_long_outputscale"],
+ lengthscale_prior=self.priors["rbf_long_lengthscale"],
+ lengthscale_constraint=gp.constraints.GreaterThan(
+ 0.5 * self.time_scale / 365.25
+ ),
+ name="RBF Trend - Long",
+ )
+ else:
+ changepoints = torch.as_tensor(self.changepoint_locations) / 365.25
+ rbf_kernels = []
+ lin_kernels = []
+ time_scale = []
+ periods = (
+ [sample_input.min()]
+ + list(self.changepoint_locations)
+ + [sample_input.min() + self.time_scale]
+ )
+ for i in range(1, len(periods)):
+ local_time_scale = periods[i] - periods[i - 1]
+ time_scale.append(local_time_scale / 365.25)
+ rbf_kernels.append(
+ Trend(
+ sample_input,
+ self.time_var,
+ kernel_cls=RBFKernel,
+ lengthscale=local_time_scale,
+ outputscale_prior=self.priors["rbf_long_outputscale"],
+ lengthscale_prior=LogNormalPrior(
+ np.log(2 * local_time_scale / 365.25), 0.5
+ ),
+ lengthscale_constraint=gp.constraints.GreaterThan(
+ 0.5 * local_time_scale / 365.25
+ ),
+ )
+ )
+ if not self._linear_trend_disabled:
+ lin_kernels.append(
+ Trend(
+ sample_input,
+ self.time_var,
+ kernel_cls=LinearKernel,
+ outputscale_prior=self.priors["lin_outputscale"],
+ )
+ )
+ steep = [
+ 1 / min(time_scale[i - 1], time_scale[i])
+ for i in range(1, len(time_scale))
+ ]
+ self.cov.append(
+ ChangePoint(
+ sample_input,
+ self.time_var,
+ rbf_kernels,
+ changepoint_location=changepoints,
+ changepoint_steep=steep,
+ fix_changepoint_location=True,
+ fix_changepoint_steep=True,
+ name="Changepoint - RBF",
+ )
+ )
+ if lin_kernels:
+ self.cov.append(
+ ChangePoint(
+ sample_input,
+ self.time_var,
+ lin_kernels,
+ changepoint_location=changepoints,
+ changepoint_steep=steep,
+ fix_changepoint_location=True,
+ fix_changepoint_steep=True,
+ name="Changepoint - Linear",
+ )
+ )
+
+ self.cov.add_trend(
+ time_axis=self.time_var,
+ kernel_cls=RBFKernel,
+ lengthscale=1.0,
+ outputscale_prior=self.priors["rbf_short_outputscale"],
+ lengthscale_prior=self.priors["rbf_short_lengthscale"],
+ name="RBF Trend - Short",
+ )
+ if self.linear_covariates:
+ self.mean.add_regression(self.linear_covariates)
+ if self.nonlinear_covariates:
+ self.cov.add_regression(features=self.nonlinear_covariates)
+
+ if not self._sm_kernel_disabled:
+ self.cov.add_spectral_mixture(
+ time_axis=self.time_var,
+ num_mixtures=5,
+ name="Spectral Mixture",
+ )
diff --git a/src/beanmachine/ppl/experimental/timeseries/sts/metrics.py b/src/beanmachine/ppl/experimental/timeseries/sts/metrics.py
new file mode 100644
index 0000000000..4b1908d996
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/sts/metrics.py
@@ -0,0 +1,234 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+"""
+This implementation of CRPS metric follows the implementation in
+https://github.com/TheClimateCorporation/properscoring.
+
+The original copyright notice:
+Copyright 2015 The Climate Corporation
+Licensed under the Apache License, Version 2.0 (the "License"); you may not use
+this file except in compliance with the License. You may obtain a copy of the
+License at http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software distributed
+under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+CONDITIONS OF ANY KIND, either express or implied. See the License for the
+specific language governing permissions and limitations under the License.
+"""
+
+
+import contextlib
+import math
+import warnings
+
+import torch
+import torch.distributions as dist
+
+
+def mape(y_pred, y_true) -> torch.Tensor:
+ """
+ Mean Absolute Percentage Error for the predictions `y_pred` when compared
+ to the baseline given by `y_true`.
+
+ :param y_pred: predictions from the model.
+ :param y_true: true observations.
+ :return: torch scalar denoting the MAPE.
+ """
+ return torch.mean(torch.abs((y_true - y_pred) / y_true)) * 100
+
+
+def MAE(y_pred, y_true):
+ """
+ Mean Absolute Error for the predictions `y_pred` when compared
+ to the baseline given by `y_true`.
+
+ :param y_pred: predictions from the model.
+ :param y_true: true observations.
+ :return: torch scalar denoting the MAE.
+ """
+ return (y_pred - y_true).abs().mean()
+
+
+def log_likelihood_error(y_pred, y_true, var):
+ """
+ Log_likelihood for the predictions `y_pred` when compared
+ to the baseline given by `y_true` with variance `var`.
+ This assumes a gaussian likelihood.
+
+ :param y_pred: predictions from the model.
+ :param y_true: true observations.
+ :param var: variance from the model.
+ :return: torch scalar denoting the log-likelihood.
+ """
+ return (
+ -0.5 * torch.log(torch.tensor(2 * math.pi * var)).mean()
+ - 0.5 * (((y_pred - y_true) ** 2) / var).mean()
+ )
+
+
+def BIC(nll: float, M: int, n: int):
+ """
+ BIC(M) = −2 log p(D | M ) + | M | log n
+ |M| is the number of kernel parameters, p(D|M) is the marginal likelihood of the data, D,
+ and n is the number of data points.
+ :param nll: the negative marginal likelihood of the data, D
+ :param M: the number of kernel parameters
+ :param n: the number of data points
+ :return: the BIC score.
+ """
+ return 2 * nll + M * torch.log(torch.tensor(n))
+
+
+def AIC(nll: float, M: int):
+ """
+ AIC(M) = −2 log p(D | M ) + 2 | M |
+ |M| is the number of kernel parameters, p(D|M) is the marginal likelihood of the data, D.
+ :param nll: the negative marginal likelihood of the data, D
+ :param M: the number of kernel parameters
+ :return: the AIC score.
+ """
+ return 2 * nll + 2 * M
+
+
+def move_axis_to_end(array, axis):
+ return torch.moveaxis(array, axis, array.ndim - 1)
+
+
+@contextlib.contextmanager
+def suppress_warnings(msg=None):
+ with warnings.catch_warnings():
+ warnings.filterwarnings("ignore", msg)
+ yield
+
+
+def crps_gaussian(x, mu, sigma):
+ """
+ Computes the CRPS of observations x relative to normally distributed
+ forecasts with mean, mu, and standard deviation, sig.
+ CRPS(N(mu, sig^2); x)
+ Formula taken from Equation (5):
+ Calibrated Probablistic Forecasting Using Ensemble Model Output
+ Statistics and Minimum CRPS Estimation. Gneiting, Raftery,
+ Westveld, Goldman. Monthly Weather Review 2004
+ http://journals.ametsoc.org/doi/pdf/10.1175/MWR2904.1
+
+ :param x : scalar or array_like
+ The observation or set of observations.
+ :param mu : scalar or array_like
+ The mean of the forecast normal distribution
+ :param sigma : scalar or array_like
+ The standard deviation of the forecast distribution
+ :return: torch.Tensor
+ The CRPS of each observation x relative to mu and sig.
+ The shape of the output array is determined by numpy
+ broadcasting rules.
+ """
+
+ x = torch.as_tensor(x)
+ mu = torch.as_tensor(mu)
+ sigma = torch.as_tensor(sigma)
+ # standardized x
+ sx = (x - mu) / sigma
+ pdf = dist.Normal(0.0, 1.0).log_prob(sx).exp()
+ cdf = dist.Normal(0.0, 1.0).cdf(sx)
+ pi_inv = 1.0 / torch.sqrt(torch.tensor(math.pi))
+ crps = sigma * (sx * (2 * cdf - 1) + 2 * pdf - pi_inv)
+ return crps
+
+
+def _nanmean(v, *args, inplace=False, **kwargs):
+ """
+ Computes the mean of v excluding nan values. Similar to numpy.nanmean.
+ :param v: torch.Tensor
+ the tensor to compute its mean
+ :param *args: list arguments to pass to sum
+ :param **kwargs: key word arguments to pass to sum
+ :return: torch.Tensor
+ mean of v excluding nan.
+ """
+ if not inplace:
+ v = v.clone()
+ is_nan = torch.isnan(v)
+ v[is_nan] = 0
+ return v.sum(*args, **kwargs) / (torch.logical_not(is_nan)).float().sum(
+ *args, **kwargs
+ )
+
+
+def _crps_ensemble_vectorized(observations, forecasts, weights):
+ """
+ A simple but expensive O(n^2) implementation of CRPS for testing purposes
+ This implementation is based on the identity:
+ .. math::
+ CRPS(F, x) = E_F|X - x| - 1/2 * E_F|X - X'|
+ where X and X' denote independent random variables drawn from the forecast
+ distribution F, and E_F denotes the expectation value under F.
+ Hence it has runtime O(n^2) instead of O(n log(n)) where n is the number of
+ ensemble members.
+ """
+
+ if weights.ndim > 0:
+ weights = torch.where(
+ torch.logical_not(torch.isnan(forecasts)), weights.double(), float("nan")
+ )
+ weights = weights / _nanmean(weights, axis=-1, keepdims=True)
+
+ if observations.ndim == forecasts.ndim - 1:
+ # sum over the last axis
+ assert observations.shape == forecasts.shape[:-1]
+ observations = observations.unsqueeze(-1)
+ with suppress_warnings("Mean of empty slice"):
+ score = _nanmean(weights * abs(forecasts - observations), -1)
+ # insert new axes along last and second to last forecast dimensions so
+ # forecasts_diff expands with broadcasting
+ forecasts_diff = forecasts.unsqueeze(-1) - forecasts.unsqueeze(-2)
+ weights_matrix = weights.unsqueeze(-1) * weights.unsqueeze(-2)
+ with suppress_warnings("Mean of empty slice"):
+ score += -0.5 * _nanmean(
+ weights_matrix * abs(forecasts_diff), axis=(-2, -1)
+ )
+ return score
+ elif observations.ndim == forecasts.ndim:
+ # there is no 'realization' axis to sum over (this is a deterministic
+ # forecast)
+ return abs(observations - forecasts)
+
+
+def crps_ensemble(observations, forecasts, issorted=False, axis=-1):
+ """
+ Calculate the continuous ranked probability score (CRPS) for a set of
+ explicit forecast realizations.
+
+ :param observations : float or array_like
+ Observations float or array. Missing values (NaN) are given scores of
+ NaN.
+ :param forecasts : float or array_like
+ Array of forecasts ensemble members, of the same shape as observations
+ except for the axis along which CRPS is calculated (which should be the
+ axis corresponding to the ensemble). If forecasts has the same shape as
+ observations, the forecasts are treated as deterministic. Missing
+ values (NaN) are ignored.
+ :param issorted : bool, optional
+ Optimization flag to indicate that the elements of `ensemble` are
+ already sorted along `axis`.
+ :param axis : int, optional
+ Axis in forecasts and weights which corresponds to different ensemble
+ members, along which to calculate CRPS.
+ : return: Tensor
+ CRPS for each ensemble forecast against the observations.
+ """
+ # TODO: Implement O(nlogn) version of the metric.
+ warnings.warn(
+ "This is a naive implementation that takes O(n^2) runtime, "
+ "and is not suited for large number of observations."
+ )
+ observations = torch.as_tensor(observations)
+ forecasts = torch.as_tensor(forecasts)
+ if axis != -1:
+ forecasts = move_axis_to_end(forecasts, axis)
+
+ if not issorted:
+ forecasts = torch.sort(forecasts, axis=-1).values
+
+ weights = torch.ones_like(forecasts)
+
+ return _crps_ensemble_vectorized(observations, forecasts, weights)
diff --git a/src/beanmachine/ppl/experimental/timeseries/sts/util.py b/src/beanmachine/ppl/experimental/timeseries/sts/util.py
new file mode 100644
index 0000000000..80ca349f37
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/sts/util.py
@@ -0,0 +1,13 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from contextlib import contextmanager
+
+
+@contextmanager
+def optional(cond, ctx, *args, **kwargs):
+ "Optionally wrap within context manager if `cond` is true."
+ if cond:
+ with ctx(*args, **kwargs) as c:
+ yield c
+ else:
+ yield
diff --git a/src/beanmachine/ppl/experimental/timeseries/test/abcd/test_expansion.py b/src/beanmachine/ppl/experimental/timeseries/test/abcd/test_expansion.py
new file mode 100644
index 0000000000..067220caea
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/test/abcd/test_expansion.py
@@ -0,0 +1,116 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import pytest
+from gpytorch.kernels import PeriodicKernel, ScaleKernel
+from sts.abcd.expansion import initialize_kernel, simplify
+from sts.abcd.kernels import ChangePointABCDKernel, ChangeWindowABCDKernel
+from sts.abcd.utils import is_kernel_type_eq
+from sts.gp.kernels import ConstantKernel, WhiteNoiseKernel
+
+
+@pytest.mark.parametrize(
+ "kernel, sim_kernel",
+ [
+ (
+ ChangePointABCDKernel(
+ WhiteNoiseKernel(noise=1e-2) + WhiteNoiseKernel(noise=1e-3),
+ WhiteNoiseKernel(noise=1e-2) + WhiteNoiseKernel(noise=1e-3),
+ ),
+ ChangePointABCDKernel(
+ WhiteNoiseKernel(noise=1e-2),
+ WhiteNoiseKernel(noise=1e-2),
+ ),
+ ),
+ (
+ ChangeWindowABCDKernel(
+ WhiteNoiseKernel(noise=1e-2) + WhiteNoiseKernel(noise=1e-3),
+ WhiteNoiseKernel(noise=1e-2) + WhiteNoiseKernel(noise=1e-3),
+ ),
+ ChangeWindowABCDKernel(
+ WhiteNoiseKernel(noise=1e-2),
+ WhiteNoiseKernel(noise=1e-2),
+ ),
+ ),
+ (
+ ChangePointABCDKernel(
+ ChangePointABCDKernel(
+ WhiteNoiseKernel(noise=1e-2) * WhiteNoiseKernel(noise=1e-3),
+ WhiteNoiseKernel(noise=1e-3),
+ ),
+ ConstantKernel(constant=1.0) * ConstantKernel(constant=1.0),
+ ),
+ ChangePointABCDKernel(
+ ChangePointABCDKernel(
+ WhiteNoiseKernel(noise=1e-2), WhiteNoiseKernel(noise=1e-2)
+ ),
+ ConstantKernel(constant=1.0),
+ ),
+ ),
+ (
+ ChangeWindowABCDKernel(
+ ConstantKernel(constant=1.0) + ConstantKernel(constant=1.0),
+ ConstantKernel(constant=1.0) + ConstantKernel(constant=1.0),
+ ),
+ ChangeWindowABCDKernel(
+ ConstantKernel(constant=1.0), ConstantKernel(constant=1.0)
+ ),
+ ),
+ (
+ ChangePointABCDKernel(
+ ConstantKernel(constant=1.0) * ConstantKernel(constant=1.0),
+ ConstantKernel(constant=1.0) + ConstantKernel(constant=1.0),
+ ),
+ ChangePointABCDKernel(
+ ConstantKernel(constant=1.0),
+ ConstantKernel(constant=1.0),
+ ),
+ ),
+ (
+ WhiteNoiseKernel(noise=1e-1)
+ + ConstantKernel(constant=1.0)
+ * (WhiteNoiseKernel(noise=1e-2) + WhiteNoiseKernel(noise=1e-3)),
+ WhiteNoiseKernel(noise=1e-1),
+ ),
+ (
+ WhiteNoiseKernel(noise=1e-1)
+ + WhiteNoiseKernel(noise=1e-1)
+ + WhiteNoiseKernel(noise=1e-1)
+ + WhiteNoiseKernel(noise=1e-1),
+ WhiteNoiseKernel(noise=1e-1),
+ ),
+ (
+ ConstantKernel(constant=100)
+ + ConstantKernel(constant=10)
+ + ConstantKernel(constant=1),
+ ConstantKernel(constant=1.0),
+ ),
+ (
+ ConstantKernel(constant=1e-1)
+ + ConstantKernel(constant=1.0)
+ * (ConstantKernel(constant=1e-2) + ConstantKernel(constant=1e-3)),
+ ConstantKernel(constant=1.0),
+ ),
+ (
+ ConstantKernel(constant=1.0)
+ * ConstantKernel(constant=1.0)
+ * ConstantKernel(constant=1.0),
+ ConstantKernel(constant=1.0),
+ ),
+ ],
+)
+def test_simplify(kernel, sim_kernel):
+ simplified_kernel = simplify(kernel)
+ assert is_kernel_type_eq(simplified_kernel, sim_kernel)
+
+
+@pytest.mark.parametrize(
+ "kernel",
+ [
+ ScaleKernel(PeriodicKernel()),
+ ],
+)
+def test_random_start(kernel):
+ kernels_init = initialize_kernel(kernel, (1.0, 10.0))
+ assert len(kernels_init) == 2
+ assert kernels_init[0].base_kernel.period_length == 1.0
+ assert kernels_init[1].base_kernel.period_length == 10.0
diff --git a/src/beanmachine/ppl/experimental/timeseries/test/abcd/test_expression.py b/src/beanmachine/ppl/experimental/timeseries/test/abcd/test_expression.py
new file mode 100644
index 0000000000..ee96d39fce
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/test/abcd/test_expression.py
@@ -0,0 +1,112 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from copy import deepcopy
+
+import pytest
+import torch
+from gpytorch.kernels import LinearKernel, PeriodicKernel, RBFKernel, ScaleKernel
+from sts.abcd.expression import KernelExpression
+from sts.abcd.kernels import ChangePointABCDKernel, ChangeWindowABCDKernel
+from sts.abcd.utils import BASE_KERNELS, is_base_kernel
+from sts.gp.kernels import ConstantKernel, WhiteNoiseKernel
+from torch.testing import assert_allclose # @manual
+
+torch.manual_seed(0)
+SAMPLE_DATA = torch.linspace(-3, 3, 100)
+
+
+@pytest.mark.parametrize(
+ "kernel",
+ [
+ deepcopy(BASE_KERNELS[0]),
+ (deepcopy(BASE_KERNELS[0]) + deepcopy(BASE_KERNELS[1]))
+ * deepcopy(BASE_KERNELS[2])
+ * deepcopy(BASE_KERNELS[2]),
+ (deepcopy(BASE_KERNELS[0]) * deepcopy(BASE_KERNELS[1]))
+ + deepcopy(BASE_KERNELS[2])
+ + deepcopy(BASE_KERNELS[2]),
+ ChangeWindowABCDKernel(ConstantKernel(0.1), deepcopy(BASE_KERNELS[1])),
+ ],
+)
+def test_kernel_expression(kernel):
+ kernel_exp = KernelExpression(kernel)
+ if is_base_kernel(kernel):
+ assert kernel_exp.lhs is None
+ assert kernel_exp.rhs is None
+
+ else:
+ if not is_base_kernel(kernel_exp.lhs.kernel):
+ assert kernel_exp.lhs.lhs is not None and kernel_exp.lhs.rhs is not None
+ if not is_base_kernel(kernel_exp.rhs.kernel):
+ assert kernel_exp.rhs.lhs is not None and kernel_exp.rhs.rhs is not None
+
+
+@pytest.mark.parametrize(
+ "kernel, name",
+ [
+ (WhiteNoiseKernel(noise=1e-3), "WN"),
+ (ConstantKernel(constant=1), "C"),
+ (ScaleKernel(PeriodicKernel()), "PER"),
+ (ScaleKernel(RBFKernel()), "RBF"),
+ (LinearKernel(), "LIN"),
+ (WhiteNoiseKernel(noise=1e-3) + ScaleKernel(PeriodicKernel()), "(WN + PER)"),
+ (
+ (WhiteNoiseKernel(noise=1e-3) + ScaleKernel(PeriodicKernel()))
+ * LinearKernel(),
+ "((WN + PER) x LIN)",
+ ),
+ (
+ WhiteNoiseKernel(noise=1e-3) + ScaleKernel(RBFKernel()) * LinearKernel(),
+ "(WN + (RBF x LIN))",
+ ),
+ (
+ ChangePointABCDKernel(
+ WhiteNoiseKernel(noise=1e-3), ScaleKernel(RBFKernel())
+ )
+ * LinearKernel(),
+ "(CP(WN, RBF) x LIN)",
+ ),
+ (
+ ChangeWindowABCDKernel(
+ ScaleKernel(PeriodicKernel()), ScaleKernel(RBFKernel())
+ )
+ * LinearKernel(),
+ "(CW(PER, RBF) x LIN)",
+ ),
+ ],
+)
+def test_kernel_repr(kernel, name):
+ kernel_exp = KernelExpression(kernel)
+ assert repr(kernel_exp) == name
+
+
+@pytest.mark.parametrize(
+ "kernel, x, kern_exp_new",
+ [
+ (
+ (LinearKernel() + WhiteNoiseKernel(noise=1e-4))
+ * ScaleKernel(PeriodicKernel())
+ * (ScaleKernel(RBFKernel()) + ConstantKernel(constant=1.0)),
+ SAMPLE_DATA,
+ "(((((LIN x PER) x RBF) + ((LIN x PER) x C)) + ((WN x PER) x RBF)) + ((WN x PER) x C))",
+ ),
+ (
+ ChangePointABCDKernel(
+ (
+ ConstantKernel(constant=1.0)
+ + WhiteNoiseKernel(noise=1e-3)
+ + WhiteNoiseKernel(noise=2e-3)
+ )
+ * LinearKernel(),
+ LinearKernel(),
+ ),
+ SAMPLE_DATA,
+ "(((CP((C x LIN), C) + CP((WN x LIN), C)) + CP((WN x LIN), C)) + CP(C, LIN))",
+ ),
+ ],
+)
+def test_distributive_law(kernel, x, kern_exp_new):
+ kernel_exp = KernelExpression(kernel)
+ kernel_new = kernel_exp.additive_form_kernel()
+ assert repr(KernelExpression(kernel_new)) == kern_exp_new
+ assert_allclose(kernel(x).evaluate(), kernel_new(x).evaluate())
diff --git a/src/beanmachine/ppl/experimental/timeseries/test/abcd/test_hill_climbing.py b/src/beanmachine/ppl/experimental/timeseries/test/abcd/test_hill_climbing.py
new file mode 100644
index 0000000000..d86be5d327
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/test/abcd/test_hill_climbing.py
@@ -0,0 +1,33 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import pandas as pd
+import pytest
+import torch
+from sts.abcd.hill_climbing import HillClimbingSearch
+from sts.abcd.utils import GRAMMAR_RULES
+from sts.data import df_to_tensor
+
+
+@pytest.mark.skip(reason="unable to run multiprocessing")
+def teset_hill_climbing_parallel():
+ num_data = 20
+ x_orig = torch.linspace(0, 1, num_data)
+ y_orig = x_orig * 8 + 2.0 + 0.2 * torch.randn(x_orig.shape)
+ train_num = round(0.8 * num_data)
+ data = {"x": x_orig, "y": y_orig}
+ df = pd.DataFrame(data, dtype=float)
+ data = df_to_tensor(df, normalize_cols=True)
+ x_train = data[:train_num, ["x"]]
+ y_train = data[:train_num, "y"]
+
+ rules = GRAMMAR_RULES["basic"]
+ searcher = HillClimbingSearch(x_train.tensor, y_train.tensor)
+ searcher.search(
+ num_restarts=2,
+ num_iters=5,
+ top_k=2,
+ output_file="./search_airline_hillclimb_nonparallel_pkl.txt",
+ pickle_file="./search_airline_hillclimb_nonparallel.pkl",
+ run_in_parallel=True,
+ grammar=rules,
+ )
diff --git a/src/beanmachine/ppl/experimental/timeseries/test/abcd/test_model.py b/src/beanmachine/ppl/experimental/timeseries/test/abcd/test_model.py
new file mode 100644
index 0000000000..75c8f6ae98
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/test/abcd/test_model.py
@@ -0,0 +1,39 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import gpytorch as gp
+import pytest
+import torch
+from sts.abcd.model import ABCDExactGPModel
+from sts.data import DataTensor
+from sts.gp.kernels import WhiteNoiseKernel
+
+
+torch.manual_seed(0)
+NUM_DATA = 10
+X_TRAIN = DataTensor(
+ torch.linspace(0, 1, NUM_DATA).unsqueeze(-1), header=["x"], normalize_cols=["x"]
+)
+Y_TRAIN = DataTensor(
+ X_TRAIN.tensor * 8 + 2.0 + torch.randn(X_TRAIN.tensor.shape),
+ header=["y"],
+ normalize_cols=["y"],
+)
+
+
+@pytest.mark.parametrize("x_train, y_train", [(X_TRAIN, Y_TRAIN)])
+@pytest.mark.filterwarnings("ignore::gpytorch.utils.warnings.GPInputWarning")
+def test_model(x_train, y_train):
+ current_kernel = WhiteNoiseKernel(noise=1e-4)
+ likelihood = gp.likelihoods.GaussianLikelihood()
+ model = ABCDExactGPModel(x_train, y_train.squeeze(-1), likelihood, current_kernel)
+ model.optimize_params(num_epochs=10)
+ score = model.score()
+ assert isinstance(score, torch.Tensor)
+ n = torch.tensor(x_train.shape[0])
+ expected = model.loss * 2 * n + len(list(model.cov.parameters())) * torch.log(n)
+ assert torch.allclose(score, expected)
+ _ = model.predict(x_train)
+ mean, cov = model.decompose_timeseries(x_train.tensor)
+ expected_train_mean = model(x_train).mean
+ sum_of_part_means = sum([model.mean(x_train)] + [p.mean for p in cov.values()])
+ assert torch.allclose(sum_of_part_means, expected_train_mean)
diff --git a/src/beanmachine/ppl/experimental/timeseries/test/abcd/test_operator_helper.py b/src/beanmachine/ppl/experimental/timeseries/test/abcd/test_operator_helper.py
new file mode 100644
index 0000000000..749d2a5c3b
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/test/abcd/test_operator_helper.py
@@ -0,0 +1,172 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from copy import deepcopy
+
+import pytest
+from gpytorch.kernels import Kernel
+from sts.abcd.expression import KernelExpression
+from sts.abcd.operator_helpers import (
+ traverse_bottom_up,
+ traverse_dfs_add,
+ traverse_dfs_cp,
+ traverse_dfs_cw,
+ traverse_dfs_mul,
+ traverse_dfs_mul_const,
+ traverse_dfs_replace,
+ traverse_dfs_simplify_add,
+ traverse_dfs_simplify_base,
+ traverse_dfs_simplify_mul,
+)
+from sts.abcd.utils import BASE_KERNELS, remove_redundancy
+
+KERNEL = (BASE_KERNELS[0] + BASE_KERNELS[1]) * BASE_KERNELS[1] * BASE_KERNELS[2]
+
+
+@pytest.mark.parametrize(
+ "k1, k2, num_kernels, num_dedup_kernels",
+ [
+ (KERNEL, BASE_KERNELS[3], 7, 5),
+ ],
+)
+def test_traverse_dfs_add(k1, k2, num_kernels, num_dedup_kernels):
+ # S->S+B
+ kernel_exp = KernelExpression(k1)
+ traverse_dfs_add(kernel_exp, deepcopy(k2))
+ res = traverse_bottom_up(kernel_exp)
+ assert len(res) == num_kernels
+ res = remove_redundancy(res)
+ assert isinstance(res[0], Kernel)
+ assert len(res) == num_dedup_kernels
+
+
+@pytest.mark.parametrize(
+ "k1, k2, num_kernels, num_dedup_kernels",
+ [
+ (KERNEL, BASE_KERNELS[3], 7, 3),
+ ],
+)
+def test_traverse_dfs_mul(k1, k2, num_kernels, num_dedup_kernels):
+ # S->S*B
+ kernel_exp = KernelExpression(k1)
+ traverse_dfs_mul(kernel_exp, deepcopy(k2))
+ res = traverse_bottom_up(kernel_exp)
+ assert len(res) == num_kernels
+ res = remove_redundancy(res)
+ assert len(res) == num_dedup_kernels
+
+
+@pytest.mark.parametrize(
+ "k1, k2, num_kernels, num_dedup_kernels",
+ [
+ (KERNEL, BASE_KERNELS[3], 4, 4),
+ ],
+)
+def test_traverse_dfs_replace(k1, k2, num_kernels, num_dedup_kernels):
+ # B->B1
+ kernel_exp = KernelExpression(k1)
+ traverse_dfs_replace(kernel_exp, deepcopy(k2))
+ res = traverse_bottom_up(kernel_exp)
+ assert len(res) == num_kernels
+ res = remove_redundancy(res)
+ assert len(res) == num_dedup_kernels
+
+
+@pytest.mark.parametrize(
+ "kernel, num_kernels, num_dedup_kernels",
+ [
+ (KERNEL, 7, 7),
+ ],
+)
+def test_traverse_dfs_cp(kernel, num_kernels, num_dedup_kernels):
+ # S->CP(S,S)
+ kernel_exp = KernelExpression(kernel)
+ traverse_dfs_cp(kernel_exp)
+ res = traverse_bottom_up(kernel_exp)
+ assert len(res) == num_kernels
+ res = remove_redundancy(res)
+ assert len(res) == num_dedup_kernels
+
+
+@pytest.mark.parametrize(
+ "kernel, num_kernels, num_dedup_kernels, num_all_kernels",
+ [
+ (KERNEL, 7, 7, 14),
+ ],
+)
+def test_traverse_dfs_cw(kernel, num_kernels, num_dedup_kernels, num_all_kernels):
+ # S->CW(S,S)
+ kernel_exp1 = KernelExpression(kernel)
+ traverse_dfs_cw(kernel_exp1, pos_constant_kernel=1)
+ res1 = traverse_bottom_up(kernel_exp1)
+ assert len(res1) == num_kernels
+ res = remove_redundancy(res1)
+ assert len(res) == num_dedup_kernels
+
+ kernel_exp2 = KernelExpression(kernel)
+ traverse_dfs_cw(kernel_exp2, pos_constant_kernel=-1)
+ res2 = traverse_bottom_up(kernel_exp2)
+ assert len(res2) == num_kernels
+ res = remove_redundancy(res2)
+ assert len(res) == num_dedup_kernels
+
+ res = res1 + res2
+ res = remove_redundancy(res)
+ assert len(res) == num_all_kernels
+
+ kernel_exp = KernelExpression(kernel)
+ traverse_dfs_cw(kernel_exp, pos_constant_kernel=0)
+ res = traverse_bottom_up(kernel_exp)
+ assert len(res) == num_kernels
+ res = remove_redundancy(res)
+ assert len(res) == num_dedup_kernels
+
+
+@pytest.mark.parametrize(
+ "k1, k2, num_kernels, num_dedup_kernels",
+ [
+ (KERNEL, BASE_KERNELS[3], 7, 3),
+ ],
+)
+def test_traverse_dfs_mul_const(k1, k2, num_kernels, num_dedup_kernels):
+ # S->S*(B+C)
+ kernel_exp = KernelExpression(k1)
+ traverse_dfs_mul_const(kernel_exp, deepcopy(k2))
+ res = traverse_bottom_up(kernel_exp)
+ assert len(res) == num_kernels
+ res = remove_redundancy(res)
+ assert len(res) == num_dedup_kernels
+
+
+@pytest.mark.parametrize(
+ "k1, k2, num_kernels, num_dedup_kernels", [(KERNEL, BASE_KERNELS[3], 3, 3)]
+)
+def test_traverse_dfs_simplify_base(k1, k2, num_kernels, num_dedup_kernels):
+ # S->B
+ kernel_exp = KernelExpression(k1)
+ traverse_dfs_simplify_base(kernel_exp, deepcopy(k2))
+ res = traverse_bottom_up(kernel_exp)
+ assert len(res) == num_kernels
+ res = remove_redundancy(res)
+ assert len(res) == num_dedup_kernels
+
+
+@pytest.mark.parametrize("kernel, num_kernels, num_dedup_kernels", [(KERNEL, 2, 2)])
+def test_traverse_dfs_simplify_add(kernel, num_kernels, num_dedup_kernels):
+ # S+S1->S
+ kernel_exp = KernelExpression(kernel)
+ traverse_dfs_simplify_add(kernel_exp)
+ res = traverse_bottom_up(kernel_exp)
+ assert len(res) == num_kernels
+ res = remove_redundancy(res)
+ assert len(res) == num_dedup_kernels
+
+
+@pytest.mark.parametrize("kernel, num_kernels, num_dedup_kernels", [(KERNEL, 8, 6)])
+def test_traverse_dfs_simplify_mul(kernel, num_kernels, num_dedup_kernels):
+ # S*S1->S
+ kernel_exp = KernelExpression(kernel)
+ traverse_dfs_simplify_mul(kernel_exp)
+ res = traverse_bottom_up(kernel_exp)
+ assert len(res) == num_kernels
+ res = remove_redundancy(res)
+ assert len(res) == num_dedup_kernels
diff --git a/src/beanmachine/ppl/experimental/timeseries/test/abcd/test_operators.py b/src/beanmachine/ppl/experimental/timeseries/test/abcd/test_operators.py
new file mode 100644
index 0000000000..92cf3752ee
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/test/abcd/test_operators.py
@@ -0,0 +1,72 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from typing import List
+
+import pytest
+from gpytorch.kernels import AdditiveKernel, ProductKernel
+from sts.abcd.expansion import expand_kernel
+from sts.abcd.kernels import ChangePointABCDKernel, ChangeWindowABCDKernel
+from sts.abcd.utils import BASE_KERNELS, is_kernel_type_eq
+
+
+@pytest.mark.parametrize(
+ "kernel",
+ BASE_KERNELS,
+)
+def test_expand_base(kernel):
+ res = expand_kernel(kernel)
+ assert isinstance(res, List)
+ # the number of kernels is always 22 if the kernel to expand is any one of the base kernels {WN, PER, RBF, LIN}
+ assert len(res) == 22
+ cnt = 0
+ for k in res:
+ # test change point/window kernels
+ if isinstance(k, ChangePointABCDKernel) or isinstance(
+ k, ChangeWindowABCDKernel
+ ):
+ cnt += 1
+ # test the basic rules
+ elif isinstance(k, AdditiveKernel) or isinstance(k, ProductKernel):
+ assert is_kernel_type_eq(k.kernels[0], kernel) or is_kernel_type_eq(
+ k.kernels[1], kernel
+ )
+ # there are 4 change kernel operators
+ assert cnt == 4
+
+
+@pytest.mark.parametrize(
+ "kernel, heuristic_list",
+ [
+ (
+ (BASE_KERNELS[0] + BASE_KERNELS[1]) * BASE_KERNELS[2] * BASE_KERNELS[1],
+ [
+ (BASE_KERNELS[0] + BASE_KERNELS[1]) * BASE_KERNELS[2],
+ (BASE_KERNELS[0] + BASE_KERNELS[1]) * BASE_KERNELS[1],
+ BASE_KERNELS[2] * BASE_KERNELS[1],
+ (BASE_KERNELS[0] + BASE_KERNELS[1]),
+ BASE_KERNELS[2],
+ BASE_KERNELS[1],
+ ],
+ )
+ ],
+)
+def test_expand_composite(kernel, heuristic_list):
+ res = expand_kernel(kernel)
+ assert isinstance(res, List)
+ cp_cnt = 0
+ heursitic_cnt = 0
+
+ for k in res:
+ # test change point/window kernel rules
+ if isinstance(k, ChangePointABCDKernel) or isinstance(
+ k, ChangeWindowABCDKernel
+ ):
+ cp_cnt += 1
+ # test heuristic rules
+ else:
+ for kh in heuristic_list:
+ if is_kernel_type_eq(k, kh):
+ heursitic_cnt += 1
+ break
+ assert cp_cnt == 4
+ assert len(heuristic_list) == heursitic_cnt
diff --git a/src/beanmachine/ppl/experimental/timeseries/test/abcd/test_search.py b/src/beanmachine/ppl/experimental/timeseries/test/abcd/test_search.py
new file mode 100644
index 0000000000..38440c6f19
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/test/abcd/test_search.py
@@ -0,0 +1,35 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import pandas as pd
+import pytest
+import torch
+from sts.abcd.search import Search
+from sts.abcd.utils import GRAMMAR_RULES
+from sts.data import df_to_tensor
+
+
+@pytest.mark.skip(reason="unable to run multiprocessing")
+def teset_search_parallel():
+ num_data = 20
+ x_orig = torch.linspace(0, 1, num_data)
+ y_orig = x_orig * 8 + 2.0 + 0.2 * torch.randn(x_orig.shape)
+ train_num = round(0.8 * num_data)
+ data = {"x": x_orig, "y": y_orig}
+ df = pd.DataFrame(data, dtype=float)
+ data = df_to_tensor(df, normalize_cols=True)
+ x_train = data[:train_num, ["x"]]
+ y_train = data[:train_num, "y"]
+
+ x_scale = x_train.transforms["x"].inv.scale
+ period_value_list = (1.0 / x_scale, 10.0 / x_scale)
+ rules = GRAMMAR_RULES["basic"]
+ search_parallel = Search(x_train.tensor, y_train.tensor)
+ search_parallel.search(
+ max_depth=5,
+ top_k=2,
+ period_value_list=period_value_list,
+ output_file="./search_parallel.txt",
+ pickle_file="./search_parallel.pkl",
+ run_in_parallel=True,
+ grammar=rules,
+ )
diff --git a/src/beanmachine/ppl/experimental/timeseries/test/abcd/test_utils.py b/src/beanmachine/ppl/experimental/timeseries/test/abcd/test_utils.py
new file mode 100644
index 0000000000..d4b2b494c8
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/test/abcd/test_utils.py
@@ -0,0 +1,69 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from copy import deepcopy
+
+import pytest
+from gpytorch.kernels import LinearKernel, PeriodicKernel, RBFKernel, ScaleKernel
+from sts.abcd.kernels import ChangeWindowABCDKernel
+from sts.abcd.utils import is_base_kernel, is_kernel_type_eq, remove_redundancy
+from sts.gp.kernels import ConstantKernel, WhiteNoiseKernel
+
+
+@pytest.mark.parametrize(
+ "k, is_base",
+ [
+ (WhiteNoiseKernel(noise=1e-4), True),
+ (LinearKernel(), True),
+ (ScaleKernel(RBFKernel()), True),
+ (ScaleKernel(PeriodicKernel()), True),
+ (ConstantKernel(constant=1.0), True),
+ (ChangeWindowABCDKernel(ConstantKernel(constant=1.0), LinearKernel()), False),
+ (RBFKernel(), False),
+ (LinearKernel() + LinearKernel(), False),
+ ],
+)
+def test_is_base_kernel_type_eq(k, is_base):
+ assert is_base_kernel(deepcopy(k)) == is_base
+
+
+@pytest.mark.parametrize(
+ "k1, k2, is_equal",
+ [
+ (
+ (WhiteNoiseKernel(noise=1e-3) + LinearKernel()) * ScaleKernel(RBFKernel()),
+ ScaleKernel(RBFKernel()) * ScaleKernel(RBFKernel()),
+ False,
+ ),
+ (ScaleKernel(RBFKernel()), RBFKernel(), False),
+ (
+ (WhiteNoiseKernel(noise=1e-3) + LinearKernel()) * ScaleKernel(RBFKernel()),
+ (LinearKernel() + WhiteNoiseKernel(noise=1e-3)) * ScaleKernel(RBFKernel()),
+ True,
+ ),
+ (
+ ChangeWindowABCDKernel(ConstantKernel(0.1), LinearKernel()),
+ ChangeWindowABCDKernel(ConstantKernel(1.0), LinearKernel()),
+ True,
+ ),
+ ],
+)
+def test_is_kernel_type_eq(k1, k2, is_equal):
+ assert is_kernel_type_eq(k1, k2) == is_equal
+
+
+@pytest.mark.parametrize(
+ "kernel_list",
+ [
+ [
+ (WhiteNoiseKernel(noise=1e-3) + LinearKernel()) * ScaleKernel(RBFKernel()),
+ ScaleKernel(RBFKernel()) * ScaleKernel(RBFKernel()),
+ ScaleKernel(RBFKernel()),
+ (LinearKernel() + WhiteNoiseKernel(noise=1e-3)) * ScaleKernel(RBFKernel()),
+ ChangeWindowABCDKernel(ConstantKernel(0.1), LinearKernel()),
+ ChangeWindowABCDKernel(ConstantKernel(1.0), LinearKernel()),
+ ]
+ ],
+)
+def test_remove_redundancy(kernel_list):
+ no_duplicate_list = remove_redundancy(kernel_list)
+ assert len(no_duplicate_list) == 4
diff --git a/src/beanmachine/ppl/experimental/timeseries/test/forecast_example.py b/src/beanmachine/ppl/experimental/timeseries/test/forecast_example.py
new file mode 100644
index 0000000000..8b0c26c51b
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/test/forecast_example.py
@@ -0,0 +1,126 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import argparse
+import time
+
+import gpytorch as gp
+import numpy as np
+import pandas as pd
+import torch
+from gpytorch.kernels import PeriodicKernel, RBFKernel, ScaleKernel
+from sts.data import df_to_tensor
+from sts.gp.model import ExactGPAdditiveModel
+
+
+def load_dataset(path):
+ births = pd.read_csv(path)
+ births["date"] = pd.to_datetime(births[["year", "month", "day"]])
+ births["log_births"] = np.log(births["births"])
+ df_convert_fns = {"date": lambda x: (x - x.iloc[0]).dt.days}
+
+ data = df_to_tensor(births, normalize_cols=True, df_convert_fns=df_convert_fns)
+
+ x_train = data[:6000, ["date"]]
+ y_train = data[:6000, "log_births"]
+ x_test = data[6000:, ["date"]]
+ y_test = data[6000:, "log_births"]
+ return x_train, y_train, x_test, y_test
+
+
+class GPTS(gp.models.ExactGP):
+ def __init__(self, train_x, train_y, likelihood):
+ super().__init__(train_x.tensor, train_y.tensor, likelihood)
+ norm = train_x.transforms["date"].inv.scale
+ self.mean_module = gp.means.ConstantMean()
+ self.slow_moving_trend = ScaleKernel(RBFKernel())
+ self.slow_moving_trend.base_kernel.lengthscale = 1000.0 / norm
+ self.slow_periodic = ScaleKernel(PeriodicKernel())
+ self.slow_periodic.base_kernel.period_length = 365.25 / norm
+ self.covar_module = self.slow_moving_trend + self.slow_periodic
+
+ def forward(self, x):
+ mean = self.mean_module(x)
+ cov = self.covar_module(x)
+ return gp.distributions.MultivariateNormal(mean, cov)
+
+
+def train_model_gpytorch(x_train, y_train, training_iter=100):
+ likelihood = gp.likelihoods.GaussianLikelihood()
+ model = GPTS(x_train, y_train, likelihood)
+ x_train, y_train = x_train.tensor, y_train.tensor
+
+ model.train()
+ likelihood.train()
+ optimizer = torch.optim.Adam(
+ set(model.parameters())
+ - {
+ model.slow_moving_trend.base_kernel.raw_lengthscale,
+ model.slow_periodic.base_kernel.raw_period_length,
+ },
+ lr=0.2,
+ )
+ mll = gp.mlls.ExactMarginalLogLikelihood(likelihood, model)
+
+ for i in range(training_iter):
+ optimizer.zero_grad()
+ output = model(x_train)
+ loss = -mll(output, y_train)
+ loss.backward()
+ if i % 10 == 0:
+ print(
+ "Iter %d/%d - Loss: %.3f"
+ % (
+ i + 1,
+ training_iter,
+ loss.item(),
+ )
+ )
+ optimizer.step()
+
+
+def train_model_bmts(x_train, y_train, training_iter=100):
+ likelihood = gp.likelihoods.GaussianLikelihood()
+ model = ExactGPAdditiveModel(x_train, y_train, likelihood)
+ model.cov.add_seasonality(365.25, time_axis="date", fix_period=True)
+ model.cov.add_trend(1000.0, time_axis="date", fix_lengthscale=True)
+
+ train_apply = model.train_init(torch.optim.Adam(model.trainable_params, lr=0.1))
+
+ for i in range(training_iter):
+ loss = train_apply(x_train, y_train)
+ if i % 10 == 0:
+ print(
+ "Iter %d/%d - Loss: %.3f"
+ % (
+ i + 1,
+ training_iter,
+ loss,
+ )
+ )
+
+
+def main(args):
+ x_train, y_train, x_test, y_test = load_dataset(args.path)
+ if args.model not in ("gpy", "bmts"):
+ raise ValueError(f"Unsupported --model ({args.model}) argument provided.")
+ train_fn = train_model_gpytorch if args.model == "gpy" else train_model_bmts
+ print(f"Calling {train_fn}...")
+ start = time.time()
+ train_fn(x_train, y_train, training_iter=args.num_training_iter)
+ print(f"Training complete in {time.time() - start:.2f} s.")
+
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ "-m", "--model", default="gpy", type=str, help="Either bmts or gpy."
+ )
+ parser.add_argument("-p", "--path", type=str, help="Path to births dataset.")
+ parser.add_argument(
+ "-n",
+ "--num-training-iter",
+ default=100,
+ type=int,
+ help="Number of training iterations.",
+ )
+ main(parser.parse_args())
diff --git a/src/beanmachine/ppl/experimental/timeseries/test/gp/test_cov.py b/src/beanmachine/ppl/experimental/timeseries/test/gp/test_cov.py
new file mode 100644
index 0000000000..0510a83ae4
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/test/gp/test_cov.py
@@ -0,0 +1,174 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import math
+
+import pytest
+import torch
+from gpytorch.kernels import RBFKernel
+from gpytorch.priors import NormalPrior
+from sts.data import DataTensor
+from sts.gp.cov import (
+ ChangePoint,
+ Covariance,
+ Regression,
+ Seasonality,
+ SpectralMixture,
+ Trend,
+ WhiteNoise,
+)
+
+
+torch.manual_seed(0)
+SAMPLE_DATA = [
+ DataTensor(
+ torch.cat([torch.randn(10, 4), torch.arange(10).unsqueeze(-1)], -1),
+ header=["a", "b", "c", "d", "t"],
+ normalize_cols=["t"],
+ )
+]
+
+
+@pytest.mark.parametrize("x", SAMPLE_DATA)
+def test_composition(x):
+ cov = Covariance(x)
+ cov.add_regression(features=["a", "b"], kernel_cls=RBFKernel)
+ cov.add_seasonality(time_axis="t", period_length=3)
+ cov.add_seasonality(time_axis="t", period_length=4)
+ cov.add_trend("t", lengthscale=1, name="Trend-short")
+ cov.add_trend("t", lengthscale=4, name="Trend-long")
+ assert len(cov.parts) == 5
+ names = list(cov.parts)
+ parts = list(cov.parts.values())
+ assert names[0] == parts[0].name == "Regression"
+ assert names[1] == parts[1].name == "Seasonality"
+ assert names[2] == parts[2].name == "Seasonality_1"
+ assert names[3] == parts[3].name == "Trend-short"
+ assert names[4] == parts[4].name == "Trend-long"
+ assert torch.allclose(
+ cov(x).evaluate(), sum(p(x.tensor).evaluate() for p in cov.parts.values())
+ )
+
+
+@pytest.mark.parametrize("x", SAMPLE_DATA)
+def test_fixed_params(x):
+ trend = Trend(x, time_axis="t", lengthscale=2, fix_lengthscale=True)
+ seasonality = Seasonality(x, time_axis="t", period_length=3, fix_period=True)
+ std = x.transforms["t"].inv.scale
+ # test normalization
+ assert torch.allclose(trend.kernel.base_kernel.lengthscale, 2.0 / std)
+ assert torch.allclose(trend.lengthscale, torch.tensor(2.0))
+ # fixed param not optimizable
+ for name, val in trend.named_parameters():
+ if "lengthscale" in name:
+ assert val in trend.fixed_params
+ # test normalization
+ assert torch.allclose(seasonality.kernel.base_kernel.period_length, 3.0 / std)
+ assert torch.allclose(seasonality.period_length, torch.tensor(3.0))
+ # fixed param not optimizable
+ for name, val in seasonality.named_parameters():
+ if "period_length" in name:
+ assert val in seasonality.fixed_params
+
+
+@pytest.mark.parametrize("x", SAMPLE_DATA)
+def test_regression(x):
+ reg = Regression(x, ["a", "b", "c"], kernel_cls=RBFKernel)
+ assert len(reg.lengthscale[0]) == 3
+ assert reg(x).shape == (x.shape[0], x.shape[0])
+
+
+@pytest.mark.parametrize("x", SAMPLE_DATA)
+@pytest.mark.parametrize("agg", ["sum", "prod"])
+def test_agg_kernel(x, agg):
+ seasonality = Seasonality(x, "t", 3, fix_period=True)
+ short_trend = Trend(x, "t", lengthscale=1, fix_lengthscale=True, name="ShortTrend")
+ long_trend = Trend(x, "t", lengthscale=3, fix_lengthscale=True, name="LongTrend")
+ if agg == "sum":
+ cov = seasonality + short_trend + long_trend
+ assert cov.name == "AdditiveKernel(Seasonality,ShortTrend,LongTrend)"
+ assert torch.allclose(
+ cov(x).evaluate(), sum(p(x).evaluate() for p in cov.parts.values())
+ )
+ else:
+ cov = seasonality * short_trend * long_trend
+ assert cov.name == "ProductKernel(Seasonality,ShortTrend,LongTrend)"
+ assert torch.allclose(
+ cov(x).evaluate(), math.prod(p(x).evaluate() for p in cov.parts.values())
+ )
+
+
+@pytest.mark.parametrize("x", SAMPLE_DATA)
+def test_spectralmixture(x):
+ spectralmixture = SpectralMixture(
+ x,
+ "t",
+ num_mixtures=2,
+ mixture_scales=torch.tensor([[[1.0]], [[1.0]]]),
+ mixture_means=torch.tensor([[[1.0]], [[1.0]]]),
+ mixture_weights=torch.tensor([1.0, 1.0]),
+ )
+ scale = x.transforms["t"].inv.scale
+ assert spectralmixture.kernel.num_mixtures == 2
+ assert torch.allclose(spectralmixture.scale, scale)
+ assert torch.allclose(
+ spectralmixture.mixture_scales,
+ spectralmixture.kernel.mixture_scales,
+ )
+ assert torch.allclose(
+ spectralmixture.mixture_means,
+ spectralmixture.kernel.mixture_means,
+ )
+ assert torch.allclose(
+ spectralmixture.mixture_weights,
+ spectralmixture.kernel.mixture_weights,
+ )
+
+
+@pytest.mark.parametrize("x", SAMPLE_DATA)
+def test_noise(x):
+ noise = WhiteNoise(x, "t", 1e-3, fix_noise=True, noise_prior=NormalPrior(0, 1))
+ assert torch.allclose(noise.kernel.noise, torch.tensor(1e-3))
+ for name, val in noise.named_parameters():
+ if "noise" in name:
+ assert val in noise.fixed_params
+ assert type(noise.kernel.noise_prior) == NormalPrior
+
+
+@pytest.mark.parametrize("data", SAMPLE_DATA)
+def test_sm_kernel_smoke(data):
+ train_size = 6
+ x = data[:train_size, ["t"]]
+ y = data[:train_size, "a"]
+ cov = Covariance(x, y)
+ cov.add_spectral_mixture(
+ time_axis="t",
+ num_mixtures=2,
+ train_x=x.tensor,
+ train_y=y.tensor,
+ name="SM1",
+ )
+ assert len(cov.parts) == 1
+ names = list(cov.parts)
+ parts = list(cov.parts.values())
+
+ assert names[0] == parts[0].name == "SM1"
+
+ assert torch.allclose(
+ cov(x).evaluate(), sum(p(x.tensor).evaluate() for p in cov.parts.values())
+ )
+
+
+@pytest.mark.parametrize("data", SAMPLE_DATA)
+def test_changepoint(data):
+ train_size = 6
+ x = data[:train_size, ["t", "b"]]
+ y = data[:train_size, "a"]
+ cov = Covariance(x, y)
+ trend = Trend(x, "t", kernel=RBFKernel, lengthscale=1.0, fix_lengthscale=True)
+ periodic = Seasonality(x, "t", period_length=1.0, fix_period=True)
+ cp = ChangePoint(x, "t", (trend, periodic), x[0][0].item(), name="CP")
+ cov.append(cp)
+ cov(x).evaluate()
+ assert not cov.fixed_params.difference(
+ trend.fixed_params.union(periodic.fixed_params)
+ )
diff --git a/src/beanmachine/ppl/experimental/timeseries/test/gp/test_graph.py b/src/beanmachine/ppl/experimental/timeseries/test/gp/test_graph.py
new file mode 100644
index 0000000000..ec17353a69
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/test/gp/test_graph.py
@@ -0,0 +1,34 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import pytest
+import torch
+from gpytorch.likelihoods import GaussianLikelihood
+from sts.data import DataTensor
+from sts.gp.graph import plot_components
+from sts.gp.model import ExactGPAdditiveModel
+
+
+@pytest.mark.parametrize("n_cols", [1, 2, 3])
+@pytest.mark.parametrize("n_components", [1, 2])
+@pytest.mark.filterwarnings("ignore::gpytorch.utils.warnings.GPInputWarning")
+def test_plot_components_smoke(n_cols, n_components):
+ data = DataTensor(
+ torch.cat([torch.arange(10).unsqueeze(-1), torch.randn(10, 1)], dim=-1),
+ header=["x", "y"],
+ normalize_cols=["y"],
+ )
+ x = data[:, ["x"]]
+ y = data[:, "y"]
+ model = ExactGPAdditiveModel(x, y, GaussianLikelihood())
+ for i in range(n_components):
+ model.cov.add_seasonality(time_axis="x", period_length=i + 1)
+ model.predict(x)
+ mean, cov = model.decompose_timeseries(x)
+ assert len(cov) == n_components
+ plot_components(
+ data[:, "x"],
+ (mean, cov),
+ transform=data.transforms["y"].inv,
+ ncols=n_cols,
+ plot_mean=True,
+ )
diff --git a/src/beanmachine/ppl/experimental/timeseries/test/gp/test_kernels.py b/src/beanmachine/ppl/experimental/timeseries/test/gp/test_kernels.py
new file mode 100644
index 0000000000..8c9f24a0cf
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/test/gp/test_kernels.py
@@ -0,0 +1,138 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+from numbers import Number
+
+import gpytorch
+import pytest
+import torch
+from gpytorch.constraints import GreaterThan
+from gpytorch.kernels import RBFKernel
+from gpytorch.priors import GammaPrior, LogNormalPrior
+from sts.gp.kernels import ChangePointKernel, ConstantKernel
+
+torch.manual_seed(0)
+SAMPLE_DATA = torch.linspace(-3, 3, 100)[:, None]
+
+
+@pytest.mark.parametrize("x", SAMPLE_DATA)
+def test_constant_kernel(x):
+ k = ConstantKernel(
+ constant=1.0,
+ constant_prior=LogNormalPrior(0, 1),
+ constant_constraint=GreaterThan(-1),
+ )
+ assert torch.allclose(k.constant, torch.tensor(1.0))
+ assert type(k.constant_prior) == LogNormalPrior
+ assert type(k.raw_constant_constraint) == GreaterThan
+
+
+@pytest.mark.parametrize("x", SAMPLE_DATA)
+def test_changepoint_kernel(x):
+ base_k1 = gpytorch.kernels.MaternKernel(lengthscales=0.2)
+ base_k2 = ConstantKernel(constant=0.0)
+ location = 1.0
+ steep = 2.0
+ k = ChangePointKernel(
+ (base_k1, base_k2),
+ location=location,
+ steep=steep,
+ location_prior=LogNormalPrior(1, 2),
+ steep_prior=GammaPrior(1, 2),
+ )
+ assert torch.allclose(k.location, torch.tensor(location))
+ assert torch.allclose(k.steep, torch.tensor(steep))
+ assert type(k.location_prior) == LogNormalPrior
+ assert type(k.steep_prior) == GammaPrior
+
+
+@pytest.mark.parametrize("x", SAMPLE_DATA)
+def test_changepoint_boundary(x):
+ x1 = torch.tensor([0.1, 0.2])
+ x2 = torch.tensor([0.8, 0.9])
+
+ base_k1 = ConstantKernel(constant=100.0)
+ base_k2 = ConstantKernel(constant=0.0)
+ location = 0.5
+ steep = 100.0
+ k = ChangePointKernel(
+ (base_k1, base_k2),
+ location=location,
+ steep=steep,
+ )
+ assert torch.allclose(k.location, torch.tensor(location))
+ assert torch.allclose(k.steep, torch.tensor(steep))
+
+ assert torch.allclose(k(x1, x1).evaluate(), base_k1(x1, x1).evaluate())
+ assert torch.allclose(k(x2, x2).evaluate(), base_k2(x2, x2).evaluate())
+ assert torch.allclose(k(x1, x2).evaluate(), torch.zeros(2, 2))
+
+
+@pytest.mark.parametrize("x", SAMPLE_DATA)
+def test_changewindow_kernel(x):
+ base_k1 = gpytorch.kernels.MaternKernel(lengthscales=0.2)
+ base_k2 = ConstantKernel(constant=0.0)
+ location = (-1.0, 1.0)
+ steep = (0.5, 50)
+ k = ChangePointKernel(
+ (base_k1, base_k2, base_k1),
+ location=location,
+ steep=steep,
+ location_prior=LogNormalPrior(1, 2),
+ steep_prior=GammaPrior(1, 2),
+ )
+ assert torch.allclose(k.location, torch.tensor(location))
+ assert torch.allclose(k.steep, torch.tensor(steep))
+ assert type(k.location_prior) == LogNormalPrior
+ assert type(k.steep_prior) == GammaPrior
+
+
+@pytest.mark.parametrize("x", SAMPLE_DATA)
+def test_changewindow_boundary(x):
+ x1 = torch.tensor([0.1, 0.2])
+ x2 = torch.tensor([0.8, 0.9])
+ x3 = torch.tensor([1.1, 1.2])
+
+ base_k1 = ConstantKernel(constant=100.0)
+ base_k2 = ConstantKernel(constant=0.0)
+ location = (0.5, 1.0)
+ steep = 100.0
+ k = ChangePointKernel(
+ (base_k1, base_k2, base_k1),
+ location=location,
+ steep=steep,
+ )
+
+ assert torch.allclose(k.location, torch.tensor(location))
+ assert torch.allclose(k.steep, torch.tensor(steep))
+
+ assert torch.allclose(k(x1, x1).evaluate(), base_k1(x1, x1).evaluate())
+ assert torch.allclose(k(x2, x2).evaluate(), base_k2(x2, x2).evaluate())
+ assert torch.allclose(k(x3, x3).evaluate(), base_k1(x3, x3).evaluate())
+ assert torch.allclose(k(x1, x2).evaluate(), torch.zeros(2, 2))
+ assert torch.allclose(k(x2, x3).evaluate(), torch.zeros(2, 2))
+
+
+@pytest.mark.parametrize("changepoint", [0.0, 1.0, [0.0, 1.0]])
+@pytest.mark.parametrize("batch_shape", [(), (1,), (3,)])
+@pytest.mark.parametrize("last_dim_is_batch", [False, True])
+@pytest.mark.parametrize("batched_input", [False, True])
+def test_changepoint_batched_shape(
+ changepoint, batch_shape, last_dim_is_batch, batched_input
+):
+ num_changepoints = 1 if isinstance(changepoint, Number) else len(changepoint)
+ kernels = [RBFKernel() for _ in range(num_changepoints + 1)]
+ cp = ChangePointKernel(kernels, location=changepoint, batch_shape=batch_shape)
+ assert cp.location.shape == (*batch_shape, 1, 1, num_changepoints)
+ N = 10
+ K = 5 # batched last dim
+ input_shape_pref = batch_shape if batched_input else ()
+ input_shape = input_shape_pref + (N, 1)
+ if last_dim_is_batch:
+ input_shape = input_shape[:-1] + (K,)
+ x1 = torch.randn(input_shape)
+ x2 = torch.randn(input_shape)
+ k_12 = cp(x1, x2, last_dim_is_batch=last_dim_is_batch).evaluate()
+ expected_shape = (
+ (*batch_shape, N, N) if not last_dim_is_batch else (*batch_shape, K, N, N)
+ )
+ assert k_12.shape == expected_shape
diff --git a/src/beanmachine/ppl/experimental/timeseries/test/gp/test_mean.py b/src/beanmachine/ppl/experimental/timeseries/test/gp/test_mean.py
new file mode 100644
index 0000000000..8d4899cbd6
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/test/gp/test_mean.py
@@ -0,0 +1,34 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import pytest
+import torch
+from sts.data import DataTensor
+from sts.gp.mean import Mean
+
+
+SAMPLE_DATA = [
+ DataTensor(
+ torch.cat([torch.randn(10, 4), torch.arange(10).unsqueeze(-1)], -1),
+ header=["a", "b", "c", "d", "t"],
+ normalize_cols=["t"],
+ )
+]
+
+
+@pytest.mark.parametrize("x", SAMPLE_DATA)
+def test_composition(x):
+ mean = Mean(x)
+ mean.add_regression(["a", "b"])
+ mean.add_regression(["c"])
+ assert len(mean.parts) == 3
+ names = list(mean.parts)
+ parts = list(mean.parts.values())
+ assert names[0] == "ConstantMean"
+ assert names[1] == "RegressionMean"
+ # Assert that no "bias" parameter exists for regression mean
+ for name, _ in parts[1].named_parameters():
+ assert "bias" not in name
+ assert names[2] == "RegressionMean_1"
+ for name, _ in parts[2].named_parameters():
+ assert "bias" not in name
+ assert torch.allclose(mean(x), sum(p(x.tensor) for p in mean.parts.values()))
diff --git a/src/beanmachine/ppl/experimental/timeseries/test/gp/test_model.py b/src/beanmachine/ppl/experimental/timeseries/test/gp/test_model.py
new file mode 100644
index 0000000000..cf096abc71
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/test/gp/test_model.py
@@ -0,0 +1,203 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import numpy as np
+import pandas as pd
+import pytest
+import torch
+from gpytorch.constraints import GreaterThan
+from gpytorch.kernels import LinearKernel, RBFKernel
+from gpytorch.likelihoods import GaussianLikelihood
+from gpytorch.priors import LogNormalPrior
+from sts.data import DataTensor, get_mvn_stats
+from sts.gp.graph import plot_components
+from sts.gp.model import AutomaticForecastingGP, ExactGPAdditiveModel
+from sts.util import optional
+
+
+torch.manual_seed(0)
+SAMPLE_DATA = [
+ DataTensor(
+ torch.cat([torch.randn(10, 4), torch.arange(10).unsqueeze(-1)], -1),
+ header=["a", "b", "c", "d", "t"],
+ normalize_cols=["t"],
+ )
+]
+
+
+@pytest.mark.parametrize("data", SAMPLE_DATA)
+def test_training_respects_requires_grad(data):
+ train_size = 6
+ x = data[:train_size, ["a", "b", "c", "t"]]
+ y = data[:train_size, "t"]
+ x_eval = data[train_size:, ["a", "b", "c", "t"]]
+ model = ExactGPAdditiveModel(x, y, GaussianLikelihood())
+ model.cov.add_regression(["a", "b"], name="Regression")
+ model.cov.add_seasonality(time_axis="t", period_length=2, fix_period=True)
+ old_outputscale = model.cov.parts["Regression"].kernel.raw_outputscale
+ old_outputscale.requires_grad_(False)
+ old_outputscale = old_outputscale.clone()
+ train_apply = model.train_init(torch.optim.Adam(model.trainable_params, lr=0.1))
+ train_apply(x, y)
+ new_outputscale = model.cov.parts["Regression"].kernel.raw_outputscale
+ assert torch.allclose(new_outputscale, old_outputscale)
+ mean, var, (ci_low, ci_high) = get_mvn_stats(model.predict(x_eval))
+ for stat in (mean, var, ci_low, ci_high):
+ assert not stat.requires_grad
+
+
+@pytest.mark.parametrize("data", SAMPLE_DATA)
+def test_exact_gp_smoke(data):
+ train_size = 6
+ x = data[:train_size, ["a", "b", "c", "t"]]
+ y = data[:train_size, "t"]
+ x_eval = data[train_size:, ["a", "b", "c", "t"]]
+ model = ExactGPAdditiveModel(x, y, GaussianLikelihood())
+ model.cov.add_regression(["a", "b"])
+ model.cov.add_seasonality(time_axis="t", period_length=2, fix_period=True)
+ train_apply = model.train_init(torch.optim.Adam(model.trainable_params))
+ for _ in range(10):
+ train_apply(x, y)
+ p = model.predict(x_eval)
+ assert not p.mean.requires_grad
+ assert p.mean.shape == (x_eval.shape[0],)
+ mean, cov = model.decompose_timeseries(x_eval)
+ assert len(mean) == 1
+ assert len(cov) == 2
+ expected_test_mean = model(x_eval).mean
+ sum_of_part_means = sum([model.mean(x_eval)] + [p.mean for p in cov.values()])
+ assert torch.allclose(sum_of_part_means, expected_test_mean)
+ plot_components(x_eval[:, "t"].squeeze(-1), (mean, cov), y=p, marker="o")
+
+
+@pytest.mark.parametrize("data", SAMPLE_DATA)
+def test_additive_spectralmixture_exact_gp(data):
+ train_size = 6
+ x = data[:train_size, ["t"]]
+ y = data[:train_size, "a"]
+ x_eval = data[train_size:, ["t"]]
+ model = ExactGPAdditiveModel(x, y, GaussianLikelihood())
+ model.cov.add_seasonality(time_axis="t", period_length=2, fix_period=True)
+ model.cov.add_spectral_mixture(
+ time_axis="t", num_mixtures=2, train_x=x.tensor, train_y=y.tensor, name="SM1"
+ )
+ model.cov.add_spectral_mixture(time_axis="t", num_mixtures=2, name="SM2")
+ model.cov.add_trend(time_axis="t", kernel_cls=LinearKernel, name="LinearTrend")
+ model.cov.add_trend(
+ time_axis="t",
+ kernel_cls=RBFKernel,
+ lengthscale=100,
+ fix_lengthscale=True,
+ name="RBFTrend",
+ )
+ train_apply = model.train_init(torch.optim.Adam(model.trainable_params))
+ for _ in range(20):
+ train_apply(x, y)
+ p = model.predict(x_eval)
+ assert not p.mean.requires_grad
+ assert p.mean.shape == (x_eval.shape[0],)
+ mean, cov = model.decompose_timeseries(x_eval.tensor)
+ assert len(mean) == 1
+ assert len(cov) == 5
+ expected_test_mean = model(x_eval).mean
+ sum_of_part_means = sum([model.mean(x_eval)] + [p.mean for p in cov.values()])
+ assert torch.allclose(sum_of_part_means, expected_test_mean, rtol=1e-4)
+
+
+@pytest.mark.parametrize("N", [5, 20, 100, 650])
+@pytest.mark.parametrize("lin_covariates", [False, True])
+@pytest.mark.parametrize("disable_sm_kernel", [False, True])
+@pytest.mark.parametrize("changepoint_locations", [[], [0.0], [0.0, 2.0]])
+@pytest.mark.parametrize("detect_changepoints", [False, True])
+@pytest.mark.filterwarnings("ignore:`changepoint_locations` will not be used")
+def test_autoforecasting_gp_smoke(
+ N, lin_covariates, disable_sm_kernel, changepoint_locations, detect_changepoints
+):
+ if N == 650:
+ pytest.skip("See: T131274126")
+ dates = np.arange("2018-01", "2021-01", dtype="datetime64[D]")
+ data = pd.DataFrame(
+ {
+ "t": dates,
+ "a": np.linspace(0.0, 1.0, len(dates)),
+ "y": np.linspace(0.0, 10.0, len(dates)),
+ }
+ )
+ with optional(N < 10, pytest.raises, ValueError):
+ if lin_covariates:
+ model = AutomaticForecastingGP(
+ data[:N],
+ "t",
+ "y",
+ linear_covariates=["a"],
+ changepoint_locations=changepoint_locations,
+ disable_sm_kernel=disable_sm_kernel,
+ )
+ else:
+ model = AutomaticForecastingGP(
+ data[:N],
+ "t",
+ "y",
+ nonlinear_covariates=["a"],
+ changepoint_locations=changepoint_locations,
+ disable_sm_kernel=disable_sm_kernel,
+ detect_changepoints=detect_changepoints,
+ )
+ if N > 10:
+ if model.changepoint_locations:
+ assert torch.allclose(
+ model.cov.parts["Changepoint - Linear"].kernel.location,
+ torch.as_tensor(changepoint_locations) / 365.25,
+ )
+ data = model.preprocess_data(data)
+ x, y = data[:, ["t", "a"]], data[:, "y"]
+ x_train = x[:N]
+ y_train = y[:N]
+ x_test = x[N:]
+ train_apply = model.train_init(torch.optim.Adam(model.trainable_params))
+ for _ in range(2):
+ train_apply(x_train, y_train)
+ model.predict(x_test)
+
+
+@pytest.mark.parametrize("data", SAMPLE_DATA)
+def test_outputscale_prior_constraint(data):
+ outputscale_prior = LogNormalPrior(-1.0, 1.0)
+ outputscale_constraint = GreaterThan(1.0)
+ train_size = 6
+ x = data[:train_size, ["t", "b", "c"]]
+ y = data[:train_size, "a"]
+ model = ExactGPAdditiveModel(x, y, GaussianLikelihood())
+ model.cov.add_seasonality(
+ time_axis="t",
+ period_length=2,
+ fix_period=True,
+ outputscale_prior=outputscale_prior,
+ outputscale_constraint=outputscale_constraint,
+ name="Seasonality",
+ )
+ model.cov.add_trend(
+ time_axis="t",
+ kernel_cls=LinearKernel,
+ outputscale_prior=outputscale_prior,
+ outputscale_constraint=outputscale_constraint,
+ name="LinearTrend",
+ )
+ model.cov.add_regression(
+ ["b", "c"],
+ kernel_cls=RBFKernel,
+ outputscale_prior=outputscale_prior,
+ outputscale_constraint=outputscale_constraint,
+ name="Regression",
+ )
+ model.cov.add_spectral_mixture(
+ time_axis="t", num_mixtures=2, train_x=x.tensor, train_y=y.tensor, name="SM"
+ )
+ train_apply = model.train_init(torch.optim.Adam(model.trainable_params))
+ for _ in range(20):
+ train_apply(x, y)
+ for p in ["Seasonality", "LinearTrend", "Regression"]:
+ kernel = model.cov.parts[p].kernel
+ constraint = kernel.raw_outputscale_constraint
+ outputscale = kernel.outputscale
+ assert "outputscale_prior" in kernel._priors
+ assert constraint.check(outputscale)
diff --git a/src/beanmachine/ppl/experimental/timeseries/test/test_changepoints.py b/src/beanmachine/ppl/experimental/timeseries/test/test_changepoints.py
new file mode 100644
index 0000000000..895ad5b617
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/test/test_changepoints.py
@@ -0,0 +1,59 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import pytest
+import torch
+from sts.changepoints import BinSegChangepoint
+
+
+@pytest.mark.parametrize("m, b", [(1, 0), (2, 1), (-1, 5)])
+def test_no_changepoint(m, b):
+ x = torch.linspace(0, 1, 100)
+ y = m * x + b
+ binseg = BinSegChangepoint()
+ cps = binseg.get_changepoints(x, y)
+ assert len(cps) == 0
+
+
+def test_one_changepoint():
+ x = torch.linspace(0, 1, 100)
+ cp = 10
+ x0, y0 = x[cp], 2 * x[cp] + 1
+ seg_1 = 2 * x[:cp]
+ seg_2 = -y0 / (1 - x0) * (x[cp:] - x0) + y0
+ y = torch.cat([seg_1, seg_2])
+ binseg = BinSegChangepoint(min_segment=5)
+ cp = binseg.get_changepoints(x, y)
+ assert len(cp) == 1
+ assert cp[0] == 10
+ binseg = BinSegChangepoint(min_segment=10)
+ cp = binseg.get_changepoints(x, y)
+ assert len(cp) == 1
+ assert cp[0] == 10
+ binseg = BinSegChangepoint(min_segment=12)
+ cp = binseg.get_changepoints(x, y)
+ assert len(cp) == 1
+ assert cp[0] == 12
+
+
+def test_pruned_changepoints():
+ r"""
+ Plot of y vs. x
+
+ y0 _ | __ /
+ |/ \/
+ --------
+ 1 2 3 (changepoint locations)
+ """
+ x = torch.linspace(0, 1, 100)
+ cp1 = 25
+ cp2 = 50
+ cp3 = 75
+ y0 = 2 * x[cp1 - 1]
+ seg_1 = 2 * x[:cp1]
+ seg_2 = y0 * torch.ones(cp2 - cp1)
+ seg_3 = -y0 / (x[cp3 - 1] - x[cp2 - 1]) * (x[cp2:cp3] - x[cp2 - 1]) + y0
+ seg_4 = 1 / (1 - x[cp3 - 1]) * (x[cp3:] - x[cp3 - 1])
+ y = torch.cat([seg_1, seg_2, seg_3, seg_4])
+ binseg = BinSegChangepoint(min_segment=5, penalty_weight=1e-4, max_changepoints=2)
+ cp = binseg.get_changepoints(x, y)
+ assert len(cp) == 2 # In general, the exact changepoints will not be recovered
diff --git a/src/beanmachine/ppl/experimental/timeseries/test/test_data.py b/src/beanmachine/ppl/experimental/timeseries/test/test_data.py
new file mode 100644
index 0000000000..761bd0c588
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/test/test_data.py
@@ -0,0 +1,504 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import inspect
+
+import numpy as np
+import pandas as pd
+import pytest
+import torch
+from gpytorch.distributions import MultivariateNormal
+from numpy import testing
+from sts.data import (
+ DataTensor,
+ df_to_tensor,
+ get_mvn_stats,
+ OVERRIDES,
+ POINTWISE_OPS,
+ REDUCTION_OPS,
+)
+from torch.distributions.transforms import (
+ AffineTransform,
+ ComposeTransform,
+ ExpTransform,
+)
+
+
+# Needed for autodep
+assert_array_equal = testing.assert_array_equal
+
+SAMPLE_DFS = [
+ pd.DataFrame({"x": list(range(3, 7)), "y": list(range(4))}),
+ pd.DataFrame({"x": list(range(3))}),
+]
+
+
+@pytest.mark.parametrize("df", SAMPLE_DFS)
+def test_indexing_pandas(df):
+ x = df_to_tensor(df, dtype=torch.double)
+ cols = list(x.header)
+ c0 = cols[0]
+ # lhs: DataTensor indexing (equiv to pytorch indexing) | rhs: pandas DF indexing
+ assert_array_equal(x[:, c0].numpy(), df[c0].to_numpy())
+ assert_array_equal(x[:, [c0]].numpy(), df[[c0]].to_numpy())
+ assert_array_equal(x[:, cols].numpy(), df[cols].to_numpy())
+ # integer indexing should work as expected
+ assert_array_equal(x[:, 0].numpy(), df[c0].to_numpy())
+ assert_array_equal(x[:, [0]].numpy(), df[[c0]].to_numpy())
+ assert_array_equal(x[:, list(range(len(x.header)))].numpy(), df[cols].to_numpy())
+
+
+def test_errors_creation():
+ # Scalar DataTensor.
+ with pytest.raises(ValueError, match="Scalar DataTensor must *"):
+ DataTensor(torch.tensor(0), ["a"])
+ # Single column tensor with no singleton dim.
+ with pytest.raises(ValueError, match="Tensor data dim size *"):
+ DataTensor(torch.ones(3), ["a"])
+ with pytest.raises(IndexError, match="dim=-3 invalid for a tensor of dim"):
+ DataTensor(torch.ones(2, 3), header=("a", "b"), dim=-3)
+ with pytest.raises(IndexError, match="dim=2 invalid for a tensor of dim"):
+ DataTensor(torch.ones(2, 3), header=("a", "b", "c"), dim=2)
+
+
+# Tensor indexing should work as expected once corresponding string
+# headers are replaced with their integer equivalents
+# i.e. dt[:, "a"] and dt[:, 0] should return the same underlying tensor
+# if "a" is the first column.
+@pytest.mark.parametrize(
+ "dt, str_idxs, torch_idxs, expected_header",
+ [
+ (
+ DataTensor(torch.randn(2, 3), ["a", "b", "c"]),
+ (slice(None), "a"),
+ (slice(None), 0),
+ (),
+ ),
+ (
+ DataTensor(torch.randn(2, 3), ["a", "b", "c"]),
+ (slice(None), ["a"]),
+ (slice(None), [0]),
+ ("a",),
+ ),
+ (
+ DataTensor(torch.randn(2, 3), ["a", "b"], dim=0),
+ ("a",),
+ (0,),
+ (),
+ ),
+ (
+ DataTensor(torch.randn(2, 3), ["a", "b"], dim=0),
+ "a",
+ 0,
+ (),
+ ),
+ (
+ DataTensor(torch.randn(2, 3), ["a", "b"], dim=0),
+ (["b", "a"]),
+ ([1, 0]),
+ ("b", "a"),
+ ),
+ (
+ DataTensor(torch.randn(2, 3), ["a", "b", "c"]),
+ (Ellipsis, ["b", "a"]),
+ (Ellipsis, [1, 0]),
+ ("b", "a"),
+ ),
+ (
+ DataTensor(torch.randn(2), ["a", "b"]),
+ ("a",),
+ (0,),
+ (),
+ ),
+ (
+ DataTensor(torch.randn(2), ["a", "b"]),
+ (["a"],),
+ ([0],),
+ ("a",),
+ ),
+ (
+ DataTensor(torch.randn(2, 1), ["a"]),
+ (slice(None), "a"),
+ (slice(None), 0),
+ (),
+ ),
+ (
+ DataTensor(torch.randn(2, 3), ["a", "b"], dim=0),
+ ("a",),
+ (0,),
+ (),
+ ),
+ # Advanced indexing: resulting tensor of size 2
+ (
+ DataTensor(torch.randn(2, 2, 3), ["a", "b"], dim=0),
+ (["a", "b"], 0, [0, 1]),
+ ([0, 1], 0, [0, 1]),
+ (),
+ ),
+ # Unsqueeze and ellipsis
+ (
+ DataTensor(torch.randn(2, 2, 3), ["a", "b"], dim=1),
+ (Ellipsis, ["a"], slice(None)),
+ (Ellipsis, [0], slice(None)),
+ ("a",),
+ ),
+ (
+ DataTensor(torch.randn(2, 2, 3), ["a", "b"], dim=1),
+ (0, None, ["a"], None, slice(None)),
+ (0, None, [0], None, slice(None)),
+ ("a",),
+ ),
+ (
+ DataTensor(torch.randn(2, 2, 3), ["a", "b", "c"]),
+ (Ellipsis, ["a", "b"], None),
+ (Ellipsis, slice(0, 2, None), None),
+ ("a", "b"),
+ ),
+ (
+ DataTensor(torch.tensor(0)),
+ (None, None),
+ (None, None),
+ (),
+ ),
+ (
+ DataTensor(torch.randn(2, 2, 3), ["a", "b"], dim=0),
+ (["a"], Ellipsis),
+ ([0], Ellipsis),
+ ("a",),
+ ),
+ (
+ DataTensor(torch.randn(2, 2, 3, 3), ["a", "b", "c"], dim=2),
+ (Ellipsis, ["a"], None, slice(None)),
+ (Ellipsis, [0], None, slice(None)),
+ ("a",),
+ ),
+ (
+ DataTensor(torch.randn(2, 2, 3, 3), ["a", "b", "c"], dim=2),
+ (None, Ellipsis, ["a"], None, slice(None)),
+ (None, Ellipsis, [0], None, slice(None)),
+ ("a",),
+ ),
+ (
+ DataTensor(torch.randn(2, 2, 3, 3), ["a", "b", "c"], dim=2),
+ (Ellipsis, None, ["a"], slice(None)),
+ (Ellipsis, None, [0], slice(None)),
+ ("a",),
+ ),
+ # Masked Indexing
+ (
+ DataTensor(torch.randn(2, 2, 3), ["a", "b"], dim=0),
+ [False, True],
+ [False, True],
+ (),
+ ),
+ (
+ DataTensor(torch.randn(2, 2, 3), ["a", "b"], dim=0),
+ torch.BoolTensor([False, True]),
+ torch.BoolTensor([False, True]),
+ (),
+ ),
+ ],
+)
+def test_indexing(dt, str_idxs, torch_idxs, expected_header):
+ str_indexed = dt[str_idxs]
+ trch_indexed = dt[torch_idxs]
+ assert_array_equal(str_indexed.numpy(), trch_indexed.numpy())
+ assert_array_equal(str_indexed.numpy(), trch_indexed.numpy())
+ assert str_indexed.header == expected_header
+ assert trch_indexed.header == expected_header
+
+
+def test_indexing_unsqueeze():
+ t = torch.randn(2, 3, 4, 4)
+ dt = DataTensor(t, header=("a", "b", "c"), dim=1)
+ t_1 = t[None]
+ dt_1 = dt[None]
+ assert dt_1.shape == t_1.shape == (1, 2, 3, 4, 4)
+ assert dt_1.data_dim == -3
+ assert dt_1.header == dt.header
+ t_2 = t[..., None]
+ dt_2 = dt[..., None]
+ assert dt_2.shape == t_2.shape == (2, 3, 4, 4, 1)
+ assert dt_2.data_dim == -4
+ assert dt_2.header == dt.header
+ t_3 = t[None, 0, ..., None]
+ dt_3 = dt[None, 0, ..., None]
+ assert dt_3.shape == t_3.shape == (1, 3, 4, 4, 1)
+ assert dt_3.data_dim == -4
+ assert dt_3.header == dt.header
+ t_4 = t[None, :, [1], ..., 0]
+ dt_4 = dt[None, :, ["a"], ..., 0]
+ assert dt_4.shape == t_4.shape == (1, 2, 1, 4)
+ assert dt_4.data_dim == -2
+ assert dt_4.header == ("a",)
+ t_5 = t[None, :, 1, ..., 0]
+ dt_5 = dt[None, :, "a", ..., 0]
+ assert dt_5.shape == t_5.shape == (1, 2, 4)
+ assert dt_5.data_dim is None
+ assert dt_5.header == ()
+ t_6 = t[None, :, 1, ..., None, 0]
+ dt_6 = dt[None, :, "a", ..., None, 0]
+ assert dt_6.shape == t_6.shape == (1, 2, 4, 1)
+ assert dt_6.data_dim is None
+ assert dt_6.header == ()
+
+
+@pytest.mark.parametrize(
+ "dt, str_idxs, err_type, err_msg",
+ [
+ (
+ DataTensor(torch.tensor(1)),
+ ("a"),
+ IndexError,
+ "too many indices for tensor",
+ ),
+ (
+ DataTensor(torch.randn(2, 2, 3), header=("a", "b"), dim=1),
+ ("a"),
+ IndexError,
+ "String indexing at dim 0",
+ ),
+ (
+ DataTensor(torch.randn(2, 2, 3), header=("a", "b"), dim=1),
+ (1, 1, ["b"]),
+ IndexError,
+ "String indexing at dim 2",
+ ),
+ (
+ DataTensor(torch.randn(2, 2, 3), header=("a", "b"), dim=1),
+ (1, ["b", "c"]),
+ IndexError,
+ "key=c not in",
+ ),
+ (
+ DataTensor(torch.randn(2, 2, 3), header=("a", "b"), dim=0),
+ "c",
+ IndexError,
+ "key=c not in",
+ ),
+ (
+ DataTensor(torch.randn(2, 2, 3), header=("a", "b"), dim=1),
+ (..., ["b", "c"], ...),
+ NotImplementedError,
+ "More than 1 ellipsis",
+ ),
+ (
+ DataTensor(torch.randn(2, 2, 3), header=("a", "b"), dim=1),
+ (1, ["b"], ["a"]),
+ IndexError,
+ "String indexing at dim 2",
+ ),
+ (
+ DataTensor(torch.randn(2, 2, 3), header=("a", "b"), dim=1),
+ (..., ["a"]),
+ IndexError,
+ "String indexing at dim -1",
+ ),
+ (
+ DataTensor(torch.randn(2, 2, 3), header=("a", "b"), dim=1),
+ (1, [None, "a"]),
+ IndexError,
+ "Nested `None` indices are disallowed",
+ ),
+ ],
+)
+def test_indexing_errors(dt, str_idxs, err_type, err_msg):
+ with pytest.raises(err_type, match=err_msg):
+ dt[str_idxs]
+
+
+@pytest.mark.parametrize(
+ "dt",
+ [
+ DataTensor(torch.randn(2, 3), ["a", "b", "c"]),
+ DataTensor(torch.randn(2), ["a", "b"]),
+ DataTensor(torch.randn(2, 1), ["a"]),
+ ],
+)
+def test_squeeze_ops(dt):
+ orig_shape = dt.shape
+ col_dim = dt.data_dim
+ # shape: (1, ...)
+ dt_unsq = dt.unsqueeze(0)
+ assert dt_unsq.shape == (1,) + orig_shape
+ assert dt_unsq.data_dim == col_dim
+ assert dt_unsq.header == dt.header
+ # shape: (1, ..., 1)
+ dt_unsq = dt_unsq.unsqueeze(-1)
+ assert dt_unsq.shape == (1,) + orig_shape + (1,)
+ assert dt_unsq.data_dim == col_dim - 1
+ assert dt_unsq.header == dt.header
+ # shape: (1, ...)
+ dt_sq = dt_unsq.squeeze(-1)
+ assert dt_sq.shape == (1,) + orig_shape
+ assert dt_sq.data_dim == col_dim
+ assert dt_sq.header == dt.header
+ # Squeeze on singleton dim removes the header (single column) and results in
+ # a reduced tensor; otherwise has no effect.
+ dt_sq = dt_sq.squeeze(-1)
+ if orig_shape[-1] != 1:
+ assert dt_sq.shape == (1,) + orig_shape
+ assert dt_sq.data_dim == col_dim
+ assert dt_sq.header == dt.header
+ else:
+ assert dt_sq.shape == (1,) + orig_shape[:-1]
+ assert dt_sq.data_dim is None
+ assert dt_sq.header == ()
+
+
+@pytest.mark.parametrize("df", SAMPLE_DFS)
+def test_normalization(df):
+ x_orig = df_to_tensor(df)
+ x = df_to_tensor(df, normalize_cols=["x"])
+ # append singleton dims for testing
+ x = x.unsqueeze(0).unsqueeze(-1)
+ # normalize 1 column
+ col = df["x"].to_numpy().astype(np.float32)
+ expected_val = (col - np.mean(col)) / np.std(col, ddof=1)
+ column = x[..., "x", :].squeeze(0).squeeze(-1).numpy()
+ assert_array_equal(column, expected_val)
+ denormalized = x.denormalize(x).squeeze(0).squeeze(-1).numpy()
+ assert_array_equal(denormalized, x_orig.numpy())
+ # normalize all columns
+ x = df_to_tensor(df, normalize_cols=True)
+ # append singleton dims for testing
+ x = x.unsqueeze(0).unsqueeze(-1)
+ arr = df.to_numpy().astype(np.float32)
+ expected_val = (arr - np.mean(arr, axis=0)) / np.std(arr, ddof=1, axis=0)
+ x_sq = x.squeeze(0).squeeze(-1)
+ assert_array_equal(x_sq.numpy(), expected_val)
+ denormalized = x_sq.denormalize(x_sq)
+ assert_array_equal(denormalized.numpy(), x_orig.numpy())
+ # assert metadata preserved after squeeze
+ assert len(x.unsqueeze(0).transforms) > 0
+
+
+@pytest.mark.parametrize("df", SAMPLE_DFS)
+def test_normalization_custom(df):
+ x_orig = df_to_tensor(df)
+ x = df_to_tensor(
+ df, normalize_cols={"x": AffineTransform(0.0, 10.0).inv}, dtype=torch.float64
+ )
+ # normalize x column
+ column = x[..., "x"].numpy()
+ expected_val = df["x"] / 10
+ assert_array_equal(column, expected_val)
+ denormalized = x.denormalize(x).numpy()
+ assert_array_equal(denormalized, x_orig.numpy())
+
+
+def test_normalization_errors():
+ df = pd.DataFrame({"x": list(range(3, 7)), "y": list(range(4))})
+ with pytest.raises(TypeError):
+ df_to_tensor(df, normalize_cols=set())
+
+ with pytest.raises(TypeError):
+ df_to_tensor(df, normalize_cols={"x": lambda x: (x - x.mean) / x.std()})
+
+ dt = df_to_tensor(df, normalize_cols=["x"])
+ with pytest.raises(ValueError, match="Column x already normalized."):
+ dt.normalize(transform_columns=["x"])
+
+ with pytest.raises(ValueError, match="Columns {'x'} already normalized."):
+ dt.normalize(transform_columns={"x": AffineTransform(0, 1)})
+ # Should not raise an error as y is unnormalized
+ dt.normalize(transform_columns=["y"])
+ # Should not raise an error even though number of rows is different
+ dt.denormalize(torch.randn(3, 2))
+ # Error as target ndim is different
+ with pytest.raises(ValueError):
+ dt.denormalize(torch.randn(2))
+ # Error as size of column dim is different
+ with pytest.raises(ValueError):
+ dt.denormalize(torch.randn(2, 3))
+
+
+@pytest.mark.parametrize("n", [2, 5, 6])
+@pytest.mark.parametrize("logspace", [False, True])
+def test_stats_mvn(n, logspace):
+ torch.manual_seed(5)
+ L = torch.randn(n, n).tril() * 0.1
+ cov = L @ L.T
+ affine_transform = AffineTransform(2.0, 3.0)
+ mvn = MultivariateNormal(mean=torch.zeros(n), covariance_matrix=cov)
+ samples = mvn.sample(torch.Size((100000,)))
+ scaled_samples = affine_transform(samples)
+ transform = affine_transform
+ if logspace:
+ scaled_samples = scaled_samples.exp()
+ transform = ComposeTransform([affine_transform, ExpTransform()])
+ mean, var, ci = get_mvn_stats(mvn, transform=transform)
+ assert torch.allclose(mean, scaled_samples.mean(dim=0), rtol=0.05)
+ assert torch.allclose(var, scaled_samples.var(dim=0), rtol=0.05)
+ q1, q2 = scaled_samples.quantile(q=torch.tensor([0.05, 0.95]), dim=0)
+ assert torch.allclose(ci[0], q1, rtol=0.05)
+ assert torch.allclose(ci[1], q2, rtol=0.05)
+
+
+@pytest.mark.parametrize(
+ "x",
+ [
+ DataTensor(torch.rand(()), header=[]),
+ DataTensor(torch.rand(1), header=["a"]),
+ DataTensor(torch.rand(1, 2), header=["a", "b"]),
+ ],
+)
+@pytest.mark.parametrize("op", POINTWISE_OPS)
+def test_pointwise_ops(x, op):
+ sig = inspect.signature(OVERRIDES[op])
+ x_float = x
+ x_long = x.long()
+ if op.__name__ in ("clamp", "clip"):
+ args = (x, 0.5)
+ else:
+ args = []
+ for p in sig.parameters.values():
+ if p.kind == p.POSITIONAL_OR_KEYWORD and p.default is p.empty:
+ args.append(x_long if op.__name__.startswith("bitwise") else x_float)
+ ret_dt = op(*args)
+ ret_trch = op(*(x.tensor if isinstance(x, DataTensor) else x for x in args))
+ assert_array_equal(ret_dt.tensor, ret_trch)
+ assert ret_dt.header == x.header
+
+
+@pytest.mark.parametrize(
+ "x",
+ [
+ DataTensor(torch.rand(()), header=[]),
+ DataTensor(torch.rand(1), header=["a"]),
+ DataTensor(torch.rand(1, 2), header=["a", "b"]),
+ ],
+)
+@pytest.mark.parametrize("op", REDUCTION_OPS)
+def test_reduction_ops(x, op):
+ sig = inspect.signature(OVERRIDES[op])
+ if "quantile" in op.__name__:
+ args = (x, 0.9)
+ elif op.__name__ == "logsumexp":
+ args = (x, 0)
+ else:
+ args = []
+ for p in sig.parameters.values():
+ if p.kind == p.POSITIONAL_OR_KEYWORD and p.default is p.empty:
+ args.append(x)
+ ret_dt = op(*args)
+ ret_trch = op(*(x.tensor if isinstance(x, DataTensor) else x for x in args))
+ bound_sig = sig.bind(*args)
+ bound_sig.apply_defaults()
+ # We check for header retention when the data dim is not reduced
+ is_reduced = x.data_dim is None or bound_sig.arguments.get("dim", None) in (
+ None,
+ x.data_dim,
+ x.ndim + x.data_dim,
+ )
+ if isinstance(ret_dt, tuple):
+ for x, y in zip(ret_dt, ret_trch):
+ if isinstance(x, DataTensor):
+ assert_array_equal(x.tensor, y)
+ if not is_reduced:
+ assert ret_dt.header == x.header
+ else:
+ assert_array_equal(x, y)
+ else:
+ assert_array_equal(ret_dt.tensor, ret_trch)
+ if not is_reduced:
+ assert ret_dt.header == x.header
diff --git a/src/beanmachine/ppl/experimental/timeseries/test/test_metrics.py b/src/beanmachine/ppl/experimental/timeseries/test/test_metrics.py
new file mode 100644
index 0000000000..14af080b9b
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/test/test_metrics.py
@@ -0,0 +1,60 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import math
+
+import pytest
+import torch
+from sts.data import DataTensor
+from sts.metrics import crps_ensemble, crps_gaussian, log_likelihood_error, MAE
+
+
+torch.manual_seed(0)
+SAMPLE_DATA = [
+ DataTensor(
+ torch.cat([torch.randn(10, 4), torch.arange(10).unsqueeze(-1)], -1),
+ header=["a", "b", "c", "d", "t"],
+ normalize_cols=["t"],
+ )
+]
+
+
+@pytest.mark.parametrize("data", SAMPLE_DATA)
+def test_MAE(data):
+ train_size = 6
+ x = data[:train_size, ["t"]]
+ y_true = data[:train_size, "a"].tensor
+ noise = torch.randn(x.size()).view(-1) * 1e-4
+ y_pred = y_true + noise
+ actual = MAE(y_pred, y_true)
+ expected = (y_pred - y_true).abs().mean()
+ assert torch.allclose(actual, expected)
+
+
+@pytest.mark.parametrize("data", SAMPLE_DATA)
+def test_LL(data):
+ var = 1
+ train_size = 6
+ y_true = data[:train_size, "a"].tensor
+ y_pred = y_true + torch.randn(y_true.size()).view(-1) * 1e-6
+ actual = -0.5 * torch.log(torch.tensor(2 * math.pi * var)).mean()
+ expected = log_likelihood_error(y_pred, y_true, var)
+ assert torch.allclose(actual, expected, rtol=1e-4)
+
+
+@pytest.mark.parametrize("data", SAMPLE_DATA)
+@pytest.mark.filterwarnings("ignore: This is a naive implementation:UserWarning")
+def test_crps(data):
+ shape = (2, 3)
+ mu = torch.normal(mean=torch.zeros(shape), std=torch.ones(shape))
+ sig = torch.square(torch.normal(mean=torch.zeros(shape), std=torch.ones(shape)))
+ obs = torch.normal(mean=mu, std=sig)
+
+ n = 1000
+ q = torch.linspace(0.0 + 0.5 / n, 1.0 - 0.5 / n, n)
+ # convert to the corresponding normal deviates
+ z = torch.distributions.Normal(torch.tensor([0.0]), torch.tensor([1.0])).icdf(q)
+ forecasts = z.reshape(-1, 1, 1) * sig + mu
+
+ expected = crps_ensemble(obs, forecasts, axis=0)
+ actual = crps_gaussian(obs, mu, sig).double()
+ assert torch.allclose(actual, expected)
diff --git a/src/beanmachine/ppl/experimental/timeseries/test/test_util.py b/src/beanmachine/ppl/experimental/timeseries/test/test_util.py
new file mode 100644
index 0000000000..24ec9c0d9c
--- /dev/null
+++ b/src/beanmachine/ppl/experimental/timeseries/test/test_util.py
@@ -0,0 +1,16 @@
+# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
+
+import pytest
+from sts.util import optional
+
+
+def test_optional():
+ entered = False
+ with optional(False, open, "dummy", "r") as f:
+ assert f is None
+ entered = True
+ assert entered
+ entered = False
+ with pytest.raises(FileNotFoundError):
+ with optional(True, open, "dummy", "r") as f:
+ pass