text:
Non-discriminating Programming
We say a string is non-discriminating if each of the string's characters appears the same number of times and at least twice.
Examples

"aa!1 1 !a !1" is non-discriminating because each of the characters  , !, a and 1 appear three times.
"abbaabb" is not non-discriminating because b appears more often than a.
"abc" is also not non-discriminating because the characters don't appear at least twice.

Task
Write a non-discriminating program or function which returns a truthy value if a given string is non-discriminating, and a falsy value otherwise.
That is, the program run on its own source code should return a truthy value.
Each submission must be able to handle non-empty strings containing printable ASCII, as well as all characters appearing in the source code of the submission.
Test Cases
Truthy:
<your program's source code>
"aaaa"
"aa!1 1 !a !1"
"aabbccddeeffgg"
"1Q!V_fSiA6Bri{|}tkDM]VjNJ=^_4(a&=?5oYa,1wh|R4YKU #9c!#Q T&f`:sm$@Xv-ugW<P)l}WP>F'jl3xmd'9Ie$MN;TrCBC/tZIL*G27byEn.g0kKhbR%>G-.5pHcL0)JZ`s:*[x2Sz68%v^Ho8+[e,{OAqn?3E<OFwX(;@yu]+z7/pdqUD"

Falsy:
"a"
"abbaabb"
"abc"
"bQf6ScA5d:4_aJ)D]2*^Mv(E}Kb7o@]krevW?eT0FW;I|J:ix %9!3Fwm;*UZGH`8tV>gy1xX<S/OA7NtB'}c u'V$L,YlYp{#[..j&gTk8jp-6RlGUL#_<^0CCZKPQfD2%s)he-BMRu1n?qdi/!5q=wn$ora+X,POzzHNh=(4{m`39I|s[+E@&y>"

@Laikoni are we able to abuse comments to get this to work?

As a side note, I love challenges where I can use other entries to test my entry's validity.

@MagicOctopusUrn I think that he did say in the sandbox that's allowed, since it can't be observably determined.

Exactly. Even if you somehow manage to ban comments in an objective fashion, then what about unused string literals ect? Anyway, I think the scoring gives incentive to avoid comments as much as possible.

I wrote a program in Retina, a language that doesn't really have a conditional construct (it sort of does, but it is based on matching a regex, so the default of matching an empty string would mean everything is truthy?). Could I submit my answer if it outputs 1 for non-discriminating input and 2 otherwise?

I get it's just a puzzle, but the conflation of "non-discriminating" with "all identifiable labeled member types existing in exactly equal parts" is mildly disturbing... To "discriminate" means "to tell the difference between", and to unfairly do this means to treat or judge someone unfairly based on seeing them as different from another class of people. Of course, keep going with the fun!

@mbomb007 I don't understand what you mean, I was only asking about the output of our programs.

@FryAmTheEggman Looking at recent Retina submissions to [tag:decision-problem] challenges suggests that zero or one are acceptable as truthy/falsy values.

@Laikoni For several, including the most recent, they assume 0 is falsy and positive is truthy. This is the problem with using this convention, I think it's actually rather bad for languages that don't have traditional if/else constructs. There was a discussion about this not too long ago, but I don't think it got enough visibility.

Is accepting an array of integers that are the ASCII decimal values of the input okay?

@FryAmTheEggman Then that's also fine with me.

@Okx I'd say that's only acceptable if the language has no way of processing strings or arrays of characters.

Apparently you need to emphasise that the program also needs to be non-discriminating too. Since you've already bolded and italicized it, I'm not sure what else you could do... Maybe ALL CAPS

"Each submission must be able to handle non-empty strings containing printable ASCII, as well as all characters appearing in the source code of the submission." -- I missed this in my initial comment. The expected result for the empty string was otherwise well-defined. Is there a particular reason you're not requiring any particular result for that? Existing answers vary in the results they give, so it's probably too late to change now.

@hvd While the definition covers the empty string it is still likely to be an edge case for many approaches to solve the challenge, and handling edge cases which are not important to the challenge is usually not fun.

@Laikoni The link you give is about not adding special cases. Excluding edge cases is actually adding special cases. If you think it's more fun like this, that's a good reason, but it's not supported by your link. :)

@hvd I don't see how saying that only non-empty strings need be handled, which is equivalent to saying that your program can do whatever it want when receiving the empty string as input, is in any way adding a special case. Requiring the empty string to be handled might lead to answers like ... or empty(s) in which the empty string is a special case. Dropping this requirement still leaves all answers valid but also allows to drop the code only needed for the special case.

@Laikoni You're trying to avoid special cases in the answers but I think the link you provided was about special cases in the challenges. But yeah, already agreed that changing the challenge now is not an option.

Brachylog, 10 bytes
=ᵍbᵐbᵐlᵍ=l

Try it online!
Explanation
=ᵍ                Group all equal elements together
  bᵐbᵐ            Remove the first element of each group twice. This fails if
                  there are fewer than 2 elements
      lᵍ          Group elements together that have the same length
        =         Are all elements of that list equal? This only succeeds if the
                  list has one element
         l        Length. This will always succeed

Java 8, 198 192 186 174 168 165 160 bytes (char-count 6 5)
o->{byte x[]=new byte[+333-3|2],u=-0,i,fe,fi,w; s:w:no0r3sswwyyy:for(int s:o){{u=++x[s];}};for(int b:x){if(!!!(2>b||u==b)|2>u|2>2){x[0]++;}}return!!(0>--x[0]);}

Try it online.
Code used to verify the occurrences of the characters, which was my answer for this challenge.
-5 bytes thanks to @OlivierGrégoire again by getting rid of the comment and making a mess. ;)
Old 168 bytes (char-count 6) answer:
o->{int w[]=new int[2222],u=0,f=0;for(int r:o)u=++w[r];for(int e:w)if(!(2>e|u==e)|2>u)f++;return!(f>0);}//[[[]]]  !!!!e(i)++,,,,-----oo////000tuww::::{{{{{;;||||}}}}}>>

Try it online.
Code used to verify the occurrences of the characters excluding comment, which was my answer for this challenge.
-6 bytes thanks to @OliverGrégoire removing < by swapping the checks to >.
Explanation of the base golfed program (98 bytes):
Try it online.
s->{                     // Method with character-array parameter and boolean return-type
  int a[]=new int[256],  //  Occurrences integer-array containing 256 zeroes
      t=0,               //  Temp integer, starting at 0
      f=0;               //  Flag integer, starting at 0
  for(int c:s)           //  Loop over the input
    t=++a[c];            //   Increase the occurrence-counter of the current character
                         //   And set the temp integer to this value
  for(int i:a)           //  Loop over the integer-array
    if(i>1               //   If the value is filled (not 0) and at least 2,
       &i!=t             //   and it's not equal to the temp integer
       |t<2)             //   Or the temp integer is lower than 2
      f++;               //    Increase the flag-integer by 1
  return f<1;}           //  Return whether the flag integer is still 0

Some things I did to reduce the amount of characters used:

Variable names o, w, u, f, r, and e were chosen on purpose to re-use characters we already had (but not exceeding 6).
2222 is used instead of 256.
Changed the if-check e>0&u!=e|u<2 to !(e<2|u==e)|u<2 to remove 6x &.
Removed the two separated returns and used a flag f, and we return whether it is still 0 in the end (this meant I could remove the 6x by from byte now that we only use n in int 6 times instead of 8).
e<2 and u<2 changed to 2>e and 2>u to remove 6x <.

What I did to reduce the char-count 6 to 5:

2x int to byte so the amount of n used is 4 instead of 6.
Used x[0] instead of a new variable f=0 so the amount of = used is 5 instead of 6.
Changed 2222 to 3333 so the amount of 2 used is 2 instead of 6.
Changed variables f and r again so they aren't 6 anymore either.

What @OlivierGrégoire did to get rid of the comment, and therefore the 5x /:

Adding unused variables ,i,fe,fi,w;.
Adding unused labels: s:w:no0r3sswwyyy:.
Adding unused |2>2
Adding {} around the for-loops and ifs, and added an unused {}-block.
Changing ! to !!!.
Changing | to ||.
Changing 333 to +333-3|2to get rid of leftover arithmetic operators +-| and the 2.
Changing !(x[0]>0) to !!(0>--x[0]).

180 bytes: changed all < into >.

@OlivierGrégoire Sorry, I'm already at 174 :) But will see if your trick can still be applied.

The change can still apply to save 6 bytes.

Closest I am to 162 characters (161 characters). I'm trying to remove the comment, but I still need to put a comma somewhere. I just can't find any place.

@OlivierGrégoire Isn't it possible to change the char-count from 6 to 5 somehow like I did in my current 165-bytes answer?

Since you only care about printable ascii, making the array size 222 works in theory to remove the 3s, but in practice that runs into an overflow issue due to the byte array which 3333 manages to cleanly avoid since it's 13*256+5 (I was looking into this before you changed it back to a byte array)  Didn't know if there was anything you could do with that information

160 bytes (proof). Very likely more golfable.

All 3s should be able to be removed by using "2220", also. Untested, though.

@AidanF.Pierce Hmm, might indeed be possible. Only problem in the current implementation where we increase the flag x[0] is that byte can only hold up to 127, and will wrap-around (127 + 1 = -128). So the check if the flag is larger than 0 in the end will return false because 2220 is too big. But perhaps there is indeed a way to remove those 333s using the three leftover 2s.

@KevinCruijssen Sorry, missed the edit. I can't see any way to do that now, but maybe there still is one.

Sorry for the mess I put here! xD Hint for further golfing: start from version at 165 bytes, golf that, then use @KevinCruyssen's analysis of my mess to remove the comments. Be ready to spend time on it!

Jelly, 18 16 12 10 bytes
Ġ¬zḊḊ¬zĠȦȦ

Try it online!
How it works
Ġ¬zḊḊ¬zĠȦȦ  Main link. Argument: s (string)

