text:
Print the Greek alphabet!
Fairly obviously, you have to print the Greek alphabet. But I thought I'd make it slightly more interesting, so there's a twist: when your program is ran with an argument (anything), it should output the Greek alphabet in lowercase.
Information

Greek alphabet (Capitals):  ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ
Greek alphabet (Lowercase): αβγδεζηθικλμνξοπρστυφχψω

Rules/Requirements

Each submission must be a full program.
Builtins to print the Greek alphabet are not permitted
Standard loopholes apply
You must print exactly what is shown.

Scoring
Programs are scored according to bytes. If you are using a character set different to UTF-8 please specify. Try to get the least bytes out of everyone, this is code-golf!
Test cases
./program
==> ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ

./program 1
==> αβγδεζηθικλμνξοπρστυφχψω

./program 'lower'
==> αβγδεζηθικλμνξοπρστυφχψω

./program 123897883421
==> αβγδεζηθικλμνξοπρστυφχψω

./program ""
==> αβγδεζηθικλμνξοπρστυφχψω

greek();
==> ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ

greek("blah");
==> αβγδεζηθικλμνξοπρστυφχψω

greek(123);
==> αβγδεζηθικλμνξοπρστυφχψω

Submissions
To make sure that your answer shows up, please start your answer with a headline, using the following Markdown template:
# Language Name, N bytes

where N is the size of your submission. If you improve your score, you can keep old scores in the headline, by striking them through. For instance:
# Ruby, <s>104</s> <s>101</s> 96 bytes

If there you want to include multiple numbers in your header (e.g. because your score is the sum of two files or you want to list interpreter flag penalties separately), make sure that the actual score is the last number in the header:
# Perl, 43 + 2 (-p flag) = 45 bytes

You can also make the language name a link which will then show up in the leaderboard snippet:
# [><>](http://esolangs.org/wiki/Fish), 121 bytes

Leaderboard
Here is a Stack Snippet to generate both a regular leaderboard and an overview of winners by language.

/* Configuration */

var QUESTION_ID = 97049; // Obtain this from the url
// It will be like https://XYZ.stackexchange.com/questions/QUESTION_ID/... on any question page
var ANSWER_FILTER = "!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe";
var COMMENT_FILTER = "!)Q2B_A2kjfAiU78X(md6BoYk";
var OVERRIDE_USER = 53406; // This should be the user ID of the challenge author.

/* App */

var answers = [], answers_hash, answer_ids, answer_page = 1, more_answers = true, comment_page;

function answersUrl(index) {
  return "https://api.stackexchange.com/2.2/questions/" +  QUESTION_ID + "/answers?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + ANSWER_FILTER;
}

function commentUrl(index, answers) {
  return "https://api.stackexchange.com/2.2/answers/" + answers.join(';') + "/comments?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + COMMENT_FILTER;
}

function getAnswers() {
  jQuery.ajax({
    url: answersUrl(answer_page++),
    method: "get",
    dataType: "jsonp",
    crossDomain: true,
    success: function (data) {
      answers.push.apply(answers, data.items);
      answers_hash = [];
      answer_ids = [];
      data.items.forEach(function(a) {
        a.comments = [];
        var id = +a.share_link.match(/\d+/);
        answer_ids.push(id);
        answers_hash[id] = a;
      });
      if (!data.has_more) more_answers = false;
      comment_page = 1;
      getComments();
    }
  });
}

function getComments() {
  jQuery.ajax({
    url: commentUrl(comment_page++, answer_ids),
    method: "get",
    dataType: "jsonp",
    crossDomain: true,
    success: function (data) {
      data.items.forEach(function(c) {
        if (c.owner.user_id === OVERRIDE_USER)
          answers_hash[c.post_id].comments.push(c);
      });
      if (data.has_more) getComments();
      else if (more_answers) getAnswers();
      else process();
    }
  });
}

getAnswers();

var SCORE_REG = /<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/;

var OVERRIDE_REG = /^Override\s*header:\s*/i;

function getAuthorName(a) {
  return a.owner.display_name;
}

function process() {
  var valid = [];

  answers.forEach(function(a) {
    var body = a.body;
    a.comments.forEach(function(c) {
      if(OVERRIDE_REG.test(c.body))
        body = '
' + c.body.replace(OVERRIDE_REG, '') + '
';
    });

    var match = body.match(SCORE_REG);
    if (match)
      valid.push({
        user: getAuthorName(a),
        size: +match[2],
        language: match[1],
        link: a.share_link,
      });

  });

  valid.sort(function (a, b) {
    var aB = a.size,
        bB = b.size;
    return aB - bB
  });

  var languages = {};
  var place = 1;
  var lastSize = null;
  var lastPlace = 1;
  valid.forEach(function (a) {
    if (a.size != lastSize)
      lastPlace = place;
    lastSize = a.size;
    ++place;

    var answer = jQuery("#answer-template").html();
    answer = answer.replace("{{PLACE}}", lastPlace + ".")
                   .replace("{{NAME}}", a.user)
                   .replace("{{LANGUAGE}}", a.language)
                   .replace("{{SIZE}}", a.size)
                   .replace("{{LINK}}", a.link);
    answer = jQuery(answer);
    jQuery("#answers").append(answer);

    var lang = a.language;
    if (/ b.lang) return 1;
    if (a.lang < b.lang) return -1;
    return 0;
  });

  for (var i = 0; i < langs.length; ++i)
  {
    var language = jQuery("#language-template").html();
    var lang = langs[i];
    language = language.replace("{{LANGUAGE}}", lang.lang)
                       .replace("{{NAME}}", lang.user)
                       .replace("{{SIZE}}", lang.size)
                       .replace("{{LINK}}", lang.link);
    language = jQuery(language);
    jQuery("#languages").append(language);
  }

}
body { text-align: left !important}

#answer-list {
  padding: 10px;
  width: 290px;
  float: left;
}

#language-list {
  padding: 10px;
  width: 290px;
  float: left;
}

table thead {
  font-weight: bold;
}

table td {
  padding: 5px;
}

<link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b">

Leaderboard

	Author	Language	Size

Winners by Language

Language	User	Score

{{PLACE}}	{{NAME}}	{{LANGUAGE}}	{{SIZE}}	Link

{{LANGUAGE}}	{{NAME}}	{{SIZE}}	Link

Does an empty string count as having an argument or having no argument? Please use the Sandbox to get feedback before posting a challenge on the main site.

@Mego That counts as an argument.

Related.

Will the argument be always one argument, or can there be two or more arguments?

@EriktheGolfer In the test cases it's just one, so I guess there will only ever be one.

@GeorgeGibson Well, that would be convenient for my Python submission.

Can nil, null, undefined, etc. be passed as an argument?

Hebrew alphabet, Greek alphabet. Next stop: Chinese alphabet?

Kritixi approves the challenge.

@Glorfindel It's not an alphabet. Though technically, Hebrew isn't either. ;)

If there is no argument passed at all, do I output the uppercase alphabet?

@TheBitByte Yes

Edit this into your question, and let everybody who's already answered know this

I'm a bit confused by your last three test cases; they look like function calls, yet the rules specifically ask for a full program.

So much for all the languages I grew up with.  That's going to be a lot of PSETs.

05AB1E, 16 bytes
Uses CP-1252 encoding.
24Ý17K913+çJDl¹s

Try it online!
Explanation
24Ý               # push range [0 ... 24]
   17K            # remove 17
      913+        # add 913 to each
          ç       # convert from code point
           J      # join to string
            Dl    # push a lowercase copy
              ¹   # push the input
               s  # swap the top 2 elements of the stack
                  # implicitly display the top of the stack

Did you mean [0 ... 23] or [0, 24) instead of [0 ... 24] or [0, 24]?

@EriktheGolfer There is one other character between the range of greek alphabet code points.

@jimmy23013 Oh right, I was really confused. I am working it in another language, which I won't tell here. I'm commited to that right now.

Ruby, 56 bytes
Full program. I don't think a function/lambda answer will be shorter than this for this language.
Dangit, sigma ς. This is why we can't have nice things. And you too, (unrenderable character that serves as a placeholder for "uppercase" ς)
print *($*[0]?([*?α..?ω]-[?ς]):[*?Α..?Ρ,*?Σ..?Ω])

I think this prints an extra lowercase sigma, ς

This now prints an extra U+03A2.

CJam, 16 bytes
25,H-ea'α'Α?f+

Try it online!
25,H-         e# 0 to 24 excluding 17.
ea'α'Α?       e# If the argument list is truthy (non-empty), alpha, otherwise Alpha.
f+            e# Return characters with each number added to the character code.

Can you add a explanation please?

@XiKuuKy I don't think so :/

@RGS Edited. :/

@jimmy23013 nice one :-P I simply scrolled through this answer and thought I'd comment if for posterity. Didn't think you would come and edit your answer! +1

JavaScript (ES6), 89 83 81 bytes
(...a)=>String.fromCharCode(...[...Array(24)].map((_,i)=>i*1.06+913+32*a.length))

If a character array is acceptable, then for 82 80 78 bytes:
(...a)=>[...Array(24)].map((_,i)=>String.fromCharCode(i*1.06+913+32*a.length))

Edit: Saved a bunch of bytes thanks to @ETHproductions.

Using String.fromCharCode(...array) is again shorter: (...a)=>String.fromCharCode(...[...Array(24)].map((_,i)=>i+(i>16)+913+32*!!a.length))

And since String.fromCharCode floors, you can save another two bytes like so: (...a)=>String.fromCharCode(...[...Array(24)].map((_,i)=>i*1.06+913+32*!!a.length))

@ETHproductions I can't believe I forgot to use String.fromCharCode(...) but I like that i*1.06 trick! Sadly comprehensions are a byte longer this time as far as I can tell.

I managed to get it down to (...a)=>String.fromCharCode(...[for(_ of Array(i=24))i++*42/41+889+32*!!a.length]) (82).

You can remove the !!, as there will only be zero or one args.

Using a single argument a, the expression 1/a+a should give truthy for every value of a except undefined. So a=>String.fromCharCode(...[...Array(24)].map((_,i)=>i*1.06+(1/a+a?945:913)))

Haskell, 114 108 bytes
import System.Environment
q[a,b]=[a..b]
f[]=q"ΑΡ"++q"ΣΩ"
f _=q"αρ"++q"σω"
main=f<$>getArgs>>=putStr

Thanks to @xnor for saving 6 bytes
This might win in the category of longest imports if nothing else…

It looks like it's worth defining q[a,b]=[a..b] to use 4 times.

getArgs>>=putStr.f is shorter.

R, 104 99 92 bytes
g=function(x)for(i in sprintf("'\\u%04X'",913:937+32*!missing(x))[-18])cat(eval(parse(t=i)))

Golfing down on the second version I had previously. Work the same way as  previous version.
Thanks to @JDL for shaving off 7 bytes!
Old versions at 104 bytes:
I have two different solutions with the same byte count:
f=function(x){a="ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ";cat(if(missing(x))a else tolower(a))}

Or:
g=function(x)for(i in sprintf("'\\u%04X'",if(missing(x))913:937 else 945:969)[-18])cat(eval(parse(t=i)))

Explanations:
#First one is trivial
f=function(x){
     a="ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ" #String to print
     #If argument missing, print uppercase else lowercase
     cat(if(missing(x))a else tolower(a))
     }
#Second one more interesting:
g=function(x)
     #Create escaped unicode strings (i. e. "'\\u03B1'" etc.), loop over them...
     for(i in sprintf("'\\u%04X'",if(missing(x))913:937 else 945:969)[-18])
          #...eval the strings
          cat(eval(parse(t=i)))

Usage:
> f()
ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ
> g()
ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ
> f(1)
αβγδεζηθικλμνξοπρστυφχψω
> g(1)
αβγδεζηθικλμνξοπρστυφχψω
> f("a")
αβγδεζηθικλμνξοπρστυφχψω
> g("a")
αβγδεζηθικλμνξοπρστυφχψω

