class_docstr: Samples data from linearly parameterized arms.
  
  The reward for context X and arm i is given by X^T * theta_i, for some
  latent set of parameters {theta_i : i = 1, ..., k}.
  The thetas are sampled uniformly at random, the contexts are Gaussian,
  and Gaussian noise is added to the rewards.
class_docstr_tok: ["Samples","data","from","linearly","parameterized","arms",".","The","reward","for","context","X","and","arm","i","is","given","by","X^T","*","theta_i",",","for","some","latent","set","of","parameters","{","theta_i",":","i","=","1",",","...",",","k","}",".","The","thetas","are","sampled","uniformly","at","random",",","the","contexts","are","Gaussian",",","and","Gaussian","noise","is","added","to","the","rewards","."]
code: def step(self, action):
      assert (
          self._elapsed_steps is not None
      ), "Cannot call env.step() beforecalling reset()"
      assert action < self.num_actions, "Invalid action."
  
      action = int(action)
      context = self._current_context
      rewards = self.thetas.dot(context)
  
      opt_action = rewards.argmax()
  
      regret = rewards.max() - rewards[action]
  
      # Add Gaussian noise
      rewards += np.random.normal(scale=self.sigma, size=rewards.shape)
  
      reward = rewards[action]
      self._current_context = self._sample_context()
      return (
          self._current_context,
          reward,
          True,
          False,
          {"regret": regret, "opt_action": opt_action},
      )
  
imports: import copy
  import gymnasium
  from gymnasium.spaces import Box, Discrete
  import numpy
  import random
label_desc: Use image node_id 4 for calling the LinearDiscreteEnv obj's underlying member method code with example usage: obj.step(action) and returns: self,  reward,  True,  False,  dict