<commit_before>"""
lowess: Locally linear regression
==================================

Implementation of the LOWESS algorithm in n dimensions.

References
=========
[HTF] Hastie, Tibshirani and Friedman (2008). The Elements of Statistical
Learning; Chapter 6

[Cleveland79] Cleveland (1979). Robust Locally Weighted Regression and Smoothing
Scatterplots. J American Statistical Association, 74: 829-836.

"""
import numpy as np
import numpy.linalg as la

# Kernel functions:
def epanechnikov(xx, **kwargs):
    """
    The Epanechnikov kernel estimated for xx values at indices idx (zero
    elsewhere)

    Parameters
    ----------
    xx: float array
        Values of the function on which the kernel is computed. Typically,
        these are Euclidean distances from some point x0 (see do_kernel)

    Notes
    -----
    This is equation 6.4 in HTF chapter 6

    """
    l = kwargs.get('l', 1.0)
    ans = np.zeros(xx.shape)
    xx_norm = xx / l
    idx = np.where(xx_norm <= 1)
    ans[idx] = 0.75 * (1 - xx_norm[idx]  ** 2)
    return ans

def tri_cube(xx, **kwargs):
    """
    The tri-cube kernel estimated for xx values at indices idx (zero
    elsewhere)

    Parameters
    ----------
    xx: float array
        Values of the function on which the kernel is computed. Typically,
        these are Euclidean distances from some point x0 (see do_kernel)

    idx: tuple
        An indexing tuple pointing to the coordinates in xx for which the
        kernel value is estimated. Default: None (all points are used!)

    Notes
    -----
    This is equation 6.6 in HTF chapter 6
    """
    ans = np.zeros(xx.shape)
    idx = np.where(xx <= 1)
    ans[idx] = (1 - np.abs(xx[idx]) ** 3) ** 3
    return ans

def bi_square(xx, **kwargs):
    """
    The bi-square weight function calculated over values of xx

    Parameters
    ----------
    xx: float array

    Notes
    -----
    This is the first equation on page 831 of [Cleveland79].
    """
    ans = np.zeros(xx.shape)
    idx = np.where(xx < 1)
    ans[idx] = (1 - xx[idx] ** 2) ** 2
    return ans

def do_kernel(x0, x, l=1.0, kernel=epanechnikov):
    """
    Calculate a kernel function on x in the neighborhood of x0

    Parameters
    ----------
    x: float array
       All values of x
    x0: float
       The value of x around which we evaluate the kernel
    l: float or float array (with shape = x.shape)
       Width parameter (metric window size)
    kernel: callable
        A kernel function. Any function with signature: `func(xx)`
    """
    # xx is the norm of x-x0. Note that we broadcast on the second axis for the
    # nd case and then sum on the first to get the norm in each value of x:
    xx = np.sum(np.sqrt(np.power(x - x0[:, np.newaxis], 2)), 0)
    return kernel(xx, l=l)

def lowess(x, y, x0, deg=1, kernel=epanechnikov, l=1, robust=False,):
    """
    Locally smoothed regression with the LOWESS algorithm.

    Parameters
    ----------
    x: float n-d array
       Values of x for which f(x) is known (e.g. measured). The shape of this
       is (n, j), where n is the number the dimensions and j is the
       number of distinct coordinates sampled.

    y: float array
       The known values of f(x) at these points. This has shape (j,)

    x0: float or float array.
        Values of x for which we estimate the value of f(x). This is either a
        single scalar value (only possible for the 1d case, in which case f(x0)
        is estimated for just that one value of x), or an array of shape (n, k).

    deg: int
        The degree of smoothing functions. 0 is locally constant, 1 is locally
        linear, etc. Default: 1.

    kernel: callable
        A kernel function. {'epanechnikov', 'tri_cube', 'bi_square'}

    l: float or float array with shape = x.shape
       The metric window size for the kernel

    robust: bool
        Whether to apply the robustification procedure from [Cleveland79], page
        831

    Returns
    -------
    The function estimated at x0.

    Notes
    -----
    The solution to this problem is given by equation 6.8 in Hastie
    Tibshirani and Friedman (2008). The Elements of Statistical Learning
    (Chapter 6).

    Example
    -------
    >>> import lowess as lo
    >>> import numpy as np

    # For the 1D case:
    >>> x = np.random.randn(100)
    >>> f = np.cos(x) + 0.2 * np.random.randn(100)
    >>> x0 = np.linspace(-1, 1, 10)
    >>> f_hat = lo.lowess(x, f, x0)
    >>> import matplotlib.pyplot as plt
    >>> fig, ax = plt.subplots(1)
    >>> ax.scatter(x, f)
    >>> ax.plot(x0, f_hat, 'ro')
    >>> plt.show()

    # 2D case (and more...)
    >>> x = np.random.randn(2, 100)
    >>> f = -1 * np.sin(x[0]) + 0.5 * np.cos(x[1]) + 0.2*np.random.randn(100)
    >>> x0 = np.mgrid[-1:1:.1, -1:1:.1]
    >>> x0 = np.vstack([x0[0].ravel(), x0[1].ravel()])
    >>> f_hat = lo.lowess(x, f, x0, kernel=lo.tri_cube)
    >>> from mpl_toolkits.mplot3d import Axes3D
    >>> fig = plt.figure()
    >>> ax = fig.add_subplot(111, projection='3d')
    >>> ax.scatter(x[0], x[1], f)
    >>> ax.scatter(x0[0], x0[1], f_hat, color='r')
    >>> plt.show()
    """
    if robust:
        # We use the procedure described in Cleveland1979
        # Start by calling this function with robust set to false and the x0
        # input being equal to the x input:
        y_est = lowess(x, y, x, kernel=epanechnikov, l=l, robust=False)
        resid = y_est - y
        median_resid = np.nanmedian(np.abs(resid))
        # Calculate the bi-cube function on the residuals for robustness
        # weights:
        robustness_weights = bi_square(resid / (6 * median_resid))

    # For the case where x0 is provided as a scalar:
    if not np.iterable(x0):
       x0 = np.asarray([x0])
    ans = np.zeros(x0.shape[-1])
    # We only need one design matrix for fitting:
    B = [np.ones(x.shape[-1])]
    for d in range(1, deg+1):
        B.append(x ** deg)

    B = np.vstack(B).T
    for idx, this_x0 in enumerate(x0.T):
        # This is necessary in the 1d case (?):
        if not np.iterable(this_x0):
            this_x0 = np.asarray([this_x0])
        # Different weighting kernel for each x0:
        W = np.diag(do_kernel(this_x0, x, l=l, kernel=kernel))
        # XXX It should be possible to calculate W outside the loop, if x0 and
        # x are both sampled in some regular fashion (that is, if W is the same
        # matrix in each iteration). That should save time.

        if robust:
            # We apply the robustness weights to the weighted least-squares
            # procedure:
            robustness_weights[np.isnan(robustness_weights)] = 0
            W = np.dot(W, np.diag(robustness_weights))
        #try:
        # Equation 6.8 in HTF:
        BtWB = np.dot(np.dot(B.T, W), B)
        BtW = np.dot(B.T, W)
        # Get the params:
        beta = np.dot(np.dot(la.pinv(BtWB), BtW), y.T)
        # We create a design matrix for this coordinat for back-predicting:
        B0 = [1]
        for d in range(1, deg+1):
            B0 = np.hstack([B0, this_x0 ** deg])
        B0 = np.vstack(B0).T
        # Estimate the answer based on the parameters:
        ans[idx] += np.dot(B0, beta)
    # If we are trying to sample far away from where the function is
    # defined, we will be trying to invert a singular matrix. In that case,
    # the regression should not work for you and you should get a nan:
        #except la.LinAlgError :
        #    ans[idx] += np.nan
    return ans.T

<commit_msg>Fixes bug in calculation of Euclidean distance<commit_after>"""
lowess: Locally linear regression
==================================

Implementation of the LOWESS algorithm in n dimensions.

References
=========
[HTF] Hastie, Tibshirani and Friedman (2008). The Elements of Statistical
Learning; Chapter 6

[Cleveland79] Cleveland (1979). Robust Locally Weighted Regression and Smoothing
Scatterplots. J American Statistical Association, 74: 829-836.

"""
import numpy as np
import numpy.linalg as la

# Kernel functions:
def epanechnikov(xx, **kwargs):
    """
    The Epanechnikov kernel estimated for xx values at indices idx (zero
    elsewhere)

    Parameters
    ----------
    xx: float array
        Values of the function on which the kernel is computed. Typically,
        these are Euclidean distances from some point x0 (see do_kernel)

    Notes
    -----
    This is equation 6.4 in HTF chapter 6

    """
    l = kwargs.get('l', 1.0)
    ans = np.zeros(xx.shape)
    xx_norm = xx / l
    idx = np.where(xx_norm <= 1)
    ans[idx] = 0.75 * (1 - xx_norm[idx]  ** 2)
    return ans

def tri_cube(xx, **kwargs):
    """
    The tri-cube kernel estimated for xx values at indices idx (zero
    elsewhere)

    Parameters
    ----------
    xx: float array
        Values of the function on which the kernel is computed. Typically,
        these are Euclidean distances from some point x0 (see do_kernel)

    idx: tuple
        An indexing tuple pointing to the coordinates in xx for which the
        kernel value is estimated. Default: None (all points are used!)

    Notes
    -----
    This is equation 6.6 in HTF chapter 6
    """
    ans = np.zeros(xx.shape)
    idx = np.where(xx <= 1)
    ans[idx] = (1 - np.abs(xx[idx]) ** 3) ** 3
    return ans

def bi_square(xx, **kwargs):
    """
    The bi-square weight function calculated over values of xx

    Parameters
    ----------
    xx: float array

    Notes
    -----
    This is the first equation on page 831 of [Cleveland79].
    """
    ans = np.zeros(xx.shape)
    idx = np.where(xx < 1)
    ans[idx] = (1 - xx[idx] ** 2) ** 2
    return ans

def do_kernel(x0, x, l=1.0, kernel=epanechnikov):
    """
    Calculate a kernel function on x in the neighborhood of x0

    Parameters
    ----------
    x: float array
       All values of x
    x0: float
       The value of x around which we evaluate the kernel
    l: float or float array (with shape = x.shape)
       Width parameter (metric window size)
    kernel: callable
        A kernel function. Any function with signature: `func(xx)`
    """
    # xx is the norm of x-x0. Note that we broadcast on the second axis for the
    # nd case and then sum on the first to get the norm in each value of x:
    xx = np.sqrt(np.sum(np.power(x - x0[:, np.newaxis], 2)), 0)
    return kernel(xx, l=l)

