diff --git a/branch-master/api-index.json b/branch-master/api-index.json index b77b09eb..b124d69e 100644 --- a/branch-master/api-index.json +++ b/branch-master/api-index.json @@ -343,7 +343,9 @@ "wiki-url": "http:\/\/clojure.github.com\/clojure-contrib\/priority-map-api.html", "name":"clojure.contrib.priority-map", - "doc":null}, + "author":"Mark Engelberg", + "doc": + "A priority map is very similar to a sorted map, but whereas a sorted map produces a\nsequence of the entries sorted by key, a priority map produces the entries sorted by value.\nIn addition to supporting all the functions a sorted map supports, a priority map\ncan also be thought of as a queue of [item priority] pairs. To support usage as\na versatile priority queue, priority maps also support conj\/peek\/pop operations.\n\nThe standard way to construct a priority map is with priority-map:\nuser=> (def p (priority-map :a 2 :b 1 :c 3 :d 5 :e 4 :f 3))\n#'user\/p\nuser=> p\n{:b 1, :a 2, :c 3, :f 3, :e 4, :d 5}\n\nSo :b has priority 1, :a has priority 2, and so on.\nNotice how the priority map prints in an order sorted by its priorities (i.e., the map's values)\n\nWe can use assoc to assign a priority to a new item:\nuser=> (assoc p :g 1)\n{:b 1, :g 1, :a 2, :c 3, :f 3, :e 4, :d 5}\n\nor to assign a new priority to an extant item:\nuser=> (assoc p :c 4)\n{:b 1, :a 2, :f 3, :c 4, :e 4, :d 5}\n\nWe can remove an item from the priority map:\nuser=> (dissoc p :e)\n{:b 1, :a 2, :c 3, :f 3, :d 5}\n\nAn alternative way to add to the priority map is to conj a [item priority] pair:\nuser=> (conj p [:g 0])\n{:g 0, :b 1, :a 2, :c 3, :f 3, :e 4, :d 5}\n\nor use into:\nuser=> (into p [[:g 0] [:h 1] [:i 2]])\n{:g 0, :b 1, :h 1, :a 2, :i 2, :c 3, :f 3, :e 4, :d 5}\n\nPriority maps are countable:\nuser=> (count p)\n6\n\nLike other maps, equivalence is based not on type, but on contents.\nIn other words, just as a sorted-map can be equal to a hash-map,\nso can a priority-map.\nuser=> (= p {:b 1, :a 2, :c 3, :f 3, :e 4, :d 5})\ntrue\n\nYou can test them for emptiness:\nuser=> (empty? (priority-map))\ntrue\nuser=> (empty? p)\nfalse\n\nYou can test whether an item is in the priority map:\nuser=> (contains? p :a)\ntrue\nuser=> (contains? p :g)\nfalse\n\nIt is easy to look up the priority of a given item, using any of the standard map mechanisms:\nuser=> (get p :a)\n2\nuser=> (get p :g 10)\n10\nuser=> (p :a)\n2\nuser=> (:a p)\n2\n\nPriority maps derive much of their utility by providing priority-based seq.\nNote that no guarantees are made about the order in which items of the same priority appear.\nuser=> (seq p)\n([:b 1] [:a 2] [:c 3] [:f 3] [:e 4] [:d 5])\nBecause no guarantees are made about the order of same-priority items, note that\nrseq might not be an exact reverse of the seq. It is only guaranteed to be in\ndescending order.\nuser=> (rseq p)\n([:d 5] [:e 4] [:c 3] [:f 3] [:a 2] [:b 1])\n\nThis means first\/rest\/next\/for\/map\/etc. all operate in priority order.\nuser=> (first p)\n[:b 1]\nuser=> (rest p)\n([:a 2] [:c 3] [:f 3] [:e 4] [:d 5])\n\nPriority maps support metadata:\nuser=> (meta (with-meta p {:extra :info}))\n{:extra :info}\n\nBut perhaps most importantly, priority maps can also function as priority queues.\npeek, like first, gives you the first [item priority] pair in the collection.\npop removes the first [item priority] from the collection.\n(Note that unlike rest, which returns a seq, pop returns a priority map).\n\nuser=> (peek p)\n[:b 1]\nuser=> (pop p)\n{:a 2, :c 3, :f 3, :e 4, :d 5}\n\nIt is also possible to use a custom comparator:\nuser=> (priority-map-by (comparator >) :a 1 :b 2 :c 3)\n{:c 3, :b 2, :a 1}\n\nAll of these operations are efficient. Generally speaking, most operations\nare O(log n) where n is the number of distinct priorities. Some operations\n(for example, straightforward lookup of an item's priority, or testing\nwhether a given item is in the priority map) are as efficient\nas Clojure's built-in map.\n\nThe key to this efficiency is that internally, not only does the priority map store\nan ordinary hash map of items to priority, but it also stores a sorted map that\nmaps priorities to sets of items with that priority.\n\nA typical textbook priority queue data structure supports at the ability to add\na [item priority] pair to the queue, and to pop\/peek the next [item priority] pair.\nBut many real-world applications of priority queues require more features, such\nas the ability to test whether something is already in the queue, or to reassign\na priority. For example, a standard formulation of Dijkstra's algorithm requires the\nability to reduce the priority number associated with a given item. Once you\nthrow persistence into the mix with the desire to adjust priorities, the traditional\nstructures just don't work that well.\n\nThis particular blend of Clojure's built-in hash sets, hash maps, and sorted maps\nproved to be a great way to implement an especially flexible persistent priority queue.\n\nConnoisseurs of algorithms will note that this structure's peek operation is not O(1) as\nit would be if based upon a heap data structure, but I feel this is a small concession for\nthe blend of persistence, priority reassignment, and priority-sorted seq, which can be\nquite expensive to achieve with a heap (I did actually try this for comparison). Furthermore,\nthis peek's logarithmic behavior is quite good (on my computer I can do a million\npeeks at a priority map with a million items in 750ms). Also, consider that peek and pop\nusually follow one another, and even with a heap, pop is logarithmic. So the net combination\nof peek and pop is not much different between this versatile formulation of a priority map and\na more limited heap-based one. In a nutshell, peek, although not O(1), is unlikely to be the\nbottleneck in your program.\n\nAll in all, I hope you will find priority maps to be an easy-to-use and useful addition\nto Clojure's assortment of built-in maps (hash-map and sorted-map)."}, {"source-url": "http:\/\/github.com\/clojure\/clojure-contrib\/blob\/\/modules\/clojure\/contrib\/probabilities\/finite_distributions.clj", "wiki-url": @@ -2656,11 +2658,11 @@ "Execute body with JMX connection specified by opts. opts can also\ninclude an optional :environment key which is passed as the\nenvironment arg to JMXConnectorFactory\/connect.", "name":"with-connection"}, {"source-url": - "http:\/\/github.com\/clojure\/clojure-contrib\/blob\/5a928e263ab88cb8d224de8585932f936aa30c8f\/modules\/json\/src\/main\/clojure\/clojure\/contrib\/json.clj#L304", + "http:\/\/github.com\/clojure\/clojure-contrib\/blob\/d6f6ccfaeac03e35b1f9dbfa04424866cd9b2a41\/modules\/json\/src\/main\/clojure\/clojure\/contrib\/json.clj#L302", "wiki-url": "http:\/\/clojure.github.com\/clojure-contrib\/\/json-api.html#clojure.contrib.json\/json-str", "namespace":"clojure.contrib.json", - "line":304, + "line":302, "file": "\/home\/tom\/src\/clj\/autodoc-stable\/..\/autodoc-work-area\/clojure-contrib\/src\/modules\/json\/src\/main\/clojure\/clojure\/contrib\/json.clj", "var-type":"function", @@ -2668,11 +2670,11 @@ "doc":"Converts x to a JSON-formatted string.", "name":"json-str"}, {"source-url": - "http:\/\/github.com\/clojure\/clojure-contrib\/blob\/5a928e263ab88cb8d224de8585932f936aa30c8f\/modules\/json\/src\/main\/clojure\/clojure\/contrib\/json.clj#L341", + "http:\/\/github.com\/clojure\/clojure-contrib\/blob\/d6f6ccfaeac03e35b1f9dbfa04424866cd9b2a41\/modules\/json\/src\/main\/clojure\/clojure\/contrib\/json.clj#L339", "wiki-url": "http:\/\/clojure.github.com\/clojure-contrib\/\/json-api.html#clojure.contrib.json\/pprint-json", "namespace":"clojure.contrib.json", - "line":341, + "line":339, "file": "\/home\/tom\/src\/clj\/autodoc-stable\/..\/autodoc-work-area\/clojure-contrib\/src\/modules\/json\/src\/main\/clojure\/clojure\/contrib\/json.clj", "var-type":"function", @@ -2680,11 +2682,11 @@ "doc":"Pretty-prints JSON representation of x to *out*", "name":"pprint-json"}, {"source-url": - "http:\/\/github.com\/clojure\/clojure-contrib\/blob\/5a928e263ab88cb8d224de8585932f936aa30c8f\/modules\/json\/src\/main\/clojure\/clojure\/contrib\/json.clj#L312", + "http:\/\/github.com\/clojure\/clojure-contrib\/blob\/d6f6ccfaeac03e35b1f9dbfa04424866cd9b2a41\/modules\/json\/src\/main\/clojure\/clojure\/contrib\/json.clj#L310", "wiki-url": "http:\/\/clojure.github.com\/clojure-contrib\/\/json-api.html#clojure.contrib.json\/print-json", "namespace":"clojure.contrib.json", - "line":312, + "line":310, "file": "\/home\/tom\/src\/clj\/autodoc-stable\/..\/autodoc-work-area\/clojure-contrib\/src\/modules\/json\/src\/main\/clojure\/clojure\/contrib\/json.clj", "var-type":"function", @@ -2692,7 +2694,7 @@ "doc":"Write JSON-formatted output to *out*", "name":"print-json"}, {"source-url": - "http:\/\/github.com\/clojure\/clojure-contrib\/blob\/5a928e263ab88cb8d224de8585932f936aa30c8f\/modules\/json\/src\/main\/clojure\/clojure\/contrib\/json.clj#L186", + "http:\/\/github.com\/clojure\/clojure-contrib\/blob\/d6f6ccfaeac03e35b1f9dbfa04424866cd9b2a41\/modules\/json\/src\/main\/clojure\/clojure\/contrib\/json.clj#L186", "wiki-url": "http:\/\/clojure.github.com\/clojure-contrib\/\/json-api.html#clojure.contrib.json\/read-json", "namespace":"clojure.contrib.json", @@ -4429,7 +4431,7 @@ "Returns a sorted seq of symbols naming public vars in\na namespace", "name":"vars"}, {"source-url": - "http:\/\/github.com\/clojure\/clojure-contrib\/blob\/a6a92b9b3d2bfd9a56e1e5e9cfba706d1aeeaae5\/modules\/priority-map\/src\/main\/clojure\/clojure\/contrib\/priority_map.clj#L306", + "http:\/\/github.com\/clojure\/clojure-contrib\/blob\/37fba7ef6697b2e46db7d38b463dba81d3b1c4e7\/modules\/priority-map\/src\/main\/clojure\/clojure\/contrib\/priority_map.clj#L306", "wiki-url": "http:\/\/clojure.github.com\/clojure-contrib\/\/priority-map-api.html#clojure.contrib.priority-map\/priority-map", "namespace":"clojure.contrib.priority-map", @@ -4442,7 +4444,7 @@ "keyval => key val\nReturns a new priority map with supplied mappings", "name":"priority-map"}, {"source-url": - "http:\/\/github.com\/clojure\/clojure-contrib\/blob\/a6a92b9b3d2bfd9a56e1e5e9cfba706d1aeeaae5\/modules\/priority-map\/src\/main\/clojure\/clojure\/contrib\/priority_map.clj#L312", + "http:\/\/github.com\/clojure\/clojure-contrib\/blob\/37fba7ef6697b2e46db7d38b463dba81d3b1c4e7\/modules\/priority-map\/src\/main\/clojure\/clojure\/contrib\/priority_map.clj#L312", "wiki-url": "http:\/\/clojure.github.com\/clojure-contrib\/\/priority-map-api.html#clojure.contrib.priority-map\/priority-map-by", "namespace":"clojure.contrib.priority-map", diff --git a/branch-master/index.html b/branch-master/index.html index 7da625e6..2f6784a0 100644 --- a/branch-master/index.html +++ b/branch-master/index.html @@ -1455,9 +1455,144 @@
A priority map is very similar to a sorted map, but whereas a sorted map produces a +sequence of the entries sorted by key, a priority map produces the entries sorted by value. +In addition to supporting all the functions a sorted map supports, a priority map +can also be thought of as a queue of [item priority] pairs. To support usage as +a versatile priority queue, priority maps also support conj/peek/pop operations. + +The standard way to construct a priority map is with priority-map: +user=> (def p (priority-map :a 2 :b 1 :c 3 :d 5 :e 4 :f 3)) +#'user/p +user=> p +{:b 1, :a 2, :c 3, :f 3, :e 4, :d 5} + +So :b has priority 1, :a has priority 2, and so on. +Notice how the priority map prints in an order sorted by its priorities (i.e., the map's values) + +We can use assoc to assign a priority to a new item: +user=> (assoc p :g 1) +{:b 1, :g 1, :a 2, :c 3, :f 3, :e 4, :d 5} + +or to assign a new priority to an extant item: +user=> (assoc p :c 4) +{:b 1, :a 2, :f 3, :c 4, :e 4, :d 5} + +We can remove an item from the priority map: +user=> (dissoc p :e) +{:b 1, :a 2, :c 3, :f 3, :d 5} + +An alternative way to add to the priority map is to conj a [item priority] pair: +user=> (conj p [:g 0]) +{:g 0, :b 1, :a 2, :c 3, :f 3, :e 4, :d 5} + +or use into: +user=> (into p [[:g 0] [:h 1] [:i 2]]) +{:g 0, :b 1, :h 1, :a 2, :i 2, :c 3, :f 3, :e 4, :d 5} + +Priority maps are countable: +user=> (count p) +6 + +Like other maps, equivalence is based not on type, but on contents. +In other words, just as a sorted-map can be equal to a hash-map, +so can a priority-map. +user=> (= p {:b 1, :a 2, :c 3, :f 3, :e 4, :d 5}) +true + +You can test them for emptiness: +user=> (empty? (priority-map)) +true +user=> (empty? p) +false + +You can test whether an item is in the priority map: +user=> (contains? p :a) +true +user=> (contains? p :g) +false + +It is easy to look up the priority of a given item, using any of the standard map mechanisms: +user=> (get p :a) +2 +user=> (get p :g 10) +10 +user=> (p :a) +2 +user=> (:a p) +2 + +Priority maps derive much of their utility by providing priority-based seq. +Note that no guarantees are made about the order in which items of the same priority appear. +user=> (seq p) +([:b 1] [:a 2] [:c 3] [:f 3] [:e 4] [:d 5]) +Because no guarantees are made about the order of same-priority items, note that +rseq might not be an exact reverse of the seq. It is only guaranteed to be in +descending order. +user=> (rseq p) +([:d 5] [:e 4] [:c 3] [:f 3] [:a 2] [:b 1]) + +This means first/rest/next/for/map/etc. all operate in priority order. +user=> (first p) +[:b 1] +user=> (rest p) +([:a 2] [:c 3] [:f 3] [:e 4] [:d 5]) + +Priority maps support metadata: +user=> (meta (with-meta p {:extra :info})) +{:extra :info} + +But perhaps most importantly, priority maps can also function as priority queues. +peek, like first, gives you the first [item priority] pair in the collection. +pop removes the first [item priority] from the collection. +(Note that unlike rest, which returns a seq, pop returns a priority map). + +user=> (peek p) +[:b 1] +user=> (pop p) +{:a 2, :c 3, :f 3, :e 4, :d 5} + +It is also possible to use a custom comparator: +user=> (priority-map-by (comparator >) :a 1 :b 2 :c 3) +{:c 3, :b 2, :a 1} + +All of these operations are efficient. Generally speaking, most operations +are O(log n) where n is the number of distinct priorities. Some operations +(for example, straightforward lookup of an item's priority, or testing +whether a given item is in the priority map) are as efficient +as Clojure's built-in map. + +The key to this efficiency is that internally, not only does the priority map store +an ordinary hash map of items to priority, but it also stores a sorted map that +maps priorities to sets of items with that priority. + +A typical textbook priority queue data structure supports at the ability to add +a [item priority] pair to the queue, and to pop/peek the next [item priority] pair. +But many real-world applications of priority queues require more features, such +as the ability to test whether something is already in the queue, or to reassign +a priority. For example, a standard formulation of Dijkstra's algorithm requires the +ability to reduce the priority number associated with a given item. Once you +throw persistence into the mix with the desire to adjust priorities, the traditional +structures just don't work that well. + +This particular blend of Clojure's built-in hash sets, hash maps, and sorted maps +proved to be a great way to implement an especially flexible persistent priority queue. + +Connoisseurs of algorithms will note that this structure's peek operation is not O(1) as +it would be if based upon a heap data structure, but I feel this is a small concession for +the blend of persistence, priority reassignment, and priority-sorted seq, which can be +quite expensive to achieve with a heap (I did actually try this for comparison). Furthermore, +this peek's logarithmic behavior is quite good (on my computer I can do a million +peeks at a priority map with a million items in 750ms). Also, consider that peek and pop +usually follow one another, and even with a heap, pop is logarithmic. So the net combination +of peek and pop is not much different between this versatile formulation of a priority map and +a more limited heap-based one. In a nutshell, peek, although not O(1), is unlikely to be the +bottleneck in your program. + +All in all, I hope you will find priority maps to be an easy-to-use and useful addition +to Clojure's assortment of built-in maps (hash-map and sorted-map).diff --git a/branch-master/json-api.html b/branch-master/json-api.html index ef87f5e5..006992ab 100644 --- a/branch-master/json-api.html +++ b/branch-master/json-api.html @@ -102,7 +102,7 @@
Converts x to a JSON-formatted string.- Source + Source
(ns your-namespace
(:require clojure.contrib.priority-map))
A priority map is very similar to a sorted map, but whereas a sorted map produces a +sequence of the entries sorted by key, a priority map produces the entries sorted by value. +In addition to supporting all the functions a sorted map supports, a priority map +can also be thought of as a queue of [item priority] pairs. To support usage as +a versatile priority queue, priority maps also support conj/peek/pop operations. + +The standard way to construct a priority map is with priority-map: +user=> (def p (priority-map :a 2 :b 1 :c 3 :d 5 :e 4 :f 3)) +#'user/p +user=> p +{:b 1, :a 2, :c 3, :f 3, :e 4, :d 5} + +So :b has priority 1, :a has priority 2, and so on. +Notice how the priority map prints in an order sorted by its priorities (i.e., the map's values) + +We can use assoc to assign a priority to a new item: +user=> (assoc p :g 1) +{:b 1, :g 1, :a 2, :c 3, :f 3, :e 4, :d 5} + +or to assign a new priority to an extant item: +user=> (assoc p :c 4) +{:b 1, :a 2, :f 3, :c 4, :e 4, :d 5} + +We can remove an item from the priority map: +user=> (dissoc p :e) +{:b 1, :a 2, :c 3, :f 3, :d 5} + +An alternative way to add to the priority map is to conj a [item priority] pair: +user=> (conj p [:g 0]) +{:g 0, :b 1, :a 2, :c 3, :f 3, :e 4, :d 5} + +or use into: +user=> (into p [[:g 0] [:h 1] [:i 2]]) +{:g 0, :b 1, :h 1, :a 2, :i 2, :c 3, :f 3, :e 4, :d 5} + +Priority maps are countable: +user=> (count p) +6 + +Like other maps, equivalence is based not on type, but on contents. +In other words, just as a sorted-map can be equal to a hash-map, +so can a priority-map. +user=> (= p {:b 1, :a 2, :c 3, :f 3, :e 4, :d 5}) +true + +You can test them for emptiness: +user=> (empty? (priority-map)) +true +user=> (empty? p) +false + +You can test whether an item is in the priority map: +user=> (contains? p :a) +true +user=> (contains? p :g) +false + +It is easy to look up the priority of a given item, using any of the standard map mechanisms: +user=> (get p :a) +2 +user=> (get p :g 10) +10 +user=> (p :a) +2 +user=> (:a p) +2 + +Priority maps derive much of their utility by providing priority-based seq. +Note that no guarantees are made about the order in which items of the same priority appear. +user=> (seq p) +([:b 1] [:a 2] [:c 3] [:f 3] [:e 4] [:d 5]) +Because no guarantees are made about the order of same-priority items, note that +rseq might not be an exact reverse of the seq. It is only guaranteed to be in +descending order. +user=> (rseq p) +([:d 5] [:e 4] [:c 3] [:f 3] [:a 2] [:b 1]) + +This means first/rest/next/for/map/etc. all operate in priority order. +user=> (first p) +[:b 1] +user=> (rest p) +([:a 2] [:c 3] [:f 3] [:e 4] [:d 5]) + +Priority maps support metadata: +user=> (meta (with-meta p {:extra :info})) +{:extra :info} + +But perhaps most importantly, priority maps can also function as priority queues. +peek, like first, gives you the first [item priority] pair in the collection. +pop removes the first [item priority] from the collection. +(Note that unlike rest, which returns a seq, pop returns a priority map). + +user=> (peek p) +[:b 1] +user=> (pop p) +{:a 2, :c 3, :f 3, :e 4, :d 5} + +It is also possible to use a custom comparator: +user=> (priority-map-by (comparator >) :a 1 :b 2 :c 3) +{:c 3, :b 2, :a 1} + +All of these operations are efficient. Generally speaking, most operations +are O(log n) where n is the number of distinct priorities. Some operations +(for example, straightforward lookup of an item's priority, or testing +whether a given item is in the priority map) are as efficient +as Clojure's built-in map. + +The key to this efficiency is that internally, not only does the priority map store +an ordinary hash map of items to priority, but it also stores a sorted map that +maps priorities to sets of items with that priority. + +A typical textbook priority queue data structure supports at the ability to add +a [item priority] pair to the queue, and to pop/peek the next [item priority] pair. +But many real-world applications of priority queues require more features, such +as the ability to test whether something is already in the queue, or to reassign +a priority. For example, a standard formulation of Dijkstra's algorithm requires the +ability to reduce the priority number associated with a given item. Once you +throw persistence into the mix with the desire to adjust priorities, the traditional +structures just don't work that well. + +This particular blend of Clojure's built-in hash sets, hash maps, and sorted maps +proved to be a great way to implement an especially flexible persistent priority queue. + +Connoisseurs of algorithms will note that this structure's peek operation is not O(1) as +it would be if based upon a heap data structure, but I feel this is a small concession for +the blend of persistence, priority reassignment, and priority-sorted seq, which can be +quite expensive to achieve with a heap (I did actually try this for comparison). Furthermore, +this peek's logarithmic behavior is quite good (on my computer I can do a million +peeks at a priority map with a million items in 750ms). Also, consider that peek and pop +usually follow one another, and even with a heap, pop is logarithmic. So the net combination +of peek and pop is not much different between this versatile formulation of a priority map and +a more limited heap-based one. In a nutshell, peek, although not O(1), is unlikely to be the +bottleneck in your program. + +All in all, I hope you will find priority maps to be an easy-to-use and useful addition +to Clojure's assortment of built-in maps (hash-map and sorted-map).