For some reasons, it doesn't work on R-Fiddle (it changes " to ' by default which makes the code throw an error) but you can try it out on Ideone.

Replace +'if'(missing(x),0,32) with +32*!missing(x)?

@JDL Thanks! Don't know why I didn't think of that one.

Pyke, 55 21 20 bytes
24Fi16>913s.C)sz!hAl

Try it here!
24F          )       -   for i in range(24):
   i16>              -       i > 16
       913s          -      sum(i, ^, 913)
           .C        -     chr(^)
              s      -  sum(^) - created uppercase alphabet
                  Al - [len, lower, upper][V](^)
                 h   -  V + 1
               z!    -   not input()

Python 3, 73 bytes
import sys
x=25
while x:print(end=chr(906-x+32*len(sys.argv))[:x^8]);x-=1

Try it online!
This still may not be as low as it can go!

Actually, 62 bytes
 "$ù"E"ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ"@ƒ.X

Try it online!
Because some of the uppercase Greek alphabet is not present in CP437, this solution is encoded in UTF-8 and scored accordingly. Here is a hexdump (reversible with xxd -r):
00000000: 2022 24c3 b922 4522 ce91 ce92 ce93 ce94   "$.."E"........
00000010: ce95 ce96 ce97 ce98 ce99 ce9a ce9b ce9c  ................
00000020: ce9d ce9e ce9f cea0 cea1 cea3 cea4 cea5  ................
00000030: cea6 cea7 cea8 cea9 2240 c692 2e58 0a    ........"@...X.

Explanation:
 "$ù"E"ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ"@ƒ.X
<space>                               push the number of items present on the stack
 `$ù`E                                select `ù` (lowercase) if the number of items is not 0, else `$` (stringify - does nothing to a string)
      "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ"      push the uppercase Greek alphabet
                                @ƒ    call the selected function
                                  .   print
                                   X  discard

Python 3, 80 77 76 bytes
import sys;a='ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ';print([a,a.lower()][-len(sys.argv)])

Old version:
import sys;a='ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ';print([a,a.lower()][len(sys.argv)-1])

Older version:
import sys;a='ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ';print(a.lower()if len(sys.argv)>1else a)

[a,a.lower()][len(sys.argv)-1] because the comments state that there will only ever be one argument.

You can shave one more byte with [a.lower(),a][-len(sys.argv)].

What encoding are you using that this is 76 bytes?

I count 100 bytes.

Japt, 21 19 18 bytes
;Ckzir)c+816+32*NÊ

Test it (no input)Test it (empty string input)
;Ckzir)c+816+32*NÊ     :Implicit input (or not)
;C                     :Lowercase alphabet.
  k                    :Remove
   zir                 :  "z" prepended with "r"
      )                :End remove
       c+              :Map charcodes and add
         816+32*       :  816 plus 32 multiplied by
                N      :   Array of all inputs
                 Ê     :   Length (0 if no input, 1 if a single input)

17 bytes. Took me a bit to get under 18

Nicely done, @Jacob :) I think that's sufficiently different from mine to warrant posting it yourself.

Ok will do. BTW you forgot to update the explanation

You can change 32 to H

PowerShell, 81 bytes
'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ'|%('*wer','*per')[!$args.Count]

Try it online!

78 bytes using 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ'|% "*$('pw'[$args.Count])er" This assumes there will ever be one or no arguments passed

C (gcc), 68 bytes
j=24;main(i){for(setlocale(6,"");j--;)putwchar(968-1/i*32-j+(j<7));}

Try it online!

R, 96 53 51 58 bytes
cat(intToUtf8((913:937)[-18]+32*!!length(commandArgs(T))))

Try it online!
I tried to make an R answer with command line args, but it's a bit longer(now a lot, lot shorter) than the loop based approach by plannapus. I used some of the tricks in their answer.
A crazy -43 bytes from Dominic Van Essen.
-2 more bytes from Dominic Van Essen.
+7 bytes after removing ς

Cool to see command-line args in action in R: we don't use them often (so I'm not very good with them...)!  There are still a couple of golfing tricks you can use: 1. you can skip the {} in the function definition if there's only 1 command (like here)...

you could actually use the function argument, instead of leaving it out & wasting bytes by calling missing (like this)...

and 3. once you've done that, you'll probably want to remove the function altogether & incorporate it into the main expression (like this)...

51 bytes with !! instead of (>0)

I'm afraid I've just noticed (from a comment in the answer above) that the Greek alphabet doesn't seem to be contiguous in Utf8-encoding!  You need to remove the 'ς' character.  This unfortunately brings it back up to 58 bytes...

Julia 1.0, 42 bytes
print.(['Α':'Ρ';'Σ':'Ω'].+32(ARGS>[]))

Try it online!
-1 byte thanks to MarcMush: use ARGS>[] instead of ARGS==[]

PHP, 84 Bytes
Online Version
<?=($argc<2?trim:mb_strtolower)("ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ");

PHP, 87 Bytes
$s="ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ";echo$argc>1?mb_strtolower($s):$s;

gotcha. You seem somehow absent. $argc>1 is 8 bytes shorter than isset($argv[1]) and doesn´t need a blank.

Scala, 82 bytes
print((('Α'to'Ρ')++('Σ'to'Ω')).mkString.map(& =>if(args.size<1)&else&toLower))

Ungolfed:
print((('Α'to'Ρ')++('Σ'to'Ω')).mkString.map(s=>if(args.size==0)s else s.toLower))

Sadly, (('Α'to'Ρ')++('Σ'to'Ω')) is a Vector[Char], which would be printed as Vector('Α', 'Β', ..., so it has to be converted to a string with mkString.The argument to map is called & to save spaces between &else, else& and & toLower.

Jelly, 21 bytes
,⁸Ea32µ24R%18T+912+µỌ

A full program
TryItOnline! - note once run with an argument a refresh will be required to run with no argument.
How?
,⁸Ea32µ24R%18T+912+µỌ - Main link
,⁸                    - pair (,) with left argument (defaults: left=0, ⁸=[])
                            no argument: [0,[]]
                               argument: [argument,argument]
  E                   - all items equal? -> no argument: 0; argument: 1
   a32                - and 32           -> no argument: 0; argument: 32
      µ               - monadic chain separation
       24R            - range(25)        -> [  1,  2,  3,..., 17, 18, 19,..., 25]
          %18         - mod 18           -> [  1,  1,  1,...,  1,  0,  1,...,  1]
             T        - truthy indices   -> [  1,  2,  3,..., 17,     19,..., 25]
              +912    - add 912          -> [913,914,915,...,929,    931,...,937]
                  +   - add the 0 or 32 (lowercase letters are 32 code points higher)
                   µ  - monadic chain separation
                    Ọ - cast to ordinals

PowerShell v2+, 68 bytes
(($a=-join([char[]](913..929+931..937))).toLower(),$a)[!$args.count]

ASCII-only, but outputs in UTF-16. Constructs a char-array of the appropriate characters, -joins it together into a string, stores it into $a. Then, uses !$args.count as an index into the tuple, to output either $a if no arguments are present, or $a.ToLower() if there is at least one argument.
PS C:\Tools\Scripts\golfing> .\print-the-greek-alphabet.ps1
ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ

PS C:\Tools\Scripts\golfing> .\print-the-greek-alphabet.ps1 ''
αβγδεζηθικλμνξοπρστυφχψω

Python 3, 80 bytes
import sys;print(''.join(chr(x+881+len(sys.argv)*32)for x in range(25)if x!=17))

C#, 174 bytes
Lazy implementation, can probably golf it a lot
class P{static void main(string[] a){System.Console.Write(a.Length>0?"αβγδεζηθικλμνξοπρστυφχψω":"ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ");}}

tcl, 73
 puts [expr $argc>0?"αβγδεζηθικλμνξοπρστυφχψω":"ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ"]

demo

Braingolf, 24 bytes
l?#α:#Α|# 9->[.!@ 1+];

Try it online!
Explanation:
l?#α:#Α|# 9->[.!@ 1+];  Implicit input of args to stack
l                       Push length of stack
 ?                      If last item (length) is != 0..
  #α                    ..Push lowercase alpha
    :                   else
     #Α                 ..Push uppercase alpha
       |                endif
        #<space>        Push 32 (ordinal of a space)
          9-            Subtract 9 (23)
            >           Move last item to start of stack
             [......]   Do-While loop, will run 24 times
              .         Duplicate last item
               !@       Print without popping
                  1     Push 1
                   +    Pop last 2 items (1 and duplicate) and push sum
                     ;  Suppress implicit output

Retina, 55 bytes
.+
αβγδεζηθικλμνξοπρστυφχψω
^$
ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ

Try it online

APL (Dyalog Extended), 26 bytes
The normal way to pass multiple arguments to APL programs is through a lists. So this program prompts for such a list, which may have 0 or 1 arguments.
'ς΢'~⍨⍳'Ω'×~≢⎕

Try it online!
⎕ prompt for argument list
≢ tally the number of arguments (0 or 1)
~ negate that (1 or 0)
'Ω'× "multiply" Omega by that (1 keeps uppercase, 0 folds to lowercase)
⍳ All characters from Α–Ω or α–ω respectively
'ς΢'~⍨ remove lowercase and "uppercase" final sigmas

Python 3, 78 bytes
import sys;a=(len(sys.argv)-1)<<5;print(''.join(map(chr,range(a+913,a+938))))

Explanation
a is an offset, 32 when an argument is given to use the lowercase range. 913 to 937 is the range of unicode values for the uppercase greek alphabet.

Python 3, 88 bytes
import sys
s=945 if sys.argv[1:] else 913
for i in range(s,s+25):
  print(chr(i),end='')

Python 3, 74 bytes
This an improvement to @HackerBoss es' answer (I don't have enough reputation to comment).
import sys;a=len(sys.argv)-1<<5;print(*map(chr,range(a+913,a+938)),sep='')

Subtraction has higher precedence than bit shift, so no need for parentheses, we save 2 bytes. Also instead of using ''.join() we unpack the map() and set print()'s default seperator to an empty string to omit the spaces, that saves 1 byte.