def lowess(x, y, x0, deg=1, kernel=epanechnikov, l=1, robust=False,):
    """
    Locally smoothed regression with the LOWESS algorithm.

    Parameters
    ----------
    x: float n-d array
       Values of x for which f(x) is known (e.g. measured). The shape of this
       is (n, j), where n is the number the dimensions and j is the
       number of distinct coordinates sampled.

    y: float array
       The known values of f(x) at these points. This has shape (j,)

    x0: float or float array.
        Values of x for which we estimate the value of f(x). This is either a
        single scalar value (only possible for the 1d case, in which case f(x0)
        is estimated for just that one value of x), or an array of shape (n, k).

    deg: int
        The degree of smoothing functions. 0 is locally constant, 1 is locally
        linear, etc. Default: 1.

    kernel: callable
        A kernel function. {'epanechnikov', 'tri_cube', 'bi_square'}

    l: float or float array with shape = x.shape
       The metric window size for the kernel

    robust: bool
        Whether to apply the robustification procedure from [Cleveland79], page
        831

    Returns
    -------
    The function estimated at x0.

    Notes
    -----
    The solution to this problem is given by equation 6.8 in Hastie
    Tibshirani and Friedman (2008). The Elements of Statistical Learning
    (Chapter 6).

    Example
    -------
    >>> import lowess as lo
    >>> import numpy as np

    # For the 1D case:
    >>> x = np.random.randn(100)
    >>> f = np.cos(x) + 0.2 * np.random.randn(100)
    >>> x0 = np.linspace(-1, 1, 10)
    >>> f_hat = lo.lowess(x, f, x0)
    >>> import matplotlib.pyplot as plt
    >>> fig, ax = plt.subplots(1)
    >>> ax.scatter(x, f)
    >>> ax.plot(x0, f_hat, 'ro')
    >>> plt.show()

    # 2D case (and more...)
    >>> x = np.random.randn(2, 100)
    >>> f = -1 * np.sin(x[0]) + 0.5 * np.cos(x[1]) + 0.2*np.random.randn(100)
    >>> x0 = np.mgrid[-1:1:.1, -1:1:.1]
    >>> x0 = np.vstack([x0[0].ravel(), x0[1].ravel()])
    >>> f_hat = lo.lowess(x, f, x0, kernel=lo.tri_cube)
    >>> from mpl_toolkits.mplot3d import Axes3D
    >>> fig = plt.figure()
    >>> ax = fig.add_subplot(111, projection='3d')
    >>> ax.scatter(x[0], x[1], f)
    >>> ax.scatter(x0[0], x0[1], f_hat, color='r')
    >>> plt.show()
    """
    if robust:
        # We use the procedure described in Cleveland1979
        # Start by calling this function with robust set to false and the x0
        # input being equal to the x input:
        y_est = lowess(x, y, x, kernel=epanechnikov, l=l, robust=False)
        resid = y_est - y
        median_resid = np.nanmedian(np.abs(resid))
        # Calculate the bi-cube function on the residuals for robustness
        # weights:
        robustness_weights = bi_square(resid / (6 * median_resid))

    # For the case where x0 is provided as a scalar:
    if not np.iterable(x0):
       x0 = np.asarray([x0])
    ans = np.zeros(x0.shape[-1])
    # We only need one design matrix for fitting:
    B = [np.ones(x.shape[-1])]
    for d in range(1, deg+1):
        B.append(x ** deg)

    B = np.vstack(B).T
    for idx, this_x0 in enumerate(x0.T):
        # This is necessary in the 1d case (?):
        if not np.iterable(this_x0):
            this_x0 = np.asarray([this_x0])
        # Different weighting kernel for each x0:
        W = np.diag(do_kernel(this_x0, x, l=l, kernel=kernel))
        # XXX It should be possible to calculate W outside the loop, if x0 and
        # x are both sampled in some regular fashion (that is, if W is the same
        # matrix in each iteration). That should save time.

        if robust:
            # We apply the robustness weights to the weighted least-squares
            # procedure:
            robustness_weights[np.isnan(robustness_weights)] = 0
            W = np.dot(W, np.diag(robustness_weights))
        #try:
        # Equation 6.8 in HTF:
        BtWB = np.dot(np.dot(B.T, W), B)
        BtW = np.dot(B.T, W)
        # Get the params:
        beta = np.dot(np.dot(la.pinv(BtWB), BtW), y.T)
        # We create a design matrix for this coordinat for back-predicting:
        B0 = [1]
        for d in range(1, deg+1):
            B0 = np.hstack([B0, this_x0 ** deg])
        B0 = np.vstack(B0).T
        # Estimate the answer based on the parameters:
        ans[idx] += np.dot(B0, beta)
    # If we are trying to sample far away from where the function is
    # defined, we will be trying to invert a singular matrix. In that case,
    # the regression should not work for you and you should get a nan:
        #except la.LinAlgError :
        #    ans[idx] += np.nan
    return ans.T

<|endoftext|>


<commit_before>#!/usr/bin/env python
import argparse
import bullet_cartpole
import datetime
import gym
import json
import numpy as np
import sys
import tensorflow as tf
import tensorflow.contrib.slim as slim
import time
import util

np.set_printoptions(precision=5, threshold=10000, suppress=True, linewidth=10000)

parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('--num-hidden', type=int, default=32)
parser.add_argument('--num-eval', type=int, default=0,
                    help="if >0 just run this many episodes with no training")
parser.add_argument('--num-train-batches', type=int, default=10,
                    help="number of training batches to run")
parser.add_argument('--rollouts-per-batch', type=int, default=10,
                    help="number of rollouts to run for each training batch")
parser.add_argument('--ckpt-dir', type=str, default=None,
                    help="if set save ckpts to this dir")
parser.add_argument('--ckpt-freq', type=int, default=300,
                    help="freq (sec) to save ckpts")
bullet_cartpole.add_opts(parser)
opts = parser.parse_args()
sys.stderr.write("%s\n" % opts)
assert not opts.use_raw_pixels, "TODO: add convnet from ddpg here"

EPSILON = 1e-3

class LikelihoodRatioPolicyGradientAgent(object):
  def __init__(self, env, hidden_dim, optimiser, gui=False):
    self.env = env
    self.gui = gui

    num_actions = self.env.action_space.n

    # we have three place holders we'll use...
    # observations; used either during rollout to sample some actions, or
    # during training when combined with actions_taken and advantages.
    shape_with_batch = [None] + list(self.env.observation_space.shape)
    self.observations = tf.placeholder(shape=shape_with_batch,
                                       dtype=tf.float32)
    # the actions we took during rollout
    self.actions = tf.placeholder(tf.int32, name='actions')
    # the advantages we got from taken 'action_taken' in 'observation'
    self.advantages = tf.placeholder(tf.float32, name='advantages')

    # our model is a very simple MLP
    with tf.variable_scope("model"):
      flat_obs = slim.flatten(self.observations)
      hidden = slim.fully_connected(inputs=flat_obs,
                                    num_outputs=hidden_dim,
                                    activation_fn=tf.nn.tanh)
      logits = slim.fully_connected(inputs=hidden,
                                    num_outputs=num_actions)

    # for rollouts we need an op that samples actions from this
    # model to give a stochastic action.
    sample_action = tf.multinomial(logits, num_samples=1),
    self.sampled_action_op = tf.reshape(sample_action, shape=[])

    # we are trying to maximise the product of two components...
    # 1) the log_p of "good" actions.
    # 2) the advantage term based on the rewards from actions.

    # first we need the log_p values for each observation for the actions we specifically
    # took by sampling...
    # first we run a softmax over the action logits to get probabilities.
    # ( +epsilon to avoid near zero instabilities )
    softmax = tf.nn.softmax(logits + 1e-20)
    softmax = tf.verify_tensor_all_finite(softmax, msg="softmax")

    # we then use a mask to only select the elements of the softmaxs that correspond
    # to the actions we actually took. we could also do this by complex indexing and a
    # gather but i always think this is more natural. the "cost" of dealing with the
    # mostly zero one hot, as opposed to doing a gather on sparse indexes, isn't a big
    # deal when the number of observations is >> number of actions.
    action_mask = tf.one_hot(indices=self.actions, depth=num_actions)
    action_prob = tf.reduce_sum(softmax * action_mask, reduction_indices=1)
    action_log_prob = tf.log(action_prob)

    # the (element wise) product of these action log_p's with the total reward of the
    # episode represents the quantity we want to maximise. we standardise the advantage
    # values so roughly 1/2 +ve / -ve as a variance control.
    action_mul_advantages = tf.mul(action_log_prob,
                                   util.standardise(self.advantages))
    self.loss = -tf.reduce_sum(action_mul_advantages)  # recall: we are maximising.
    with tf.variable_scope("optimiser"):
      self.train_op = optimiser.minimize(self.loss)

  def sample_action_given(self, observation):
    """ sample one action given observation"""
    return tf.get_default_session().run(self.sampled_action_op,
                                        feed_dict={self.observations: [observation]})

  def rollout(self):
    """ run one episode collecting observations, actions and advantages"""
    observations, actions, rewards = [], [], []
    observation = self.env.reset()
    done = False
    while not done:
      observations.append(observation)
      action = self.sample_action_given(observation)
      observation, reward, done, _ = self.env.step(action)
      actions.append(action)
      rewards.append(reward)
      if self.gui:
        self.env.render()
    return observations, actions, rewards

  def train(self, observations, actions, advantages):
    """ take one training step given observations, actions and subsequent advantages"""
    _, loss = tf.get_default_session().run([self.train_op, self.loss],
                                           feed_dict={self.observations: observations,
                                                      self.actions: actions,
                                                      self.advantages: advantages })
    return float(loss)

  def run_training(self, num_batches, rollouts_per_batch, saver_util):
    for batch_id in xrange(num_batches):
      # perform a number of rollouts
      batch_observations, batch_actions, batch_advantages = [], [], []
      total_rewards = []
      for _ in xrange(rollouts_per_batch):
        observations, actions, rewards = self.rollout()
        batch_observations += observations
        batch_actions += actions
        # train with advantages, not per observation/action rewards.
        # _every_ observation/action in this rollout gets assigned
        # the _total_ reward of the episode. (crazy that this works!)
        batch_advantages += [sum(rewards)] * len(rewards)
        # keep total rewards just for debugging / stats
        total_rewards.append(sum(rewards))

      if min(total_rewards) == max(total_rewards):
        # converged ??
        sys.stderr.write("converged? standardisation of advantaged will barf here....\n")
        loss = 0
      else:
        loss = self.train(batch_observations, batch_actions, batch_advantages)

      # dump some stats
      stats = {"time": int(time.time()),
               "batch": batch_id,
               "rewards": total_rewards,
               "loss": loss}
      print "STATS %s\t%s" % (datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                              json.dumps(stats))

      # save if required
      if saver_util is not None:
        saver_util.save_if_required()

  def run_eval(self, num_eval):
    for _ in xrange(num_eval):
      _, _, rewards = self.rollout()
      print sum(rewards)

def main():
  env = bullet_cartpole.BulletCartpole(opts=opts, discrete_actions=True)

  with tf.Session() as sess:
    agent = LikelihoodRatioPolicyGradientAgent(env=env, gui=opts.gui,
                                               hidden_dim=opts.num_hidden,
                                               optimiser=tf.train.AdamOptimizer())

    # setup saver util; will load latest ckpt, or init if none...
    saver_util = None
    if opts.ckpt_dir is not None:
      saver_util = util.SaverUtil(sess, opts.ckpt_dir, opts.ckpt_freq)
    else:
      sess.run(tf.initialize_all_variables())

    # run either eval or training
    if opts.num_eval > 0:
      agent.run_eval(opts.num_eval)
    else:
      agent.run_training(opts.num_train_batches, opts.rollouts_per_batch,
                         saver_util)
      if saver_util is not None:
        saver_util.force_save()

