I think that this kind of question is more dedicated to sage-support
because it does not deal about combinatorics
(http://groups.google.com/group/sage-support)

2010/7/28 Christian Stump <christian.st...@gmail.com>:
> Salut cython specialists,
>
> I would like to implement a routine adding dictionaries with possibly
> different keys pointwise and delete all zero entries in the end:
>
> sage: def dict_sum( list_of_dics, remove_zeros=True ):
> ...       return_dict = {}
> ...       for D in list_of_dics:
> ...           for key in D:
> ...               if key in return_dict:
> ...                   return_dict[ key ] += D[ key ]
> ...               else:
> ...                   return_dict[ key ] = D[ key ]
> ...
> ...       if remove_zeros:
> ...           return_dict = dict( [ (key,value) for key,value in
> d.iteritems() if value != 0 ] )
> ...       return return_dict
>
> sage: d = dict(zip(range(100000),range(0,100000,2)))
> sage: timeit("p = dict_sum([d]*10, True)")
> sage: timeit("p = dict_sum([d]*10, False)")
> 5 loops, best of 3: 216 ms per loop
> 5 loops, best of 3: 138 ms per loop
>
> Improving it a little and putting it into cython gives
>
> sage: %cython
> sage: def dict_sum_cython( list_of_dicts, remove_zeros=True ):
> ...       return_dict = list_of_dicts[0].copy()
> ...       for D in list_of_dicts[1:]:
> ...           for key in D:
> ...               if key in return_dict:
> ...                   return_dict[key] += D[key]
> ...               else:
> ...                   return_dict[key] = D[key]
> ...
> ...       if remove_zeros:
> ...           for_removal = [key for (key,value) in
> return_dict.iteritems() if not value]
> ...           for key in for_removal:
> ...               del return_dict[key]
> ...       return return_dict
>
> sage: timeit("p = dict_sum_cython([d]*10, True)")
> sage: timeit("p = dict_sum_cython([d]*10, False)")
> 5 loops, best of 3: 56 ms per loop
> 5 loops, best of 3: 57.8 ms per loop
>
> This is already much faster! Any ideas how to improve the speed now?
> All I know about the variables is that all dict values live in a
> common ring ( mostly QQ ), can I use this somehow?
>
> Thanks for your help, Christian

One remark: for a list l it is much more faster to use l.append(0)
than l += [0]. Moreover, dictionnaries have a special method for
iteration through key and values which is a little bit faster

{{{
sage: d=dict((i,i) for i in xrange(10000))
sage: timeit('for i in d: d[i]')
625 loops, best of 3: 1.1 ms per loop
sage: timeit('for i,j in d.iteritems(): pass')
625 loops, best of 3: 839 µs per loop
}}}

 I would have written for the main loop
{{{
       for D in list_of_dicts[1:]:
           for key,value in D.iteritems():
               if key in return_dict:
                   return_dict[key].append(value)
               else:
                   return_dict[key] = [value]
}}}

Cheers,
Vincent

-- 
To post to this group, send email to sage-support@googlegroups.com
To unsubscribe from this group, send email to 
sage-support+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sage-support
URL: http://www.sagemath.org

Reply via email to