Ġ           Group the indices of s by their corresponding elements.
            "abcba" -> [[1, 5], [2, 4], [3]]

 ¬          Take the logical NOT of each 1-based(!) index.
            [[1, 5], [2, 4], [3]] -> [[0, 0], [0, 0], [0]]

   Ḋ        Dequeue; yield s without its fist element.
            "abcba" -> "bcba"

  z         Zip-longest; zip the elements of the array to the left, using the
            string to the right as filler.
            ([[0, 0], [0, 0], [0]], "bcba") -> [[0, 0, 0], [0, 0, "bcba"]]

    Ḋ       Dequeue; remove the first array of the result.
            This yields an empty array if s does not contain duplicates.
            [[0, 0, 0], [0, 0, "bcba"]] -> [[0, 0, "bcba"]]

    ¬       Take the logical NOT of all zeros and characters.
            [[0, 0, "bcba"]] -> [[1, 1, [0, 0, 0, 0]]]

      Ġ     Group.

     z      Zip-longest. Since all arrays in the result to the left have the same
            number of elements, this is just a regular zip.
            [[1, 1, [0, 0, 0, 0]]] -> [[1], [1], [[0, 0, 0, 0]]

       Ȧ    Any and all; test if the result is non-empty and contains no zeroes,
            at any depth. Yield 1 if so, 0 if not.
            [[1], [1], [[0, 0, 0, 0]] -> 0

        Ȧ   Any and all.
            0 -> 0

Brachylog, 14 12 bytes
ọtᵐℕ₂ᵐ==tℕ₂ọ

Try it online!
Explanation
ọ   Occurrences. Gives a list of [char, count] pairs for the entire input.
tᵐ  Map "tail" over this list, giving each character count.
ℕ₂ᵐ Make sure that each count is at least 2.
=   Make sure that all counts are equal.
    At this point we're done with the actual code, but we need another copy
    of each character (except ᵐ). We can just put them after this, as long as
    we make sure that they can never cause the predicate to fail.
=   Make sure that all counts are equal, again...
t   Extract the last count.
ℕ₂  Make sure that it's at least 2, again...
ọ   Get the digit occurrences in that count, this can't fail.

Alternative 12-byte solution that reuses t instead of ᵐ:
ọtᵐ==tℕ₂ℕ₂ọᵐ

T-SQL, 320 bytes (32 chars x 10 each)
Input is via pre-existing table FILL with varchar field STEW, per our IO standards.
WITH BUMPF AS(SeLeCT GYP=1
UNION ALL
SeLeCT GYP+1FROM BUMPF
WHeRe GYP<=1000)SeLeCT
IIF(MIN(WAXBY)<MAX(WAXBY)OR
MAX(WAXBY)<=1,+0,+1)FROM(SeLeCT
WAXBY=COUNT(1),WHICH=+1+0,HEXCHANGE=+01,HUNG=+0+1,CHLUB=+0,GEFF=+0FROM
BUMPF,FILL WHERE
GYP<=LEN(STEW)GROUP BY
SUBSTRING(STEW,GYP,1))CHEXX
OPTION(MAXRECURSION 0)----------<<<<<<

I have never been more pleased, yet horrified, by a piece of code.
Must be run on a server or database set to a case-sensitive collation. There are 10 each of 32 different characters, including upper and lowercase E (SQL commands are case-insensitive, so flipped a few as needed), spaces and tabs (tabs are shown as line breaks in the code above, for readability).
I found ways to include 10 each of the other symbols + = , in the code, but unfortunately couldn't find a way to do that with <, so I had to add the comment character -.
Here is the formatted code before I crammed in all the extra filler:
WITH b AS (SELECT g=1 UNION ALL SELECT g+1 FROM b WHERE g<1000)
SELECT IIF(MIN(w)<MAX(w) OR MAX(w)<1+1,0,1)
FROM(
    SELECT w=COUNT(1), --extra constant fields here are ignored
    FROM b, fill
    WHERE g < 1+LEN(stew)
    GROUP BY SUBSTRING(stew,g,1)
)a OPTION(MAXRECURSION 0)

The top line is a recursive CTE that generates a number table b, which we join to the source string to separate by character. Those characters are grouped and counted, and the IIF statement returns 0 or 1 depending on whether the input string is non-discriminating.

C (gcc),  333  168 bytes
Thanks to @Kevin Cruijssen for saving 9 bytes and thanks to @Laikoni for saving 45 bytes!
f(r,h,a){char*o=r,c[222]={!o};for(a=!o;*o;)++c[*o++];for(h=!o;222/++h;c[h]&&c[h]!=a&&(a=!*c))!a&&c[h]&&(a=c[h]);r=!(2/2/a);}/////!(())****++,,,,,[[]]fffffrr{{{{{{}}}}}}

Try it online!
C, 333 bytes
i,v;f(S){char*s=S,L[128]={0};for(v=0;*s;)++L[*s++];for(i=-1;++i<128;L[i]&&L[i]-v?v=-1:0)!v&&L[i]?v=L[i]:0;return-v<-1;}/////////!!!!!!!!&&&&&(((((())))))******+++,,,,,,,----00000111122222228888888:::::::<<<<<<<===???????LLLSSSSSSS[[[]]]aaaaaaaacccccccceeeeeeeeffffffhhhhhhhhiinnnnnnnnooooooorrrrssssssttttttttuuuuuuuuvv{{{{{{{}}}}}}}

Even the bytecount is non-discriminating!
Try it online!

Awwhh... I wanted to be the first comment abuser. Nice one though, I like how you sorted the chars for the comment ^_^

You can lower it to 324 bytes by changing both the 128 to 222 so the 8 can be dropped.

279 bytes by renaming i, v, S, s and L to characters which already appear in the keywords char, for and return: Try it online!

@Laikoni Thanks! I didn't have the time to properly golf this yesterday.

@MagicOctopusUrn They are sorted because I was too lazy to add them by hand.

You might be able to drop the comment entirely including all / by somehow putting everything inside useless variables. OlivierGrégoire did something similar in my Java answer, and I also did something similar in ovs' Python 2 answer. I don't have time right now to try it though, and I'm not too skilled in C either..

@KevinCruijssen Perhaps, but I need those /s there anyway, because otherwise I would need a lot of <s.

05AB1E, 20 18 16 14 bytes
S¢Z≠sË*sZ¢≠SË*

Try it online!
The program is essentially divided into 2 parts where the goal of the first part is to do the actual task and the goal of the second part is to use the same functions as the first part without altering the result.
Explanation (first part)
S          # push input split into list of chars
 ¢         # count the occurrence of each char in input
  Z≠       # check that the max count is not 1
    sË     # check if all counts are equal
      *    # multiply

Explanation (second part)
s          # swap input to top of stack
 Z¢        # count the number of occurrences of the largest element
   ≠       # check that the count isn't 1
    SË     # split into list and check that each element are equal (always true)
      *    # multiply (as it is with 1, the original result is left unchanged)

{γ€gDË*P≠qq{γ€gDË*P≠ is another for 20 ;).

@MagicOctopusUrn: Nice! I had a couple of others at 20 as well. I do have one at 18 now as well :)

WITCHCRAFT! No other explanation!

¢... good idea man, also I'm glad to see ≠ was as useful as I thought it may be haha!

Husk, 14 bytes
§<ε#εu§m#u
m
<

Try it online!
Explanation
The two short lines are no-ops, since the main function never calls them.
§<ε#εu§m#u  Implicit input, say S = "asasdd"
         u  Remove duplicates: "asd"
      §m#   For each, get number of occurrences in S: [2,2,2]
     u      Remove duplicates: L = [2]
   #ε       Number of elements in L that are at most 1: 0
  ε         1 if L is a singleton, 0 otherwise: 1
§<          Is the former value smaller than the latter?

But this has ‘u’ more than ‘m’, so it doesn’t meet the requirements.

@WGroleau m also occurs twice: on the first line and on the second line. The explanation doesn't include the two short lines because they don't affect the behavior of the program.

I guess the OP should clarify whether an explanation of the program can be scanned along with the program.but actually, if you include that, then you have four ‘u’ and two ‘m’

Never mind; this confused me the same way another answer did.

Python 2, 75 69 bytes
def f(s):len({2<<s.count(c)-2for c,in s})<2or{{e.dil:-tu,r.dil:-tu,}}

Output is via presence or absence of an error. The error is either a ValueError (one or more characters occur only once) or a NameError (the character counts are unequal).
Try it online!

The negative shift error trick is neat! I like how it takes advantage of the shift operator low precedence.

{{e.dil:-tu,r.dil:-tu,}}  Good lord what is that?

@AdamBarnes Syntactically valid gibberish that throws a NameError if evaluated.

I don't get it.  I tried swapping it out for a and everything broke.  Could you explain further please?

@AdamBarnes That should work, as long as you leave a space after the or. I'll add an explanation when I'm at a computer.

Doesn't seem to work, The True disappears from the end of the Self test: True line in the output.

@AdamBarnes That because the resulting source code is no longer non-discriminating. Tje program itself still works as intended.

Good lord I didn't even notice that was a requirement.  Thanks, that makes sense.

Brachylog v2, 8 bytes (in Brachylog's character set)
oḅ\k\koḅ

Try it online!
Looks like there's been a golfing war going on on this question in Brachylog, so I thought I'd join in, saving a couple of bytes over the next best answer.
This is a full program that takes input as a list of character codes. (This is partly because Brachylog appears to have some very bizarre bugs related to backslashes in strings, and partly because the \ command doesn't work on lists of strings.)
Explanation
oḅ\k\koḅ
o          Sort {standard input}
 ḅ         Group identical adjacent values
  \        Assert rectangular; if it is, swap rows and columns
   k       Delete last element
    \      Assert rectangular; (rest of the program is irrelevant)

The koḅ at the end is irrelevant; k will always have an element to act on and o and ḅ cannot fail if given a list as input.
The reason for the starting oḅ should be clear; it partitions the input list by value, e.g. [1,2,1,2,4,1] would become [[1,1,1],[2,2],[4]]. In order for each character to appear the same number of times, each of these lists must be the same length, i.e. the resulting list is a rectangle. We can assert this rectangularity using \, which also transposes the rows and columns as a side effect.
We now have a current value consisting of multiple copies of the character set, e.g. if the input was [4,2,1,2,4,1] the current value would be [[1,2,4],[1,2,4]]. If we delete a copy, the resulting matrix is still rectangular, so we can turn it back using \. However, if the reason the matrix was rectangular was that all the input characters were distinct, the resulting matrix will have no elements left, and \ does not treat a "0×0" matrix as rectangular (rather, it fails). So oḅ\k\ effectively asserts that each character that appears in the input appears the same number of times, and that number of times is not 1.
That's the entire functionality of our program (as a full program, we get true if no assertion failures occurred, false if some did). We do have to obey the source layout restriction, though, so I added an additional koḅ that has no purpose but which cannot fail (unlike \, o and ḅ are happy to act on empty lists).

It's the language of this month!

Python 2, 84 80 bytes
x=input()
c=map(x.count,x)
print max(c)==min(c)>1
1. or our>ram>>utopia,
1., 1.,

Try it online!

+1 for non-error-producing short Python code and our ram utopia ;)

JavaScript (Node.js), 144 ... 100 96 bytes
o=>!(a=o.split``.map(i=>o.split(i||aeehhhlmmnnnpst)[`length`]-1)).some(g=>![g>1][-!1]||a[-!1]-g)

Try it online!
24 different characters * 6 times each
28 different characters * 5 times each
27 different characters * 5 times each
27 different characters * 4 times each
26 different characters * 4 times each
25 different characters * 4 times each
24 different characters * 4 times each
Explanation

o=>!(
 a=o.split``.map(                            // Split the input into character array and
  i=>o.split(i||aeehhhlmmnnnpst)[`length`]-1 // count the occurrences of each character.
 )
).some(                                      // Then check
 g=>![g>1][-!1]                              // If each character appears at least twice
 ||a[-!1]-g                                  // and the counts are all the same number.
)

More to add:
1. Using {s.split``} instead of {[...s]} is to reduce the number of {.} that dominates
   the count.
2. Using {!c.some} instead of {c.every} to reduce the number of inefficient characters
   (v,r,y in every)
3. Still one unavoidable inefficient character left ({h}).

Update:
1. Got rid of one {.} by replacing {.length} by {["length"]}.
2. Got rid of one {=} by replacing {c[-!1]!=g} by {c[-!1]-g}.
3. Got rid of one {()} by replacing {!(g>1)} by {![g>1][-!1]}.
4. Finally, because count per character is now 4, the backslashes can be taken out.

Update:
1. Got rid of all {"} by replacing {"length"} by {`length`} and exploiting shortcut
   evaluation.
   {aaaeehhhlmmnnnpst} is not defined but is not evaluated either because of {c} which
   must be evaluated to true.

Update:
1. Got rid of all {c} by shortcutting the undefined variable at {split(i)} and replacing
   all {c} by {a}.
   Since {i} is never an empty string, it is always evaluated true (except compared
   directly to true).

Update:
1. Got rid of all {,} by moving the assignment after the argument list. The {()} at the
   front can therefore be moved to the assignment, retaining same number of {()}s.

what on golf's green is "aaaeehhhlmmnnnpst"?

@thejonymyster a dummy filler that's never evaluated

Brachylog, 18 bytes
oḅlᵐ=h≥2
oḅlᵐ=h≥2

Try it online!
Unfortunately, I can't remove the linefeeds, since ḅ on a number triggers a fail.

It is definitely possible to do something shorter that doesn't require linefeeds (but you might need to change some things) ;)

@Fatalize No time to currently, and yes I did read that discussion. :)

Python 2, 108 104 92 88 bytes
-12 bytes thanks to Rod
-4 bytes thanks to Kevin Cruijssen
s=input();c=s.count;print[all(c(s[[]>[1]])==c(o)>1. for o in s)];aaafffillpprrtuu>1.>1.;

Try it online!

Your program must be non-discriminating.

The program itself must be non-discriminating.

@user202729 Thanks for telling me, I updated my answer.

@HyperNeutrino updated my answer

s=input();c=s.count;print[all(c(s[[]>[1]])>=c(o)>1. for o in s)];aaafffillpprrtuu=1.>1.; 88 bytes by getting rid of the comment.

aaabb seems to yield True

@Vincent fixed it.

PowerShell, 104 bytes
($qe=$args[0]| group |sort count|% count)[0]-eq$qe[-1]-and$qe[0]-gt1####((()))%%%pppddd===aaccss11nu|0gr

Try it online!
This was great fun to golf. The limitation was $, which we need four of at minimum (one for the input $args, one for assigning the computation result $qe, one for checking the last character $qe[-1] and one for checking the first character $qe[0], so that was the working maximum number of characters.
From there, it was a matter of golfing (and not-golfing, like having a two-letter variable name) to get the program nicely divisible by four. Note that we have a small comment (everything following the #) to account for some missing elements, but I tried to keep the comment as small as possible.

Haskell, 90 75 72 bytes
a[i]|d:n<-[[i|n<-i,n==a]|a<-i]=and[[i]<d,[d|i<-n]==n]--aadd,,,,:::::<=||

Each character appears 6 times. The input string is taken as a singleton list.
Try it online!
For reference, old versions:
75 bytes, each char 5 times
n(l)|d<-[[0|n<-l,n==a]|a<-l]=and[[0]<d!!0,all(==d!!0)d]--an!((())),,,0<[]||

Try it online!
90 bytes, each char 3 times:
a x|h:u<-[sum[1|d<-x,not(d/=c)]|c<-x],"  \"\\&,../1::>acdlmmnosst">[]=h>1&&all(not.(/=h))u

Try it online!

MATL, 12 bytes
q&=sqt&=tsvv

The input is a string enclosed in single quotes. Single quotes in the string are escaped by duplicating.
The output is a non-empty matrix, which is truthy if it doesn't contains zeros, and is falsy if it contains at least a zero.
Try it online! Or verify all test cases, including the standard truthiness/falsiness test for convenience.
How it works
Statements marked with (*) are neither necessary nor harmful, and have been included only to make the source code non-discriminating.
q     % Implicit input. Convert chars to code points and subtract 1 from each (*)
&=    % Square matrix of all pairwise equality comparisons
s     % Sum of each column. Gives a row vector
q     % Subtract 1 from each value. An entry equal to 0 indicates the input string
      % is discriminating because some character appears only once
t     % Duplicate
&=    % Square matrix of all pairwise equality comparisons. An entry equal to 0
      % indicates the input string is discriminating because some character is
      % more repeated than some other
t     % Duplicate (*)
s     % Sum of each column (*) (all those sums will be positive if the previous
      % matrix doesn't contain zeros)
v     % Vertically concatenate the matrix and the vector of its column sums
v     % Vertically concatenate the resulting matrix with nothing (*)
      % Implicit display

Ruby, 87 78 bytes
c=->m{y=m.chars;x=y.map{|d|y.count d}|[];x[-1]>1and not x[1]};->{pushrortpush}

26 characters repeated 3 times each
Try it online!

@nimi Thanks for pointing it out, I think that was some weirdness with gets and ;. Changed it, it's shorter as a lambda anyway

Perl 5, -p 57 bytes
Each character appears 3 times. Only a single 1 doesn't do anything
12 bytes added to a basic 45 character solution to make in non-discriminating
s{.}[@m[@1{$&}+=$.].=g]eg;$\=s()(e@m;1)&&m[e(\sg+)\1+;]}{

Try it online!

R, 90 bytes
"?"=`u\164f8ToI\x6Et`;'!'=prod;!{y<-xtabs(~?readLines())}%in%{z<-y[1]}&z>T##&[]>~48bEfILpu

Try it online!
Outputs TRUE for a non-discriminating string, and FALSE for a discriminating string. I have written a lot of ugly code for challenges on this site, but I think this is the ugliest so far.
45 characters, used twice each (including a few in a comment). The previous best R answer was 116 bytes, with 29 characters used 4 times each; I am posting this separately since it is substantially different.
The code is equivalent to
y = table(utf8ToInt(readLines()))
z = y[1]
all(y == z) & (z > 1)

which converts the input to a vector of integers, computes a contingency table y of the values, then checks that all counts in that table are equal to the first count, and that the first count is greater than 1.
The initial difficulty was in using only 2 pairs of brackets. This is achieved by redefining the unary functions ! and ? to be utf8ToInt and prod respectively. (I can't use all because I need the a). There are four assignments: two with = and two with <-. This means that the equality test between y and z cannot use y==z nor y-z; y%in%z comes to the rescue.
Defining these functions uses up all the possible quotes: two double quotes, two single quotes, and I'll need the two backticks in the next paragraph, so I had to resort to readLines() instead of scan(,""). (The other options, such as scan(,letters) or scan(,month.abb) all used a precious t  which I couldn't spare.)
At this point, I had most of the building blocks: utf8ToInt, prod, table, readLines, %in%. Three characters appear three times in those names: ent. First, I discovered that table(foo) is equivalent to xtabs(~foo), saving the e. I can rescue the n and the t with the hex/octal code trick; the golfiest solution is to use u\164f8ToI\x6Et (in backticks) for utf8ToInt.

It's impressive you can discriminate the two cases in 90 bytes (and nice abuse of the help operator), but alas NA is not considered a truthy value (in R, if(NA) x else y causes an error, so NA is neither truthy nor falsey)

@JDL Thanks, you're right. The latest edit fixes this issue.

@JDL the comments suggest that consistent, distinct answers are ok for truthy and falsy.

@Giuseppe Actually, I solved this issue seconds ago (see new version, which is quite different but same byte count); now outputs TRUE and FALSE.

R, 132 116 bytes
crudcardounenforceableuploads<-function(b){{pi&&pi[[1-!1]];;;"";{1<{f<<-table(strsplit(b,"",,,)[[1]])}}&&!!!sd(-f)}}

It doesn't contain any comments or superfluous strings, either, though this will probably be my only time in code golf calling a function crudcardounenforceableuploads. There's probably a great anagram in there somewhere for the function name!Thanks to John Dvorak for pointing out a nice anagram solver, which I used for the name.
Character table:
- , ; ! " ( ) [ ] { } & < 1 a b c d e f i l n o p r s t u
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4

examples:
> crudcardounenforceableuploads("aaabbbccc")
[1] TRUE
> crudcardounenforceableuploads("aaabbbcc")
[1] FALSE
> crudcardounenforceableuploads("abc")
[1] FALSE
> crudcardounenforceableuploads("crudcardounenforceableuploads<-function(b){{pi&&pi[[1-!1]];;;\"\";{1<{f<<-table(strsplit(b,\"\",,,)[[1]])}}&&!!!sd(-f)}}")
[1] TRUE

don't know if byte count is important but we can probably remove the 2s and the >s, by switching round the comparison with f. Also can use = instead of <<-. strsplit is probably unavoidable though, which is the source of most of the other characters.

do you need the spaces? you could also try utf8ToInt instead of strsplit, but not sure if that'll help. Also maybe include a link to TIO?

also all the . seem to be superfluous.

This is [tag:code-golf], so byte count is important, per your comment.

Can someone explain to me why the two semicolons after table(strsplit(l,"",,,)[[1.]]); are legal?

some possible anagrams: no pip-bonded cupboard bureaucracies; RIP carbonaceous barbecued pound dip. Found using https://www.wordplays.com/anagrammer

Vlo, they are equivalent to blank lines (I could have used \n in place of each of the ;)

golfed away those 16 now. It might be possible to remove the ; as well, though it will be tricky (perhaps starting pi[[1-!1]]&&... and having "1" instead of 1 somewhere?

90 bytes, using a different strategy.

C (gcc), 153 bytes
f(h,a,c,f){{{{{{{char*o=f=h,*r;for(a=!h;*o;o++){for(c=!h,r=h;*r;c+=!(*r++^*o)){}f*=!!(c^!!h)*(!a+!(a^c));a=c;}(a^c^c^f^f^h)+o,a+r,o,o,+h^*r;(a=f);}}}}}}}

Try it online!
Returns address of string as truthy value, and zero as falsy.
f(
h,                              Address of string.
a,                              # instances of previous character
c,                              # instances of current character
f                               Return value
){{{{{{{
char*o=f=h,*r;                  Point o to string, while giving f a non-zero value.
for(a=!h;*o;o++){               Set previous char count to 0, and then traverse the string.
for(c=!h,r=h;*r;                Set current char count to 0 and r to string,
                                and start counting instances of current character.
c+=!(*r++^*o))                  Add to counter if current character matches.
{}                              Lower the amount of semi-colons
f*=                             Multiply (AND) return value with:
   !!(c^!!h)                    Is current count not 1? (Must be 2 or above.)
            *(!a+!(a^c));       AND, is previous count valid (meaning this is not the first
                                character counted), and matches current count?
a=c;}                           Previous count = current count.
(a^c^c^f^f^h)+o,a+r,o,o,+h^*r;  Spend surplus characters to make source code valid.
(a=f);}}}}}}}                   Return value.

Stax, 26 24 18 bytes
:u{m*_{y#m:u_hy#h*

Try it online!
Shortest solution so far that only uses printable ASCIIs Beaten by MATL.
Guess I was approaching the problem the wrong way. Repeating a working block is neither golfy nor interesting. Now at least it looks better ...
Explanation
:u{m* produces some garbage that does not affect the output.
_{y#m:u_hy#h*
_{y#m           map each character to its number of occurences in the string
     :u         all counts are equal (result 1)
       _hy#     get the count of appearance for the first character
           h    halve it and take the floor, so that 1 becomes 0(result 2)
            *   multiply the two results

@WGroleau which characters appear once? Did you read my answer carefully enough?

‘#’ appears more often than ‘:’ (just one example). Oops, misreading (see other comment)

@WGroleau There are exactly two #'s and two :s, did you read my answer on the second line? Did you just skip the first paragraph in my "Explanation"?

Sorry, thought the line above the explanation was the whole thing.

BASH 144 bytes
grep -o .|sort|uniq -c|awk '{s=$1}{e[s]=1}END{print((s>1)*(length(e)==1))}##>>>#|'#wwwuuutrqqqppooNNNnlllkkkiihhhggEEEDDDcccaaa1***{}[[[]]]...--''

This line of code takes an stdin string as input. "grep -o ." puts each character on a new line. "uniq -c" counts each chacter's usage. The awk script creates an array with each usage as a different element, and outputs true when there is only 1 array index and the value is at least 2. Each character is used 4 times, so this source returns true

Pip, 22 18 bytes
^1>=Y^aNaYMNy=My>1

Attempt This Online!
Explanation
Each character occurs twice.
^1>=Y^aNaYMNy=My>1
      a             First command-line argument (a string)
     ^              Split into a list of characters
       Na           Count occurrences of each character in a
    Y               Yank the result into y
^1>=                No-op: compare with [1]
          MNy       Minimum of y
             =      is equal to
              My    Maximum of y
                >1  which is also greater than one
         Y          No-op: yank that result
                    Autoprint the result of the last expression

Alternate 18-byters:
Y^!1Y^aNaMNy=My!=1
Y_<=1Y_NaMa1<Ny=My

CoffeeScript 1, 96 93 90 bytes
(q,a=q.split(h).length-1for h in[q][0])->a.every (w,s,pplitnggffoorsvvyy)->w>1&&a[0&10]==w

Try it online!
Started from my ES6 answer but walked back to using Array.every. 32 31 30 tokens @ 3 each

SmileBASIC, 164 152 148 140 bytes
DeF M(X)DIM W[#R]WHILE""<X
INC w[ASC(x)]X[n]=""wEND
FOR F=e#TO--nOT-LEN(W)U=w[F]H=H||U&&U<MAx(W)neXT-!!!AASSS#&&Oxx||CCLL<<wIM#
RETURN!H
enD

35 different characters, repeated 4 times each.
No comments were used (but the expression after neXT is never actually evaluated)
Script to check answers:

//javascript is a convenient language that I love using!
var input=document.getElementById("input");
var button=document.getElementById("button");
var output=document.getElementById("output");

button.onclick=function(){
  var text=input.value;
  var freqs={};
  for(var i=0;i<text.length;i++){
    var letter=text.charAt(i);
    if (freqs[letter]==undefined) freqs[letter]=0
    freqs[letter]++
  }
  sorted=Object.keys(freqs).sort(function(a,b){return freqs[b]-freqs[a]})
  var out="";
  var min=Infinity,max=0;
  for (var i in sorted) {
    var letter=sorted[i];
    var count=freqs[letter];
    if(count<min)min=count;
    if(count>max)max=count;
    out+="\n"+letter+":"+count;
  }
  output.textContent="min:"+min+"\nmax:"+max+"\nunique:"+sorted.length+"\nlength:"+text.length+out;
}
<textarea id="input" placeholder="code here"></textarea>
<button id="button"butt>count</button>
<pre id="output">...</pre>

Retina 0.8.2, 168 90 bytes
The output will be empty if false, or non-empty if true.
***???;;;;```!!$$$$MMMMOOOO..1111ssss222{{{{\^^^^

s;{O`.
M!*\`^((.)\2(?!\2))*$
(.)(?!\1)

Try it online
Core program (39 bytes)
s;{O`.
M!*\`^((.)\2(?!\2))*$
(.)(?!\1)

Explanation
The entire core program is in a silent loop. The first stage sorts the input. The second stage will print the current string if it consists of successive pairs of different characters. The third stage removes the last occurrence of every character (removing one of each character in the string).
About the junk at the top: the order is important. In addition to needing to be syntactically valid, a semicolon must be after the asterisks and before the backticks, so long as * is in the config string, in order for it to not print.

Nice, my answer is shorter but I'm not sure it scales well to being fixed for 0/1 as output, so I'm just going to add it here in case it helps you: https://tio.run/##K0otycxLNPz/vzhBQ09Tw97GVsPeVgNIG9rFGGrW6Glqa@ppadYUA4GdnV2NXYw2BKoAgbK9srJyjYuLi5aLkZaRkVFCQoKNlg3QCFtbQ8ND2w5t0@NSUQYyuLi4XBL0tICMQ9tqjOhoFQA

@FryAmTheEggman I was looking for a pure regex solution to match character groups of same lengths all in a row, but I couldn't figure it out.

@FryAmTheEggman Made a big improvement! I didn't really use what you had, but I started from scratch trying to think of a better method.

Nicely done! And I hadn't thought enough about my program it seems, but at least you found a better one :)

Whispers v2, 1750* 1305 bytes
> 1
> InputAll
>> ∪2
>> #2
>> #3
>> 4÷5
>> ⌊6⌋
>> L⋅7
>> Each 8 3
>> 9ᴺ
>> 2ᴺ
>> 10=11
>> 6>1
>> 12⋅13
>> Output 14

           ###########################00000000000000000000000000001111111111111111111112222222222222222222222222333333333333333333333333334444444444444444444444444445555555555555555555555555555666666666666666666666666666777777777777777777777777777788888888888888888888888888889999999999999999999999999999============================AAAAAAAAAAAAAAAAAAAAAAAAAAAAEEEEEEEEEEEEEEEEEEEEEEEEEEEEIIIIIIIIIIIIIIIIIIIIIIIIIIIILLLLLLLLLLLLLLLLLLLLLLLLLLLLOOOOOOOOOOOOOOOOOOOOOOOOOOOOaaaaaaaaaaaaaaaaaaaaaaaaaaaacccccccccccccccccccccccccccchhhhhhhhhhhhhhhhhhhhhhhhhhhhlllllllllllllllllllllllllllnnnnnnnnnnnnnnnnnnnnnnnnnnnnpppppppppppppppppppppppppppttttttttttttttttttttttttttuuuuuuuuuuuuuuuuuuuuuuuuuu÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷ᴺᴺᴺᴺᴺᴺᴺᴺᴺᴺᴺᴺᴺᴺᴺᴺᴺᴺᴺᴺᴺᴺᴺᴺᴺᴺᴺ∪∪∪∪∪∪∪∪∪∪∪∪∪∪∪∪∪∪∪∪∪∪∪∪∪∪∪∪⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⌊⌊⌊⌊⌊⌊⌊⌊⌊⌊⌊⌊⌊⌊⌊⌊⌊⌊⌊⌊⌊⌊⌊⌊⌊⌊⌊⌊⌋⌋⌋⌋⌋⌋⌋⌋⌋⌋⌋⌋⌋⌋⌋⌋⌋⌋⌋⌋⌋⌋⌋⌋⌋⌋⌋⌋

Try it online!
* Golfs made while explaining it. You can see the original here
Interesting task, fairly boring restriction.
Unfortunately, due to the fact that every line must start with either >> or >, this forces the number of each character to be disproportionately large. Luckily, Whispers ignores every line that doesn't match one of its regexes, all of which require the line to begin with >. Therefore we just have a large character dump at the end of the program. In addition to this, Whispers, being designed for mathematical operations, struggles when applied to a array-manipulation question. Overall, this means that the task is interesting to attempt, but the source code requirements are a bit boring.
If we strip all the unnecessary characters from the program, we end up with
> 1
> InputAll
>> ∪2
>> #2
>> #3
>> 4÷5
>> ⌊6⌋
>> L⋅7
>> Each 8 3
>> 9ᴺ
>> 2ᴺ
>> 10=11
>> 6>1
>> 12⋅13
>> Output 14

Try it online!
which is the part of the code we're actually interested in.
How that works
Here we conduct two key tests: the count of each is the same and the counts are greater than 1. However, the code for these two tests are shared between them, so a complete walkthrough of the program is a more effective method of explaining this.
We start with the shared code:
> InputAll
>> ∪2
>> #2
>> #3
>> 4÷5

Here, we take the input and store it on line 2 (> InputAll). We then create a ∪nique version of that string (i.e. the input without duplicate characters). With our next two lines, we take the length of the untouched input (>> #2) and the number of unique characters in the input (>> #3). Finally, we divide the former by the latter.
Why? Let's have a look at the two inputs of aabbcc and abbaabb. With the first string, the division becomes 6÷3 = 2, and the second results in 7÷2 = 3.5. For non-discriminating strings, the result of this division is a) An integer and b) Greater than 1. Unfortunately, this also applies to some non-discriminating strings, such as abbccc, so we have to perform one more test.
>> ⌊6⌋
>> L⋅7
>> Each 8 3
>> 9ᴺ
>> 2ᴺ
>> 10=11

Note: line 6 is the result of the division.
First, we take the floor of the division, because Python strings cannot be repeated a float number of times. Then we reach our Each statement:
>> L⋅7
>> Each 8 3

3 is a reference to line 3, which contains our deduplicated input characters, so we map line 8 (>> L⋅7) over this list. Line 8 multiplies the character being iterated over by the floor of our division (>> ⌊6⌋). This creates an array of the deduplicated characters, repeated n times.
The results from our two previous strings, aabbcc and abbaabb, along with abcabc, would be aabbcc, aaabbb and aabbcc respectively. We can see that the first and last two are identical to their inputs, just with the letters shuffled around, whereas the middle one isn't (it has one less b). Therefore, we simply sort both the input and this new string, before comparing for equality:
>> 9ᴺ
>> 2ᴺ
>> 10=11

Finally, we need to check that the number of characters in the string is 2 or greater. Luckily, the division we performed earlier will always result in a value greater than 1 if a character repeats more than once, meaning we just need to assert that line 6 is greater than 1:
>> 6>1

Now we have two booleans, one for each test. They both need to be true, so we perform a logical AND (boolean multiplication) with >> 12⋅13, before finally outputting the final result.

Pyth, 30 bytes
  "&8<MQSlqr{"&q1lJ{hMrSz8<1hJ

Leading spaces necessary.
Try it online!
The actual program is just &q1lJ{hMrSz8<1hJ. I just prepended the string "&8<MQSlqr{" to make it non-discriminating. But to make the string not print itself, I had to add a space, so I added 2 spaces.
&q1lJ{hMrSz8<1hJ

 q1l                (1 == len(
    J{                  J = deduplicate(
      hM                  map(lambda a: a[0],
        r  8                length_encode(
         Sz                   sorted(input())
                            )
                          )
                        )
                    )
&                     and
            <1hJ    (1 < J[0])

length_encode here (r <any> 8) takes a sequence and outputs the length of each run of the same character, ex. "aaabbcc" becomes [[3, "a"], [2, "b"], [2, "c"]].
So this takes the input, sorts it to put in length encode, and takes the first element of each list in the resulting list (e.g. the earlier example would become [3, 2, 2]). This gives a count of how many times characters occur. Then it's deduplicated (the earlier example would become [3, 2]), and J is set to that.
Then it checks if the length is 1, i.e. there is only 1 unique number of times a character occurs, and if that is > 1, i.e. >= 2.
There might be a built-in to replace rSz8 or hMrSz8 but I can't find one.

Perl 6, 58 57 bytes
{.max==.min>()**()}o{(bag .comb){*}}###=>>abccggiinnoxx

Try it online!
Turns out the three character version is slightly shorter than the two character one.

Julia 1.7, 88 bytes
x->(n=-[-all([])][];t=count.(x∪x,x);all(c->c==t[n]>n,t))####,,...;;>aacooouuu∪∪∪

Attempt This Online!
Ungolfed and unrestricted version:
x -> ( chars=count.(unique(x),x); all(c->c==chars[1]>1,chars) )

The logic ensures that each character's count is equal to the count of the first character and greater than 1. Julia 1.8 includes the relevant function allequal.
Golfing in Julia:

unique(x) is usually substituted with x∪x to save bytes. Here, it is done to reduce the number of ( and ) used.

Generally, Int and Bool are not converted automatically and need to be specified. It was a challenge to conjure up a 1 from the leftover characters, but I came up with -[-all([])][], which relies on -true == -1 and -[-1][] == 1.

-3 bytes: x->(n=-[-all([])][];t=count.(x∪x,x);all(@.t==t[n]>n))####,,...;;>aacooouuu∪∪∪

With the source restriction (all characters must appear the same number of times and at least twice), your solution comes to 92 bytes: x->(n=-[-all([])][];t=count.(x∪x,x);all(@.t==t[n]>n))####,,,-..;;>>@@@aacccooouuu∪∪∪

Oh nevermind, I forgot to change the source in the source variable too, so I thought it was valid. Thanks

Go, 444 420 bytes
func(s string)bool{m,c:=make(map[rune]int),make(map[int][]rune)
for _,d:=range s{m[d]++}
for o,a:=range m{if a<1+1{return 1<000000000000}
c[a]=append(c[a],o)}

//abbbbbbbbbbbcccccccdddddddddeeffffffff
//gggggggggiiiiiiiikkkkkkkkkkllllllllllmmmmmoooooo
//pppppppprssssssssstttttttuuuuuuu
//    11111111<<<<<<<<<<:::::::::
//___________+++++++++,,,,,,,======
//{{{{{{{{}}}}}}}}((((((()))))))[[[[[[]]]]]]
return len(c)==1}

Attempt This Online!
Adds characters as comments and whitespace to make it non-discriminating.
Discriminated version, 165 163 bytes
func(s string)bool{m,c:=make(map[rune]int),make(map[int][]rune)
for _,d:=range s{m[d]++}
for o,a:=range m{if a<2{return 1<0}
c[a]=append(c[a],o)}
return len(c)==1}

Attempt This Online!

Vyxal, 16 bytes
≈?Ċfy‹≈ß?Ċfy‹AßA

Try it Online!
Non-commented 16 byter

Each character needs to occur at least twice for a string to be "non-discriminating". This answer doesn't account for that

oh i missed that part lemme fix that

Perl 6, 132 100 bytes
my &f={{$_[0]>1&&[==] $_}(.comb.categorize({$_}).values)}#myy ff[]00>>11()cobbattggrriizzvvlluuss##

Pyth, 66 bytes
 " &&))//0<<==??@@IIJNNVVaallqq{"zJ.{zVJ=aY/zN)I&q1l.{Y<1@Y01.?0 "

Try it online!
Pyth (indented) | Python 3 (translation)
                                  | def a(A,B):
                                  |     c=list(A)
                                  |     c.append(B)
                                  |     return c
                                  | Y=[]
                                  | z=input()
 " &&))//0<<==??@@IIJNNVVaallqq{" | " &&))//0<<==??@@IIJNNVVaallqq{"
z                                 | print(z)
J.{z                              | J=set(z)
VJ                                | for N in J:
    =aY/zN)                       |     Y=a(Y,z.count(N))
I&q1l.{Y<1@Y0                     | if 1==len(set(Y)) and 1<Y[0]:
    1                             |     print(1)
.?                                | else:
    0                             |     print(0)
     "                            |     ""

APL, 19 72 bytes
This is my second attempt at golfing and also second program in APL.  I cant figure out if I can do an unnamed lambda within a named function.  If I can do that I can shave some bytes and make it more readable.  Was happy to land on a solution so quick #I♥APL

i ← ⍞ ◊ 2 ≤ ∨ / { ⍴ i ∩ ⍵ } ¨ ∪ i[⍋i]

i←{⍞}◊{}◊{}◊◊2≤∨/∨/∨/∨/{∪⍴i∩∪⍵}¨∪i[∪⍋i]⍝⍝⍝⍝⍞⍞⍞←←←222≤≤≤¨¨¨∩∩∩⍴⍴⍴⍵⍵⍵[[[]]]⍋⍋⍋

Try Apl Online Note you will need to change ⍞ to your string as character input is not supported in the online platform
Explination
Basically it gets character input and saves as i then sorts i and makes a list of the number of occurances of each unique element in i then it reduces the list with a logical or to check that there are the same number of each unique element and finally checks if there are at least 2 of each unique element.
Feel free to tear into my solution! I need to learn and I am still very new to APL and golfing.
Edit!!!
I am an idiot (as was kindly pointed out in the comments) and forgot to make my program non-deterministic. FAIL.
quack!

I cant figure out if I can do an unnamed lambda within a named function. You could ask in the APL orchard.

Jotlin, 116 bytes
{c(it).map({(_,ebb)->ebb}).l{a.none({icmp_2->icmp_2<2||icmp_2!=a[0]||",,,-->>llnnoooaettt<<<!!=[[[000!]]]".l==""})}}

Full program code:
val f: (String)->Boolean =

{c(it).map({(_,ebb)->ebb}).l{a.none({icmp_2->icmp_2<2||icmp_2!=a[0]||",,,-->>llnnoooaettt<<<!!=[[[000!]]]".l==""})}}

val trues = listOf(
        "aaaa",
        "aa!1 1 !a !1",
        "aabbccddeeffgg",
        "1Q!V_fSiA6Bri{|}tkDM]VjNJ=^_4(a&=?5oYa,1wh|R4YKU #9c!#Q T&f`:sm$@Xv-ugW<P)l}WP>F'jl3xmd'9Ie\$MN;TrCBC/tZIL*G27byEn.g0kKhbR%>G-.5pHcL0)JZ`s:*[x2Sz68%v^Ho8+[e,{OAqn?3E<OFwX(;@yu]+z7/pdqUD",
        "{c(it).map({(_,ebb)->ebb}).l{a.none({icmp_2->icmp_2<2||icmp_2!=a[0]||\",,,-->>llnnoooaettt<<<!!=[[[000!]]]\".l==\"\"})}}"
)

val falses = listOf(
        "a",
        "abbaabb",
        "abc",
        "bQf6ScA5d:4_aJ)D]2*^Mv(E}Kb7o@]krevW?eT0FW;I|J:ix %9!3Fwm;*UZGH`8tV>gy1xX<S/OA7NtB'}c u'V\$L,YlYp{#[..j&gTk8jp-6RlGUL#_<^0CCZKPQfD2%s)he-BMRu1n?qdi/!5q=wn\$ora+X,POzzHNh=(4{m`39I|s[+E@&y>"
)

for (t in trues) {
    val r1 = f(t)
    if (!r1) throw AssertionError("'$t' gave the wrong value, ($r1 != true)")
}
for (t in falses) {
    val r1 = f(t)
    if (r1) throw AssertionError("'$t' gave the wrong value ($r1 != false)")
}

Uses a check for lowercase equaling an empty string to get rid of extra characters.

Pascal (FPC), 288 280 bytes
35 distinct characters * 8 times
var c:char;g:array[0..222]of byte;w,v:byte;begin;repeat read(c);inc(g[ord(c)]);v:=g[ord(c)]until eof;foR w:=0to 222do if(g[w]>=2)and(g[w]<>v)oR(v<2)then v:=0;wRitE(v>0)End.,,,,,,,.....0000::<<<<<<====>>>>>[[[]]]abbbbbccddffffgghhhhhhiiilllllllnnppppppptuuuuuuuvwwwyyyyyEEEEEERRRRR

Try it online!
-8 bytes by kicking out y from the program! (See below)
Now for the reduced range of characters, but still covering printable ASCII.
This is the basic program:
var c:char;g:array[0..255]of byte;w,v,y:byte;begin;repeat read(c);inc(g[ord(c)]);v:=g[ord(c)]until eof;for w:=0to 255do if(g[w]>=2)and(g[w]<>v)or(v<2)then y:=2;write(y=0)end.

The task was juggling between number of spaces, ;s and ()s and it seems that less than 8 characters on all of them is impossible.
There are more than 8 of es and rs in the basic program, so I introduced some capital letters or I would need to increase number of occurences of other characters.

Wolfram Language (Mathematica), 57 54 bytes
(Apply[Equal]@#)~And~(1<Last[#])&@*Counts

yEqd1<L*Co&

Try it online!

PowerShell Core, 75 bytes
-!(($ps=$args| group |% co*|gu).count-1)*!($ps-le1)###1alnn*%=.raclette!.=%

Try it online!
Takes the input as a splatted string

Swift 5.9, 156 bytes (39 unique chars, 4 of each char)
var vrum$vuv={!(!false)},
y=[+0],////&&||!>>
lomrocfacefilm$={sS in [y=(sS+"").map{p in
sS.filter{!($0<p||$0>p)}.count},
Set(y).count<1<<1&&y[+0]>1,""][+1]}

The function you want is lomrocfacefilm$(_:). (Because apparently dollar signs are valid in identifiers as long as they're not the first character.)
I managed to get most of the extras shoved into the code without a comment, at the cost of creating an unmaintainable nightmare. I had fun with the names, though.


text:
Codegolf the Hafnian
The challenge is to write codegolf for the Hafnian of a matrix.
The Hafnian of an \$2n \times 2n\$ symmetric matrix \$A\$ is defined as:
$$\operatorname{haf}(A) = \frac 1 {n!2^n} \sum_{\sigma \in S_{2n}} \prod^n_{j=1} A_{\sigma(2j-1),\sigma(2j)}$$
Here \$S_{2n}\$ represents the set of all permutations of the integers from \$1\$ to \$2n\$, that is \$[1, 2n]\$.
The Wikipedia link talks about adjacency matrices but your code should work for any real valued symmetric input matrices.
For those interested in applications of the Hafnian, the mathoverflow link discusses some more.
Your code can take input however it wishes and give output in any sensible format but please include in your answer a full worked example including clear instructions for how to supply input to your code.
The input matrix is always square and will be at most 16 by 16. There is no need to be able to handle the empty matrix or matrices of odd dimension.
Reference implementation
Here is some example python code from Mr. Xcoder.
from itertools import permutations
from math import factorial

def hafnian(matrix):
    my_sum = 0
    n = len(matrix) // 2
    for sigma in permutations(range(n*2)):
        prod = 1
        for j in range(n):
            prod *= matrix[sigma[2*j]][sigma[2*j+1]]
        my_sum += prod
    return my_sum / (factorial(n) * 2 ** n)

print(hafnian([[0, 4.5], [4.5, 0]]))
4.5
print(hafnian([[0, 4.7, 4.6, 4.5], [4.7, 0, 2.1, 0.4], [4.6, 2.1, 0, 1.2], [4.5, 0.4, 1.2, 0]])
16.93
print(hafnian([[1.3, 4.1, 1.2, 0.0, 0.9, 4.4], [4.1, 4.2, 2.7, 1.2, 0.4, 1.7], [1.2, 2.7, 4.9, 4.7, 4.0, 3.7], [0.0, 1.2, 4.7, 2.2, 3.3, 1.8], [0.9, 0.4, 4.0, 3.3, 0.5, 4.4], [4.4, 1.7, 3.7, 1.8, 4.4, 3.2]])
262.458

The wiki page has now (March 2 2018) been updated by  ShreevatsaR to include a different way of calculating the Hafnian.  It would be very interesting to see this golfed.

I think this would be easier to digest with an informal explanation of the hafnian. Something like, take all subsets of n matrix entries where their n row indices and n column indices form a partition of 1..2n, take the product of each, add them, and scale the sum.

R, 150 142 127 119 bytes
function(A,N=nrow(A),k=1:(N/2)*2)sum(apply(gtools::permutations(N,N),1,function(r)prod(A[cbind(r[k-1],r[k])])))/prod(k)

Try it online!
Uses the same trick I discovered golfing down this answer to index the matrix P, and @Vlo suggested an approach to entirely remove the for loop for -6 bytes!
To create a new test case, you can do matrix(c(values,separated,by,commas,going,across,rows),nrow=2n,ncol=2n,byrow=T).
Explanation: (the code is the same; it uses an apply rather than a for loop but the logic is otherwise identical).
function(A){
N <- nrow(A)                   #N = 2*n
k <- 1:(N/2) * 2               #k = c(2,4,...,N) -- aka 2*j in the formula
P <- gtools::permutations(N,N) #all N-length permutations of 1:N
for(i in 1:nrow(P))
 F <- F + prod(A[cbind(P[i,k-1],P[i,k])]) # takes the product of all A_sigma(2j-1)sigma(2j) for fixed i and adds it to F (initialized to 0)
F / prod(k)                    #return value; prod(k) == n! * 2^n
}

Apply is cheaper by 2 bytes, which allows for additional 4 bytes of saving by cramming the other lines together. https://tio.run/##PY6xDoIwEIZ3nsLxzpxiS4ymkYEXYHIjDFDEEKBtSokS47PX4sDw5/svX@5y1re728G3s5Ku0woy/OSpsvoVWtSnTEAec9zzaJpHqIwZFng6rYdJCPOw4@yqdW2CnHIkRtsdi8bqBrJC1p1qwBb9gZUUUGKJiPHf9vj1LYyVs90bJCR0Op5DLpQgceKI0WaZuNL6Vhog9RBQL@t4R/Q/ It is also quite interesting how base R lacks a permutation function for a statistical programming language

@Vlo very nice! we can move N and k into function arguments to get it to one statement, removing the {} and saving another two bytes.

@Giuseppe Darn keeps on forgetting that you can define them in the function args. Spent a few minutes trying to ember those variables...

Pyth, 24 bytes
sm*Fmc@@Qhkek2d{mScd2.pU

Try it here!

Old version, 35 bytes
*c1**FK/lQ2^2Ksm*Fm@@Q@dtyk@dykK.pU

Try it here!

Currently the lead but you have to fear the Jelly answers to come.... :)

Eh Jelly will definitely beat my by about 10 bytes. Pyth ain’t the best tool for the job

05AB1E is looking like it may even tie Pyth (believe it or not, finally a matrix challenge where a[b] is enough to compete).

@MagicOctopusUrn I already have an 05AB1E solution that beats Pyth :-) Not going to post it (for now, at least)

Is it something along the lines of xÍysè<¹sès·<ysè<è lmao? P.S. Mine is 40 bytes and isn't working so well hah, so feel free to post it, unsure I'm able to finish before I have to go home.

@MagicOctopusUrn status-completed

Stax, 23 22 19 17 bytes
ü;Y╙◘▌Φq↓ê²╧▐å↑┌C

Run and debug it online
The corresponding ascii representation of the same program is this.
%r|TF2/{xsE@i^H/m:*+

The program suffers from some floating point rounding error.  In particular, it reports 33673.5000000011 instead of 33673.5.  But I think the accuracy is acceptable given that this program operates on floating point values.  It's also very slow, taking almost a minute for the example inputs on this machine.
%                             get size of matrix
 r|T                          get all permutations of [0 ... size-1]
    F                         for each, execute the rest of the program
     2/                       get consecutive pairs
       {        m             map each pair...
        xsE@                      the matrix element at that location
            i^H/                  divided by 2*(i+1) where i=iteration index
                 :*           product of array
                   +          add to running total

Very impressive!

Finally, I actually see someone using Stax! I thought I was the only person that knew about it.

I know a lot about it, but I'm equally surprised to find someone else who knows about it. :)

you created Stax?! No way!
... also could I create a chat room for Stax? I don't know, I want to chat with the legendary tomtheisen (at least legendary to me)

I used to have a chat room some months ago, but it's fallen into disuse.  I have no problem with you creating a chat room.  The idea of being legendary over is pretty amusing to me. :)

05AB1E, 21 bytes
ā<œε2ô{}Ùεε`Isèsè;]PO

Try it online!

Old version, 32 bytes
āœvIg;©Lε·UIyX<èèyXèè}P}Oθ®!/®o/

Try it online!
How it works?
āœvIg;©Lε·UIyX<èèyXèè}P}Oθ®!/®o/ – Full program. Argument: A matrix M.
ā                                – The range [1 ... len(M)].
 œ                               – Permutations.
  v                    }         – Iterate over the above with a variable y.
   Ig;©                          – Push len(M) / 2 and also store it in register c.
       Lε            }           – For each integer in the range [1 ... ^]:
         ·U                      – Double it and store it in a variable X.
            yX<                  – Push the element of y at index X-1.
           I   è                 – And index with the result into M.
                yXè              – Push the element of y at index X.
                   è             – And index with the result into ^^.
                      P          – Take the product of the resulting list.
                        O        – Sum the result of the mapping.
                         θ       – And take the last element*.
                          ®!     – Take the factorial of the last item in register c.
                             ®o  – Raise 2 to the power of the last item in register c.
                            /  / – And divide the sum of the mapping accordingly.

* – Yeah, this is needed because I mess up the stack when pushing so many values in the loop and not popping correctly ;P

No kidding èsè, hah... haha... I'm punny.

R, 84 78 bytes
h=function(m)"if"(n<-nrow(m),{for(j in 2:n)F=F+m[1,j]*h(m[v<--c(1,j),v]);F},1)

Try it online!
Edit: Thanks to Vlo for -6 bytes.
It seems that everybody here is implementing the standard reference algorithm with permutations, but I tried to take advantage of the community knowledge gained in the related challenge, which is basically the same task targeted for fastest code instead of golf.
It turns out that for a language that is good at slicing matrices (like R), the recursive algorithm: hafnian(m) = sum(m[i,j] * hafnian(m[-rows and columns at i,j]) is not only faster, but also quite golfy. Here is the ungolfed code:
hafnian<-function(m)
{
    n=nrow(m)
    #Exits one step earlier than golfed version
    if(n == 2) return(m[1,2])
    h = 0
    for(j in 2:n) {
        if(m[1,j] == 0) next
        h = h + m[1,j] * hafnian(m[c(-1,-j),c(-1,-j)])
    }
    h
}

Very nice answer. -1 for calling If with parenthesis, -4 for using F as initialized variable, -1 for assigning n within the if. https://tio.run/##XU/LCsIwELz7FcFTVtOQl1pf1/6EeJBCsUJTKFoF8dvrbrtVFMKG2RlmZpuuO@@LW8yvZR1lBdOymMq4S2JT3xGqZ1E38iLKKNwmQrbP5tXBqstxdpbVod0lSS4RgmqPsM1eykKHxOnalA@ZS6NE0AseBpRw@AAm/5IVjeVHjBDXTlv8dWBugEpY7UZD4npI1qT7tbbak9KOIm1orGkXmAhEOApkSe84QjcUW38qooHv2@lvkRXpHBGedilncHHDhBkuCzz6DD8Epbzz2uEZeOkSoHsD

neat! I'd say post it in the speed challenge, but there are probably some more optimizations (like threading) that can be made, and while R isn't exactly known for its speed, it'd be good to have it there for reference.

Do it for benchmark purposes!

I actually tried testing this for speed, but got quickly discouraged by the results. The slowest Python submission in the speed challenge using the same exact algorithm crunches 24x24 matrix in a few seconds on TIO, but R times out. On my local machine it also didn't respond in a reasonable time, even when aided with memoization from package 'memo'...

Jelly, 19 bytes
LŒ!s€2Ṣ€QḅL_LịFHP€S

Try it online!
Alternate version, 15 bytes, postdates challenge
LŒ!s€2Ṣ€QœịHP€S

Jelly finally got n-dimensional array indexing.
Try it online!
How it works
LŒ!s€2Ṣ€QœiHP€S  Main link. Argument: M (matrix / 2D array)

L                Take the length, yielding 2n.
 Œ!              Generate all permutations of [1, ..., 2n].
   s€2           Split each permutation into pairs.
      Ṣ€         Sort the pair arrays.
        Q        Unique; deduplicate the array of pair arrays.
                 This avoids dividing by n! at the end.
           H     Halve; yield M, with all of its elements divided by 2.
                 This avoids dividing by 2**n at the end.
         œị      At-index (n-dimensional); take each pair of indices [i, j] and
                 yield M[i][j].
            P€   Take the product the results corresponding the same permutation.
              S  Take the sum of the products.

The 19-byte version works in a similar fashion; it just has to implement œị itself.
...ḅL_LịFH...    Return value: Array of arrays of index pairs. Argument: M

    L            Length; yield 2n.
   ḅ             Convert each pair of indices [i, j] from base 2n to integer,
                 yielding ((2n)i + j).
     _L          Subtract 2n, yielding ((2n)(i - 1) + j).
                 This is necessary because indexing is 1-based in Jelly, so the
                 index pair [1, 1] must map to index 1.
        F        Yield M, flattened.
       ị         Take the indices to the left and get the element at these indices
                 from the array to the right.
         H       Halve; divide all retrieved elements by 2.

C (gcc), 288 285 282 293 292 272 271 263 bytes

Saved three bytes by fiddling with two post-increments and for loop placement.
Saved three bytes by fiddling with anothter post-increment, moving both variable initializations before the branch -- golfed if(...)...k=0...else...,j=0... to if(k=j=0,...)...else... -- and performed an index shift.
Required eleven bytes by supporting float matrices.
Saved a byte thanks to Mr. Xcoder; golfing 2*j+++1 to j-~j++.
Saved twenty bytes by removing a superfluous int variable type declaration and not using a factorial function but instead calculating the factorial value by using an already existing for loop.
Saved a byte by golfing S=S/F/(1<<n); to S/=F*(1<<n);.
Saved eight bytes thanks to ceilingcat.

float S,p,F;j,i;s(A,n,P,l,o,k)float*A;int*P;{if(o-l)for(k=0;k<l;s(A,n,P,l,o+1))P[o]=k++;else{for(p=j=l;j--;)for(i=l;i--;)p-=P[j]==P[i];if(!p){for(F=p=1,j=0;j<n;F*=j)p*=A[P[2*j]*2*n+P[j+++j]];S+=p;}}}float h(A,n)float*A;{int P[j=2*n];S=0;s(A,n,P,j,0);S/=F*(1<<n);}

Try it online!

Explanation (271 bytes version)
float S,p,F;                    // global float variables: total sum, temporary, factorial
j,i;                            // global integer variables: indices
s(A,n,P,l,o,k)float*A;int*P;{   // recursively look at every permutation in S_n
 if(k=j=0,o-l)                  // initialize k and j, check if o != l (possible  permutation not yet fully generated)
  for(;k<l;s(A,n,P,l,o+1))      // loop through possible values for current possible  permuation position
   P[o]=k++;                    // set possible  permutation, recursively call (golfed into the for loop)
 else{for(p=-l;j<l;j++)         // there exists a possible permutation fully generated
  for(i=0;i<l;)                 // test if the possible permutation is a bijection
   p+=P[j]==P[i++];             // check for unique elements
  if(!p){                       // indeed, it is a permutation
   for(F=p=1,j=0;j<n;F*=j)      // Hafnian product loop and calculate the factorial (over and over to save bytes)
    p*=A[P[2*j]*2*n+P[j-~j++]]; // Hafnian product
   S+=p;}}}                     // add to sum
float h(A,n)float*A;{           // Hafnian function
 int P[j=2*n];S=0;              // allocate permutation memory, initialize sum
 s(A,n,P,j,0);                  // calculate Hafnian sum
 S/=F*(1<<n);}                  // calculate Hafnian

Try it online!
At the program's core is the following permutation generator which loops through S_n. All Hafnian computation is simply build upon it -- and further golfed.
j,i,p;Sn(A,l,o,k)int*A;{          // compute every element in S_n
 if(o-l)                          // o!=l, the permutation has not fully been generated
  for(k=0;k<l;k++)                // loop through the integers [0, n)
   A[o]=k,Sn(A,l,o+1);            // modify permutation, call recursively
 else{                            // possible permutation has been generated
  for(p=-l,j=0;j<l;j++)           // look at the entire possible permutation
   for(i=0;i<l;i++)p+=A[j]==A[i]; // check that all elements appear uniquely
  if(!p)                          // no duplicat elements, it is indeed a permutation
   for(printf("["),j=0;j<l        // print
   ||printf("]\n")*0;)            //  the
    printf("%d, ",A[j++]);}}      //   permutation
main(){int l=4,A[l];Sn(A,l,0);}   // all permutations in S_4

Try it online!

2*j+++1 is equivalent to j+j+++1, which is the same as j-(-j++-1), so we can use the bitwise complement efficiently to save a byte: j-~j++ (Try it online)

Haskell, 136 bytes
-14 bytes thanks to ovs.
import Data.List
f m|n<-length m`div`2=sum[product[m!!(s!!(2*j-2)-1)!!(s!!(2*j-1)-1)/realToFrac(2*j)|j<-[1..n]]|s<-permutations[1..n*2]]

Try it online!
Ugh...

Jelly, 29 bytes
LHµ2*×!
LŒ!s€2;@€€Wị@/€€P€S÷Ç

Try it online!
I think the ;@€€Wị@/€€P€ part can likely be golfed down. Need to come back later to check and add an explanation.

Identical to my solution (except the J) before golfed down. Jelly minds think alike? source

I was able to reduce it a bit more by refactoring the part that you mentioned as well as the division by 2 and the factorial. LḶŒ!s€2ḅL‘ịFZµPS÷JḤ$P$ TIO

@user202729 haha nice

@miles Wow that's a lot of savings. I'll edit it into my answer but it's pretty different so feel free to submit your own answer if you want

MATL, 29 24 22 bytes
Zy:Y@!"G@2eZ{)tn:E/pvs

Try it online! Or verify all test cases: 1, 2, 3.
How it works
Zy       % Size of (implicit) input: pushes [2*n 2*n], where the
         % input is a 2*n × 2*n matrix.
:        % Range: gives row vector [1 2 ... 2*n]
Y@       % All permutation of that vector as rows of a matrix
!"       % For each permutation
  G      %   Push input matrix
  @      %   Push current permutation
  2e     %   Reshape as a 2-row array
  Z{     %   Split rows into a cell array of size 2
  )      %   Reference indexing. With a cell array as index this
         %   applies element-wise indexing (similar to sub2ind).
         %   Gives a row vector with the n matrix entries selected
         %   by the current permutation
  t      %   Duplicate
  n:     %   Number of elements, range: this gives [1 2 ... n]
  E      %   Double, element-wise: gives [2 4 ... 2*n]
  /      %   Divide, element-wise
  p      %   Product
  vs     %   Vertically concatenate and sum
         % End (implicit). Display (implicit)

JavaScript (Node.js), 121 119 117 115 101 bytes
A=>(F=(a,t,r)=>{a--?A[t].map((x,i)=>F[i]=F[i]||F(F[i]=a,i,a%2?r:r*x/(a+2))):s+=r})(A.length,s=0,1)||s

Try it online!
Explanation & Ungolfed
function hafnian(A) {            // Main function taking an array
 return (
  F = function(                  //  Helper function, and also a temporary storage
   a,                            //   how many numbers left
   t,                            //   previous number
   r                             //   the product
  ) {                            //   The braces are to avoid returning value
   a-- ?                         //   If a > 0:
    A[t].map((x, i) =>           //    Loop from i = 2n - 1 downto 0:
     F[i] = F[i] || F(           //     Skip if F[i] is truthy, i.e. i used in the permutation
      F[i] = a,                  //     Otherwise: Set F[i] to truthy* & start a new recursion
      i,                         //      with i as the previous number
      a % 2                      //      If a - 1 is odd:
       ? r                       //       r does not change
       : r * x / (a + 2)         //      Otherwise: multiply A[t][i] to r, divide by a + 1
     )                           //      Set back F[i] to undefined after the recursion
    )
   : s += r;                     //   Otherwise: add r to s. The factor 1/(n!*2^n) = 1/(2n)!!
  }                              //   has been included in the recursion
 )(
  A.length,                      //  2n = size of the array
  s = 0,                         //  Initial sum s = 0
  1                              //  Initial product r = 1
 ) || s;                         //  Return s
}

/* Note that when a = 1 F[i] will be falsy, but the next recursion will just
   skip this part anyway. */

Coconut, 165 145 128 127 bytes
-1 byte thanks to Mr. Xcoder
m->sum(reduce((o,j)->o*m[p[2*j]][p[j-~j]]/-~j/2,range(len(m)//2),1)for p in permutations(range(len(m))))
from itertools import*

Try it online!

Wolfram Language (Mathematica), 84 bytes
aTr[1##&@@(a[[##]]&@@@#~Partition~2)&/@Permutations@Range[n=Tr[1^a]]]/(n/=2)!/2^n

Try it online!

Wolfram Language (Mathematica), 68 bytes
If[#=={},1,Sum[d=Rest@*Delete[i];#[[1,i]]#0@d[d/@#],{i,2,Tr[1^#]}]]&

Try it online!

Very slightly disappointed Mathematica doesn't have a function for this :)

Perl 6, 86 bytes
{my \n=$^m/2;^$m .permutations.map({[*] .map(->\a,\b{$m[a][b]})}).sum/(2**n*[*] 1..n)}

JavaScript (Node.js), 87 86 bytes
f=A=>A[0]?A[0].reduce((y,x,i)=>i&&y+x*f((g=B=>B.filter((_,j)=>j&&i-j))(A).map(g)),0):1

Try it online!
This is a port of Kirill's algorithm, and this turns out to be shorter than the naive approach! However I'm retaining my original answer and posting this as a separate one.
Explanation
f = A =>                               // A function receiving an array as input
 A[0]                                  //  If A is not empty:
  ? A[0].reduce((y, x, i) =>           //   Calculate the sum
   i                                   //   for i = 1 to 2n - 1:
   && y + x * f(                       //    A[0][i] * the hafnian of
    (g = B =>
     B.filter((_, j) => j && i - j)    //    array A removing rows 0 and i
    )(A).map(g)                        //    as well as columns 0 and i
   ),
   0
  )
  : 1                                  //  If A is empty: return 1

Pari/GP, 51 bytes
h(m)=if(#m,sum(n=2,#m,m[1,n]*h(m[^n,^n][^1,^1])),1)

Try it online!

Python 3.8 (pre-release), 185 181 bytes
def f(m):
 a=0;n=len(m)//2
 for x in itertools.permutations(range(n*2)):p=1;[p:=p*m[x[2*j]][x[2*j+1]]for j in range(n)];a+=p
 return a/(math.factorial(n)*2**n)
import math,itertools

Try it online!
Golfed reference implementation provided in the question.

source: Stack Exchange

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

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

sort: votes


text:
Simplify and Take Partial Derivative to a Polynomial String
Introduction
Write a program to calculate the partial derivative of a polynomial (possibly multivariate) with respect to a variable.
Challenge
Derivatives are very important mathematical tools that has been widely applied in physics, chemistry, biology, economics, psychology and more to handle all kinds of problems. Expressions with multiple variables are also very common.
In the scope of this challenge, a polynomial string ("polystr") is defined by the following BNF (Backus–Naur form):
<polystr> ::= <term> | <term><plusminus><polystr>

<plusminus> ::= "+" | "-"

<term> ::= <coeff> | <coeff><baseterm> | <baseterm>

<baseterm> ::= <variable> | <variable><exponent> | <baseterm><baseterm>

<coeff> ::= positive_integer

<exponent> ::= positive_integer

<variable> ::= lowercase_ASCII_letters

Where positive_integer and lowercase_ASCII_letters are quite self-explanatory.
For example, The string 3x2y-x3y-x2y+5 means 3*(x^2)*y-(x^3)*y-(x^2)*y+5. The terms given in the input may appear in any order, and the variables in each term also may appear in any order. So for example 5-yx2-x3y+y3x2 is also a valid input and is in fact the same as the previous example.
The rule for taking partial derivative is just doing it term by term. If the variable appears does not appear in the term, the derivative is zero. Otherwise, the coefficient of the term is multiplied by the exponent of that variable, and then the exponent of the variable is decreased by one. The exponents for other variables do not change. This is just following the definition in mathematics. In addition, if the resulting exponent is zero, remove the variable from the term.
For example, to take the partial derivative of 5z-z2y2-5w3y with respect to y. The following process is done (in accordance with the BNF defined above, the "coefficient" are all taken to be positive numbers, i.e. the signs are considered separately)
          5z          -   z2y2        - 5w3y

Coeff                 1->1*2=2      5->5*1=5
Expon                 2->2-1=1      1->1-1=0
Term                  -   2yz2         - 5w3
      (y is not here            (expon 0->y removed)
     so the term is 0)

The result is -2yz2-5w3y.
On the other hand, if the above expression is taken partial derivative with respect to a, the result is 0 because a is in none of the terms.
Your task is to write a function or a full program to calculate this derivative. It should take a polynomial string and a single character (the variable to take derivative with respect to), and return the derivative in the simplest form.
"Simplest form" means three things.

The number 0 (not the digit) should not appear in the output unless the output itself is just 0. So neither 0+10y nor 3-y0z will be valid output and should be transformed to 10y and 3-z, respectively.

The number 1 should not appear as an exponent or a coefficient, but can appear as a standalone term itself.

The terms with exactly the same set of variables and exponents should be merged, which means 3a2b5-4b5a2 is not a valid output, and it should be -a2b5 instead. More information about the input and output can be found in the "Specs" section.

Test Cases
Input
Output

2xy+4ax-5+7mx4-4-7x4m, x
2y+4a

4upv+5u2v3w4-4w4u2v3+qr-v,v
4up+3u2v2w4-1

12ux-7x2m3+ab5,q
0

-a+10ca11y-1nv3rt3d-poly, a
-1+110ca10y

1y+1x3y, y
1+x3

Specs

Input can be taken through standard forms. In other words, you can take input as a string, a list of characters, a nested array of coefficients, variables (possibly denoted by their ASCII value minus 'a' or something alike) and exponents, etc. You are also free to change the string to 2*x^3y^2 or alike instead of 2x3y2.

However, please do not use the input [2,0,0,0,1,0,0,3,0,0,...0] (an array of 27 elements) for the term 2dg, or any other verbose format that enumerates the 26 letters like this. Your input format should also be able to treat ab and ba as different inputs (so the 27-element array format is invalid due to this restriction as well).

Each variable (letter) will only appear once in each term of the input, that means xx will not appear and will always be presented as x2, nor will something like a3b4a2 appear.

To reiterate, the terms in the input may appear in any order.

You are also free to choose the output format provided that the verbose format mentioned above is avoided. The output should however always be in the simplest form as defined above. Just like the input, the terms in the output can appear in any order, and the variables in each term can also appear in any order and does not have to be consistent between terms. That means pu+2up2 is a valid output. The sign for the leading term can be either positive or negative and -y+3x and 3x-y are both valid, so is +3x-y.

The input are always given such that all the coefficients and exponents in the output will be less than 232-1, or the largest integer your language can handle, whichever is smaller. Claiming that the largest integer your language can handle is unreasonably small and trivializing the challenge falls into the category of default loopholes.

This is code-golf, the lowest number of bytes wins.

As usual, default loopholes apply here.

Edit: Since most of the answers so far turn out to be internals that do the whole challenge, and despite knowing there are builtins I don't have the intention to ban such internals from the very beginning, nor do I have now. I will make the winning criteria one that is based on a per-language basis, i.e. the submission with the least bytes in each language wins in that language. I will add a standard snippet for a catalogue if there are enough submissions. Feel free to go on submitting builtins to showcase the power of your language but please do not hesitate to submit your non-builtin answers even if it's way longer and your language does not have a builtin. Happy code golfing in your favorite language!

@JonathanFrech The second and the third term in the input can be merged. Together they give the second term in the output.

Ah, okay. In your first example, why does -9 appear in the output?

The only reason you can merge in the output is because the input could already be merged. That makes this really a combination of 2 independent problems take derivative and merge

I assume simplest form also implies no exponent 1, though you don't seem to state this

@JonathanFrech That's a typo. Fixed.

@TonHospel That's true. No coefficient 1 either. Added the requirement.

In your example, shouldn't -y2z2 become -2yz2, not -2y2z?

@HyperNeutrino You are right. I think I didn't have enough coffee ...

@Downvoter care to explain what's the issue with the challenge?

Python 2, 252 245 bytes
o,d=input()
D={};s=''
for c,t in o:T=`sorted(t)`;D[T]=D.get(T,0)+c
for t in D:
 c,t=D[t],dict(eval(t))
 if(d in t)*c:e=t[d];c*=e;t[d]=e-1;s+=('%+d '%c)[:~((-2<c<2)*sum(t.values())>0)]+''.join((v+`t[v]`*(t[v]>1))*(t[v]>0)for v in t)
print s or'0'

Try it online!
Takes input as a nested list of coefficients and terms:
[
 [coeff1, [[var1_1,exp1_1],
           [var1_2,exp1_2],
           ... ]
 ],
 [coeff2, [[var2_1,exp2_1], ...]],
 ...
]

For instance the first example (5z-z2y2-5w3y) is given as:
[
 [ 5, [['z', 1]          ] ],
 [-1, [['z', 2], ['y', 2]] ],
 [-5, [['w', 3], ['y', 1]] ]
]

The footer contains a function which parses a string input to the desired input format: parse(s).

Edit:

Takes input instead of function

Retina, 249 233 bytes
(.)(?=.*¶\1$)
$&_
L`.\w*
G`_
^\b
+
%O`._?\d*
_\d+
*
\b[a-z]
1$&
\b(\d+)(?=.*?(_+))
$1*$2
O$`(.)_+(.+)
$2$1
+`((\+|-)_+)(.*)¶\2(_+\3)\b
$1$4
+`\+_(_*(.*)¶-)_(_*\2\b)
+$1$3
G`\b_
\b_+
$.&
_(__+)
$.1
^\+|¶|(.)__|._
$1
\b1([a-z])
$1
^$
0

Try it online! Link includes test cases. Explanation:
(.)(?=.*¶\1$)
$&_

Add a _ after each occurence of the given variable.
L`.\w*

Split the input into terms.
G`_

Keep only the terms that referenced the variable.
^\b
+

Prefix a + if the first term doesn't have a sign.
%O`._?\d*

Sort each term alphabetically. (The sign matches, but that's not a problem; it sorts at the start anyway.)
_\d+
*

Convert all exponents of the variable into unary.
\b[a-z]
1$&

Temporarily prefix 1 to those terms without a multiplier.
\b(\d+)(?=.*?(_+))
$1*$2

Multiply the multiplier by the exponent of the variable, leaving the result in unary.
O$`(.)_+(.+)
$2$1

Sort all of the terms.
+`((\+|-)_+)(.*)¶\2(_+\3)\b
$1$4

Add terms of the same sign.
+`\+_(_*(.*)¶-)_(_*\2\b)
+$1$3

Subtract terms of different signs.
G`\b_

Remove terms that were cancelled by a term of a different sign.
\b_+
$.&

Convert the multiplier back to decimal.
_(__+)
$.1

Decrement exponents greater than three and convert back to decimal.
^\+|¶|(.)__|._
$1

a) Remove a leading + sign b) Join all the terms back together c) convert squares of the variable to the plain variable d) remove the variable if it didn't have an exponent.
\b1([a-z])
$1

Remove the temporary 1 unless it's no longer got anything to multiply.
^$
0

If there were no terms left then the result is zero.
Supporting duplicate terms cost almost half of my byte count. Previous 123 byte solution that didn't deduplicate terms:
(.)(?=.*¶\1$)
$&_
L`.\w*
G`_
_\d+
*
\b[a-z]
1$&
\b(\d+)(?=.*?(_+))
$.($1*$2
_(__+)
$.1
^\+|¶|(.)__|._
$1
\b1([a-z])
$1
^$
0

Try it online! Explanation:
(.)(?=.*¶\1$)
$&_

Add a _ after each occurence of the given variable.
L`.\w*

Split the input into terms.
G`_

Keep only the terms that referenced the variable.
_\d+
*

Convert all exponents of the variable into unary.
\b[a-z]
1$&

Temporarily prefix 1 to those terms without a multiplier.
\b(\d+)(?=.*?(_+))
$.($1*$2

Multiply the multiplier by the exponent of the variable.
_(__+)
$.1

Decrement exponents greater than three and convert back to decimal.
^\+|¶|(.)__|._
$1

a) Remove a leading + sign b) Join all the terms back together c) convert squares of the variable to the plain variable d) remove the variable if it didn't have an exponent.
\b1([a-z])
$1

Remove the temporary 1 unless it's no longer got anything to multiply.
^$
0

If there were no terms left then the result is zero.

Impressive, but you need to merge those two terms in your TIO example.

@WeijunZhou Sorry, I'd overlooked that bit of the spec. Let me think about it...

@WeijunZhou Ugh, it cost me far too many bytes, but I think I've got it working.

Thank you very much for your impressive hard work. I guess this is an good point for me to start learning Retina from.

Wolfram Language (Mathematica), 21 20 bytes
-1 byte thanks to Jonathan Frech!
ToExpression@#~D~#2&

Try it online!
The input is formatted so that every term follows coeff * var1 ^ exp1 * var2 ^ exp2 .... If the input can be taken as an expression rather than a string, the solution is 1 byte: D.

#1 can be #.

Physica, 3 bytes
∂

This doesn't use any new feature. ∂ and its ASCII-only alternative, Differentiate have been introduced more than 10 days ago.
Demo
Assumes that both the expression and the variable are passed as a string. Testing code:
f = ∂

Print[f['2*x*y+4*a*x-5+7*m*x^4-4-7*x^4*m'; 'x']]
Print[f['4*u*p*v+5*u^2*v^3*w^4-4*w^4*u^2*v^3+q*r-v'; 'v']]
Print[f['-a+10*c*a^11*y-1*n*v^3*r*t^3*d-p*o*l*y'; 'a']]

Exact output:
4*a + 2*y
4*p*u + 3*u**2*v**2*w**4 - 1
110*a**10*c*y - 1

Expression format: * for multiplication, ** for exponentiation, + and - for addition and subtraction accordingly.

Python 3 + SymPy, 23 bytes
from sympy import*
diff

Try it online!

Pari/GP, 5 bytes
deriv

Try it online!

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


text:
Halting Problem for Simplified Hexagony
Introduction
Decide whether a Hexagony program composed solely of the characters .)_|\/><@ will halt using least bytes.
Challenge
Hexagony is a language developed by Martin Ender in which the source code is presented in the form of a hexagon. It has been extensively used in PPCG and there has been many impressive submissions using this language. Your task is to take a Hexagony program in its short form (one liner) that contains the characters .)_|\/><@ only and decide whether it will halt.
Since a challenge should be self-contained (per comment by @Mr.Xcoder), the language specifications related to this challenge is given in the appendix. If there is anything unclear you can refer to the document itself, which I believe is pretty clear.
You can use a set of output values as truthy and another set as falsy provided that the intersection of the two sets is empty, and at least one of them should be finite (Thanks@JonathanAllan for fixing the loophole). Please indicate in the answer which sets you will use.
You can use TIO to check whether a Hexagony program halts within 60 seconds.
Bonus point for solutions in Hexagony!
Test cases
Input
Hexagonal Form
Output

.
.
False

.....@
 . .
. . .
 @ .
False

)\..@
 ) \
. . @
 . .
True

.\|<..@
 . \
| < .
 . @
False

)\|<..@
 ) \
| < .
 . @
True

..\...@|.<.\....>._
  . . \
 . . . @
| . < . \
 . . . .
  > . _
False

Specs

The input is a string or an array of characters of a Hexagony program in its short form
The length of the program will be less than or equal to 169 characters (side length of 8)
To reiterate, please clarify the truthy/falsy value sets you use in the answer
Your program should halt for all valid inputs. Halting with error is fine as long as a truthy/falsy value is written to stdout or its closest equivalent in your language. (Thanks
@moonheart08 for pointing out this)
This is code-golf, the lowest number of bytes wins.
As usual, default loopholes apply here.

Appendix: Hexagony language specs related to this challenge
Overview
Source code
The source code consists of printable ASCII characters and line feeds and is interpreted as a pointy-topped hexagonal grid, where each cell holds a single-character command. The full form of the source code must always be a regular hexagon. A convenient way to represent hexagonal layouts in ASCII is to insert a space after each cell and offset every other row. A hexagon of side-length 3 could be represented as
  . . .
 . . . .
. . . . .
 . . . .
  . . .

Within the scope of this challenge, the source code is padded to the next centered hexagonal number with no-ops (.s) and rearranged it into a regular hexagon. This means that the spaces in the examples above were only inserted for cosmetic reasons but don't have to be included in the source code.
For example, abcdefgh and abcdef will be padded to
  a b c
 d e f g            a b
h . . . .   and    c d e  ,   respectively.
 . . . .            f .
  . . .

Control flow
Within the scope of this challenge, the IP of Hexagony start at the top left corner of the hexagon moving to the right. There are commands which let you change the directions of IP movement based on its current direction and the value in the memory.
The edges of the hexagon wrap around to the opposite edge. In all of the following grids, if an IP starts out on the a moving towards the b, the letters will be executed in alphabetical order before returning to a:
   . . . .          . a . .          . . k .          . g . .
  a b c d e        . . b . .        . . j . .        . h . . a
 . . . . . .      g . . c . .      . . i . . e      . i . . b .
. . . . . . .    . h . . d . .    . . h . . d .    . j . . c . .
 f g h i j k      . i . . e .      . g . . c .      k . . d . .
  . . . . .        . j . . f        f . . b .        . . e . .
   . . . .          . k . .          . . a .          . f . .

If the IP leaves the grid through a corner in the direction of the corner there are two possibilities:
-> . . . .
  . . . . .
 . . . . . .
. . . . . . . ->
 . . . . . .
  . . . . .
-> . . . .

If value in the memory is non-zero, the IP will continue on the bottom row. If it's zero, the IP will continue on the top row. For the other 5 corners, just rotate the picture. Note that if the IP leaves the grid in a corner but doesn't point at a corner, the wrapping happens normally. This means that there are two paths that lead to each corner:
      . . . . ->
     . . . . .
    . . . . . .
-> . . . . . . .
    . . . . . .
     . . . . .
      . . . . ->

Memory model
In the scope of this challenge, the memory is a single cell containing an unbounded unsigned integer, and is initialized to zero before the start of the program.
Command list
The following is a reference of all commands relevant to this challenge.

. is a no-op: the IP will simply pass through.
@ terminates the program.
) increments the value in the memory
_, |, /, \ are mirrors. They reflect the IP in the direction you'd expect. For completeness, the following table shows how they deflect an incoming IP. The top row corresponds to the current direction of the IP, the left column to the mirror, and the table cell shows the outgoing direction of the IP:
cmd   E SE SW  W NW NE

 /   NW  W SW SE  E NE
 \   SW SE  E NE NW  W
 _    E NE NW  W SW SE
 |    W SW SE  E NE NW

< and > act as either mirrors or branches, depending on the incoming direction:
cmd   E SE SW  W NW NE

 <   ?? NW  W  E  W SW
 >    W  E NE ?? SE  E

The cells indicated as ?? are where they act as branches. In these cases, if the value in the memory is non-zero, the IP takes a 60 degree right turn (e.g. < turns E into SE). If the value is zero, the IP takes a 60 degree left turn (e.g. < turns E into NE).

Example
This is a program taken from the test case: )\..@. Its full form is
 ) \
. . @
 . .

And here is how it executes before coming to a halt. To make it terse I will number the cells in the hexagon and use the notation 1E) if the IP is currently at cell 1, executes the instruction ) and is heading east after execution of the instruction.
 1 2
3 4 5
 6 7

The IP starts from cell 1 heading east. The memory cell was initialized to 0.

1E), memory cell is now 1
2\SW, the IP is reflected
4SW., no-op.
6SW., no-op. Then it branches, as the memory cell is nonzero, it wraps to cell 1 instead of cell 5.
1SW), memory cell is now 2.
3SW., no-op.
2E\, the IP is reflected then wrapped.
3E., no-op.
4E., no-op.
5E@, the program halts.

Credits to @MartinEnder, @FryAmTheEggman and @Nitrodon for their helpful comments.
@FryAmTheEggman brought the issue of decidablity of halting problems of programs with both ( and ) to attention.
@MartinEnder pointed out that if ( and ) cannot appear in the same program then ( can be dropped entirely.
@Nitrodon gave a simple proof for the decidability of the halting problem for programs with both ( and ).

Related (much easier)

The version with both ( and ) is decidable. In a program that doesn't halt, the memory edge will flip its sign either finitely often or infinitely often, and both cases lead to a loop that can be detected.

Maybe useful, if someone feels like going the extra mile parsec...

The challenge doesn't forbid using whether or not your own program halts as output, which basically bypasses the entire point.

@moonheart08 Good point taken.

@MartinEnder According to the link I think it should be flat-topped instead of pointy-topped?

@WeijunZhou No, the entire program looks like a flat-topped hexagon, but the grid itself is pointy-topped (because there are horizontally adjacent cells, but no vertically adjacent cells).

@MartinEnder I see. Thank you for the clarification.

Related.

@moonheart08 Unless the challenge allows it explicitly, all answers have to terminate.

So "the program is given in its short form" implies that there are no whitespaces? What about trailing .s?

@user202729 Actually that is redundant. "A program with only .)_|\/><@" says it all. That means no whitespaces, no newlines. Trailing .s can appear.

Theorem: If a Simplified Hexagony doesn't halt after (full program size) * 12 steps (= 12 * ((side length) * (side length - 1) * 3 + 1)), it will run forever. For side length 8, that is 2028 steps.

I fully agree with you, and I have been expecting people answer this question by making use of this property.

APL (Dyalog Unicode), 616 bytesSBCS
{l←3 3 1⊥⍨s←⌊.5+.5*⍨3÷⍨¯1+≢⍵
X d n←(s 0)(2 0)0
'@'∊⍵{V W←X+d⊢←⍎'d⊣n∨←1' 'd×1 ¯1' 'd×¯1 1' '(¯1 ¯1)(1 1)(2 0)(¯2 0)d⊃⍨(2 0)(¯2 0)(¯1 ¯1)(1 1)⍳⊂d' '(¯1 1)(1 ¯1)(2 0)(¯2 0)d⊃⍨(2 0)(¯2 0)(¯1 1)(1 ¯1)⍳⊂d' '(1,¯1+2×n)(¯2 0)(-d)⊃⍨2 ¯1⍳⊃d' '(¯1,1-2×n)(2 0)(-d)⊃⍨¯2 1⍳⊃d' 'd'⊃⍨')_|/\<>'⍳o←X⌷⍉(l↑⍺)@{(((¯3×s)≤-)∧(s≥-)∧((5×s)≥+)∧(s≤+)∧0=2|s++)/¨⍵}⍳1+2 4×s
⍵,o⊣X⊢←(s×1,2×n)(s×3,2×~n)(s×(1+3×n),2-n)(s×(3×n),1+n)(s×(4-3×n),~n)(s×(3-3×n),n)(X+3 1×s)(X+0 2×s)(X+¯3 1×s)(X-3 1×s)(X×1 0)(X+3 ¯1×s)(V W)⊃⍨(V=2+4×s)(V=¯2)((W<0)∧V<s)((W<0)∧V>3×s)((W>2×s)∧V<s)((W>2×s)∧V>3×s)(s>V+W)(W<0)((3×s)<V-W)((5×s)<V+W)(W>2×s)(s<W-V)⍳1}⍣(12×l)⊢''}

Try it online!
The function accepts a Simplified Hexagony source code as a character vector, and returns 1 if @ is included in the first 12 * full program size instructions run, 0 otherwise.
Uses the property pointed out by user202729, which is

Theorem: If a Simplified Hexagony doesn't halt after (full program size) * 12 steps (= 12 * ((side length) * (side length - 1) * 3 + 1)), it will run forever.

Simple proof: A Simplified Hexagony program can have "full program size=N" PC positions × 6 directions × 2 memory states (zero or nonzero) distinct internal states. If the program doesn't halt within that many steps, it leads to 12N+1th internal state which is identical to some previous state (by pigeonhole principle). This means the program has a cycle in the internal state, so it never terminates.
Other than that, it runs the Hexagony code very literally, with a small number trick that using side length - 1 as a variable allows cleaner expressions here and there.
Ungolfed & How it works
f←{
  ⍝ length of the input program
  l←≢⍵

  ⍝ side length - 1
  side←⌊.5+.5*⍨3÷⍨l-1

  ⍝ full program length
  full←side⊥3 3 1

  ⍝ pad the input program with spaces
  p←full↑⍵

  ⍝ create a dummy grid of the size of the full hexagon grid
  grid←⍳1+2 4×side

  ⍝ replace the appropriate positions of the grid with the padded program
  grid←p@{(((¯3×side)≤-)∧(side≥-)∧((5×side)≥+)∧(side≤+)∧0=2|side++)/¨⍵}grid

  ⍝ initialize the positions(x y), directions(dx dy), memory state(n) and the PC trajectory(t)
  x y dx dy n t←side 0 2 0 0 ''

  ⍝ run the program (12×full) steps and check if the trajectory contains a '@'
  '@'∊t⊣{

    ⍝ extract the opcode from the grid
    op←grid[y;x]

    ⍝ append to the trajectory
    t,←op

    ⍝ classify the op so that we can choose which code fragment to run
    idx←')_|/\<>'⍳op

    ⍝ specify the code fragments for the opcodes (which includes dummy '⍬' for no-op)
    fns←'n∨←1' 'dy×←¯1' 'dx×←¯1' 'dx dy⊢←(¯1 ¯1)(1 1)(2 0)(¯2 0)(dx dy)⊃⍨(2 0)(¯2 0)(¯1 ¯1)(1 1)⍳⊂dx dy'
    fns,←⊂'dx dy⊢←(¯1 1)(1 ¯1)(2 0)(¯2 0)(dx dy)⊃⍨(2 0)(¯2 0)(¯1 1)(1 ¯1)⍳⊂dx dy'
    fns,←'dx dy⊢←(1,¯1+2×n)(¯2 0)(-dx dy)⊃⍨2 ¯1⍳dx' 'dx dy⊢←(¯1,1-2×n)(2 0)(-dx dy)⊃⍨¯2 1⍳dx' '⍬'

    ⍝ choose the code fragment, run it, and move the PC one step forward
    x2 y2←x y+dx dy⊣⍎idx⊃fns

    ⍝ check for boundary conditions (first 6 are "branching" outs, next 6 are non-branching outs)
    idx2←(x2=2+4×side)(x2=¯2)((y2<0)∧x2<side)((y2<0)∧x2>3×side)((y2>2×side)∧x2<side)((y2>2×side)∧x2>3×side)(side>x2+y2)(y2<0)((3×side)<x2-y2)((5×side)<x2+y2)(y2>2×side)(side<y2-x2)⍳1

    ⍝ specify the code fragments for destination coordinates
    fns2←'side×1,2×n' 'side×3,2×~n' 'side×(1+3×n),2-n' 'side×(3×n),1+n' 'side×(4-3×n),~n' 'side×(3-3×n),n' 'x y+3 1×side' 'x,2×side' 'x y+¯3 1×side' 'x y-3 1×side' 'x 0' 'x y+3 ¯1×side' 'x2 y2'

    ⍝ run the selected opcode and return a dummy value via ⊢
    ⊢x y⊢←⍎idx2⊃fns2
  }⍣(12×full)⊢⍬
}

This is insane! Wooooooooooooow

Python 3, 979 bytes
R=range
p=input()
l=len(p)
s=int((~-l/3)**.5+.5)
f=s*-~s*3+1
p+=(f-l)*'.'
o=0
g=[]
for i in[*R(s,s*2),*R(s*2,s-1,-1)]:
 w=[' ']*(s*4+1)
 for j in R(i+1):w[j*2+s*2-i]=p[o+j]
 g+=w,
 o+=i+1
x=s;y=0;u=2;v=0;n=0;t=''
M={'/':lambda e:{(2,0):(-1,-1),(-2,0):(1,1),(-1,-1):(2,0),(1,1):(-2,0)}.get(e,e),'\\':lambda e:{(2,0):(-1,1),(-2,0):(1,-1),(-1,1):(2,0),(1,-1):(-2,0)}.get(e,e),'<':lambda e:(1,2*n-1)if e[0]>1else(-2,0)if-1==e[0]else(-e[0],-e[1]),'>':lambda e:(-1,1-2*n)if-1>e[0]else(2,0)if e[0]==1else(-e[0],-e[1])}
exec("""
o=g[y][x];t+=o
if')'==o:n=1
elif'_'==o:v*=-1
elif'|'==o:u*=-1
elif o in M:u,v=M[o]((u,v))
X,Y=x+u,y+v
if X==s*4+2:X=s;Y=2*s*n
if X==-2:X=3*s;Y=2*s*(1-n)
if Y<0and X<s:X=s*(1+3*n);Y=s*(2-n)
if Y<0and X>s*3:X=s*3*n;Y=s*(1+n)
if Y>s*2and X<s:X=s*(4-3*n);Y=s*(1-n)
if Y>s*2and X>s*3:X=s*(3-3*n);Y=s*n
if X+Y<s:X=x+3*s;Y=y+s
if Y<0:X=x;Y=2*s
if X-Y>3*s:X=x-3*s;Y=y+s
if X+Y>5*s:X=x-3*s;Y=y-s
if Y>2*s:X=x;Y=0
if Y-X>s:X=x+3*s;Y=y-s
x,y=X,Y"""*12*f)
print('@'in t)

Try it online!
A full program. Prints True to stdout if the input program halts, False otherwise. Note that TIO version has four backslashes instead of two, in order to wrap the entire program in exec call.
Port of my own APL answer. The underlying algorithm is the same; it just uses different language-specific constructs to do the same thing. Golfing suggestions are welcome.
Ungolfed
p=input()  # one line of input program from stdin
l=len(p)   # length of the original program
s=int((~-l/3)**.5+.5)  # side length - 1
f=s*-~s*3+1            # length of the full program
p=p.ljust(f,'.')       # pad with dots

o=0        # offset in the original program for doing the layout
g=[]       # grid to format the program as a hexagon
# loop for generating hexagonal layout
for i in[*range(s,s*2),*range(s*2,s-1,-1)]:
 row=[' ']*(s*4+1)
 for j in range(i+1):row[j*2+s*2-i]=p[o+j]
 g+=[row]
 o+=i+1

# initial condition: position(x,y),direction(dx,dy),memory(n),trajectory(t)
x=s;y=0;dx=2;dy=0;n=0;t=''
# mirror maps just for '/\<>' because '_|' are relatively easy
M={
 '/':lambda e:{(2,0):(-1,-1),(-2,0):(1,1),(-1,-1):(2,0),(1,1):(-2,0)}.get(e,e),
 '\\':lambda e:{(2,0):(-1,1),(-2,0):(1,-1),(-1,1):(2,0),(1,-1):(-2,0)}.get(e,e),
 '<':lambda e:(1,2*n-1)if e[0]==2else(-2,0)if e[0]==-1else(-e[0],-e[1]),
 '>':lambda e:(-1,1-2*n)if e[0]==-2else(2,0)if e[0]==1else(-e[0],-e[1])
}

# run the loop f*12 times
for _ in range(f*12):

 # run the opcode
 op=g[y][x];t+=op
 if op==')':n=1
 elif op=='_':dy*=-1
 elif op=='|':dx*=-1
 elif op in M:dx,dy=M[op]((dx,dy))

 # one step forward
 x2,y2=x+dx,y+dy

 # handle "branching outs"
 if x2==s*4+2:x2=s;y2=2*s*n
 if x2==-2:x2=3*s;y2=2*s*(1-n)
 if y2<0and x2<s:x2=s*(1+3*n);y2=s*(2-n)
 if y2<0and x2>s*3:x2=s*3*n;y2=s*(1+n)
 if y2>s*2and x2<s:x2=s*(4-3*n);y2=s*(1-n)
 if y2>s*2and x2>s*3:x2=s*(3-3*n);y2=s*n

 # handle "non-branching outs"
 if x2+y2<s:x2=x+3*s;y2=y+s
 if y2<0:x2=x;y2=2*s
 if x2-y2>3*s:x2=x-3*s;y2=y+s
 if x2+y2>5*s:x2=x-3*s;y2=y-s
 if y2>2*s:x2=x;y2=0
 if y2-x2>s:x2=x+3*s;y2=y-s
 x,y=x2,y2

# finally, does the trajectory include '@'?
print('@'in t)

Could you replace any of the =='s with < or > to golf it?

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