if __name__ == "__main__":
  main()
<commit_msg>clean up lrpg a bit. - dont want activation for logits - eval should be using argmax, not sampling - use log_softmax explicitly and drop (visible) epsilon hacks ( note: still seeing the multinomial sampling bug :/ )<commit_after>#!/usr/bin/env python
import argparse
import bullet_cartpole
import datetime
import gym
import json
import numpy as np
import sys
import tensorflow as tf
import tensorflow.contrib.slim as slim
from tensorflow.python.ops import init_ops
import time
import util
import collections

np.set_printoptions(precision=3, threshold=10000, suppress=True, linewidth=10000)

parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('--num-hidden', type=int, default=32)
parser.add_argument('--num-eval', type=int, default=0,
                    help="if >0 just run this many episodes with no training")
parser.add_argument('--num-train-batches', type=int, default=10,
                    help="number of training batches to run")
parser.add_argument('--rollouts-per-batch', type=int, default=10,
                    help="number of rollouts to run for each training batch")
parser.add_argument('--ckpt-dir', type=str, default=None,
                    help="if set save ckpts to this dir")
parser.add_argument('--ckpt-freq', type=int, default=300,
                    help="freq (sec) to save ckpts")
bullet_cartpole.add_opts(parser)
opts = parser.parse_args()
sys.stderr.write("%s\n" % opts)
assert not opts.use_raw_pixels, "TODO: add convnet from ddpg here"

class LikelihoodRatioPolicyGradientAgent(object):
  def __init__(self, env, hidden_dim, optimiser, gui=False):
    self.env = env
    self.gui = gui

    num_actions = self.env.action_space.n

    # we have three place holders we'll use...
    # observations; used either during rollout to sample some actions, or
    # during training when combined with actions_taken and advantages.
    shape_with_batch = [None] + list(self.env.observation_space.shape)
    self.observations = tf.placeholder(shape=shape_with_batch,
                                       dtype=tf.float32)
    # the actions we took during rollout
    self.actions = tf.placeholder(tf.int32, name='actions')
    # the advantages we got from taken 'action_taken' in 'observation'
    self.advantages = tf.placeholder(tf.float32, name='advantages')

    # our model is a very simple MLP
    with tf.variable_scope("model"):
      flat_obs = slim.flatten(self.observations)
      hidden1 = slim.fully_connected(inputs=flat_obs,
                                     num_outputs=hidden_dim,
                                     biases_initializer=init_ops.constant_initializer(0.1))
      hidden2 = slim.fully_connected(inputs=hidden1,
                                     num_outputs=hidden_dim,
                                     biases_initializer=init_ops.constant_initializer(0.1))
      logits = slim.fully_connected(inputs=hidden2,
                                    num_outputs=num_actions,
                                    activation_fn=None)

    # in the eval case just pick arg max
    self.action_argmax = tf.argmax(logits, 1)

    # for rollouts we need an op that samples actions from this
    # model to give a stochastic action.
    sample_action = tf.multinomial(logits, num_samples=1)
    self.sampled_action_op = tf.reshape(sample_action, shape=[])

    # we are trying to maximise the product of two components...
    # 1) the log_p of "good" actions.
    # 2) the advantage term based on the rewards from actions.

    # first we need the log_p values for each observation for the actions we specifically
    # took by sampling... we first run a log_softmax over the action logits to get
    # probabilities.
    log_softmax = tf.nn.log_softmax(logits)
    self.debug_softmax = tf.exp(log_softmax)

    # we then use a mask to only select the elements of the softmaxs that correspond
    # to the actions we actually took. we could also do this by complex indexing and a
    # gather but i always think this is more natural. the "cost" of dealing with the
    # mostly zero one hot, as opposed to doing a gather on sparse indexes, isn't a big
    # deal when the number of observations is >> number of actions.
    action_mask = tf.one_hot(indices=self.actions, depth=num_actions)
    action_log_prob = tf.reduce_sum(log_softmax * action_mask, reduction_indices=1)

    # the (element wise) product of these action log_p's with the total reward of the
    # episode represents the quantity we want to maximise. we standardise the advantage
    # values so roughly 1/2 +ve / -ve as a variance control.
    action_mul_advantages = tf.mul(action_log_prob,
                                   util.standardise(self.advantages))
    self.loss = -tf.reduce_sum(action_mul_advantages)  # recall: we are maximising.
    with tf.variable_scope("optimiser"):
      self.train_op = optimiser.minimize(self.loss)

  def sample_action_given(self, observation, sampling):
    """ sample one action given observation"""
    if not sampling:
      # pure argmax eval
      am, sm = tf.get_default_session().run([self.action_argmax, self.debug_softmax],
                                             feed_dict={self.observations: [observation]})
      print "EVAL sm ", sm, "argmax", am[0]
      return am[0]

    # epilson greedy "noise" will do for this simple case..
    if (np.random.random() < 0.1):
      return self.env.action_space.sample()

    # sample from logits
    return tf.get_default_session().run(self.sampled_action_op,
                                        feed_dict={self.observations: [observation]})

  def rollout(self, sampling=True):
    """ run one episode collecting observations, actions and advantages"""
    observations, actions, rewards = [], [], []
    observation = self.env.reset()
    done = False
    while not done:
      observations.append(observation)
      action = self.sample_action_given(observation, sampling)
      if action == 5:
        print >>sys.stderr, "FAIL! (multinomial logits sampling bug?)"
        action = 0
      observation, reward, done, _ = self.env.step(action)
      actions.append(action)
      rewards.append(reward)
      if self.gui:
        self.env.render()
    return observations, actions, rewards

  def train(self, observations, actions, advantages):
    """ take one training step given observations, actions and subsequent advantages"""
    _, loss = tf.get_default_session().run([self.train_op, self.loss],
                                           feed_dict={self.observations: observations,
                                                      self.actions: actions,
                                                      self.advantages: advantages})
    return float(loss)

  def run_training(self, num_batches, rollouts_per_batch, saver_util):
    for batch_id in xrange(num_batches):
      self.run_eval(1)

      # perform a number of rollouts
      batch_observations, batch_actions, batch_advantages = [], [], []
      total_rewards = []
      for _ in xrange(rollouts_per_batch):
        observations, actions, rewards = self.rollout()
        batch_observations += observations
        batch_actions += actions
        # train with advantages, not per observation/action rewards.
        # _every_ observation/action in this rollout gets assigned
        # the _total_ reward of the episode. (crazy that this works!)
        batch_advantages += [sum(rewards)] * len(rewards)
        # keep total rewards just for debugging / stats
        total_rewards.append(sum(rewards))

      if min(total_rewards) == max(total_rewards):
        # converged ??
        sys.stderr.write("converged? standardisation of advantaged will barf here....\n")
        loss = 0
      else:
        loss = self.train(batch_observations, batch_actions, batch_advantages)

      # dump some stats
      stats = collections.OrderedDict()
      stats["time"] = int(time.time())
      stats["batch"] = batch_id
      stats["mean_batch"] = np.mean(total_rewards)
      stats["rewards"] = total_rewards
      stats["loss"] = loss
      print "STATS %s\t%s" % (datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                              json.dumps(stats))

      # save if required
      if saver_util is not None:
        saver_util.save_if_required()

  def run_eval(self, num_eval):
    for _ in xrange(num_eval):
      _, _, rewards = self.rollout(sampling=False)
      print sum(rewards)

def main():
  env = bullet_cartpole.BulletCartpole(opts=opts, discrete_actions=True)

  with tf.Session() as sess:
    agent = LikelihoodRatioPolicyGradientAgent(env=env, gui=opts.gui,
                                               hidden_dim=opts.num_hidden,
                                               optimiser=tf.train.AdamOptimizer())

    # setup saver util; will load latest ckpt, or init if none...
    saver_util = None
    if opts.ckpt_dir is not None:
      saver_util = util.SaverUtil(sess, opts.ckpt_dir, opts.ckpt_freq)
    else:
      sess.run(tf.initialize_all_variables())

    # run either eval or training
    if opts.num_eval > 0:
      agent.run_eval(opts.num_eval)
    else:
      agent.run_training(opts.num_train_batches, opts.rollouts_per_batch,
                         saver_util)
      if saver_util is not None:
        saver_util.force_save()

if __name__ == "__main__":
  main()
<|endoftext|>


<commit_before>"""Print a list of jobs."""

from __future__ import print_function, division

import os
import sys
import re
from time import time
from subprocess import check_output
from collections import defaultdict

from utility import color, fractioncolor, findstringpattern
from utility import format_duration, format_mem, format_time
from useraliases import getuseralias

def printjoblong(job, sumjob=False, file=sys.stdout):
    """Print a job in long format."""
    keys = ("jobid", "stat", "user", "user_group", "queue", "job_name",
            "job_description", "interactive", "X11", "proj_name",
            "application", "service_class", "job_group", "job_priority",
            "dependency", "notify_begin", "notify_end", "command",
            "pre_exec_command", "post_exec_command",
            "resize_notification_command", "pids", "exit_code", "exit_reason",
            "exclusive", "from_host", "first_host", "exec_host", "nexec_host",
            "alloc_slot", "nalloc_slot", "host_file", "host_req",
            "submit_time", "start_time", "estimated_start_time",
            "specified_start_time", "specified_terminate_time", "runlimit",
            "time_left", "finish_time", "%complete", "warning_action",
            "action_warning_time", "pend_time", "pend_reason", "cpu_used",
            "run_time", "idle_factor", "exception_status", "slots", "mem",
            "max_mem", "avg_mem", "memlimit", "swap", "swaplimit",
            "min_req_proc", "max_req_proc", "resreq", "effective_resreq",
            "network_req", "filelimit", "corelimit", "stacklimit",
            "processlimit", "input_file", "output_file", "error_file",
            "output_dir", "sub_cwd", "exec_home", "exec_cwd",
            "forward_cluster", "forward_time")
    for key in keys:
        if not job[key]:
            continue
        if sumjob and isinstance(job[key], dict):
            if len(job[key]) == 1 and job[key].keys()[0] is None:
                continue
        print(key.ljust(20), file=file, end="")
        if key in ("swap", "mem", "avg_mem", "max_mem", "memlimit",
                   "swaplimit", "corelimit", "stacklimit"):
            print(format_mem(job[key]), file=file)
        elif key in ("submit_time", "start_time", "finish_time"):
            print(format_time(job[key]), file=file)
        elif key in ("cpu_used", "time_left", "runlimit", "run_time",
                     "pend_time"):
            print(format_duration(job[key]), file=file)
        elif key == "pend_reason":
            items = job[key]
            key2, val = items[0]
            print("%4d * %s" % (val, key2), file=file)
            for key2, val in items[1:]:
                print(20 * " " + "%4d * %s" % (val, key2), file=file)
        elif key in ("command", "pre_exec_command", "post_exec_command",
                     "resize_notification_command"):
            script = job[key]
            for _ in xrange(3):
                script = script.replace("; ", ";;")
            script = script.replace(";;;; ", "; ")
            script = script.replace(";", "\n")
            script = re.sub("for \(\((.*?)\n\n(.*?)\n\n(.*?)\)\)",
                            "for ((\\1; \\2; \\3))", script)
            script = script.splitlines()
            print(script[0], file=file)
            for line in script[1:]:
                print(20 * " " + line, file=file)
        elif key == "pids":
            print(" ".join(map(str, job[key])), file=file)
        else:
            if isinstance(job[key], dict):
                if len(job[key]) == 1:
                    print(job[key].keys()[0], file=file)
                else:
                    items = sorted(job[key].items())
                    print("%4d * %s" % items[0][::-1], file=file)
                    for key2, val in items[1:]:
                        print(20 * " " + "%4d * %s" % (val, key2), file=file)
            elif isinstance(job[key], list):
                print(" ".join(job[key]), file=file)
            else:
                print(job[key], file=file)

