{"action":"created","comment":{"url":"https://api.github.com/repos/hoburg/gpkit/pulls/comments/55854215","id":55854215,"diff_hunk":"@@ -0,0 +1,227 @@\n+\"Implements ConstraintSet\"\n+from ..small_classes import HashVector\n+from ..keydict import KeySet, KeyDict\n+from ..small_scripts import try_str_without\n+from ..repr_conventions import _str, _repr, _repr_latex_\n+\n+\n+class ConstraintSet(list):\n+    \"Recursive container for ConstraintSets and Inequalities\"\n+    def __init__(self, constraints, substitutions=None):\n+        list.__init__(self, constraints)\n+        subs = substitutions if substitutions else {}\n+        if hasattr(self, \"cost\"):\n+            subs.update(self.cost.values)\n+        if not isinstance(constraints, ConstraintSet):\n+            # constraintsetify everything\n+            for i, constraint in enumerate(self):\n+                if (hasattr(constraint, \"__iter__\") and\n+                        not isinstance(constraint, ConstraintSet)):\n+                    self[i] = ConstraintSet(constraint)\n+        else:\n+            # grab the substitutions dict from the top constraintset\n+            subs.update(constraints.substitutions)\n+        self.substitutions = KeyDict.with_keys(self.varkeys,\n+                                               self._iter_subs(subs))\n+\n+    __str__ = _str\n+    __repr__ = _repr\n+    _repr_latex_ = _repr_latex_\n+\n+    def str_without(self, excluded=None):\n+        \"String representation of a ConstraintSet.\"\n+        if not excluded:\n+            excluded = [\"units\"]\n+        if \"cost\" in excluded:\n+            lines = []  # start with nothing\n+        else:\n+            excluded.append(\"cost\")\n+            if hasattr(self, \"cost\"):\n+                lines = [\"  # minimize\",\n+                         \"        %s\" % self.cost.str_without(excluded),\n+                         \"  # subject to\"]\n+            else:\n+                lines = [\"\"]  # start with a newline\n+        for constraint in self:\n+            if hasattr(constraint, \"_subconstr_str\"):\n+                cstr = constraint._subconstr_str(excluded)\n+                if cstr is None:\n+                    cstr = try_str_without(constraint, excluded)\n+            else:\n+                cstr = try_str_without(constraint, excluded)\n+            if cstr[:8] != \"        \":  # require indentation\n+                cstr = \"        \" + cstr\n+            lines.append(cstr)\n+        return \"\\n\".join(lines)\n+\n+    def latex(self, excluded=None):\n+        \"LaTeX representation of a ConstraintSet.\"\n+        if not excluded:\n+            excluded = [\"units\"]\n+        if \"cost\" in excluded:\n+            lines = []  # start with nothing\n+        else:\n+            excluded.append(\"cost\")\n+            lines = [\"\\\\begin{array}[ll]\", \"\\\\text{}\"]\n+            if hasattr(self, \"cost\"):\n+                lines.extend([\"\\\\text{minimize}\",\n+                              \"    & %s \\\\\\\\\" % self.cost.latex(excluded),\n+                              \"\\\\text{subject to}\"])\n+        for constraint in self:\n+            if hasattr(constraint, \"_subconstr_latex\"):\n+                cstr = constraint._subconstr_latex(excluded)\n+                if cstr is None:\n+                    cstr = constraint.latex(excluded)\n+            else:\n+                cstr = constraint.latex(excluded)\n+            if cstr[:6] != \"    & \":  # require indentation\n+                cstr = \"    & \" + cstr\n+            lines.append(cstr)\n+        lines.append(\"\\\\end{array}\")\n+        return \"\\n\".join(lines)\n+\n+    def _subconstr_str(self, excluded=None):","path":"gpkit/constraints/set.py","position":83,"original_position":83,"commit_id":"b71dca1537c9952fa3cdddfd6f79056ceeede750","original_commit_id":"b71dca1537c9952fa3cdddfd6f79056ceeede750","user":{"login":"bqpd","id":1482776,"avatar_url":"https://avatars.githubusercontent.com/u/1482776?v=3","gravatar_id":"","url":"https://api.github.com/users/bqpd","html_url":"https://github.com/bqpd","followers_url":"https://api.github.com/users/bqpd/followers","following_url":"https://api.github.com/users/bqpd/following{/other_user}","gists_url":"https://api.github.com/users/bqpd/gists{/gist_id}","starred_url":"https://api.github.com/users/bqpd/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bqpd/subscriptions","organizations_url":"https://api.github.com/users/bqpd/orgs","repos_url":"https://api.github.com/users/bqpd/repos","events_url":"https://api.github.com/users/bqpd/events{/privacy}","received_events_url":"https://api.github.com/users/bqpd/received_events","type":"User","site_admin":false},"body":"The idea right now is that it's implemented by subclasses (e.g. ConstraintBase) when they want to simplify their representations. I could see `ArrayConstraints`, gpfits, and taylor expansions implementing it too.","created_at":"2016-03-11T16:41:18Z","updated_at":"2016-03-11T16:41:18Z","html_url":"https://github.com/hoburg/gpkit/pull/493#discussion_r55854215","pull_request_url":"https://api.github.com/repos/hoburg/gpkit/pulls/493","_links":{"self":{"href":"https://api.github.com/repos/hoburg/gpkit/pulls/comments/55854215"},"html":{"href":"https://github.com/hoburg/gpkit/pull/493#discussion_r55854215"},"pull_request":{"href":"https://api.github.com/repos/hoburg/gpkit/pulls/493"}}},"pull_request":{"url":"https://api.github.com/repos/hoburg/gpkit/pulls/493","id":52086107,"html_url":"https://github.com/hoburg/gpkit/pull/493","diff_url":"https://github.com/hoburg/gpkit/pull/493.diff","patch_url":"https://github.com/hoburg/gpkit/pull/493.patch","issue_url":"https://api.github.com/repos/hoburg/gpkit/issues/493","number":493,"state":"open","locked":false,"title":"Newconstr and keydict","user":{"login":"bqpd","id":1482776,"avatar_url":"https://avatars.githubusercontent.com/u/1482776?v=3","gravatar_id":"","url":"https://api.github.com/users/bqpd","html_url":"https://github.com/bqpd","followers_url":"https://api.github.com/users/bqpd/followers","following_url":"https://api.github.com/users/bqpd/following{/other_user}","gists_url":"https://api.github.com/users/bqpd/gists{/gist_id}","starred_url":"https://api.github.com/users/bqpd/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bqpd/subscriptions","organizations_url":"https://api.github.com/users/bqpd/orgs","repos_url":"https://api.github.com/users/bqpd/repos","events_url":"https://api.github.com/users/bqpd/events{/privacy}","received_events_url":"https://api.github.com/users/bqpd/received_events","type":"User","site_admin":false},"body":"@pgkirsch, this should work for your needs...\r\n\r\ntodo:\r\n  - [x] ConstraintSet docstrings\r\n  - [x] pass tests\r\n  - [x] unify and fix ConstraintSet/GeometricProgram/etc printing\r\n  - [ ] hand test `gpkit.interactive` features still work","created_at":"2015-11-30T05:14:34Z","updated_at":"2016-03-11T16:41:18Z","closed_at":null,"merged_at":null,"merge_commit_sha":"6e5f68a7c3a1b6c79388ef6536b6da2213e80221","assignee":null,"milestone":{"url":"https://api.github.com/repos/hoburg/gpkit/milestones/11","html_url":"https://github.com/hoburg/gpkit/milestones/Constraint%20and%20Key%20Refactor","labels_url":"https://api.github.com/repos/hoburg/gpkit/milestones/11/labels","id":1608310,"number":11,"title":"Constraint and Key Refactor","description":"","creator":{"login":"whoburg","id":6042395,"avatar_url":"https://avatars.githubusercontent.com/u/6042395?v=3","gravatar_id":"","url":"https://api.github.com/users/whoburg","html_url":"https://github.com/whoburg","followers_url":"https://api.github.com/users/whoburg/followers","following_url":"https://api.github.com/users/whoburg/following{/other_user}","gists_url":"https://api.github.com/users/whoburg/gists{/gist_id}","starred_url":"https://api.github.com/users/whoburg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/whoburg/subscriptions","organizations_url":"https://api.github.com/users/whoburg/orgs","repos_url":"https://api.github.com/users/whoburg/repos","events_url":"https://api.github.com/users/whoburg/events{/privacy}","received_events_url":"https://api.github.com/users/whoburg/received_events","type":"User","site_admin":false},"open_issues":16,"closed_issues":0,"state":"open","created_at":"2016-02-26T15:56:07Z","updated_at":"2016-03-10T05:07:56Z","due_on":"2016-02-29T05:00:00Z","closed_at":null},"commits_url":"https://api.github.com/repos/hoburg/gpkit/pulls/493/commits","review_comments_url":"https://api.github.com/repos/hoburg/gpkit/pulls/493/comments","review_comment_url":"https://api.github.com/repos/hoburg/gpkit/pulls/comments{/number}","comments_url":"https://api.github.com/repos/hoburg/gpkit/issues/493/comments","statuses_url":"https://api.github.com/repos/hoburg/gpkit/statuses/b71dca1537c9952fa3cdddfd6f79056ceeede750","head":{"label":"hoburg:newconstr_and_keydict","ref":"newconstr_and_keydict","sha":"b71dca1537c9952fa3cdddfd6f79056ceeede750","user":{"login":"hoburg","id":16762937,"avatar_url":"https://avatars.githubusercontent.com/u/16762937?v=3","gravatar_id":"","url":"https://api.github.com/users/hoburg","html_url":"https://github.com/hoburg","followers_url":"https://api.github.com/users/hoburg/followers","following_url":"https://api.github.com/users/hoburg/following{/other_user}","gists_url":"https://api.github.com/users/hoburg/gists{/gist_id}","starred_url":"https://api.github.com/users/hoburg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hoburg/subscriptions","organizations_url":"https://api.github.com/users/hoburg/orgs","repos_url":"https://api.github.com/users/hoburg/repos","events_url":"https://api.github.com/users/hoburg/events{/privacy}","received_events_url":"https://api.github.com/users/hoburg/received_events","type":"Organization","site_admin":false},"repo":{"id":20954246,"name":"gpkit","full_name":"hoburg/gpkit","owner":{"login":"hoburg","id":16762937,"avatar_url":"https://avatars.githubusercontent.com/u/16762937?v=3","gravatar_id":"","url":"https://api.github.com/users/hoburg","html_url":"https://github.com/hoburg","followers_url":"https://api.github.com/users/hoburg/followers","following_url":"https://api.github.com/users/hoburg/following{/other_user}","gists_url":"https://api.github.com/users/hoburg/gists{/gist_id}","starred_url":"https://api.github.com/users/hoburg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hoburg/subscriptions","organizations_url":"https://api.github.com/users/hoburg/orgs","repos_url":"https://api.github.com/users/hoburg/repos","events_url":"https://api.github.com/users/hoburg/events{/privacy}","received_events_url":"https://api.github.com/users/hoburg/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/hoburg/gpkit","description":"Python package for defining and manipulating geometric programming models.","fork":false,"url":"https://api.github.com/repos/hoburg/gpkit","forks_url":"https://api.github.com/repos/hoburg/gpkit/forks","keys_url":"https://api.github.com/repos/hoburg/gpkit/keys{/key_id}","collaborators_url":"https://api.github.com/repos/hoburg/gpkit/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/hoburg/gpkit/teams","hooks_url":"https://api.github.com/repos/hoburg/gpkit/hooks","issue_events_url":"https://api.github.com/repos/hoburg/gpkit/issues/events{/number}","events_url":"https://api.github.com/repos/hoburg/gpkit/events","assignees_url":"https://api.github.com/repos/hoburg/gpkit/assignees{/user}","branches_url":"https://api.github.com/repos/hoburg/gpkit/branches{/branch}","tags_url":"https://api.github.com/repos/hoburg/gpkit/tags","blobs_url":"https://api.github.com/repos/hoburg/gpkit/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/hoburg/gpkit/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/hoburg/gpkit/git/refs{/sha}","trees_url":"https://api.github.com/repos/hoburg/gpkit/git/trees{/sha}","statuses_url":"https://api.github.com/repos/hoburg/gpkit/statuses/{sha}","languages_url":"https://api.github.com/repos/hoburg/gpkit/languages","stargazers_url":"https://api.github.com/repos/hoburg/gpkit/stargazers","contributors_url":"https://api.github.com/repos/hoburg/gpkit/contributors","subscribers_url":"https://api.github.com/repos/hoburg/gpkit/subscribers","subscription_url":"https://api.github.com/repos/hoburg/gpkit/subscription","commits_url":"https://api.github.com/repos/hoburg/gpkit/commits{/sha}","git_commits_url":"https://api.github.com/repos/hoburg/gpkit/git/commits{/sha}","comments_url":"https://api.github.com/repos/hoburg/gpkit/comments{/number}","issue_comment_url":"https://api.github.com/repos/hoburg/gpkit/issues/comments{/number}","contents_url":"https://api.github.com/repos/hoburg/gpkit/contents/{+path}","compare_url":"https://api.github.com/repos/hoburg/gpkit/compare/{base}...{head}","merges_url":"https://api.github.com/repos/hoburg/gpkit/merges","archive_url":"https://api.github.com/repos/hoburg/gpkit/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/hoburg/gpkit/downloads","issues_url":"https://api.github.com/repos/hoburg/gpkit/issues{/number}","pulls_url":"https://api.github.com/repos/hoburg/gpkit/pulls{/number}","milestones_url":"https://api.github.com/repos/hoburg/gpkit/milestones{/number}","notifications_url":"https://api.github.com/repos/hoburg/gpkit/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/hoburg/gpkit/labels{/name}","releases_url":"https://api.github.com/repos/hoburg/gpkit/releases{/id}","deployments_url":"https://api.github.com/repos/hoburg/gpkit/deployments","created_at":"2014-06-18T08:04:06Z","updated_at":"2016-01-25T01:21:54Z","pushed_at":"2016-03-11T15:35:10Z","git_url":"git://github.com/hoburg/gpkit.git","ssh_url":"git@github.com:hoburg/gpkit.git","clone_url":"https://github.com/hoburg/gpkit.git","svn_url":"https://github.com/hoburg/gpkit","homepage":"http://gpkit.readthedocs.org","size":29681,"stargazers_count":7,"watchers_count":7,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":4,"mirror_url":null,"open_issues_count":114,"forks":4,"open_issues":114,"watchers":7,"default_branch":"master"}},"base":{"label":"hoburg:master","ref":"master","sha":"8fa9cc4c59f2df7ee4666ea4be0388b5830cf8c8","user":{"login":"hoburg","id":16762937,"avatar_url":"https://avatars.githubusercontent.com/u/16762937?v=3","gravatar_id":"","url":"https://api.github.com/users/hoburg","html_url":"https://github.com/hoburg","followers_url":"https://api.github.com/users/hoburg/followers","following_url":"https://api.github.com/users/hoburg/following{/other_user}","gists_url":"https://api.github.com/users/hoburg/gists{/gist_id}","starred_url":"https://api.github.com/users/hoburg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hoburg/subscriptions","organizations_url":"https://api.github.com/users/hoburg/orgs","repos_url":"https://api.github.com/users/hoburg/repos","events_url":"https://api.github.com/users/hoburg/events{/privacy}","received_events_url":"https://api.github.com/users/hoburg/received_events","type":"Organization","site_admin":false},"repo":{"id":20954246,"name":"gpkit","full_name":"hoburg/gpkit","owner":{"login":"hoburg","id":16762937,"avatar_url":"https://avatars.githubusercontent.com/u/16762937?v=3","gravatar_id":"","url":"https://api.github.com/users/hoburg","html_url":"https://github.com/hoburg","followers_url":"https://api.github.com/users/hoburg/followers","following_url":"https://api.github.com/users/hoburg/following{/other_user}","gists_url":"https://api.github.com/users/hoburg/gists{/gist_id}","starred_url":"https://api.github.com/users/hoburg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hoburg/subscriptions","organizations_url":"https://api.github.com/users/hoburg/orgs","repos_url":"https://api.github.com/users/hoburg/repos","events_url":"https://api.github.com/users/hoburg/events{/privacy}","received_events_url":"https://api.github.com/users/hoburg/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/hoburg/gpkit","description":"Python package for defining and manipulating geometric programming models.","fork":false,"url":"https://api.github.com/repos/hoburg/gpkit","forks_url":"https://api.github.com/repos/hoburg/gpkit/forks","keys_url":"https://api.github.com/repos/hoburg/gpkit/keys{/key_id}","collaborators_url":"https://api.github.com/repos/hoburg/gpkit/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/hoburg/gpkit/teams","hooks_url":"https://api.github.com/repos/hoburg/gpkit/hooks","issue_events_url":"https://api.github.com/repos/hoburg/gpkit/issues/events{/number}","events_url":"https://api.github.com/repos/hoburg/gpkit/events","assignees_url":"https://api.github.com/repos/hoburg/gpkit/assignees{/user}","branches_url":"https://api.github.com/repos/hoburg/gpkit/branches{/branch}","tags_url":"https://api.github.com/repos/hoburg/gpkit/tags","blobs_url":"https://api.github.com/repos/hoburg/gpkit/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/hoburg/gpkit/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/hoburg/gpkit/git/refs{/sha}","trees_url":"https://api.github.com/repos/hoburg/gpkit/git/trees{/sha}","statuses_url":"https://api.github.com/repos/hoburg/gpkit/statuses/{sha}","languages_url":"https://api.github.com/repos/hoburg/gpkit/languages","stargazers_url":"https://api.github.com/repos/hoburg/gpkit/stargazers","contributors_url":"https://api.github.com/repos/hoburg/gpkit/contributors","subscribers_url":"https://api.github.com/repos/hoburg/gpkit/subscribers","subscription_url":"https://api.github.com/repos/hoburg/gpkit/subscription","commits_url":"https://api.github.com/repos/hoburg/gpkit/commits{/sha}","git_commits_url":"https://api.github.com/repos/hoburg/gpkit/git/commits{/sha}","comments_url":"https://api.github.com/repos/hoburg/gpkit/comments{/number}","issue_comment_url":"https://api.github.com/repos/hoburg/gpkit/issues/comments{/number}","contents_url":"https://api.github.com/repos/hoburg/gpkit/contents/{+path}","compare_url":"https://api.github.com/repos/hoburg/gpkit/compare/{base}...{head}","merges_url":"https://api.github.com/repos/hoburg/gpkit/merges","archive_url":"https://api.github.com/repos/hoburg/gpkit/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/hoburg/gpkit/downloads","issues_url":"https://api.github.com/repos/hoburg/gpkit/issues{/number}","pulls_url":"https://api.github.com/repos/hoburg/gpkit/pulls{/number}","milestones_url":"https://api.github.com/repos/hoburg/gpkit/milestones{/number}","notifications_url":"https://api.github.com/repos/hoburg/gpkit/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/hoburg/gpkit/labels{/name}","releases_url":"https://api.github.com/repos/hoburg/gpkit/releases{/id}","deployments_url":"https://api.github.com/repos/hoburg/gpkit/deployments","created_at":"2014-06-18T08:04:06Z","updated_at":"2016-01-25T01:21:54Z","pushed_at":"2016-03-11T15:35:10Z","git_url":"git://github.com/hoburg/gpkit.git","ssh_url":"git@github.com:hoburg/gpkit.git","clone_url":"https://github.com/hoburg/gpkit.git","svn_url":"https://github.com/hoburg/gpkit","homepage":"http://gpkit.readthedocs.org","size":29681,"stargazers_count":7,"watchers_count":7,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":4,"mirror_url":null,"open_issues_count":114,"forks":4,"open_issues":114,"watchers":7,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/hoburg/gpkit/pulls/493"},"html":{"href":"https://github.com/hoburg/gpkit/pull/493"},"issue":{"href":"https://api.github.com/repos/hoburg/gpkit/issues/493"},"comments":{"href":"https://api.github.com/repos/hoburg/gpkit/issues/493/comments"},"review_comments":{"href":"https://api.github.com/repos/hoburg/gpkit/pulls/493/comments"},"review_comment":{"href":"https://api.github.com/repos/hoburg/gpkit/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/hoburg/gpkit/pulls/493/commits"},"statuses":{"href":"https://api.github.com/repos/hoburg/gpkit/statuses/b71dca1537c9952fa3cdddfd6f79056ceeede750"}}}}