Zsh, 45 bytes
A=({Α..Ω})
((#))&&A=${(L)A}
tr -d \ -z<<<$A

Try it online!

Rust, 134 bytes
fn main(){let mut s:String=('α'..'ϊ').collect();s.remove(34);print!("{}",if std::env::args().nth(1)==None{s.to_uppercase()}else{s})}

Try it on the Rust Playground!
ungolfed:
fn main() {                                    //full program
    let mut s: String = ('α'..'ϊ').collect();  //create a range of chars from 'α'(inclusive) to 'ϊ' (exclusive) and collect into string
    s.remove(34);                              //remove 'ς'
    print!(                                    //print
        "{}",                                  //with default formatting
        if std::env::args().nth(1) == None {   //if the 2nd arg doesn't exist (first is filename)
            s.to_uppercase()                   // uppercase string then return
        } else {                               // else
            s                                  // return unmodified string
        }
    )
}

This doesn't work on tio for some reason so this is on the playground, where you can't add input- turn the == to a != to test lowercase version.

Python, 81 Bytes
lambda*x,b="αβγδεζηθικλμνξοπρστυφχψω":(b.upper(),b)[x>()]

-6 from TheThonnu for using *.
-2 from TheThonnu for telling me that the brackets are unneeded.
-28 from mousetail for using an uppercasing function.
-7 from TheThonnu for assigning the greek letters to a variable.

Fails for falsy arguments, like "" and 0

You can fix it and save a few bytes: 118 bytes

@TheThonnu what does the asterik do?

It allows the function to take any number of arguments (including no arguments), and then wraps it all into a tuple, x.

Also, the parentheses are unnecessary, since and has a higher precedence than or: 116 bytes

88 bytes Note that high Unicode values cost multiple bytes

@mousetail an error occurs.

The link gives the output though, there is no error in python 3.10

@mousetail maybe because I’m using my phone?

Try using TIO or ATO, it's much easier

81 bytes

Thunno 2 J, 17 16 15 14 bytes
24Ė17Ɗ913+C¤?L

-1 thanks to @TheThonnu :), saved 1 extra by using different method.
Explanation:
24Ė              # range [0, 24]
   17Ɗ           # remove index 17
      913+       # add 913 to each
          C      # convert to character array
           ¤?    # if there is input:
             L   #   convert to lowercase (vectorizes)
                 # J flag joins character array

Thunno 2 isn't on ATO yet, but I have confirmed that this works on my machine for both the input and no input versions.

Not at my computer right now, but would ¤?kj+ work in place of kj¤l×+? Also, doesn't the B flag give a string not a character array, so the J flag isn't necessary?

@TheThonnu Thanks, it does work! Not sure why it wasn't working for me earlier

Raku, 53 bytes
{say @*ARGS??.lc!!$_}([~] flat 'Α'..'Ρ','Σ'..'Ω')

Try it online!

[~] flat 'Α'..'Ρ','Σ'..'Ω' constructs the uppercase Greek alphabet.
{ say @*ARGS ?? .lc !! $_ } is an anonymous function which receives the uppercase alphabet as an argument.  If there are any command-line arguments, the alphabet is lowercased and printed, otherwise it is printed as-is.

Japt -P, 17 bytes
25od913+H*NÊ fÏÉ7

Test it
Explanation
25o                 map each n in range [0, 25):
   d                  convert the following codepoint to a character:
    913                 n + 913
       +H*NÊ            + (number of inputs * 32)
             fÏ     keep elements where the following is truthy:
               É7     subtract 17 from the index
                      (if index is 17, this will be 0 = falsy)
-P                  P flag joins the array to a string

The cool part of this is fÏÉ7: É7 transforms to -17 by using the shortcut for -1 (i.e. decrement). The regular way of doing this would be something like fÏ¶17 which is one byte longer.

Python 2, 108 bytes
#coding=iso-8859-7
import sys;print'αβγδεζηθικλμνξοπρστυφχψω'if~-len(sys.argv)else'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ'

Terribly golfed, maybe :(
And no, I can't use A.lower().
Thanks to 13285 (alexwlchan) for -11 bytes.

This is the most golfed version I can do.

You can save 8 bytes by skipping the assignment to A,a, and just using those strings directly in the print.

@alexwlchan Right, I just didn't think of it... still terribly golfed, though.

Mathematica, 91 bytes
Print@{#&,ToLowerCase}[[Length@$ScriptCommandLine]][""<>"Α"~CharacterRange~"Ω"~Drop~{18}]

Script. Just takes the character range from Α to Ω, removes U+03A2/ς, either converts to lowercase or doesn't, and prints.

Perl, 39 + 3 (-C2 flag) = 44 42 bytes
 perl -C2 -E 'say map{chr$_+954-!@ARGV*32}-9..7,9..15'

JavaScript, 95 bytes
95 bytes, but only 71 characters. Byte counter. Using @Neil s way to determine if arguments are passed.
(...a)=>'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ'[`to${a.length?'Low':'Upp'}erCase`]()

Pip, 21 20 bytes
C:913+32*#g+Y,24RM17

This is a memorable day. Pip has tied beaten Jelly!1
1 And lost to two other golflangs, but whatever.
Try it online!
Explanation
             ,25      Numbers 0 through 24
                RM17  Remove 17 (ς)
            Y         Yank (to get correct order of operations)
  913                 Char code of capital alpha
      32*#g           32 times number of cmdline args (must be 0 or 1)
     +     +          Add everything up
C:                    Convert to characters (using the compute-and-assign metaoperator to
                        lower the precedence of C)

Java 7, 176 bytes
class M{public static void main(String[]a){System.out.print(a.length>0?"αβγδεζηθικλμνξοπρστυφχψω":"ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ");}}

Java 8, 173 bytes
interface M{static void main(String[]a){System.out.print(a.length>0?"αβγδεζηθικλμνξοπρστυφχψω":"ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ");}}

Groovy Script, 54 51 bytes
((913..937)-930).each{print((char)(args?it+32:it))}

Edit
Switched from 913..937 and it==930?: to (913..937)-930

Can someone explain me, why my answer was downvoted? Did it broke any rules?

PHP, 79 bytes
for($i=944-32*!--$argc;$i++-9&31;$i+=$i%32==1)echo html_entity_decode("&#$i;");

generates unicode html entities and decodes them. Run with -r.

MATLAB, 35 bytes
@(x)disp(char((913:937)+32*nargin))

Pretty self-explainatory, I think.

PowerShell, 94 bytes
param($n)$k=((0..16)+(18..24)|%{[char]($_+913)})-join'';if($n){$k.tolower()}else{$k.toupper()}

Try it online!

It looks like omega is missing.  I think the 23 should be 24.

@Axuary thank you!

Down to 69 bytes: ((0..16)+18..24|%{[char]($_+913)})-join''|% "*$('pw'[$args.Count])er"

Excel, 48 bytes
=CONCAT(UNICHAR(ROW(1:24)*19/18+944-(A1="")*32))

Alternatively, you could put the upper case alphabet in B2 and use the formula below for a combined 47 bytes (or more depending on how you account for multiple cells)
=IF(A1="",B2,LOWER(B2))

APL, 27 bytes
{⎕UCS(912+32×0∊⍴⍵)+18~⍨⍳25}

The program switched to uppercase, when empty array or empty string is received. Unfortunately, it is technically impossible to distinguish them.

Scala, 171 bytes
Modified from @Value Ink's Ruby solution.

Golfed version. Try it online!
object Main{def main(args:Array[String])=println((if(args.nonEmpty)('α'to'ω').toSet.diff(Set('ς')).toList else('Α'to'Ρ').toList++('Σ'to 'Ω').toList).mkString(" "))}

Ungolfed version. Try it online!
object Main {
  def main(args: Array[String]): Unit = {
    val result = if (args.nonEmpty) ('α' to 'ω').toSet.diff(Set('ς')).toList
                 else ('Α' to 'Ρ').toList ++ ('Σ' to 'Ω').toList
    println(result.mkString(" "))
  }
}

Perl under Windows -- console has no Unicode support -- (42 bytes, including spaces)
This is not my solution, I am just merely adapting the Perl solution of Denis Ibaev above, to Windows console Perl.
perl -E"say map{chr$_+151-!@ARGV*24}1..24"
ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ
$ perl -E"say map{chr$_+151-!@ARGV*24}1..24" with one or many arguments
αβγδεζηθικλμνξοπρσςτυφχψ

The console page code must be Greek of course:
chcp 737

NOTE: Just a small idea. On this page I can see that some of the answers use CHARACTERS that seem to been Unicode above 255. Therefore those characters take at least 2 bytes to code (perhaps 4 if one is using a console using 32bits Unicode chars?). Would not it be better if the contest measure was the CHARACTER unit (being Unicode or ASCII or EBCDIC ou whatever) rather than just BYTES? Would not it be simpler and more unifying (wonder if this adjectif exists in English, "unificateur" in French)?

Previous code in error:
Does not print lowercase omega.
Corrected code (70 chars) :
perl -E"$i=!@ARGV+0;@a=73;pop@a if$i;say map{chr$_+151-$i*24}1..24,@a"
ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ
perl -E"$i=!@ARGV+0;@a=73;pop@a if$i;say map{chr$_+151-$i*24}1..24,@a" foo
αβγδεζηθικλμνξοπρσςτυφχψω

I know we are not supposed to print the 'end-of-word' sigma form ('ς') but as it is a mispelling error in ancient Greek to use regular sigma ('σ') at the end of a lowercase word, I choose to print it, as the tittle of this puzzle is "Print the Greek alphabet" and that this character is part of it...


text:
Calculate the permanent as quickly as possible
The challenge is to write the fastest code possible for computing the permanent of a matrix.
The permanent of an n-by-n matrix A = (ai,j) is defined as

Here S_n represents the set of all permutations of [1, n].
As an example (from the wiki):

In this question matrices are all square and will only have the values -1 and 1 in them.
Examples
Input:
[[ 1 -1 -1  1]
 [-1 -1 -1  1]
 [-1  1 -1  1]
 [ 1 -1 -1  1]]

Permanent:
-4

Input:
[[-1 -1 -1 -1]
 [-1  1 -1 -1]
 [ 1 -1 -1 -1]
 [ 1 -1  1 -1]]

Permanent:
0

Input:
[[ 1 -1  1 -1 -1 -1 -1 -1]
 [-1 -1  1  1 -1  1  1 -1]
 [ 1 -1 -1 -1 -1  1  1  1]
 [-1 -1 -1  1 -1  1  1  1]
 [ 1 -1 -1  1  1  1  1 -1]
 [-1  1 -1  1 -1  1  1 -1]
 [ 1 -1  1 -1  1 -1  1 -1]
 [-1 -1  1 -1  1  1  1  1]]

Permanent:
192

Input:
[[1, -1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1],
 [1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1],
 [-1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1],
 [-1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1],
 [-1, 1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, 1],
 [1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1],
 [1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1],
 [1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1],
 [1, -1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1],
 [-1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1],
 [-1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1],
 [1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1],
 [-1, 1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1],
 [1, 1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1],
 [1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1],
 [1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1],
 [-1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1],
 [1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1],
 [1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, 1],
 [-1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1]]

Permanent:
1021509632

The task
You should write code that, given an n by n matrix, outputs its permanent.
As I will need to test your code it would be helpful if you could give a simple way for me to give a matrix as input to your code, for example by reading from standard in.
Be warned that the permanent can be large (the all 1s matrix is the extreme case).
Scores and ties
I will test your code on random +-1 matrices of increasing size and stop the first time your code takes more than 1 minute on my computer.  The scoring matrices will be consistent for all submissions in order to ensure fairness.
If two people get the same score then the winner is the one which is fastest for that value of n. If those are within 1 second of each other then it is the one posted first.
Languages and libraries
You can use any available language and libraries you like but no pre-existing function to compute the permanent. Where feasible, it would be good to be able to run your code so please include a full explanation for how to run/compile your code in Linux if at all possible.`
Reference implementations
There is already a codegolf question question with lots of code in different languages for computing the permanent for small matrices. Mathematica and Maple also both have permanent implementations if you can access those.
My Machine The timings will be run on my 64-bit machine. This is a standard ubuntu install with 8GB RAM, AMD FX-8350 Eight-Core Processor and Radeon HD 4250.  This also means I need to be able to run your code.
Low level information about my machine
cat /proc/cpuinfo/|grep flags gives

flags     : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov
  pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt
  pdpe1gb rdtscp lm constant_tsc rep_good nopl nonstop_tsc extd_apicid
  aperfmperf pni pclmulqdq monitor ssse3 fma cx16 sse4_1 sse4_2 popcnt
  aes xsave avx f16c lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a
  misalignsse 3dnowprefetch osvw ibs xop skinit wdt lwp fma4 tce
  nodeid_msr tbm topoext perfctr_core perfctr_nb cpb hw_pstate vmmcall
  bmi1 arat npt lbrv svm_lock nrip_save tsc_scale vmcb_clean flushbyasid
  decodeassists pausefilter pfthreshold

I will ask a closely related follow up multi-language question that doesn't suffer from the big Int problem so lovers of Scala, Nim, Julia, Rust, Bash can show off their languages too.
Leader board

n = 33 (45 seconds. 64 seconds for n = 34). Ton Hospel in C++ with g++ 5.4.0.
n = 32 (32 seconds). Dennis in C with gcc 5.4.0 using Ton Hospel's gcc flags.
n = 31 (54 seconds). Christian Sievers in Haskell
n = 31 (60 seconds). primo in rpython
n = 30 (26 seconds). ezrast in Rust
n = 28 (49 seconds). xnor with Python + pypy 5.4.1
n = 22 (25 seconds). Shebang with Python + pypy 5.4.1

Note. In practice the timings for Dennis and Ton Hospel's vary a lot for mysterious reasons. For example they seem to be faster after I have loaded a web browser! The timings quoted are the fastest in all the tests I have done.

I read the first sentence, thought 'Lembik', scrolled down, yep - Lembik.

@orlp :)  It's been a long time.

One other thing I forgot to ask in sandbox, are submissions limited to using a single thread or are multiple threads allowed? Also, I just noticed you mentioned your GPU type, are you also expecting and allowing submissions to use OpenCL or something similar? Finally, what is the deadline to when you will test our submissions?

@miles Your code can take advantage of anything my PC has to offer. That is it can use all the cores and anything you can get out of my unimpressive GPU.

Could you please include a bigger test case we can check?

@xnor I am away from a computer for 36 hours but hopefully Shebang will post his/her simple python code soon that can be used for testing. Otherwise I will post a bigger example then.

@Lembik I added a large test case. I'll wait for someone to confirm it to be sure.

@Lembik What size of the matrix do you expect? Is it allowed to mix programming languages?

@MartinRosenau You can mix in any way you like. Please do help me run your code though. It's hard to guess how fast people's code will be but anything more than n=25 is impressive.

Is Mathematica code allowed?

Can we rely on the fact that In this question matrices are all square and will only have the values -1 and 1 in them. or should solutions be theoretically correct no matter what?

What is on the flags line on your systems /proc/cpuinfo ?

@JHM Yes although it's not clear what score I can give.  Maybe you could compare your code to the python reference code ?

@SocraticPhoenix  Ideally your code should be correct for any real number inputs but I won't enforce it.

@TonHospel I will have to tell in 24 hours sorry. I am away from my computer.

One of the answer prints an approximate result, since it uses double precision floats to store the permanent. Is that allowed?

When you say "I will test your code on random +-1 matrices," I assume you mean matrices in which the entries are independent and identically distributed, from a distribution where -1 and +1 have equal probability? It would be good to be explicit about that, since the structure of the random matrices could conceivably affect the speed of the computation.

@Nathaniel Yes that is right.

Dennis Yes the answer outputted should be the exact integer not an approximation.

@SocraticPhoenix Do you know a way to use the fact that matrix entries are restricted to 1 and -1? I searched and thought a lot and didn't find one. (Well, I now use that the entries are not very big...)

@ChristianSievers I thought I might be able to do some magic with signs, but it didn't pan out...

gcc C++ n ≈ 36 (57 seconds on my system)
Uses Glynn formula with a Gray code for updates if all column sums are even, otherwise uses Ryser's method. Threaded and vectorized. Optimized for AVX, so don't expect much on older processors. Don't bother with n>=35 for a matrix with only +1's even if your system is fast enough since the signed 128 bit accumulator will overflow. For random matrices you will probably not hit the overflow. For n>=37 the internal multipliers will start to overflow for an all 1/-1 matrix. So only use this program for n<=36.
Just give the matrix elements on STDIN separated by any kind of whitespace
permanent
1 2
3 4
^D

permanent.cpp:
/*
  Compile using something like:
    g++ -Wall -O3 -march=native -fstrict-aliasing -std=c++11 -pthread -s permanent.cpp -o permanent
*/

#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <cstdint>
#include <climits>
#include <array>
#include <vector>
#include <thread>
#include <future>
#include <ctgmath>
#include <immintrin.h>

using namespace std;

bool const DEBUG = false;
int const CACHE = 64;

using Index  = int_fast32_t;
Index glynn;
// Number of elements in our vectors
Index const POW   = 3;
Index const ELEMS = 1 << POW;
// Over how many floats we distribute each row
Index const WIDTH = 9;
// Number of bits in the fraction part of a floating point number
int const FLOAT_MANTISSA = 23;
// Type to use for the first add/multiply phase
using Sum  = float;
using SumN = __restrict__ Sum __attribute__((vector_size(ELEMS*sizeof(Sum))));
// Type to convert to between the first and second phase
using ProdN = __restrict__ int32_t __attribute__((vector_size(ELEMS*sizeof(int32_t))));
// Type to use for the third and last multiply phase.
// Also used for the final accumulator
using Value = __int128;
using UValue = unsigned __int128;

// Wrap Value so C++ doesn't really see it and we can put it in vectors etc.
// Needed since C++ doesn't fully support __int128
struct Number {
    Number& operator+=(Number const& right) {
        value += right.value;
        return *this;
    }
    // Output the value
    void print(ostream& os, bool dbl = false) const;
    friend ostream& operator<<(ostream& os, Number const& number) {
        number.print(os);
        return os;
    }

    Value value;
};

using ms = chrono::milliseconds;

auto nr_threads = thread::hardware_concurrency();
vector<Sum> input;

// Allocate cache aligned datastructures
template<typename T>
T* alloc(size_t n) {
    T* mem = static_cast<T*>(aligned_alloc(CACHE, sizeof(T) * n));
    if (mem == nullptr) throw(bad_alloc());
    return mem;
}

// Work assigned to thread k of nr_threads threads
Number permanent_part(Index n, Index k, SumN** more) {
    uint64_t loops = (UINT64_C(1) << n) / nr_threads;
    if (glynn) loops /= 2;
    Index l = loops < ELEMS ? loops : ELEMS;
    loops /= l;
    auto from = loops * k;
    auto to   = loops * (k+1);

    if (DEBUG) cout << "From=" << from << "\n";
    uint64_t old_gray = from ^ from/2;
    uint64_t bit = 1;
    bool bits = (to-from) & 1;

    Index nn = (n+WIDTH-1)/WIDTH;
    Index ww = nn * WIDTH;
    auto column = alloc<SumN>(ww);
    for (Index i=0; i<n; ++i)
        for (Index j=0; j<ELEMS; ++j) column[i][j] = 0;
    for (Index i=n; i<ww; ++i)
        for (Index j=0; j<ELEMS; ++j) column[i][j] = 1;
    Index b;
    if (glynn) {
        b = n > POW+1 ? n - POW - 1: 0;
        auto c = n-1-b;
        for (Index k=0; k<l; k++) {
            Index gray = k ^ k/2;
            for (Index j=0; j< c; ++j)
                if (gray & 1 << j)
                    for (Index i=0; i<n; ++i)
                        column[i][k] -= input[(b+j)*n+i];
                else
                    for (Index i=0; i<n; ++i)
                        column[i][k] += input[(b+j)*n+i];
        }
        for (Index i=0; i<n; ++i)
            for (Index k=0; k<l; k++)
                column[i][k] += input[n*(n-1)+i];

        for (Index k=1; k<l; k+=2)
            column[0][k] = -column[0][k];

        for (Index i=0; i<b; ++i, bit <<= 1) {
            if (old_gray & bit) {
                bits = bits ^ 1;
                for (Index j=0; j<ww; ++j)
                    column[j] -= more[i][j];
            } else {
                for (Index j=0; j<ww; ++j)
                    column[j] += more[i][j];
            }
        }

        for (Index i=0; i<n; ++i)
            for (Index k=0; k<l; k++)
                column[i][k] /= 2;
    } else {
        b = n > POW ? n - POW : 0;
        auto c = n-b;
        for (Index k=0; k<l; k++) {
            Index gray = k ^ k/2;
            for (Index j=0; j<c; ++j)
                if (gray & 1 << j)
                    for (Index i=0; i<n; ++i)
                        column[i][k] -= input[(b+j)*n+i];
        }

        for (Index k=1; k<l; k+=2)
            column[0][k] = -column[0][k];

        for (Index i=0; i<b; ++i, bit <<= 1) {
            if (old_gray & bit) {
                bits = bits ^ 1;
                for (Index j=0; j<ww; ++j)
                    column[j] -= more[i][j];
            }
        }
    }

    if (DEBUG) {
        for (Index i=0; i<ww; ++i) {
            cout << "Column[" << i << "]=";
            for (Index j=0; j<ELEMS; ++j) cout << " " << column[i][j];
            cout << "\n";
        }
    }

    --more;
    old_gray = (from ^ from/2) | UINT64_C(1) << b;
    Value total = 0;
    SumN accu[WIDTH];
    for (auto p=from; p<to; ++p) {
        uint64_t new_gray = p ^ p/2;
        uint64_t bit = old_gray ^ new_gray;
        Index i = __builtin_ffsl(bit);
        auto diff = more[i];
        auto c = column;
        if (new_gray > old_gray) {
            // Phase 1 add/multiply.
            // Uses floats until just before loss of precision
            for (Index i=0; i<WIDTH; ++i) accu[i] = *c++ -= *diff++;

            for (Index j=1; j < nn; ++j)
                for (Index i=0; i<WIDTH; ++i) accu[i] *= *c++ -= *diff++;
        } else {
            // Phase 1 add/multiply.
            // Uses floats until just before loss of precision
            for (Index i=0; i<WIDTH; ++i) accu[i] = *c++ += *diff++;

            for (Index j=1; j < nn; ++j)
                for (Index i=0; i<WIDTH; ++i) accu[i] *= *c++ += *diff++;
        }

        if (DEBUG) {
            cout << "p=" << p << "\n";
            for (Index i=0; i<ww; ++i) {
                cout << "Column[" << i << "]=";
                for (Index j=0; j<ELEMS; ++j) cout << " " << column[i][j];
                cout << "\n";
            }
        }

        // Convert floats to int32_t
        ProdN prod32[WIDTH] __attribute__((aligned (32)));
        for (Index i=0; i<WIDTH; ++i)
            // Unfortunately gcc doesn't recognize the static_cast<int32_t>
            // as a vector pattern, so force it with an intrinsic
#ifdef __AVX__
            //prod32[i] = static_cast<ProdN>(accu[i]);
            reinterpret_cast<__m256i&>(prod32[i]) = _mm256_cvttps_epi32(accu[i]);
#else   // __AVX__
            for (Index j=0; j<ELEMS; ++j)
                prod32[i][j] = static_cast<int32_t>(accu[i][j]);
#endif  // __AVX__

        // Phase 2 multiply. Uses int64_t until just before overflow
        int64_t prod64[3][ELEMS];
        for (Index i=0; i<3; ++i) {
            for (Index j=0; j<ELEMS; ++j)
                prod64[i][j] = static_cast<int64_t>(prod32[i][j]) * prod32[i+3][j] * prod32[i+6][j];
        }
        // Phase 3 multiply. Collect into __int128. For large matrices this will
        // actually overflow but that's ok as long as all 128 low bits are
        // correct. Terms will cancel and the final sum can fit into 128 bits
        // (This will start to fail at n=35 for the all 1 matrix)
        // Strictly speaking this needs the -fwrapv gcc option
        for (Index j=0; j<ELEMS; ++j) {
            auto value = static_cast<Value>(prod64[0][j]) * prod64[1][j] * prod64[2][j];
            if (DEBUG) cout << "value[" << j << "]=" << static_cast<double>(value) << "\n";
            total += value;
        }
        total = -total;

        old_gray = new_gray;
    }

    return bits ? Number{-total} : Number{total};
}

// Prepare datastructures, Assign work to threads
Number permanent(Index n) {
    Index nn = (n+WIDTH-1)/WIDTH;
    Index ww = nn*WIDTH;

    Index rows  = n > (POW+glynn) ? n-POW-glynn : 0;
    auto data = alloc<SumN>(ww*(rows+1));
    auto pointers = alloc<SumN *>(rows+1);
    auto more = &pointers[0];
    for (Index i=0; i<rows; ++i)
        more[i] = &data[ww*i];
    more[rows] = &data[ww*rows];
    for (Index j=0; j<ww; ++j)
        for (Index i=0; i<ELEMS; ++i)
            more[rows][j][i] = 0;

    Index loops = n >= POW+glynn ? ELEMS : 1 << (n-glynn);
    auto a = &input[0];
    for (Index r=0; r<rows; ++r) {
        for (Index j=0; j<n; ++j) {
            for (Index i=0; i<loops; ++i)
                more[r][j][i] = j == 0 && i %2 ? -*a : *a;
            for (Index i=loops; i<ELEMS; ++i)
                more[r][j][i] = 0;
            ++a;
        }
        for (Index j=n; j<ww; ++j)
            for (Index i=0; i<ELEMS; ++i)
                more[r][j][i] = 0;
    }

    if (DEBUG)
        for (Index r=0; r<=rows; ++r)
            for (Index j=0; j<ww; ++j) {
                cout << "more[" << r << "][" << j << "]=";
                for (Index i=0; i<ELEMS; ++i)
                    cout << " " << more[r][j][i];
                cout << "\n";
            }

    // Send work to threads...
    vector<future<Number>> results;
    for (auto i=1U; i < nr_threads; ++i)
        results.emplace_back(async(DEBUG ? launch::deferred: launch::async, permanent_part, n, i, more));
    // And collect results
    auto r = permanent_part(n, 0, more);
    for (auto& result: results)
        r += result.get();

    free(data);
    free(pointers);

    // For glynn we should double the result, but we will only do this during
    // the final print. This allows n=34 for an all 1 matrix to work
    // if (glynn) r *= 2;
    return r;
}

// Print 128 bit number
void Number::print(ostream& os, bool dbl) const {
    const UValue BILLION = 1000000000;

    UValue val;
    if (value < 0) {
        os << "-";
        val = -value;
    } else
        val = value;
    if (dbl) val *= 2;

    uint32_t output[5];
    for (int i=0; i<5; ++i) {
        output[i] = val % BILLION;
        val /= BILLION;
    }
    bool print = false;
    for (int i=4; i>=0; --i) {
        if (print) {
            os << setfill('0') << setw(9) << output[i];
        } else if (output[i] || i == 0) {
            print = true;
            os << output[i];
        }
    }
}

// Read matrix, check for sanity
void my_main() {
    Sum a;
    while (cin >> a)
        input.push_back(a);

    size_t n = sqrt(input.size());
    if (input.size() != n*n)
        throw(logic_error("Read " + to_string(input.size()) +
                          " elements which does not make a square matrix"));

    vector<double> columns_pos(n, 0);
    vector<double> columns_neg(n, 0);
    Sum *p = &input[0];
    for (size_t i=0; i<n; ++i)
        for (size_t j=0; j<n; ++j, ++p) {
            if (*p >= 0) columns_pos[j] += *p;
            else         columns_neg[j] -= *p;
        }
    std::array<double,WIDTH> prod;
    prod.fill(1);

    int32_t odd = 0;
    for (size_t j=0; j<n; ++j) {
        prod[j%WIDTH] *= max(columns_pos[j], columns_neg[j]);
        auto sum = static_cast<int32_t>(columns_pos[j] - columns_neg[j]);
        odd |= sum;
    }
    glynn = (odd & 1) ^ 1;
    for (Index i=0; i<WIDTH; ++i)
        // A float has an implicit 1. in front of the fraction so it can
        // represent 1 bit more than the mantissa size. And 1 << (mantissa+1)
        // itself is in fact representable
        if (prod[i] && log2(prod[i]) > FLOAT_MANTISSA+1)
            throw(range_error("Values in matrix are too large. A subproduct reaches " + to_string(prod[i]) + " which doesn't fit in a float without loss of precision"));

    for (Index i=0; i<3; ++i) {
        auto prod3 = prod[i] * prod[i+3] * prod[i+6];
        if (log2(prod3) >= CHAR_BIT*sizeof(int64_t)-1)
            throw(range_error("Values in matrix are too large. A subproduct reaches " + to_string(prod3) + " which doesn't fit in an int64"));
    }

    nr_threads = pow(2, ceil(log2(static_cast<float>(nr_threads))));
    uint64_t loops = UINT64_C(1) << n;
    if (glynn) loops /= 2;
    if (nr_threads * ELEMS > loops)
        nr_threads = max(loops / ELEMS, UINT64_C(1));
    // if (DEBUG) nr_threads = 1;

    cout << n << " x " << n << " matrix, method " << (glynn ? "Glynn" : "Ryser") << ", " << nr_threads << " threads" << endl;

    // Go for the actual calculation
    auto start = chrono::steady_clock::now();
    auto perm = permanent(n);
    auto end = chrono::steady_clock::now();
    auto elapsed = chrono::duration_cast<ms>(end-start).count();

    cout << "Permanent=";
    perm.print(cout, glynn);
    cout << " (" << elapsed / 1000. << " s)" << endl;
}

// Wrapper to print any exceptions
int main() {
    try {
        my_main();
    } catch(exception& e) {
        cerr << "Error: " << e.what() << endl;
        exit(EXIT_FAILURE);
    }
    exit(EXIT_SUCCESS);
}

flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl nonstop_tsc extd_apicid aperfmperf pni pclmulqdq monitor ssse3 fma cx16 sse4_1 sse4_2 popcnt aes xsave avx f16c lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw ibs xop skinit wdt lwp fma4 tce nodeid_msr tbm topoext perfctr_core perfctr_nb cpb hw_pstate vmmcall bmi1 arat npt lbrv svm_lock nrip_save tsc_scale vmcb_clean flushbyasid decodeassists pausefilter pfthreshold

I am still debugging my test harness to run your code but it looks very fast, thank you!   I was wondering if the larger int size might be causing a speed problem (as you suggested). I saw https://accu.org/index.php/articles/1849 in case its of any interest.

I had to modify your code to remove the quick_exit as those made it very hard to use in a test harness.  Out of interest, why are you using Ryser's formula when the wiki seems to claim the other one should be twice as fast?

@Lembik I switched to Ryser's formula since with the other I need to scale back by 2 << (n-1) at the end which means my int128 accumulator overflowed far before that point.

@TonHospel Oh I see.  Do you think there is any further room for improvement now?

@Lembik Yes :-)

C99, n ≈ 33 (35 seconds)
#include <stdint.h>
#include <stdio.h>

#define CHUNK_SIZE 12
#define NUM_THREADS 8

#define popcnt __builtin_popcountll
#define BILLION (1000 * 1000 * 1000)
#define UPDATE_ROW_PPROD() \
    update_row_pprod(row_pprod, row, rows, row_sums, mask, mask_popcnt)

typedef __int128 int128_t;

static inline int64_t update_row_pprod
(
    int64_t* row_pprod, int64_t row, int64_t* rows,
    int64_t* row_sums, int64_t mask, int64_t mask_popcnt
)
{
    int64_t temp = 2 * popcnt(rows[row] & mask) - mask_popcnt;

    row_pprod[0] *= temp;
    temp -= 1;
    row_pprod[1] *= temp;
    temp -= row_sums[row];
    row_pprod[2] *= temp;
    temp += 1;
    row_pprod[3] *= temp;

    return row + 1;
}

int main(int argc, char* argv[])
{
    int64_t size = argc - 1, rows[argc - 1];
    int64_t row_sums[argc - 1];
    int128_t permanent = 0, sign = size & 1 ? -1 : 1;

    if (argc == 2)
    {
        printf("%d\n", argv[1][0] == '-' ? -1 : 1);
        return 0;
    }

    for (int64_t row = 0; row < size; row++)
    {
        char positive = argv[row + 1][0] == '+' ? '-' : '+';

        sign *= ',' - positive;
        rows[row] = row_sums[row] = 0;

        for (char* p = &argv[row + 1][1]; *p; p++)
        {
            rows[row] <<= 1;
            rows[row] |= *p == positive;
            row_sums[row] += *p == positive;
        }

        row_sums[row] = 2 * row_sums[row] - size;
    }

    #pragma omp parallel for reduction(+:permanent) num_threads(NUM_THREADS)
    for (int64_t mask = 1; mask < 1LL << (size - 1); mask += 2)
    {
        int64_t mask_popcnt = popcnt(mask);
        int64_t row = 0;
        int128_t row_prod = 1 - 2 * (mask_popcnt & 1);
        int128_t row_prod_high = -row_prod;
        int128_t row_prod_inv = row_prod;
        int128_t row_prod_inv_high = -row_prod;

        for (int64_t chunk = 0; chunk < size / CHUNK_SIZE; chunk++)
        {
            int64_t row_pprod[4] = {1, 1, 1, 1};

            for (int64_t i = 0; i < CHUNK_SIZE; i++)
                row = UPDATE_ROW_PPROD();

            row_prod *= row_pprod[0], row_prod_high *= row_pprod[1];
            row_prod_inv *= row_pprod[3], row_prod_inv_high *= row_pprod[2];
        }

        int64_t row_pprod[4] = {1, 1, 1, 1};

        while (row < size)
            row = UPDATE_ROW_PPROD();

        row_prod *= row_pprod[0], row_prod_high *= row_pprod[1];
        row_prod_inv *= row_pprod[3], row_prod_inv_high *= row_pprod[2];
        permanent += row_prod + row_prod_high + row_prod_inv + row_prod_inv_high;
    }

    permanent *= sign;

    if (permanent < 0)
        printf("-"), permanent *= -1;

    int32_t output[5], print = 0;

    output[0] = permanent % BILLION, permanent /= BILLION;
    output[1] = permanent % BILLION, permanent /= BILLION;
    output[2] = permanent % BILLION, permanent /= BILLION;
    output[3] = permanent % BILLION, permanent /= BILLION;
    output[4] = permanent % BILLION;

    if (output[4])
        printf("%u", output[4]), print = 1;
    if (print)
        printf("%09u", output[3]);
    else if (output[3])
        printf("%u", output[3]), print = 1;
    if (print)
        printf("%09u", output[2]);
    else if (output[2])
        printf("%u", output[2]), print = 1;
    if (print)
        printf("%09u", output[1]);
    else if (output[1])
        printf("%u", output[1]), print = 1;
    if (print)
        printf("%09u\n", output[0]);
    else
        printf("%u\n", output[0]);
}

Input is currently a bit cumbersome; it is taken with rows as command line arguments, where each entry is represented by its sign, i.e., + indicates a 1 and - indicates a -1.
Test run
$ gcc -Wall -std=c99 -march=native -Ofast -fopenmp -fwrapv -o permanent permanent.c
$ ./permanent +--+ ---+ -+-+ +--+
-4
$ ./permanent ---- -+-- +--- +-+-
0
$ ./permanent +-+----- --++-++- +----+++ ---+-+++ +--++++- -+-+-++- +-+-+-+- --+-++++
192
$ ./permanent +-+--+++----++++-++- +-+++++-+--+++--+++- --+++----+-+++---+-- ---++-++++++------+- -+++-+++---+-+-+++++ +-++--+-++++-++-+--- +--+---+-++++---+++- +--+-++-+++-+-+++-++ +-----+++-----++-++- --+-+-++-+-++++++-++ -------+----++++---- ++---++--+-++-++++++ -++-----++++-----+-+ ++---+-+----+-++-+-+ +++++---+++-+-+++-++ +--+----+--++-+----- -+++-++--+++--++--++ ++--++-++-+++-++-+-+ +++---+--++---+----+ -+++-------++-++-+--
1021509632
$ time ./permanent +++++++++++++++++++++++++++++++{,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,}     # 31
8222838654177922817725562880000000

real    0m8.365s
user    1m6.504s
sys     0m0.000s
$ time ./permanent ++++++++++++++++++++++++++++++++{,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,}   # 32
263130836933693530167218012160000000

real    0m17.013s
user    2m15.226s
sys     0m0.001s
$ time ./permanent +++++++++++++++++++++++++++++++++{,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,} # 33
8683317618811886495518194401280000000

real    0m34.592s
user    4m35.354s
sys     0m0.001s

Do you have any ideas for improvements?

@xnor A few. I want to try packed multiplication with SSE and partially unrolling the big loop (to see if I can speed up parallelization and to compute more than 4 values at once without calling popcnt). If that saves any time, the next big hurdle is the integer type. For randomly generated matrices, the permanent is comparatively small. If I can find an easy way to compute a bound before doing the actual calculation, I might wrap the whole thing in a big conditional.

@Dennis About unrolling the loop, a small possible optimization is to make the top row be all +1's.

@xnor Yeah, I tried that at some point, but then reverted the change to try something else (which didn't work out at all). The bottleneck seems to be the integer multiplication (which is slow for 64 bits and really slow for 128), which is why I hope SSE will help a bit.

@Dennis I see. About bounds, one non-obvious bound is in terms of the operator norm |Per(M)|<=|M|^n. See https://arxiv.org/pdf/1606.07474v1.pdf

Let us continue this discussion in chat.

You know, I really like this input format. Do you mind if I use it in my answer?

@R.Kap Not at all. Go ahead.

Python 2, n ≈ 28
from operator import mul

def fast_glynn_perm(M):
    row_comb = [sum(c) for c in zip(*M)]
    n=len(M)

    total = 0
    old_grey = 0
    sign = +1

    binary_power_dict = {2**i:i for i in range(n)}
    num_loops = 2**(n-1)

    for bin_index in xrange(1, num_loops + 1):
        total += sign * reduce(mul, row_comb)

        new_grey = bin_index^(bin_index/2)
        grey_diff = old_grey ^ new_grey
        grey_diff_index = binary_power_dict[grey_diff]

        new_vector = M[grey_diff_index]
        direction = 2 * cmp(old_grey,new_grey)

        for i in range(n):
            row_comb[i] += new_vector[i] * direction

        sign = -sign
        old_grey = new_grey

    return total/num_loops

Uses the Glynn formula with a Gray code for updates. Runs up to n=23 in a minute on my machine. One can surely do better implementing this in a faster language and with better data structures. This doesn't use that the matrix is ±1-valued.
A Ryser formula implementation is very similar, summing over all 0/1 vectors of coefficients rather than ±1-vectors. It takes about twice as long as Glynn's formula because adds over all 2^n such vectors, whereas Glynn's halves that using symmetry to only those starting with +1.
from operator import mul

def fast_ryser_perm(M):
    n=len(M)
    row_comb = [0] * n

    total = 0
    old_grey = 0
    sign = +1

    binary_power_dict = {2**i:i for i in range(n)}
    num_loops = 2**n

    for bin_index in range(1, num_loops) + [0]:
        total += sign * reduce(mul, row_comb)

        new_grey = bin_index^(bin_index/2)
        grey_diff = old_grey ^ new_grey
        grey_diff_index = binary_power_dict[grey_diff]

        new_vector = M[grey_diff_index]
        direction = cmp(old_grey, new_grey)

        for i in range(n):
            row_comb[i] += new_vector[i] * direction

        sign = -sign
        old_grey = new_grey

    return total * (-1)**n

Awesome.   Have you got pypy to test too?

@Lembik No, I don't have much installed.

I will use pypy when I test it too.  Can you see how to implement the other fast formula? I find it confusing.

@Lembik What's the other fast formula?

The Balasubramanian-Bax/Franklin-Glynn formula .

As reference, on my machine with pypy this was able to easily calculate n=28 in 44.6 seconds. Lembik's system seems to be fairly comparable to mine in speed if not a bit faster.

what does it mean p ^ p/2 the xor of p and p/2?

@RosLuP Yes, that's the formula for the p'th element of the Grey code.

If p=(2^n) -1 => p^(p/2)=2^(n-1)

For pypy the top tip is to remove all the builtin functions. For example, zip and sum and replace by pure python code.

Haskell, n=31 (54s)
With a lot of invaluable contributions by @Angs: use Vector, use short circuit products, look at odd n.
import Control.Parallel.Strategies
import qualified Data.Vector.Unboxed as V
import Data.Int

type Row = V.Vector Int8

x :: Row -> [Row] -> Integer -> Int -> Integer
x p (v:vs) m c = let c' = c - 1
                     r = if c>0 then parTuple2 rseq rseq else r0
                     (a,b) = ( x p                  vs m    c' ,
                               x (V.zipWith(-) p v) vs (-m) c' )
                             `using` r
                 in a+b
x p _      m _ = prod m p

prod :: Integer -> Row -> Integer
prod m p = if 0 `V.elem` p then 0
                           else V.foldl' (\a b->a*fromIntegral b) m p

p, pt :: [Row] -> Integer
p (v:vs) = x (foldl (V.zipWith (+)) v vs) (map (V.map (2*)) vs) 1 11
           `div` 2^(length vs)
p [] = 1 -- handle 0x0 matrices too  :-)

pt (v:vs) | even (length vs) = p ((V.map (2*) v) : vs ) `div` 2
pt mat                       = p mat

main = getContents >>= print . pt . map V.fromList . read

My first attempts at parallelism in Haskell. You can see a lot of optimization steps through the revision history. Amazingly, it were mostly very small changes. The code is based on the formula in the section "Balasubramanian-Bax/Franklin-Glynn formula" in the Wikipedia article on computing the permanent.
p computes the permanent. It is called via pt which transforms the matrix in a way that is always valid, but especially useful for the matrices that we get here.
Compile with ghc -O2 -threaded -fllvm -feager-blackholing -o <name> <name>.hs. To run with parallelisation, give it runtime parameters like this: ./<name> +RTS -N. Input is from stdin with nested comma separated lists in brackets like [[1,2],[3,4]] as in the last example (newlines allowed everywhere).

Thank you.  Some comments. line 3 is repeated in the source. Also it doesn't seem to actually run in parallel. At least "top" doesn't show more than 1 core working.

Oops, that's the result of partially changing the code. Did you use the specified runtime parameters?

My mistake! Makes it to 26 now.

Oh, I hoped for more with 8 cores...

This is my testing code https://bpaste.net/show/e74c87dfd19d in case you want to try it.

I was able to get a speed improvement of 20-25% by plugging in Data.Vector. The changes excluding changed function types: import qualified Data.Vector as V, x (V.zipWith(-) p v) vs (-m) c' ), p (v:vs) = x (foldl (V.zipWith (+)) v vs) (map (V.map (2*)) vs) 1 11, main = getContents >>= print . p  . map V.fromList . read

@Angs Thanks a lot! I didn't really feel like looking into better suited datatypes. It's amazing how little things have to change (also had to use V.product). That only gave me ~10%. Changed the code so that the vectors only contain Ints. That's okay because they are only added, the big numbers come from multiplication. Then it was ~20%. I had tried the same change with the old code, but at that time it slowed it down. I tried again because it allows to use unboxed vectors, which helped a lot!

@christian-sievers glab I could be of help. Here's another fun luck-based optimization I found: x p _      m _ =  m * (sum $ V.foldM' (\a b -> if b==0 then Nothing else Just $ a*fromIntegral b) 1 p) - product as a monadic fold where 0 is a special case. Seems to be beneficial more often than not.

@Angs Great! I changed that into a form that doesn't need Transversable (I see your not changing product eatlier was no mistake...) for ghc from e.g. Debian stable. It's using the form of the input, but that seems fine: we're not relying on it, only optimizing for it. Makes timing much more exciting: my random 30x30 matrix is slightly faster than 29x29, but then 31x31 take 4x time. - That INLINE doesn't seem to work for me. AFAIK it's ignored for recursive functions.

@christian-sievers Yeah, I was about to say something about that product  but forgot. It seems only even lengths have zeros in p, so for odd length we should use the regular product instead of the short circuiting to get the best of both worlds.

@Angs But that's only true for this special kind of input. And the overhead isn't that bad.

Much faster indeed!

@Angs Thanks for your observation that there are no zeros in the odd n case. It's obvious in hindsight, but I may not have noticed it. (It also explains that my results with 29x29, 30x30 and 31x31 matrices were nothing special.) Now that you made me think about it, I found a way to force zeros into the odd case.

Faster again! Out of interest, how hard would it be for your code to support floating point inputs?

@lembik I think I can answer that for you: just replace all Int8 and Integer with Double, remove the fromIntegral and change _`div`_ to /. Was n=30 close? :)

@Angs Thank you.There is a great deal of non-determinism in the run times so I ran it a few more times and eventually got to 57 seconds for n - 30 :)

@lembik that's weird. I was wondering because on my system, n+1 is always faster than n when n is odd. You can also change m * prod p to m * V.product p because with floating point inputs the optimization won't work.

@Lembik Yes, all the things @Angs said, and you can undo the optimization for the odd case, which costs almost nothing, but is completely useless after undoing the also useless product optimization: in main replace pt with p, and remove the definition of pt. (And ofprod. And the last two import lines.) @Angs, do you have that optimization? With it I'm back to smoothly increasing running times.

@ChristianSievers I thought I had but I had rolled my own main and forgot to change p to pt.

By the way, is the 11 experimental or how did you end up with it?

@Angs Yes, completely experimental and totally not understood by me. The number is higher than expected, and statistics (with run time option -s) still sometimes show GC'ed sparks (why does that happen at all?), but lowering the number such that most sparks are converted slightly increases execution time.

@Lembik For the new version, please note the added compiler options

Python 2, n = 22 [Reference]
This is the 'reference' implementation I shared with Lembik yesterday, it misses making it to n=23 by a few seconds on his machine, on my machine it does it in about 52 seconds. To achieve these speeds you need to run this through PyPy.
The first function calculates the permanent similar to how the determinant could be calculated, by going over each submatrix until you are left with a 2x2 which you can apply the basic rule to. It is incredibly slow.
The second function is the one implementing the Ryser function (the second equation listed in Wikipedia). The set S is essentially the powerset of the numbers {1,...,n} (variable s_list in the code).
from random import *
from time import time
from itertools import*

def perm(a): # naive method, recurses over submatrices, slow
    if len(a) == 1:
        return a[0][0]
    elif len(a) == 2:
        return a[0][0]*a[1][1]+a[1][0]*a[0][1]
    else:
        tsum = 0
        for i in xrange(len(a)):
            transposed = [zip(*a)[j] for j in xrange(len(a)) if j != i]
            tsum += a[0][i] * perm(zip(*transposed)[1:])
        return tsum

def perm_ryser(a): # Ryser's formula, using matrix entries
    maxn = len(a)
    n_list = range(1,maxn+1)
    s_list = chain.from_iterable(combinations(n_list,i) for i in range(maxn+1))
    total = 0
    for st in s_list:
        stotal = (-1)**len(st)
        for i in xrange(maxn):
            stotal *= sum(a[i][j-1] for j in st)
        total += stotal
    return total*((-1)**maxn)

def genmatrix(d):
    mat = []
    for x in xrange(d):
        row = []
        for y in xrange(d):
            row.append([-1,1][randrange(0,2)])
        mat.append(row)
    return mat

def main():
    for i in xrange(1,24):
        k = genmatrix(i)
        print 'Matrix: (%dx%d)'%(i,i)
        print '\n'.join('['+', '.join(`j`.rjust(2) for j in a)+']' for a in k)
        print 'Permanent:',
        t = time()
        p = perm_ryser(k)
        print p,'(took',time()-t,'seconds)'

if __name__ == '__main__':
    main()

I think you should rephrase the description "similar to how the determinant would be calculated". It's not like the method for determinants is slow for permanents, but one slow method for determinants works similarly (and as slowly) for permanents.

@ChristianSievers Good point, I've altered it.

Rust + extprim
This straightforward Ryser with Gray code implementation takes about 65 90 seconds to run n=31 on my laptop. I imagine your machine will get there in well under 60s. I'm using extprim 1.1.1 for i128.
I have never used Rust and have no idea what I'm doing. No compiler options other than whatever cargo build --release does. Comments/suggestions/optimizations are appreciated.
Invocation is identical to Dennis' program.
use std::env;
use std::thread;
use std::sync::Arc;
use std::sync::mpsc;

extern crate extprim;
use extprim::i128::i128;

static THREADS : i64 = 8; // keep this a power of 2.

fn main() {
  // Read command line args for the matrix, specified like
  // "++- --- -+-" for [[1, 1, -1], [-1, -1, -1], [-1, 1, -1]].
  let mut args = env::args();
  args.next();

  let mat : Arc<Vec<Vec<i64>>> = Arc::new(args.map( |ss|
    ss.trim().bytes().map( |cc| if cc == b'+' {1} else {-1}).collect()
  ).collect());

  // Figure how many iterations each thread has to do.
  let size = 2i64.pow(mat.len() as u32);
  let slice_size = size / THREADS; // Assumes divisibility.

  let mut accumulator : i128;
  if slice_size >= 4 { // permanent() requires 4 divides slice_size
    let (tx, rx) = mpsc::channel();

    // Launch threads.
    for ii in 0..THREADS {
      let mat = mat.clone();
      let tx = tx.clone();
      thread::spawn(move ||
        tx.send(permanent(&mat, ii * slice_size, (ii+1) * slice_size))
      );
    }

    // Accumulate results.
    accumulator = extprim::i128::ZERO;
    for _ in 0..THREADS {
      accumulator += rx.recv().unwrap();
    }
  }
  else { // Small matrix, don't bother threading.
    accumulator = permanent(&mat, 0, size);
  }
  println!("{}", accumulator);
}

fn permanent(mat: &Vec<Vec<i64>>, start: i64, end: i64) -> i128 {
  let size = mat.len();
  let sentinel = std::i64::MAX / size as i64;

  let mut bits : Vec<bool> = Vec::with_capacity(size);
  let mut sums : Vec<i64> = Vec::with_capacity(size);

  // Initialize gray code bits.
  let gray_number = start ^ (start / 2);

  for row in 0..size {
    bits.push((gray_number >> row) % 2 == 1);
    sums.push(0);
  }

  // Initialize column sums
  for row in 0..size {
    if bits[row] {
      for column in 0..size {
        sums[column] += mat[row][column];
      }
    }
  }

  // Do first two iterations with initial sums
  let mut total = product(&sums, sentinel);
  for column in 0..size {
    sums[column] += mat[0][column];
  }
  bits[0] = true;

  total -= product(&sums, sentinel);

  // Do rest of iterations updating gray code bits incrementally
  let mut gray_bit : usize;
  let mut idx = start + 2;
  while idx < end {
    gray_bit = idx.trailing_zeros() as usize;

    if bits[gray_bit] {
      for column in 0..size {
        sums[column] -= mat[gray_bit][column];
      }
      bits[gray_bit] = false;
    }
    else {
      for column in 0..size {
        sums[column] += mat[gray_bit][column];
      }
      bits[gray_bit] = true;
    }

    total += product(&sums, sentinel);

    if bits[0] {
      for column in 0..size {
        sums[column] -= mat[0][column];
      }
      bits[0] = false;
    }
    else {
      for column in 0..size {
        sums[column] += mat[0][column];
      }
      bits[0] = true;
    }

    total -= product(&sums, sentinel);
    idx += 2;
  }
  return if size % 2 == 0 {total} else {-total};
}

#[inline]
fn product(sums : &Vec<i64>, sentinel : i64) -> i128 {
  let mut ret : Option<i128> = None;
  let mut tally = sums[0];
  for ii in 1..sums.len() {
    if tally.abs() >= sentinel {
      ret = Some(ret.map_or(i128::new(tally), |n| n * i128::new(tally)));
      tally = sums[ii];
    }
    else {
      tally *= sums[ii];
    }
  }
  if ret.is_none() {
    return i128::new(tally);
  }
  return ret.unwrap() * i128::new(tally);
}

Could you give copy and pasteable command lines for installing extprim and compiling the code please.

The output looks like "i128!(-2)" where -2 is the correct answer. Is this expected and could you change it to just to output the permanent please?

@Lembik: Output should be fixed now. Looks like you figured out compilation, but I threw it in Git so you can do git clone https://gitlab.com/ezrast/permanent.git; cd permanent; cargo build --release if you want to be sure of having the same setup as me. Cargo will handle dependencies. Binary goes in target/release.

Unfortunately this gives the wrong answer for n = 29. https://bpaste.net/show/99d6e826d968

@Lembik gah, sorry, intermediate values were overflowing earlier than I thought. It's fixed, though the program is a lot slower now.

Mathematica, n ≈ 20
p[m_] := Last[Fold[Take[ListConvolve[##, {1, -1}, 0], 2^Length[m]]&,
  Table[If[IntegerQ[Log2[k]], m[[j, Log2[k] + 1]], 0], {j, n}, {k, 0, 2^Length[m] - 1}]]]

Using the Timing command, a 20x20 matrix requires about 48 seconds on my system. This is not exactly as efficient as the other since it relies on the fact that the permanent can be found as the coefficient of the product of polymomials from each row of the matrix. Efficient polynomial multiplication is performed by creating the coefficient lists and performing convolution using ListConvolve. This requires about O(2n n2) time assuming convolution is performed using a Fast Fourier transform or similar which requires O(n log n) time.

RPython 5.4.1, n ≈ 32 (37 seconds)
from rpython.rlib.rtime import time
from rpython.rlib.rarithmetic import r_int, r_uint
from rpython.rlib.rrandom import Random
from rpython.rlib.rposix import pipe, close, read, write, fork, waitpid
from rpython.rlib.rbigint import rbigint

from math import log, ceil
from struct import pack

bitsize = len(pack('l', 1)) * 8 - 1

bitcounts = bytearray([0])
for i in range(16):
  b = bytearray([j+1 for j in bitcounts])
  bitcounts += b

def bitcount(n):
  bits = 0
  while n:
    bits += bitcounts[n & 65535]
    n >>= 16
  return bits

def main(argv):
  if len(argv) < 2:
    write(2, 'Usage: %s NUM_THREADS [N]'%argv[0])
    return 1
  threads = int(argv[1])

  if len(argv) > 2:
    n = int(argv[2])
    rnd = Random(r_uint(time()*1000))
    m = []
    for i in range(n):
      row = []
      for j in range(n):
        row.append(1 - r_int(rnd.genrand32() & 2))
      m.append(row)
  else:
    m = []
    strm = ""
    while True:
      buf = read(0, 4096)
      if len(buf) == 0:
        break
      strm += buf
    rows = strm.split("\n")
    for row in rows:
      r = []
      for val in row.split(' '):
        r.append(int(val))
      m.append(r)
    n = len(m)

  a = []
  for row in m:
    val = 0
    for v in row:
      val = (val << 1) | -(v >> 1)
    a.append(val)

  batches = int(ceil(n * log(n) / (bitsize * log(2))))

  pids = []
  handles = []
  total = rbigint.fromint(0)
  for i in range(threads):
    r, w = pipe()
    pid = fork()
    if pid:
      close(w)
      pids.append(pid)
      handles.append(r)
    else:
      close(r)
      total = run(n, a, i, threads, batches)
      write(w, total.str())
      close(w)
      return 0

  for pid in pids:
    waitpid(pid, 0)

  for handle in handles:
    strval = read(handle, 256)
    total = total.add(rbigint.fromdecimalstr(strval))
    close(handle)

  print total.rshift(n-1).str()

  return 0

def run(n, a, mynum, threads, batches):
  start = (1 << n-1) * mynum / threads
  end = (1 << n-1) * (mynum+1) / threads

  dtotal = rbigint.fromint(0)
  for delta in range(start, end):
    pdelta = rbigint.fromint(1 - ((bitcount(delta) & 1) << 1))
    for i in range(batches):
      pbatch = 1
      for j in range(i, n, batches):
        pbatch *= n - (bitcount(delta ^ a[j]) << 1)
      pdelta = pdelta.int_mul(pbatch)
    dtotal = dtotal.add(pdelta)

  return dtotal

def target(*args):
  return main

To compile, download the most recent PyPy source, and execute the following:
pypy /path/to/pypy-src/rpython/bin/rpython matrix-permanent.py

The resulting executable will be named matrix-permanent-c or similiar in the current working directory.
As of PyPy 5.0, RPython's threading primitives are a lot less primitive than they used to be. Newly spawned threads require the GIL, which is more or less useless for parallel computations. I've used fork instead, so it may not work as expected on Windows, although I haven't tested fails to compile (unresolved external symbol _fork).
The executable accepts up to two command line parameters. The first is the number of threads, the second optional parameter is n. If it is provided, a random matrix will be generated, otherwise it will be read from stdin. Each row must be newline separated (without a trailing newline), and each value space separated. The third example input would be given as:
1 -1 1 -1 -1 1 1 1 -1 -1 -1 -1 1 1 1 1 -1 1 1 -1
1 -1 1 1 1 1 1 -1 1 -1 -1 1 1 1 -1 -1 1 1 1 -1
-1 -1 1 1 1 -1 -1 -1 -1 1 -1 1 1 1 -1 -1 -1 1 -1 -1
-1 -1 -1 1 1 -1 1 1 1 1 1 1 -1 -1 -1 -1 -1 -1 1 -1
-1 1 1 1 -1 1 1 1 -1 -1 -1 1 -1 1 -1 1 1 1 1 1
1 -1 1 1 -1 -1 1 -1 1 1 1 1 -1 1 1 -1 1 -1 -1 -1
1 -1 -1 1 -1 -1 -1 1 -1 1 1 1 1 -1 -1 -1 1 1 1 -1
1 -1 -1 1 -1 1 1 -1 1 1 1 -1 1 -1 1 1 1 -1 1 1
1 -1 -1 -1 -1 -1 1 1 1 -1 -1 -1 -1 -1 1 1 -1 1 1 -1
-1 -1 1 -1 1 -1 1 1 -1 1 -1 1 1 1 1 1 1 -1 1 1
-1 -1 -1 -1 -1 -1 -1 1 -1 -1 -1 -1 1 1 1 1 -1 -1 -1 -1
1 1 -1 -1 -1 1 1 -1 -1 1 -1 1 1 -1 1 1 1 1 1 1
-1 1 1 -1 -1 -1 -1 -1 1 1 1 1 -1 -1 -1 -1 -1 1 -1 1
1 1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 1 -1 1 1 -1 1 -1 1
1 1 1 1 1 -1 -1 -1 1 1 1 -1 1 -1 1 1 1 -1 1 1
1 -1 -1 1 -1 -1 -1 -1 1 -1 -1 1 1 -1 1 -1 -1 -1 -1 -1
-1 1 1 1 -1 1 1 -1 -1 1 1 1 -1 -1 1 1 -1 -1 1 1
1 1 -1 -1 1 1 -1 1 1 -1 1 1 1 -1 1 1 -1 1 -1 1
1 1 1 -1 -1 -1 1 -1 -1 1 1 -1 -1 -1 1 -1 -1 -1 -1 1
-1 1 1 1 -1 -1 -1 -1 -1 -1 -1 1 1 -1 1 1 -1 1 -1 -1

Sample Usage
$ time ./matrix-permanent-c 8 30
8395059644858368

real    0m8.582s
user    1m8.656s
sys     0m0.000s

Method
I've used the Balasubramanian-Bax/Franklin-Glynn formula, with a runtime complexity of O(2nn). However, instead of iterating the δ in grey code order, I've instead replaced vector-row multiplication with a single xor operation (mapping (1, -1) → (0, 1)). The vector sum can likewise be found in a single operation, by taking n minus twice the popcount.

Unfortunately the code gives the wrong answer for https://bpaste.net/show/8690251167e7

@Lembik updated. Out of curiosity, could you tell me the result of the following code? https://bpaste.net/show/76ec65e1b533

It gives "True
18446744073709551615"  I added the results for your very nice to code now as well.

@Lembik thanks. I had already split the multiplication as to not overflow 63-bits. Was the result listed taken with 8 threads? Does 2 or 4 make a difference? If 30 finishes in 25, it seems like 31 should be under a minute.

Racket 84 bytes
Following simple function works for smaller matrices but hangs on my machine for larger matrices:
(for/sum((p(permutations(range(length l)))))(for/product((k l)(c p))(list-ref k c)))

Ungolfed:
(define (f ll)
  (for/sum ((p (permutations (range (length ll)))))
    (for/product ((l ll)(c p))
      (list-ref l c))))

The code can easily be modified for unequal number of rows and columns.
Testing:
(f '[[ 1 -1 -1  1]
     [-1 -1 -1  1]
     [-1  1 -1  1]
     [ 1 -1 -1  1]])

(f '[[ 1 -1  1 -1 -1 -1 -1 -1]
 [-1 -1  1  1 -1  1  1 -1]
 [ 1 -1 -1 -1 -1  1  1  1]
 [-1 -1 -1  1 -1  1  1  1]
 [ 1 -1 -1  1  1  1  1 -1]
 [-1  1 -1  1 -1  1  1 -1]
 [ 1 -1  1 -1  1 -1  1 -1]
 [-1 -1  1 -1  1  1  1  1]])

Output:
-4
192

As I mentioned above, it hangs on testing following:
(f '[[1 -1 1 -1 -1 1 1 1 -1 -1 -1 -1 1 1 1 1 -1 1 1 -1]
 [1 -1 1 1 1 1 1 -1 1 -1 -1 1 1 1 -1 -1 1 1 1 -1]
 [-1 -1 1 1 1 -1 -1 -1 -1 1 -1 1 1 1 -1 -1 -1 1 -1 -1]
 [-1 -1 -1 1 1 -1 1 1 1 1 1 1 -1 -1 -1 -1 -1 -1 1 -1]
 [-1 1 1 1 -1 1 1 1 -1 -1 -1 1 -1 1 -1 1 1 1 1 1]
 [1 -1 1 1 -1 -1 1 -1 1 1 1 1 -1 1 1 -1 1 -1 -1 -1]
 [1 -1 -1 1 -1 -1 -1 1 -1 1 1 1 1 -1 -1 -1 1 1 1 -1]
 [1 -1 -1 1 -1 1 1 -1 1 1 1 -1 1 -1 1 1 1 -1 1 1]
 [1 -1 -1 -1 -1 -1 1 1 1 -1 -1 -1 -1 -1 1 1 -1 1 1 -1]
 [-1 -1 1 -1 1 -1 1 1 -1 1 -1 1 1 1 1 1 1 -1 1 1]
 [-1 -1 -1 -1 -1 -1 -1 1 -1 -1 -1 -1 1 1 1 1 -1 -1 -1 -1]
 [1 1 -1 -1 -1 1 1 -1 -1 1 -1 1 1 -1 1 1 1 1 1 1]
 [-1 1 1 -1 -1 -1 -1 -1 1 1 1 1 -1 -1 -1 -1 -1 1 -1 1]
 [1 1 -1 -1 -1 1 -1 1 -1 -1 -1 -1 1 -1 1 1 -1 1 -1 1]
 [1 1 1 1 1 -1 -1 -1 1 1 1 -1 1 -1 1 1 1 -1 1 1]
 [1 -1 -1 1 -1 -1 -1 -1 1 -1 -1 1 1 -1 1 -1 -1 -1 -1 -1]
 [-1 1 1 1 -1 1 1 -1 -1 1 1 1 -1 -1 1 1 -1 -1 1 1]
 [1 1 -1 -1 1 1 -1 1 1 -1 1 1 1 -1 1 1 -1 1 -1 1]
 [1 1 1 -1 -1 -1 1 -1 -1 1 1 -1 -1 -1 1 -1 -1 -1 -1 1]
 [-1 1 1 1 -1 -1 -1 -1 -1 -1 -1 1 1 -1 1 1 -1 1 -1 -1]])

Is this answer better in the codegolf version rather than the speed version of this question?

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/

sort: votes


text:
Balanced triplet brackets
A "triplet bracket" (that I made up for this challenge) is one of the following:
(...+...)
[...:...]
{...|...}
<...-...>

A balanced triplet bracket string (BTBS for short) is either an empty string, two BTBSes concatenated, or one of the above triplet brackets with each ... replaced with a BTBS.
Your task is to write a program or function that checks whether a string that consists of only (+)[:]{|}<-> is balanced. Shortest code wins.
Examples
Your program should return truthy for the following strings:
(+)(+)(+)
[[[:]:]:(+(+))]{<->|<(+)->[:]}(+)
<<<<<<<<<<<<->->->->->->->->->->->->
{|(+[:<-{|(+[:<->])}>])}
[[[:]:[:]]:[[:]:[:]]]
{[:](+)|<->{|}}[(+)<->:{|}(+)]

Your program should return falsy for the following strings:
:[
<|>
(+(+)
[:][:](+[[:]):]
{|{|{|(+{|{|{|}}}}}+)}[:]{|}
{{||}}
<<->-<->-<->>
[(+):((+)+)+(+(+))]
<<<<<->->->->->->

Is (|) valid. I don't think so, but I'm not sure

@RomanGräf No, as <|> in the falsy examples.

Japt, 25 bytes
!Ue"%(%+%)|%[:]|\{%|}|<->

Test it online!
e on strings is a recursive-replace function. The second parameter defaults to the empty string, which means this recursively removes matches of the Japt regex "%(%+%)|%[:]|\{%|}|<->" (in regular terms, /\(\+\)|\[:]|{\|}|<->/). This returns an empty string for balanced triplet strings and a non-empty string for non-balanced, so the correct return value is the logical NOT of this.

JavaScript (ES6), 77 58 57 56 bytes
f=s=>s==(s=s.replace(/\(\+\)|\[:]|{\|}|<->/,''))?!s:f(s)

Test cases

f=s=>s==(s=s.replace(/\(\+\)|\[:]|{\|}|<->/,''))?!s:f(s)

console.log("Testing truthy values");
console.log(f("(+)(+)(+)"));
console.log(f("[[[:]:]:(+(+))]{<->|<(+)->[:]}(+)"));
console.log(f("<<<<<<<<<<<<->->->->->->->->->->->->"));
console.log(f("{|(+[:<-{|(+[:<->])}>])}"));
console.log(f("[[[:]:[:]]:[[:]:[:]]]"));
console.log(f("{[:](+)|<->{|}}[(+)<->:{|}(+)]"));

console.log("Testing falsy values");
console.log(f(":["));
console.log(f("<|>"));
console.log(f("(+(+)"));
console.log(f("[:][:](+[[:]):]"));
console.log(f("{|{|{|(+{|{|{|}}}}}+)}[:]{|}"));
console.log(f("{{||}}"));
console.log(f("<<->-<->-<->>"));
console.log(f("[(+):((+)+)+(+(+))]"));
console.log(f("<<<<<->->->->->->"));

The same idea in Retina is 26 bytes (the first line just makes it a test suite): http://retina.tryitonline.net/#code=JShHYAorYFwoXCtcKXxcWzpdfHtcfH18PC0-CgpeJA&input=KCspKCspKCspCltbWzpdOl06KCsoKykpXXs8LT58PCgrKS0-WzpdfSgrKQo8PDw8PDw8PDw8PDwtPi0-LT4tPi0-LT4tPi0-LT4tPi0-LT4Ke3woK1s6PC17fCgrWzo8LT5dKX0-XSl9CltbWzpdOls6XV06W1s6XTpbOl1dXQp7WzpdKCspfDwtPnt8fX1bKCspPC0-Ont8fSgrKV0KOlsKPHw-CigrKCspCls6XVs6XSgrW1s6XSk6XQp7fHt8e3woK3t8e3x7fH19fX19Kyl9Wzpde3x9Cnt7fHx9fQo8PC0-LTwtPi08LT4-ClsoKyk6KCgrKSspKygrKCspKV0KPDw8PDwtPi0-LT4tPi0-LT4

And 39 with perl : perl -lpe 's/<->|\(\+\)|{\|}|\[:]//&&redo;$_=!$_'.

@Dada That will consider 0 a BTBS. Use this 38 instead: perl -pe 's/<->|\(\+\)|{\|}|\[:]//&&redo;$_=/^$/'

@TonHospel Didn't thought of that, indeed.. thanks for pointing it out! (feel free to post it if you want by the way, or at least don't hold back because of me)

That S/s mix was slightly confusing, perhaps f=s=>s==(s=s.replace(...))?!s:f(s)?

@Neil I'm personally not sure if s==(s=s.replace(...)) is really more readable, but I like the idea of not introducing an extra variable anyway.

sed, 28 27 bytes
:
s#(+)\|\[:]\|{|}\|<->##
t

sed doesn't have a concept of truthy/falsy, so I'm considering an empty string truthy and a non-empty string falsy. This checks out if we consider the conditional /^$/.
Thanks to @Neil for golfing off 1 byte!
Try it online!

For once, BRE is actually an advantage.

Do you need the \] or does ] suffice?

Python, 77 bytes
lambda s:eval("s"+".replace('%s','')"*4%('(+)','[:]','{|}','<->')*len(s))==''

Uses Arnauld's replacement idea. Generates and evaluates a long string like
s.replace('(+)','').replace('[:]','').replace('{|}','').replace('<->','').replace('(+)','').replace('[:]','').replace('{|}','').replace('<->','')

to cycle between replacing all the bracket types. Then, checks if the result is the empty string.

Mathematica, 55 bytes
StringDelete["(+)"|"[:]"|"{|}"|"<->"]~FixedPoint~#==""&

Anonymous function. Takes a string as input and returns True or False as output. Uses the standard method for doing this.

Grime, 39 bytes
e`\(_\+_\)|\[_\:_\]|\{_\|_\}|\<_\-_\>v*

Try it online! Sadly, the TIO version runs out of memory on most of the test cases.
Explanation
Nothing too fancy here.
_ is shorthand for the entire pattern, and v* is the same as *, but with lower precedence.
e`                                       Match entire input against this pattern:
  \(_\+_\)                               '(', match of _, '+', match of _, ')'
          |                              or
           \[_\:_\]|\{_\|_\}|\<_\-_\>    same for the other bracket types
                                     v*  repeated 0-∞ times

J, 48 bytes
a:=([:delstring&.>/'(+)';'[:]';'{|}';'<->';])^:_

Similar to the others, this is also based on Arnauld's method.
Usage
   f =: a:=([:delstring&.>/'(+)';'[:]';'{|}';'<->';])^:_
   f '(+)(+)(+)'
1
   f '[[[:]:]:(+(+))]{<->|<(+)->[:]}(+)'
1
   f '<<<<<<<<<<<<->->->->->->->->->->->->'
1
   f '<|>'
0
   f '[:][:](+[[:]):]'
0
   f '{|{|{|(+{|{|{|}}}}}+)}[:]{|}'
0

Explanation
a:=([:delstring&.>/'(+)';'[:]';'{|}';'<->';])^:_  Input: string S
   (                                        )^:_  Repeat until convergence
                                         ]          Get S
                 '(+)';'[:]';'{|}';'<->';           Append to ['(+)', '[:]', '{|}', '<->']
    [:delstring&.>/                                 Reduce right-to-left by deleting
                                                    occurrences of each string on the
                                                    left from the right
                                                    Return the final string as the new S
a:=                                               Test if the final value of S is empty

Pip, 26 bytes
L#aaR:"(+)[:]{|}<->"<>3x!a

Try it online!
Loops len(a) times, replacing all occurrences of empty triplet brackets ("(+)[:]{|}<->"<>3, where <> is the "group" operator, => ["(+)"; "[:]"; "{|}"; "<->"]) with empty string (x). This many iterations is overkill, but it will always be more than enough to completely reduce all properly formed triplet brackets to nothing. After the loop completes, outputs !a: 0 if a is truthy (still has some characters), 1 if a is falsey (empty).

Scala, 96 bytes
def&(s:String):Any={val t=s.replaceAll(raw"\(\+\)|\[:]|\{\|}|<->","")
if(t==s)t.size<1 else&(t)}

This is basically the same idea as the other answers, but with some scala boilerplate.
without stealing ideas from others (188 bytes):
import scala.util.parsing.combinator._
val a = new RegexParsers{def r:Parser[_]="("~r~"+"~r~")"|"["~r~":"~r~"]"|"{"~r~"|"~r~"}"|"<"~r~"-"~r~">"|""
def!(s:String)= !parseAll(r,s).isEmpty}!_

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/