def printjobs(jobs, wide=False, long=False, output=None, title=None,
              header=True, file=sys.stdout):
    """Print a list of jobs."""
    if len(jobs) == 0:
        return
    sumjob = not isinstance(jobs[0]["jobid"], str)
    if long:
        for job in jobs:
            printjoblong(job, sumjob=sumjob, file=file)
        return
    if output:
        # header
        print(*output, sep="\t", file=file)
        for job in jobs:
            print(*[job[field] for field in output], sep="\t", file=file)
        return
    # begin output
    whoami = os.getenv("USER")
    namelen = max(map(len, (job["job_name"] for job in jobs)))
    if sumjob:
        titlelen = 0
        if "title" in jobs[0]:
            titlelen = max(map(len, (job["title"] for job in jobs)))
    lens = {
        "title": 10,
        "jobid": 10,
        "name": min(20, max(6, namelen + 1)),
        "stat": 6,
        "user": 10,
        "time": 12,
        "model": 14
    }
    if sumjob:
        lens["stat"] = 12
    else:
        if any(job["jobid"][-1] == "]" for job in jobs):
            lens["jobid"] = 14
    if wide:
        if sumjob:
            lens["title"] = max(6, titlelen + 1)
        lens["name"] = max(6, namelen + 1)
        lens["queue"] = 8
        lens["project"] = 8
        lens["prio."] = 6
    # header
    if header:
        h = ""
        if sumjob and "title" in jobs[0]:
            h += "group".ljust(lens["title"])
        if not sumjob:
            h += "jobid".ljust(lens["jobid"])
        h += "".join(n.ljust(lens[n]) for n in ("name", "stat", "user"))
        if wide:
            h += "".join(n.ljust(lens[n]) for n in ("queue", "project"))
            if not sumjob:
                h += "prio.".ljust(lens["prio."])
        if sumjob:
            h += "runtime".rjust(lens["time"])
        else:
            h += "wait/runtime".rjust(lens["time"])
        h += "  resources"
        h = h.upper()
        if title:
            h += "  " + color(title, "b")
        print(h, file=file)
    for job in jobs:
        l = ""
        if sumjob and "title" in job:
            # title
            title = job["title"]
            if not wide:
                if len(title) >= lens["title"]:
                    title = title[:lens["title"] - 2] + "*"
            l += color(title.ljust(lens["title"]), "b")
        if not sumjob:
            # jobid
            l += (job["jobid"] + " ").ljust(lens["jobid"])
        # job name
        jobname = job["job_name"] if job["job_name"] else ""
        if not wide:
            if len(jobname) >= lens["name"]:
                jobname = "*" + jobname[-lens["name"] + 2:]
        l += jobname.ljust(lens["name"])
        # status
        if sumjob and isinstance(job["stat"], defaultdict):
            l += color("%3d " % job["stat"]["PEND"], "r")
            l += color("%3d " % job["stat"]["RUN"], "g")
            done = job["stat"]["EXIT"] + job["stat"]["DONE"]
            if done:
                l += color("%3d " % done, "y")
            else:
                l += "    "
        else:
            stat = job["stat"]
            if stat == "PEND":
                c = "r"
                if len(job["pend_reason"]) == 1:
                    pr = job["pend_reason"][0]
                    if "New job is waiting for scheduling" in pr[0]:
                        stat = "NEW"
                        c = "b"
                    if "Waiting for rescheduling after parameters" in pr[0]:
                        stat = "MOD"
                        c = "b"
                    if "Job dependency condition not satisfied" in pr[0]:
                        stat = "DEP"
                        c = "b"
            elif stat == "RUN":
                c = "g"
                if job["interactive"]:
                    stat = "INT"
                    if job["X11"]:
                        stat = "X11"
            else:
                c = "y"
            l += color(stat.ljust(lens["stat"]), c)
        # user
        if sumjob and isinstance(job["user"], defaultdict):
            l += color(str(len(job["user"])).ljust(lens["user"]), "b")
        else:
            c = "g" if job["user"] == whoami else 0
            username = getuseralias(job["user"])
            l += color((username + " ").ljust(lens["user"]), c)
        if wide:
            # queue
            if sumjob and isinstance(job["queue"], defaultdict):
                l += color(str(len(job["queue"])).ljust(lens["queue"]), "b")
            else:
                l += job["queue"].ljust(lens["queue"])
            # project
            if sumjob and isinstance(job["project"], defaultdict):
                l += color(str(len(job["project"])).ljust(lens["project"]),
                           "b")
            else:
                l += job["project"].ljust(lens["project"])
            if not sumjob:
                # priority
                l += str(job["priority"]).rjust(lens["prio."] - 1) + " "
        # wait/runtime
        t = job["run_time"]
        if not sumjob and job["stat"] == "PEND":
                t = time() - job["submit_time"]
        s = format_duration(t)
        l += s.rjust(lens["time"])
        # resources
        # %t
        if job["%complete"]:
            ptime = job["%complete"]
            c = fractioncolor(1 - ptime / 100)
            if wide:
                s = "%6.2f" % round(ptime, 2)
            else:
                s = "%3d" % int(round(ptime))
            l += " " + color(s, c) + "%t"
        elif not sumjob and job["stat"] == "RUN":
            l += "      "
            if wide:
                l += "   "
        # %m
        if job["memlimit"] and job["mem"] and job["slots"]:
            memlimit = job["memlimit"] * job["slots"]
            pmem = 100 * job["mem"] / memlimit
            c = fractioncolor(1 - pmem / 100)
            if wide:
                s = "%6.2f" % round(pmem, 2)
            else:
                s = "%3d" % int(round(pmem))
            l += " " + color(s, c) + "%m"
        elif not sumjob and job["stat"] == "RUN":
            l += "      "
            if wide:
                l += "   "
        # time
        if job["runlimit"]:
            l += "  " + format_duration(job["runlimit"])
        # memory
        memlimit = None
        if job["memlimit"]:
            memlimit = job["memlimit"]
            if job["min_req_proc"]:
                memlimit *= job["min_req_proc"]
        if memlimit is not None:
            l += format_mem(memlimit).rjust(10)
        else:
            l += "".rjust(10)
        # Hosts
        if job["exec_host"]:
            if wide or len(job["exec_host"]) == 1:
                d = job["exec_host"]
            else:
                d = defaultdict(int)
                for key, val in job["exec_host"].iteritems():
                    d[re.match("(.*?)\d+", key).groups()[0] + "*"] += val
            for key in sorted(d.keys()):
                val = d[key]
                c = "r" if val >= 100 else "y" if val >= 20 else 0
                exclusive = job["exclusive"]
                if sumjob and exclusive not in (True, False):
                    exclusive = False
                times = color("x", "r") if exclusive else "*"
                l += color(" %3d" % val, c) + times + "%s" % key
        else:
            if not sumjob:
                if job["min_req_proc"]:
                    times = color("x", "r") if job["exclusive"] else "*"
                    l += " %3d" % job["min_req_proc"] + times
                elif job["exclusive"]:
                    l += "   1" + color("x", "r")
                else:
                    l += "   1*"
                if job["host_req"]:
                    hosts = job["host_req"]
                    if len(hosts) == 1:
                        hosts = hosts[0]
                    else:
                        if wide:
                            hosts = "(%s)" % ", ".join(hosts)
                        else:
                            hosts = findstringpattern(hosts)
                    l += hosts.ljust(lens["model"])
                elif job["resreq"]:
                    match = re.search("model==(\w+)", job["resreq"])
                    model = ""
                    if match:
                        model += match.groups()[0]
                    if re.search("phi", job["resreq"]):
                        if match:
                            model += "+"
                        model += "Phi"
                    l += model.ljust(lens["model"])
            if job["alloc_slot"]:
                l += color("  rsvd:", "y")
                if wide or len(job["alloc_slot"]) == 1:
                    d = job["alloc_slot"]
                else:
                    d = defaultdict(int)
                    for key, val in job["alloc_slot"].iteritems():
                        d[re.match("(.*?)\d+", key).groups()[0] + "*"] += val
                for key, val in d.iteritems():
                    c = "r" if val >= 100 else "y" if val >= 20 else 0
                    l += color(" %3d" % val, c) + "*%s" % key
            if wide and job["pend_reason"] and len(job["pend_reason"]) == 1:
                reason = job["pend_reason"][0][0]
                if reason != title:
                    l += color("  %s" % reason, "b")
                    if job["dependency"]:
                        l += color(":", "b")
            if job["dependency"]:
                l += color(" %s" % job["dependency"], "b")
        print(l, file=file)
        file.flush()
<commit_msg>show dependencies only if they're pending reasons<commit_after>"""Print a list of jobs."""

from __future__ import print_function, division

import os
import sys
import re
from time import time
from subprocess import check_output
from collections import defaultdict

from utility import color, fractioncolor, findstringpattern
from utility import format_duration, format_mem, format_time
from useraliases import getuseralias

def printjoblong(job, sumjob=False, file=sys.stdout):
    """Print a job in long format."""
    keys = ("jobid", "stat", "user", "user_group", "queue", "job_name",
            "job_description", "interactive", "X11", "proj_name",
            "application", "service_class", "job_group", "job_priority",
            "dependency", "notify_begin", "notify_end", "command",
            "pre_exec_command", "post_exec_command",
            "resize_notification_command", "pids", "exit_code", "exit_reason",
            "exclusive", "from_host", "first_host", "exec_host", "nexec_host",
            "alloc_slot", "nalloc_slot", "host_file", "host_req",
            "submit_time", "start_time", "estimated_start_time",
            "specified_start_time", "specified_terminate_time", "runlimit",
            "time_left", "finish_time", "%complete", "warning_action",
            "action_warning_time", "pend_time", "pend_reason", "cpu_used",
            "run_time", "idle_factor", "exception_status", "slots", "mem",
            "max_mem", "avg_mem", "memlimit", "swap", "swaplimit",
            "min_req_proc", "max_req_proc", "resreq", "effective_resreq",
            "network_req", "filelimit", "corelimit", "stacklimit",
            "processlimit", "input_file", "output_file", "error_file",
            "output_dir", "sub_cwd", "exec_home", "exec_cwd",
            "forward_cluster", "forward_time")
    for key in keys:
        if not job[key]:
            continue
        if sumjob and isinstance(job[key], dict):
            if len(job[key]) == 1 and job[key].keys()[0] is None:
                continue
        print(key.ljust(20), file=file, end="")
        if key in ("swap", "mem", "avg_mem", "max_mem", "memlimit",
                   "swaplimit", "corelimit", "stacklimit"):
            print(format_mem(job[key]), file=file)
        elif key in ("submit_time", "start_time", "finish_time"):
            print(format_time(job[key]), file=file)
        elif key in ("cpu_used", "time_left", "runlimit", "run_time",
                     "pend_time"):
            print(format_duration(job[key]), file=file)
        elif key == "pend_reason":
            items = job[key]
            key2, val = items[0]
            print("%4d * %s" % (val, key2), file=file)
            for key2, val in items[1:]:
                print(20 * " " + "%4d * %s" % (val, key2), file=file)
        elif key in ("command", "pre_exec_command", "post_exec_command",
                     "resize_notification_command"):
            script = job[key]
            for _ in xrange(3):
                script = script.replace("; ", ";;")
            script = script.replace(";;;; ", "; ")
            script = script.replace(";", "\n")
            script = re.sub("for \(\((.*?)\n\n(.*?)\n\n(.*?)\)\)",
                            "for ((\\1; \\2; \\3))", script)
            script = script.splitlines()
            print(script[0], file=file)
            for line in script[1:]:
                print(20 * " " + line, file=file)
        elif key == "pids":
            print(" ".join(map(str, job[key])), file=file)
        else:
            if isinstance(job[key], dict):
                if len(job[key]) == 1:
                    print(job[key].keys()[0], file=file)
                else:
                    items = sorted(job[key].items())
                    print("%4d * %s" % items[0][::-1], file=file)
                    for key2, val in items[1:]:
                        print(20 * " " + "%4d * %s" % (val, key2), file=file)
            elif isinstance(job[key], list):
                print(" ".join(job[key]), file=file)
            else:
                print(job[key], file=file)

def printjobs(jobs, wide=False, long=False, output=None, title=None,
              header=True, file=sys.stdout):
    """Print a list of jobs."""
    if len(jobs) == 0:
        return
    sumjob = not isinstance(jobs[0]["jobid"], str)
    if long:
        for job in jobs:
            printjoblong(job, sumjob=sumjob, file=file)
        return
    if output:
        # header
        print(*output, sep="\t", file=file)
        for job in jobs:
            print(*[job[field] for field in output], sep="\t", file=file)
        return
    # begin output
    whoami = os.getenv("USER")
    namelen = max(map(len, (job["job_name"] for job in jobs)))
    if sumjob:
        titlelen = 0
        if "title" in jobs[0]:
            titlelen = max(map(len, (job["title"] for job in jobs)))
    lens = {
        "title": 10,
        "jobid": 10,
        "name": min(20, max(6, namelen + 1)),
        "stat": 6,
        "user": 10,
        "time": 12,
        "model": 14
    }
    if sumjob:
        lens["stat"] = 12
    else:
        if any(job["jobid"][-1] == "]" for job in jobs):
            lens["jobid"] = 14
    if wide:
        if sumjob:
            lens["title"] = max(6, titlelen + 1)
        lens["name"] = max(6, namelen + 1)
        lens["queue"] = 8
        lens["project"] = 8
        lens["prio."] = 6
    # header
    if header:
        h = ""
        if sumjob and "title" in jobs[0]:
            h += "group".ljust(lens["title"])
        if not sumjob:
            h += "jobid".ljust(lens["jobid"])
        h += "".join(n.ljust(lens[n]) for n in ("name", "stat", "user"))
        if wide:
            h += "".join(n.ljust(lens[n]) for n in ("queue", "project"))
            if not sumjob:
                h += "prio.".ljust(lens["prio."])
        if sumjob:
            h += "runtime".rjust(lens["time"])
        else:
            h += "wait/runtime".rjust(lens["time"])
        h += "  resources"
        h = h.upper()
        if title:
            h += "  " + color(title, "b")
        print(h, file=file)
    for job in jobs:
        l = ""
        if sumjob and "title" in job:
            # title
            title = job["title"]
            if not wide:
                if len(title) >= lens["title"]:
                    title = title[:lens["title"] - 2] + "*"
            l += color(title.ljust(lens["title"]), "b")
        if not sumjob:
            # jobid
            l += (job["jobid"] + " ").ljust(lens["jobid"])
        # job name
        jobname = job["job_name"] if job["job_name"] else ""
        if not wide:
            if len(jobname) >= lens["name"]:
                jobname = "*" + jobname[-lens["name"] + 2:]
        l += jobname.ljust(lens["name"])
        # status
        if sumjob and isinstance(job["stat"], defaultdict):
            l += color("%3d " % job["stat"]["PEND"], "r")
            l += color("%3d " % job["stat"]["RUN"], "g")
            done = job["stat"]["EXIT"] + job["stat"]["DONE"]
            if done:
                l += color("%3d " % done, "y")
            else:
                l += "    "
        else:
            stat = job["stat"]
            if stat == "PEND":
                c = "r"
                if len(job["pend_reason"]) == 1:
                    pr = job["pend_reason"][0]
                    if "New job is waiting for scheduling" in pr[0]:
                        stat = "NEW"
                        c = "b"
                    if "Waiting for rescheduling after parameters" in pr[0]:
                        stat = "MOD"
                        c = "b"
                    if "Job dependency condition not satisfied" in pr[0]:
                        stat = "DEP"
                        c = "b"
            elif stat == "RUN":
                c = "g"
                if job["interactive"]:
                    stat = "INT"
                    if job["X11"]:
                        stat = "X11"
            else:
                c = "y"
            l += color(stat.ljust(lens["stat"]), c)
        # user
        if sumjob and isinstance(job["user"], defaultdict):
            l += color(str(len(job["user"])).ljust(lens["user"]), "b")
        else:
            c = "g" if job["user"] == whoami else 0
            username = getuseralias(job["user"])
            l += color((username + " ").ljust(lens["user"]), c)
        if wide:
            # queue
            if sumjob and isinstance(job["queue"], defaultdict):
                l += color(str(len(job["queue"])).ljust(lens["queue"]), "b")
            else:
                l += job["queue"].ljust(lens["queue"])
            # project
            if sumjob and isinstance(job["project"], defaultdict):
                l += color(str(len(job["project"])).ljust(lens["project"]),
                           "b")
            else:
                l += job["project"].ljust(lens["project"])
            if not sumjob:
                # priority
                l += str(job["priority"]).rjust(lens["prio."] - 1) + " "
        # wait/runtime
        t = job["run_time"]
        if not sumjob and job["stat"] == "PEND":
                t = time() - job["submit_time"]
        s = format_duration(t)
        l += s.rjust(lens["time"])
        # resources
        # %t
        if job["%complete"]:
            ptime = job["%complete"]
            c = fractioncolor(1 - ptime / 100)
            if wide:
                s = "%6.2f" % round(ptime, 2)
            else:
                s = "%3d" % int(round(ptime))
            l += " " + color(s, c) + "%t"
        elif not sumjob and job["stat"] == "RUN":
            l += "      "
            if wide:
                l += "   "
        # %m
        if job["memlimit"] and job["mem"] and job["slots"]:
            memlimit = job["memlimit"] * job["slots"]
            pmem = 100 * job["mem"] / memlimit
            c = fractioncolor(1 - pmem / 100)
            if wide:
                s = "%6.2f" % round(pmem, 2)
            else:
                s = "%3d" % int(round(pmem))
            l += " " + color(s, c) + "%m"
        elif not sumjob and job["stat"] == "RUN":
            l += "      "
            if wide:
                l += "   "
        # time
        if job["runlimit"]:
            l += "  " + format_duration(job["runlimit"])
        # memory
        memlimit = None
        if job["memlimit"]:
            memlimit = job["memlimit"]
            if job["min_req_proc"]:
                memlimit *= job["min_req_proc"]
        if memlimit is not None:
            l += format_mem(memlimit).rjust(10)
        else:
            l += "".rjust(10)
        # Hosts
        if job["exec_host"]:
            if wide or len(job["exec_host"]) == 1:
                d = job["exec_host"]
            else:
                d = defaultdict(int)
                for key, val in job["exec_host"].iteritems():
                    d[re.match("(.*?)\d+", key).groups()[0] + "*"] += val
            for key in sorted(d.keys()):
                val = d[key]
                c = "r" if val >= 100 else "y" if val >= 20 else 0
                exclusive = job["exclusive"]
                if sumjob and exclusive not in (True, False):
                    exclusive = False
                times = color("x", "r") if exclusive else "*"
                l += color(" %3d" % val, c) + times + "%s" % key
        else:
            if not sumjob:
                if job["min_req_proc"]:
                    times = color("x", "r") if job["exclusive"] else "*"
                    l += " %3d" % job["min_req_proc"] + times
                elif job["exclusive"]:
                    l += "   1" + color("x", "r")
                else:
                    l += "   1*"
                if job["host_req"]:
                    hosts = job["host_req"]
                    if len(hosts) == 1:
                        hosts = hosts[0]
                    else:
                        if wide:
                            hosts = "(%s)" % ", ".join(hosts)
                        else:
                            hosts = findstringpattern(hosts)
                    l += hosts.ljust(lens["model"])
                elif job["resreq"]:
                    match = re.search("model==(\w+)", job["resreq"])
                    model = ""
                    if match:
                        model += match.groups()[0]
                    if re.search("phi", job["resreq"]):
                        if match:
                            model += "+"
                        model += "Phi"
                    l += model.ljust(lens["model"])
            if job["alloc_slot"]:
                l += color("  rsvd:", "y")
                if wide or len(job["alloc_slot"]) == 1:
                    d = job["alloc_slot"]
                else:
                    d = defaultdict(int)
                    for key, val in job["alloc_slot"].iteritems():
                        d[re.match("(.*?)\d+", key).groups()[0] + "*"] += val
                for key, val in d.iteritems():
                    c = "r" if val >= 100 else "y" if val >= 20 else 0
                    l += color(" %3d" % val, c) + "*%s" % key
            if wide and job["pend_reason"] and len(job["pend_reason"]) == 1:
                reason = job["pend_reason"][0][0]
                if reason != title:
                    l += color("  %s" % reason, "b")
                    if job["dependency"]:
                        l += color(":", "b")
                if job["dependency"]:
                    l += color(" %s" % job["dependency"], "b")
        print(l, file=file)
        file.flush()
<|endoftext|>


<commit_before>#!/usr/bin/env python

"""
PURPOSE:

To scrape all the bf data for all US cities with more than 100k people.

Created on 2015-09-22T21:29:50
"""

from __future__ import division, print_function
import sys
import datetime
import argparse
import pandas as pd
import splinter_scrape_bf as ssbf

__author__ = "Matt Giguere (github: @mattgiguere)"
__license__ = "MIT"
__version__ = '0.0.1'
__maintainer__ = "Matt Giguere"
__email__ = "matthew.giguere@yale.edu"
__status__ = " Development NOT(Prototype or Production)"

def drive_bf_us_cities(num_cities=5, run_scraper=True, starting_city=''):
    """PURPOSE:
    To read in the US cities and add the bf results
    to the DB.
    """
    if num_cities is not 'all':
        num_cities = int(num_cities)

    csf = pd.read_csv('../data/us_cities_over_100k.txt',
                      names=['city', 'state'], delimiter=' ')

    if starting_city is not '':
        num_cities += csf[csf['city'] == starting_city[:-3]].index.values[0]

    if num_cities != 'all':
        cs = csf.head(int(num_cities))
    else:
        cs = csf

    # set pass_starting_city to False if it is not the default empty string:
    if starting_city is not '':
        pass_starting_city = False
    else:
        pass_starting_city = True

    for row_index, row in cs.iterrows():
        print('{}, {}'.format(row['city'], row['state']))
        print(datetime.datetime.now())
        if starting_city is not '' and row['city']+'_'+row['state'] == starting_city:
            pass_starting_city = True

        if pass_starting_city:
            print('Thundercats GO!!!')

        if run_scraper and pass_starting_city:
            ssbf.splinter_scrape_bf(row['city'], row['state'])

if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        description='argparse object.')
    parser.add_argument(
        '-n', '--num_cities',
        help='The number of cities to add to the db. ' +
             'The default is the five most populous cities.',
             nargs='?', default=5)
    parser.add_argument(
        '-r', '--run_scraper',
        help='If run_scraper is set, this code runs splinter_scrape_bf. ' +
             'Otherwise, it simply prints out the city and state.',
             action='store_true', default=False)
    parser.add_argument(
        '-s', '--starting_city',
        help='Specify a city to start on. Otherwise, drive_bf_us_cities will ' +
        'start with the first one in the list (new york). The format should ' +
        'be city_state (e.g. san_francisco_ca', default='')
    if len(sys.argv) > 7:
        print('use the command')
        print('python drive_bf_us_cities.py --num_cities all --run_scraper')
        sys.exit(2)

    args = parser.parse_args()

    drive_bf_us_cities(num_cities=args.num_cities,
                       run_scraper=args.run_scraper,
                       starting_city=args.starting_city)
<commit_msg>print end time at end of doc<commit_after>#!/usr/bin/env python

"""
PURPOSE:

To scrape all the bf data for all US cities with more than 100k people.

Created on 2015-09-22T21:29:50
"""

from __future__ import division, print_function
import sys
import datetime
import argparse
import pandas as pd
import splinter_scrape_bf as ssbf

__author__ = "Matt Giguere (github: @mattgiguere)"
__license__ = "MIT"
__version__ = '0.0.1'
__maintainer__ = "Matt Giguere"
__email__ = "matthew.giguere@yale.edu"
__status__ = " Development NOT(Prototype or Production)"

def drive_bf_us_cities(num_cities=5, run_scraper=True, starting_city=''):
    """PURPOSE:
    To read in the US cities and add the bf results
    to the DB.
    """
    if num_cities is not 'all':
        num_cities = int(num_cities)

    csf = pd.read_csv('../data/us_cities_over_100k.txt',
                      names=['city', 'state'], delimiter=' ')

    if starting_city is not '':
        num_cities += csf[csf['city'] == starting_city[:-3]].index.values[0]

    if num_cities != 'all':
        cs = csf.head(int(num_cities))
    else:
        cs = csf

    # set pass_starting_city to False if it is not the default empty string:
    if starting_city is not '':
        pass_starting_city = False
    else:
        pass_starting_city = True

    for row_index, row in cs.iterrows():
        print('{}, {}'.format(row['city'], row['state']))
        print(datetime.datetime.now())
        if starting_city is not '' and row['city']+'_'+row['state'] == starting_city:
            pass_starting_city = True

        if pass_starting_city:
            print('Thundercats GO!!!')

        if run_scraper and pass_starting_city:
            ssbf.splinter_scrape_bf(row['city'], row['state'])
    print(datetime.datetime.now())

if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        description='argparse object.')
    parser.add_argument(
        '-n', '--num_cities',
        help='The number of cities to add to the db. ' +
             'The default is the five most populous cities.',
             nargs='?', default=5)
    parser.add_argument(
        '-r', '--run_scraper',
        help='If run_scraper is set, this code runs splinter_scrape_bf. ' +
             'Otherwise, it simply prints out the city and state.',
             action='store_true', default=False)
    parser.add_argument(
        '-s', '--starting_city',
        help='Specify a city to start on. Otherwise, drive_bf_us_cities will ' +
        'start with the first one in the list (new york). The format should ' +
        'be city_state (e.g. san_francisco_ca', default='')
    if len(sys.argv) > 7:
        print('use the command')
        print('python drive_bf_us_cities.py --num_cities all --run_scraper')
        sys.exit(2)

    args = parser.parse_args()

    drive_bf_us_cities(num_cities=args.num_cities,
                       run_scraper=args.run_scraper,
                       starting_city=args.starting_city)
<|endoftext|>


<commit_before>import json
import os
from datetime import datetime

def start(params):
    """Capture exp start """
    exp_start = datetime.now()
    experiment_id = params['experiment_id']

    search_space = []
    for key, val in params.items():
        search_space.append("{}: {}".format(key, val))

    msg = [{
        'experiment_id': experiment_id,
        'start_time': str(exp_start),
        'search_space': search_space
    }]
    save("experiment_start.json", msg)

def end(experiment_id):
    """Capture exp end """
    exp_end = datetime.now()
    msg = {
        'experiment_id': experiment_id,
        'status': {'set': 'Finished'},
        'end_time': {'set': str(exp_end)}
    }
    save("experiment_end.json", msg)

def save(filename, msg):
    """Save log message"""
    path = os.getenv('TURBINE_OUTPUT')
    with open(path + "/" + filename, "w") as file_json:
        file_json.write(json.dumps(
            msg, indent=4, separators=(',', ': ')))
<commit_msg>fix format<commit_after>import json
import os
from datetime import datetime

def start(params):
    """Capture exp start """
    exp_start = datetime.now()
    experiment_id = params['experiment_id']

    search_space = []
    for key, val in params.items():
        search_space.append("{}: {}".format(key, val))

    msg = [{
        'experiment_id': experiment_id,
        'start_time': str(exp_start),
        'search_space': search_space
    }]
    save("experiment_start.json", msg)

def end(experiment_id):
    """Capture exp end """
    exp_end = datetime.now()
    msg = [{
        'experiment_id': experiment_id,
        'status': {'set': 'Finished'},
        'end_time': {'set': str(exp_end)}
    }]
    save("experiment_end.json", msg)

def save(filename, msg):
    """Save log message"""
    path = os.getenv('TURBINE_OUTPUT')
    with open(path + "/" + filename, "w") as file_json:
        file_json.write(json.dumps(
            msg, indent=4, separators=(',', ': ')))
<|endoftext|>


<commit_before>from collections import OrderedDict
import logging

from django.core.paginator import EmptyPage
from django.http import Http404
from django.utils.translation import get_language
from rest_framework.generics import GenericAPIView, get_object_or_404
from rest_framework.response import Response
from rest_framework.reverse import reverse
from rest_framework.utils.urls import remove_query_param, replace_query_param

from api.views import LogUserMixin, PermissionMixin
from configuration.configured_questionnaire import ConfiguredQuestionnaire
from questionnaire.views import ESQuestionnaireQueryMixin
from search.search import get_element
from ..conf import settings
from ..models import Questionnaire
from ..utils import get_list_values, get_questionnaire_data_in_single_language

logger = logging.getLogger(__name__)

class QuestionnaireAPIMixin(PermissionMixin, LogUserMixin, GenericAPIView):
    """
    Shared functionality for list and detail view.
    """
    add_detail_url = False

    def update_dict_keys(self, es_hits: list):
        """
        Some keys need to be updated (e.g. description has a different key
        depending on the config) for a more consistent behavior of the APIs
        data.
        This cannot be done when indexing (elasticsearch) the data, as the
        templates expect the variable names in the 'original' format.
        After discussion with the people consuming the api, the language of
        the content is used as key, i.e.: 'unccd_description': 'a title' becomes
        'definition: {'en': 'a title'}
        """
        for es_hit in es_hits:
            yield self.replace_keys(es_hit)

    def language_text_mapping(self, **item) -> list:
        """
        The consumers of the API require the text values in the format:
        {
            'language': 'en',
            'text': 'my text'
        }
        """
        return [{'language': key, 'text': value} for key, value in item.items()]

    def replace_keys(self, es_hit: dict) -> dict:
        """
        Replace all keys as defined by the configuration. Also, list all
        translated versions. This was requested by the consumers of the API.
        To access description and name in all versions, the config must be
        loaded again.
        """
        try:
            list_values = get_list_values(es_hits=[es_hit])[0]
        except IndexError:
            # We want to know about these errors.
            raise Exception('Possibly invalid data in ES (unable to serialize)'
                            ': %s' % es_hit)

        # 'name' and 'definition' must include all translations.
        list_values['name'] = es_hit['_source']['list_data']['name']
        list_values['definition'] = es_hit['_source']['list_data']['definition']

        # Restore state of configuration for v1.
        list_values['configurations'] = [list_values['configuration']]
        list_values['native_configuration'] = True

        # Remove keys that are not available on v1.
        delete_keys = ['serializer_config', 'serializer_edition', 'has_new_configuration_edition']
        for key in delete_keys:
            del list_values[key]

        # Add 'full' data, even for the list view.
        list_values['data'] = self.get_object_data(code=list_values['code'])

        if self.add_detail_url:
            list_values['api_url'] = reverse(
                '{api_version}:questionnaires-api-detail'.format(
                    api_version=self.request.version
                ),
                kwargs={'identifier': list_values['code']}
            )

        return list_values

    def get_object_data(self, code: str) -> dict:
        obj = self.object if hasattr(self, 'object') else self.get_current_object(code=code)
        return obj.data

    def filter_dict(self, items: dict):
        """
        Starting with API v2 only name and url to the detail page are displayed.
        """
        for item in items:
            yield {
                'name': item.get('name'),
                'created': item.get('created'),
                'updated': item.get('updated'),
                'compiler': item.get('compilers')[0]['name'],
                'reviewer': [reviewers['name'] for reviewers in item.get('reviewers')],
                'code': item.get('code'),
                'edition': item.get('serializer_edition'),
                'url': reverse(
                    viewname='{configuration}:questionnaire_details'.format(
                        configuration=item['configuration']
                    ),
                    kwargs={'identifier': item['code']}),
                'translations': item.get('translations'),
                'details': reverse(
                    '{api_version}:questionnaires-api-detail'.format(
                        api_version=self.request.version
                    ), kwargs={'identifier': item['code']}
                ),
            }

    def get_current_object(self, code='') -> Questionnaire:
        """
        Check if the model entry is still valid.

        Returns: object (Questionnaire instance)
        """
        return get_object_or_404(
            Questionnaire.with_status.public(), code=self.kwargs.get('identifier', code)
        )

class QuestionnaireListView(QuestionnaireAPIMixin, ESQuestionnaireQueryMixin):
    """
    Get a list of Questionnaires, for v1 and v2

    Return a list of Questionnaires. The same filter parameters as for the list
    view (search/filter in QCAT) can be passed.

    ``page``: Optional page offset.
    """
    page_size = settings.API_PAGE_SIZE
    add_detail_url = True
    configuration_code = 'wocat'

    def get(self, request, *args, **kwargs) -> Response:
        self.set_attributes()
        items = self.get_elasticsearch_items()
        return self.get_paginated_response(items)

    def get_elasticsearch_items(self):
        """
        Don't touch the database, but fetch everything from elasticsearch.

        Returns:
            list of questionnaires
        """
        es_results = self.get_es_results(call_from='api')

        es_pagination = self.get_es_paginated_results(es_results)
        questionnaires, self.pagination = self.get_es_pagination(es_pagination)

        # Combine configuration and questionnaire values.
        if self.request.version == 'v1':
            return self.update_dict_keys(es_hits=questionnaires)
        else:
            return self.filter_dict(
                get_list_values(es_hits=questionnaires)
            )

    def get_paginated_response(self, data) -> Response:
        """
        Build a response as if it were from the django rest framework. This
        will be replaced after the refactor.

        Args:
            data: dict The data which is returned

        Returns:
            Response

        """
        return Response(OrderedDict([
            ('count', self.pagination.count),
            ('next', self.get_next_link()),
            ('previous', self.get_previous_link()),
            ('results', list(data))
        ]))

    def _get_paginate_link(self, page_number) -> str:
        """
        Args:
            page_number: int

        Returns:
            string: URL of the requested page

        """
        try:
            self.pagination.validate_number(page_number)
        except EmptyPage:
            return ''

        url = self.request.build_absolute_uri()
        if page_number == 1:
            return remove_query_param(url, 'page')
        return replace_query_param(url, 'page', page_number)

    def get_next_link(self) -> str:
        return self._get_paginate_link(self.current_page + 1)

    def get_previous_link(self)  -> str:
        return self._get_paginate_link(self.current_page - 1)

class QuestionnaireDetailView(QuestionnaireAPIMixin):
    """
    Return a single item from elasticsearch, if object is still valid on the
    model.

    Used for API v1 only
    """
    add_detail_url = False

    def get(self, request, *args, **kwargs):
        """
        Set the current object to 'self', so the query is not executed again
        in the method 'replace_keys'.
        """
        self.object = self.get_current_object()
        # Get the single element from ES.
        es_hit = get_element(questionnaire=self.object)
        if not es_hit:
            raise Http404

        return Response(self.replace_keys(es_hit={'_source': es_hit}))

class ConfiguredQuestionnaireDetailView(QuestionnaireDetailView):
    """
    Get a single Questionnaire for API v2.

    Return a single Questionnaire by its code. The returned data contains the
    full configuration (including labels of sections, questiongroups etc.).

    ``identifier``: The identifier / code of the questionnaire.
    """

    def prepare_data(self) -> dict:
        """
        Merge configuration keyword, label and questionnaire data to a dict.
        """
        data = get_questionnaire_data_in_single_language(
            questionnaire_data=self.object.data,
            locale=get_language(),
            original_locale=self.object.original_locale
        )
        # Links are removed from the 'data' dict, but available on the
        # serialized element.
        data['links'] = self.prepare_link_data(
            *self.object.links_property
        )
        return data

    @staticmethod
    def prepare_link_data(*links):
        """
        Get data in current language; see: Questionnaire.links_property
        """
        translate_fields = ['name', 'url']
        for link in links:
            for field in translate_fields:
                link[field] = link[field].get(get_language(), link[field]['default'])
        return links

    def get_configured_questionnaire(self, **data):
        return ConfiguredQuestionnaire(
            config=self.object.configuration_object,
            questionnaire=self.object,
            **data
        ).store

    def get(self, request, *args, **kwargs):
        self.object = self.get_current_object()
        prepared_data = self.prepare_data()
        return Response(self.get_configured_questionnaire(**prepared_data))
<commit_msg>Revert "Merge branch 'baggids-add-attributes-questionnaire-api-call' into develop"<commit_after>from collections import OrderedDict
import logging

from django.core.paginator import EmptyPage
from django.http import Http404
from django.utils.translation import get_language
from rest_framework.generics import GenericAPIView, get_object_or_404
from rest_framework.response import Response
from rest_framework.reverse import reverse
from rest_framework.utils.urls import remove_query_param, replace_query_param

from api.views import LogUserMixin, PermissionMixin
from configuration.configured_questionnaire import ConfiguredQuestionnaire
from questionnaire.views import ESQuestionnaireQueryMixin
from search.search import get_element
from ..conf import settings
from ..models import Questionnaire
from ..utils import get_list_values, get_questionnaire_data_in_single_language

logger = logging.getLogger(__name__)

class QuestionnaireAPIMixin(PermissionMixin, LogUserMixin, GenericAPIView):
    """
    Shared functionality for list and detail view.
    """
    add_detail_url = False

    def update_dict_keys(self, es_hits: list):
        """
        Some keys need to be updated (e.g. description has a different key
        depending on the config) for a more consistent behavior of the APIs
        data.
        This cannot be done when indexing (elasticsearch) the data, as the
        templates expect the variable names in the 'original' format.
        After discussion with the people consuming the api, the language of
        the content is used as key, i.e.: 'unccd_description': 'a title' becomes
        'definition: {'en': 'a title'}
        """
        for es_hit in es_hits:
            yield self.replace_keys(es_hit)

    def language_text_mapping(self, **item) -> list:
        """
        The consumers of the API require the text values in the format:
        {
            'language': 'en',
            'text': 'my text'
        }
        """
        return [{'language': key, 'text': value} for key, value in item.items()]

    def replace_keys(self, es_hit: dict) -> dict:
        """
        Replace all keys as defined by the configuration. Also, list all
        translated versions. This was requested by the consumers of the API.
        To access description and name in all versions, the config must be
        loaded again.
        """
        try:
            list_values = get_list_values(es_hits=[es_hit])[0]
        except IndexError:
            # We want to know about these errors.
            raise Exception('Possibly invalid data in ES (unable to serialize)'
                            ': %s' % es_hit)

        # 'name' and 'definition' must include all translations.
        list_values['name'] = es_hit['_source']['list_data']['name']
        list_values['definition'] = es_hit['_source']['list_data']['definition']

        # Restore state of configuration for v1.
        list_values['configurations'] = [list_values['configuration']]
        list_values['native_configuration'] = True

        # Remove keys that are not available on v1.
        delete_keys = ['serializer_config', 'serializer_edition', 'has_new_configuration_edition']
        for key in delete_keys:
            del list_values[key]

        # Add 'full' data, even for the list view.
        list_values['data'] = self.get_object_data(code=list_values['code'])

        if self.add_detail_url:
            list_values['api_url'] = reverse(
                '{api_version}:questionnaires-api-detail'.format(
                    api_version=self.request.version
                ),
                kwargs={'identifier': list_values['code']}
            )

        return list_values

    def get_object_data(self, code: str) -> dict:
        obj = self.object if hasattr(self, 'object') else self.get_current_object(code=code)
        return obj.data

    def filter_dict(self, items: dict):
        """
        Starting with API v2 only name and url to the detail page are displayed.
        """
        for item in items:
            yield {
                'name': item.get('name'),
                'updated': item.get('updated'),
                'code': item.get('code'),
                'edition': item.get('serializer_edition'),
                'url': reverse(
                    viewname='{configuration}:questionnaire_details'.format(
                        configuration=item['configuration']
                    ),
                    kwargs={'identifier': item['code']}),
                'translations': item.get('translations'),
                'details': reverse(
                    '{api_version}:questionnaires-api-detail'.format(
                        api_version=self.request.version
                    ), kwargs={'identifier': item['code']}
                ),
            }

    def get_current_object(self, code='') -> Questionnaire:
        """
        Check if the model entry is still valid.

        Returns: object (Questionnaire instance)
        """
        return get_object_or_404(
            Questionnaire.with_status.public(), code=self.kwargs.get('identifier', code)
        )

class QuestionnaireListView(QuestionnaireAPIMixin, ESQuestionnaireQueryMixin):
    """
    Get a list of Questionnaires, for v1 and v2

    Return a list of Questionnaires. The same filter parameters as for the list
    view (search/filter in QCAT) can be passed.

    ``page``: Optional page offset.
    """
    page_size = settings.API_PAGE_SIZE
    add_detail_url = True
    configuration_code = 'wocat'

    def get(self, request, *args, **kwargs) -> Response:
        self.set_attributes()
        items = self.get_elasticsearch_items()
        return self.get_paginated_response(items)

    def get_elasticsearch_items(self):
        """
        Don't touch the database, but fetch everything from elasticsearch.

        Returns:
            list of questionnaires
        """
        es_results = self.get_es_results(call_from='api')

        es_pagination = self.get_es_paginated_results(es_results)
        questionnaires, self.pagination = self.get_es_pagination(es_pagination)

        # Combine configuration and questionnaire values.
        if self.request.version == 'v1':
            return self.update_dict_keys(es_hits=questionnaires)
        else:
            return self.filter_dict(
                get_list_values(es_hits=questionnaires)
            )

    def get_paginated_response(self, data) -> Response:
        """
        Build a response as if it were from the django rest framework. This
        will be replaced after the refactor.

        Args:
            data: dict The data which is returned

        Returns:
            Response

        """
        return Response(OrderedDict([
            ('count', self.pagination.count),
            ('next', self.get_next_link()),
            ('previous', self.get_previous_link()),
            ('results', list(data))
        ]))

    def _get_paginate_link(self, page_number) -> str:
        """
        Args:
            page_number: int

        Returns:
            string: URL of the requested page

        """
        try:
            self.pagination.validate_number(page_number)
        except EmptyPage:
            return ''

        url = self.request.build_absolute_uri()
        if page_number == 1:
            return remove_query_param(url, 'page')
        return replace_query_param(url, 'page', page_number)

    def get_next_link(self) -> str:
        return self._get_paginate_link(self.current_page + 1)

    def get_previous_link(self)  -> str:
        return self._get_paginate_link(self.current_page - 1)

class QuestionnaireDetailView(QuestionnaireAPIMixin):
    """
    Return a single item from elasticsearch, if object is still valid on the
    model.

    Used for API v1 only
    """
    add_detail_url = False

    def get(self, request, *args, **kwargs):
        """
        Set the current object to 'self', so the query is not executed again
        in the method 'replace_keys'.
        """
        self.object = self.get_current_object()
        # Get the single element from ES.
        es_hit = get_element(questionnaire=self.object)
        if not es_hit:
            raise Http404

        return Response(self.replace_keys(es_hit={'_source': es_hit}))

class ConfiguredQuestionnaireDetailView(QuestionnaireDetailView):
    """
    Get a single Questionnaire for API v2.

    Return a single Questionnaire by its code. The returned data contains the
    full configuration (including labels of sections, questiongroups etc.).

    ``identifier``: The identifier / code of the questionnaire.
    """

    def prepare_data(self) -> dict:
        """
        Merge configuration keyword, label and questionnaire data to a dict.
        """
        data = get_questionnaire_data_in_single_language(
            questionnaire_data=self.object.data,
            locale=get_language(),
            original_locale=self.object.original_locale
        )
        # Links are removed from the 'data' dict, but available on the
        # serialized element.
        data['links'] = self.prepare_link_data(
            *self.object.links_property
        )
        return data

    @staticmethod
    def prepare_link_data(*links):
        """
        Get data in current language; see: Questionnaire.links_property
        """
        translate_fields = ['name', 'url']
        for link in links:
            for field in translate_fields:
                link[field] = link[field].get(get_language(), link[field]['default'])
        return links

    def get_configured_questionnaire(self, **data):
        return ConfiguredQuestionnaire(
            config=self.object.configuration_object,
            questionnaire=self.object,
            **data
        ).store

    def get(self, request, *args, **kwargs):
        self.object = self.get_current_object()
        prepared_data = self.prepare_data()
        return Response(self.get_configured_questionnaire(**prepared_data))
<|endoftext|>


<commit_before><commit_msg>actually fix loop toggling<commit_after><|endoftext|>


<commit_before># This file is autogenerated from /cellzome/pyRserve/pyRserve/test_rparser.pyc
# It contains the translation of r expressions into their
# (network-) serialized representation.

binaryRExpressions = {
    '"abc"': '\x01\x00\x01\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x08\x00\x00\x22\x04\x00\x00\x61\x62\x63\x00',
    '1': '\x01\x00\x01\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x0c\x00\x00\x21\x08\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x3f',
    'as.integer(c(1))': '\x01\x00\x01\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x08\x00\x00\x20\x04\x00\x00\x01\x00\x00\x00',
    'c(1, 2)': '\x01\x00\x01\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x14\x00\x00\x21\x10\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x3f\x00\x00\x00\x00\x00\x00\x00\x40',
    'as.integer(c(1, 2))': '\x01\x00\x01\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x0c\x00\x00\x20\x08\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00',
    'c("abc", "defghi")': '\x01\x00\x01\x00\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x10\x00\x00\x22\x0c\x00\x00\x61\x62\x63\x00\x64\x65\x66\x67\x68\x69\x00\x01',
    'seq(1, 5)': '\x01\x00\x01\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x18\x00\x00\x20\x14\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00',
    'list("otto", "gustav")': '\x01\x00\x01\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x1c\x00\x00\x10\x18\x00\x00\x22\x08\x00\x00\x6f\x74\x74\x6f\x00\x01\x01\x01\x22\x08\x00\x00\x67\x75\x73\x74\x61\x76\x00\x01',
    'list(husband="otto", wife="erna")': '\x01\x00\x01\x00\x44\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x40\x00\x00\x90\x3c\x00\x00\x15\x20\x00\x00\x22\x10\x00\x00\x68\x75\x73\x62\x61\x6e\x64\x00\x77\x69\x66\x65\x00\x01\x01\x01\x13\x08\x00\x00\x6e\x61\x6d\x65\x73\x00\x00\x00\x22\x08\x00\x00\x6f\x74\x74\x6f\x00\x01\x01\x01\x22\x08\x00\x00\x65\x72\x6e\x61\x00\x01\x01\x01',
    'list(n="Fred", no_c=2, c_ages=c(4,7))': '\x01\x00\x01\x00\x58\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x54\x00\x00\x90\x50\x00\x00\x15\x20\x00\x00\x22\x10\x00\x00\x6e\x00\x6e\x6f\x5f\x63\x00\x63\x5f\x61\x67\x65\x73\x00\x01\x01\x13\x08\x00\x00\x6e\x61\x6d\x65\x73\x00\x00\x00\x22\x08\x00\x00\x46\x72\x65\x64\x00\x01\x01\x01\x21\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x21\x10\x00\x00\x00\x00\x00\x00\x00\x00\x10\x40\x00\x00\x00\x00\x00\x00\x1c\x40',
    }
<commit_msg>new unittests<commit_after># This file is autogenerated from /home/heinkel/Cellzome/pyRserve/pyRserve/test_rparser.pyc
# It contains the translation of r expressions into their
# (network-) serialized representation.

binaryRExpressions = {
    '"abc"': '\x01\x00\x01\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x08\x00\x00\x22\x04\x00\x00\x61\x62\x63\x00',
    '1': '\x01\x00\x01\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x0c\x00\x00\x21\x08\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x3f',
    'as.integer(c(1))': '\x01\x00\x01\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x08\x00\x00\x20\x04\x00\x00\x01\x00\x00\x00',
    'c(1, 2)': '\x01\x00\x01\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x14\x00\x00\x21\x10\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x3f\x00\x00\x00\x00\x00\x00\x00\x40',
    'as.integer(c(1, 2))': '\x01\x00\x01\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x0c\x00\x00\x20\x08\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00',
    'c("abc", "defghi")': '\x01\x00\x01\x00\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x10\x00\x00\x22\x0c\x00\x00\x61\x62\x63\x00\x64\x65\x66\x67\x68\x69\x00\x01',
    'seq(1, 5)': '\x01\x00\x01\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x18\x00\x00\x20\x14\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00',
    'list("otto", "gustav")': '\x01\x00\x01\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x1c\x00\x00\x10\x18\x00\x00\x22\x08\x00\x00\x6f\x74\x74\x6f\x00\x01\x01\x01\x22\x08\x00\x00\x67\x75\x73\x74\x61\x76\x00\x01',
    'list(husband="otto", wife="erna")': '\x01\x00\x01\x00\x44\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x40\x00\x00\x90\x3c\x00\x00\x15\x20\x00\x00\x22\x10\x00\x00\x68\x75\x73\x62\x61\x6e\x64\x00\x77\x69\x66\x65\x00\x01\x01\x01\x13\x08\x00\x00\x6e\x61\x6d\x65\x73\x00\x00\x00\x22\x08\x00\x00\x6f\x74\x74\x6f\x00\x01\x01\x01\x22\x08\x00\x00\x65\x72\x6e\x61\x00\x01\x01\x01',
    'list(n="Fred", no_c=2, c_ages=c(4,7))': '\x01\x00\x01\x00\x58\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x54\x00\x00\x90\x50\x00\x00\x15\x20\x00\x00\x22\x10\x00\x00\x6e\x00\x6e\x6f\x5f\x63\x00\x63\x5f\x61\x67\x65\x73\x00\x01\x01\x13\x08\x00\x00\x6e\x61\x6d\x65\x73\x00\x00\x00\x22\x08\x00\x00\x46\x72\x65\x64\x00\x01\x01\x01\x21\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x21\x10\x00\x00\x00\x00\x00\x00\x00\x00\x10\x40\x00\x00\x00\x00\x00\x00\x1c\x40',
    'array(1:20, dim=c(4, 5))': '\x01\x00\x01\x00\x70\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x6c\x00\x00\xa0\x68\x00\x00\x15\x14\x00\x00\x20\x08\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00\x13\x04\x00\x00\x64\x69\x6d\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x08\x00\x00\x00\x09\x00\x00\x00\x0a\x00\x00\x00\x0b\x00\x00\x00\x0c\x00\x00\x00\x0d\x00\x00\x00\x0e\x00\x00\x00\x0f\x00\x00\x00\x10\x00\x00\x00\x11\x00\x00\x00\x12\x00\x00\x00\x13\x00\x00\x00\x14\x00\x00\x00',
    }
<|endoftext|>


<commit_before><commit_msg>fix _star, _bind; some tests are passing<commit_after><|endoftext|>


<commit_before># -*- coding: utf-8 -*-

'''
If the numbers 1 to 5 are written out in words: one, two, three, four, five,
then there are 3 + 3 + 5 + 4 + 4 = 19 letters used in total.

If all the numbers from 1 to 1000 (one thousand) inclusive were written out in
words, how many letters would be used?

NOTE: Do not count spaces or hyphens. For example, 342 (three hundred and
forty-two) contains 23 letters and 115 (one hundred and fifteen) contains 20 letters.
The use of "and" when writing out numbers is in compliance with British usage.
'''

import timeit

start = timeit.default_timer()

def euler_17():
    number_words = [['', 'one', 'two', 'three', 'four', 'five',
                     'six', 'seven', 'eight', 'nine'],
                    ['ten', 'eleven', 'twelve', 'thirteen',
                     'fourteen', 'fifteen', 'sixteen',
                     'seventeen', 'eighteen', 'nineteen'],
                    ['twenty', 'thirty', 'forty', 'fifty',
                     'sixty', 'seventy', 'eighty', 'ninety'],
                    ['hundred', 'hundredand'],
                    ['thousand']]
    letter_count = number = 0
    while number < 1000:
        number += 1
        curr = number
        if curr / 1000:
            letter_count += (len(number_words[0][curr / 1000]) +
                             len(number_words[4][0]))
        curr %= 1000
        if curr / 100 and not curr % 100:
            letter_count += (len(number_words[0][curr / 100]) +
                             len(number_words[3][0]))
            continue
        if curr / 100:
            letter_count += (len(number_words[0][curr / 100]) +
                             len(number_words[3][1]))
        curr %= 100
        if curr / 10 == 1:
            letter_count += len(number_words[1][curr % 10])
            continue
        if curr / 10:
            letter_count += len(number_words[2][(curr / 10) - 2])
        curr %= 10
        letter_count += len(number_words[0][curr % 10])
    return letter_count

print "Answer: %s" % euler_17()
stop = timeit.default_timer()
print "Time: %f" % (stop - start)
<commit_msg>py3 compatible<commit_after># -*- coding: utf-8 -*-

from __future__ import print_function

'''
If the numbers 1 to 5 are written out in words: one, two, three, four, five,
then there are 3 + 3 + 5 + 4 + 4 = 19 letters used in total.

If all the numbers from 1 to 1000 (one thousand) inclusive were written out in
words, how many letters would be used?

NOTE: Do not count spaces or hyphens. For example, 342 (three hundred and
forty-two) contains 23 letters and 115 (one hundred and fifteen) contains 20 letters.
The use of "and" when writing out numbers is in compliance with British usage.
'''

import timeit

start = timeit.default_timer()

def euler_17():
    number_words = [['', 'one', 'two', 'three', 'four', 'five',
                     'six', 'seven', 'eight', 'nine'],
                    ['ten', 'eleven', 'twelve', 'thirteen',
                     'fourteen', 'fifteen', 'sixteen',
                     'seventeen', 'eighteen', 'nineteen'],
                    ['twenty', 'thirty', 'forty', 'fifty',
                     'sixty', 'seventy', 'eighty', 'ninety'],
                    ['hundred', 'hundredand'],
                    ['thousand']]
    letter_count = number = 0
    while number < 1000:
        number += 1
        curr = number
        if curr // 1000:
            letter_count += (len(number_words[0][curr // 1000]) +
                             len(number_words[4][0]))
        curr %= 1000
        if curr // 100 and not curr % 100:
            letter_count += (len(number_words[0][curr // 100]) +
                             len(number_words[3][0]))
            continue
        if curr // 100:
            letter_count += (len(number_words[0][curr // 100]) +
                             len(number_words[3][1]))
        curr %= 100
        if curr // 10 == 1:
            letter_count += len(number_words[1][curr % 10])
            continue
        if curr // 10:
            letter_count += len(number_words[2][(curr // 10) - 2])
        curr %= 10
        letter_count += len(number_words[0][curr % 10])
    return letter_count

print("Answer: {}".format(euler_17()))
stop = timeit.default_timer()
print("Time: {0:9.5f}".format(stop - start))
<|endoftext|>