Carl Love

Carl Love

26508 Reputation

25 Badges

11 years, 186 days
Himself
Wayland, Massachusetts, United States
My name was formerly Carl Devore.

MaplePrimes Activity


These are answers submitted by Carl Love

You can set defaut options for all 3-D plots with the command

plots:-setoptions3d('axesfont'= ["TimesNewRoman", 24], 'labelfont'= ["TimesNewRoman", 24]);

These options can be overridden, if desired, on any individual plot command simply by including a different version of the option in the individual command.

You can use plots:-setoptions to do the same thing for 2-D plots.

These can be put into an initialization file which is automatically run whenever a new worksheet is loaded or a restart is executed.

One way:

(Int = rcurry(int, 'AllSolutions'))(1/x, x= a..2);

I have verified conclusively that the bondage number of your example graph is 7 by showing that a certain 7-subset of edges is a bondage set (that part is extremely easy), and using multithreaded processing with the Iterator package to verify exhaustively that none of the 439,381,916 edge subsets with less than 7 edges is a bondage set. With careful multithreading (using 8 threads on my computer), I reduced the average real time to verify whether an edge subset is a bondage set to about 17.3 microseconds (equivalent to about 3.4 million subsets checked per minute).

I'll put the main code and the worksheet separately because the main code is in a Code Edit Region within the worksheet.

MinBondageSet:= module()
option `Author: Carl Love <carl.j.love@gmail.com> 2023-Jun-22`;
local
    #Declaring module locals that are modified in multithreaded code as "thread_local"
    #causes the creation of a separate copy for each thread.
    A::thread_local #modified adjacency array after edge removal
;
export
    #All of this module's exports are essentially "static", but they're not declared
    #"static" because this module is not an "object"
    VL, n, V, A0, #VL = vertex labels, n= # of vertices, V={$n}, A0 = list of vertex neighborhoods
    edges, NE,
    DS, #minimum dominating sets of input graph, as a listlist

    #returns the set of minimum dominating sets of G as a listlist:
    MinDominatingSets:= module()
    local 
        N, s,
        Scans:= subs~(
            _s=~ [0, s, s[-1]],
            proc()
            local N0:= eval(N), Ns, v;
                N:= evaln(N); #garbage collection 
                (
                    for s, Ns in eval(N0) do
                    (
                        for v from _s+1 to n do
                            if (N[s,v]:= Ns union A0[v]) = V then [s,v] fi
                        od
                    )
                    od
                )
            end proc
        ),
        ModuleApply:= proc($)
        local Scan, R;
            N:= table([()= {}]);
            for Scan in Scans do if (R:= Scan()) <> () then return [R] fi od;
            [do R:= Scan() until R <> ()]
        end proc
    ;
    end module,

    GetEdges:= ()-> local k; seq['reduce'= `union`](`{}`~(k, select(`>`, A0[k], k)), k= 1..n-1),

    GetGraphData:= proc(G::Graph) #Assign exports specific to this graph:
        VL:= op(3,G);
        n:= nops(VL);                    
        V:= {$n};                             
        A0:= [seq](op(4,G) union~ `{}`~(V));  
        edges:= GetEdges();
        NE:= nops(edges);
        DS:= MinDominatingSets()
    end proc,

    #This proc essentially makes a local copy of the modified graph,
    #but does so in an efficient way:
    RemoveEdges:= proc(E::{set,list}(set), $)
    option threadsafe;
    local A1:= rtable(A0), e;
         for e in E do A1[e[1]] minus= {e[2]}; A1[e[2]] minus= {e[1]} od;
            A:= seq(A1); #This is why A is thread_local
            return
       end proc,

       #returns true iff no dominating set of the original graph is still dominating after
       #edge removal:
       CheckDS:= proc() option threadsafe; local d; andseq(`union`(A[d]) <> V, d= DS) end proc,
       
    #much slower than CheckDS, but potenially useful for some "greedy" algorithms: selects 
    #all of the original dominating sets that are still dominating after edge removal:
    ReduceDS:= ()-> select(d-> `union`(A[d]) = V, DS),

    ModuleApply:= module()
        local 
         k,        #size of edge subsets being checked
            Min, Max,    #min and max values of k to use  
            C,        #combinations Iterator for k-subsets
          st,        #time at start of an iteration
            found?,     #Flag set in one thread to make the others stop: Has a bondage set been found?

            TimeReport:= proc() #per-iteration userinfo timing report and estimate:
            local T:= time['real']() - st;
                if k = Min or T = 0 then return fi;
            userinfo(
                1, 'MinBondageSet', 'NoName',
                sprintf(
                    "Time to check %d-subsets of edges: %9.1f s; "
                    "expected time to check %d-subsets: %9.1f s.",
                    k, T, k+1, T*(NE-k)/(k+1)
                ) 
            ) 
        end proc
      ;
    export
            CheckSplit:= proc(rnk, num) #main multithreaded procedure:
            option threadsafe;
           local (h,g):= ModuleIterator(Object(C, 'rank'= rnk)), J:= g(), B;
                to num while h() do
                    RemoveEdges((B:= edges[[seq](J+~1)]));
                    if CheckDS() and not found? then found?:= true; return B fi
               until found? #can be set true by any thread
            end proc,

            ModuleApply:= proc(
               G::Graph,    
            { #keyword options:
                #Return after fully processing the input graph but 
                #before examining any edge subset:
                    setup_only::truefalse:= false,

                    #Skip the setup phase because the setup of G is already stored
                    #in the module:
                    no_setup::truefalse:= false,
                    
                    #sizes of edge subsets to check for being bondage sets:
                set_sizes::range({posint, identical()}):= .. 
                },
                $
            )
        uses It= Iterator, TT= Threads:-Task;
        local ne, R;        
            if not no_setup then GetGraphData(G) fi;
            if NE = 0 then return {} fi;
            if setup_only then return fi;

            Min:= lhs(set_sizes); if Min=() then Min:= 1 fi;
            Max:= rhs(set_sizes); if Max=() then Max:= NE fi;
            ne:= binomial(NE, Min);
            found?:= false;
            for k from Min to Max do
                    st:= time['real']();
                    C:= It:-RevolvingDoorCombination(NE, k);
                    R:= TT:-Start('passed', 'Tasks'= [CheckSplit, It:-SplitRanks(ne)[]]);
                    if R <> () then return R fi;
                    ne*= (NE-k)/(k+1); #update binomial(NE, k) -> binomial(NE, k+1) 
                    TimeReport()
            od
            end proc
    ;
    end module,

    #utility that lets the user convert vertex-label indices (default output) back
    #to the original vertex labels,
    LabelVertices:= e-> evalindets(e, integer[1..n], j-> VL[j])
;
end module
:


 

Minimum bondage sets of graphs[1]:

A multi-threaded use of the Iterator package

 

Author: Carl Love <carl.j.love@gmail.com> 2023-Jun-22

 

[1] We only consider here so-called simple graphs: no directed edges, no self-loops, no multiple edges. In other words, a simple graph's edge set is nothing more than a subset of the set of 2-subsets of its vertices. In the following worksheet, "graph" will always mean "simple graph" without further comment. Likewise, we only consider graphs with a finite number of vertices.

 

Definitions:

 

Of course, it's expected that the reader has some familiarity with graph theory; so, the first two definitions here are primarily to clarify my notation for the reader.

 

1. Graph, Vertices, Edges: A graph  is an ordered pair of sets G = (V, E), where V is any nonempty set (called the vertices), and E is any set of 2-subsets of V. E is called the edges.

 

Henceforth, let G = (V, E) be a graph.

 

2. Neighborhood: Given v 2V, the (closed} neighborhood  of v is the union of all edges containing v. The neighborhood of v contains v itself. If it's necessary to make that distinction (it isn't in this worksheet), it's called a closed neighborhood. For A3V, the neighborhood of A is the union of the neighborhoods of the elements of A.

 

3. Dominating set: A dominating set of G is a subset of V whose neighborhood is V.

 

4. Minimum dominating set: A minimum dominating set of G is a dominating set of the minimum size of all its dominating sets. (There is a closely related concept called a minimAL dominating set, which is not used in this worksheet.)

 

5. Domination number: The  (lower) domination number of G is the size of any of its minimum dominating sets. (A similar concept applied to minimAL dominating sets is called the upper domination number. We have no need of this here, so I'll just say domination number for the lower domination number.) The domination number of G is denoted by γ(G).

 

6. Bondage set: A bondage set (I prefer the term unbinding set) of G is a B 3 E such that the domination number of (V, E \ B) is greater than the domination number of G.

 

7. Minimum bondage set: A minimum bondage set of G is a bondage set of the minimum size of all its bondage sets.

 

8. Bondage number: The bondage  number of G is the size of any of its minimum bondage sets.

 

 

The following proposition is fundamental to the algorithm below, making it possible to function within a reasonable amount of time and memory:

 

Proposition: Let S be the set of all minimum dominating sets of G. A B 3E is a bondage set of G if and only if no member of S is a dominating set of (V, E \ B).

 

Proof: (0) If B is a bondage set, then γ((V, E \ B)) > γ(G). Thus every dominating set of (V, E \ B) has greater than γ(G) elements. Thus no dominating set of (V, E \ B) is in S.

 

(*) Removing an edge from G cannot decrease its domination number. Since S is all dominating sets of G of size γ(G), γ((V, E \ B)) >  γ(G). Thus B is a bondage set.

 

The bondage set produced as a result of the proposition is not necessarily minimum.

 

The reason that this can vastly improve the efficiency of finding a bondage set is that there are likely to be relatively few minimum dominating sets of G, and they'll always be the same regardless of the B currently being considered as a bondage set. In the main example below, there are 300 minimum bondage sets (of size 4) for a graph with |V| = 24. Checking whether any of these is a dominating set of (V, E \ B) is trivial. Indeed, we can stop as soon as any of the 300 is found to be dominating, thus verifying that B is not a bondage set.

 

Furthermore, that checking can be done by shared-memory parallel processing via Maple's Threads:-Task model using very little memory by using the Iterator package.

 

restart
:

MinBondageSet:= module()

#
# Example: A 7-regular graph with 24 vertices
#
g:= (GT:= GraphTheory):-Graph(
    (`union`@op@(`{}`~@op@`[]`)~)(
        [$24],
        [
            {2,3,4,5,7,9,11}, {3,5,6,7,12,14},  {4,7,8,9,16},  {5,9,10,11,17},
            {6,11,12,19},     {7,12,13,14,21},  {8,14,15},     {9,14,15,16,22},
            {10,16,17},       {11,17,18,19,23}, {12,18,19},    {13,19,20},
            {14,19,20,21,24}, {15,21},          {16,21,22,24}, {17,22,23},
            {18,22,23},       {19,20,23,24},    {20},          {21,23,24},
            {22,24},          {23,24},          {24},          {}
        ]
    )
);

GRAPHLN(undirected, unweighted, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24], Array(1..24, {(1) = {2, 3, 4, 5, 7, 9, 11}, (2) = {1, 3, 5, 6, 7, 12, 14}, (3) = {1, 2, 4, 7, 8, 9, 16}, (4) = {1, 3, 5, 9, 10, 11, 17}, (5) = {1, 2, 4, 6, 11, 12, 19}, (6) = {2, 5, 7, 12, 13, 14, 21}, (7) = {1, 2, 3, 6, 8, 14, 15}, (8) = {3, 7, 9, 14, 15, 16, 22}, (9) = {1, 3, 4, 8, 10, 16, 17}, (10) = {4, 9, 11, 17, 18, 19, 23}, (11) = {1, 4, 5, 10, 12, 18, 19}, (12) = {2, 5, 6, 11, 13, 19, 20}, (13) = {6, 12, 14, 19, 20, 21, 24}, (14) = {2, 6, 7, 8, 13, 15, 21}, (15) = {7, 8, 14, 16, 21, 22, 24}, (16) = {3, 8, 9, 15, 17, 22, 23}, (17) = {4, 9, 10, 16, 18, 22, 23}, (18) = {10, 11, 17, 19, 20, 23, 24}, (19) = {5, 10, 11, 12, 13, 18, 20}, (20) = {12, 13, 18, 19, 21, 23, 24}, (21) = {6, 13, 14, 15, 20, 22, 24}, (22) = {8, 15, 16, 17, 21, 23, 24}, (23) = {10, 16, 17, 18, 20, 22, 24}, (24) = {13, 15, 18, 20, 21, 22, 23}}), `GRAPHLN/table/1`, 0)

MBS:= MinBondageSet:
infolevel[MBS]:= 1:

CodeTools:-Usage(MBS(g, setup_only));

memory used=13.97MiB, alloc change=37.00MiB, cpu time=109.00ms, real time=77.00ms, gc time=62.50ms

# Just out of curiosity, display and count the dominating sets:
#
MBS:-DS;

[[3, 6, 10, 21], [3, 6, 10, 24], [3, 11, 17, 21], [6, 9, 10, 21], [6, 9, 10, 24], [11, 14, 16, 18], [11, 14, 16, 20], [11, 14, 16, 21], [11, 14, 16, 23], [11, 14, 16, 24], [4, 6, 16, 18], [4, 6, 16, 20], [1, 16, 19, 21], [7, 10, 15, 19], [1, 13, 19, 22], [1, 8, 10, 13], [2, 14, 17, 18], [4, 7, 17, 20], [2, 10, 22, 24], [6, 8, 11, 18], [6, 8, 11, 23], [1, 6, 16, 18], [3, 6, 15, 18], [6, 9, 15, 18], [5, 6, 8, 18], [5, 6, 8, 23], [1, 12, 14, 23], [2, 4, 20, 22], [1, 11, 16, 21], [1, 14, 17, 20], [1, 13, 14, 17], [1, 13, 14, 23], [3, 12, 17, 21], [1, 7, 20, 23], [2, 12, 15, 17], [4, 14, 17, 20], [5, 8, 20, 23], [2, 9, 18, 21], [2, 9, 18, 24], [2, 4, 15, 20], [4, 6, 15, 18], [4, 6, 15, 20], [7, 13, 17, 19], [3, 14, 19, 22], [3, 14, 19, 23], [2, 10, 16, 20], [2, 10, 16, 21], [2, 10, 16, 24], [4, 6, 8, 18], [4, 6, 8, 20], [3, 11, 18, 21], [1, 6, 15, 18], [3, 6, 16, 18], [6, 9, 16, 18], [5, 7, 13, 17], [3, 13, 19, 22], [1, 6, 8, 18], [9, 10, 12, 15], [7, 12, 15, 17], [6, 7, 17, 18], [4, 13, 14, 17], [4, 13, 14, 23], [2, 9, 12, 24], [4, 8, 12, 20], [4, 8, 12, 24], [6, 11, 16, 18], [6, 11, 16, 20], [6, 11, 16, 21], [6, 11, 16, 23], [6, 11, 16, 24], [6, 7, 10, 23], [5, 8, 21, 23], [2, 9, 19, 22], [2, 9, 19, 24], [3, 17, 19, 21], [9, 12, 15, 17], [9, 12, 15, 18], [9, 12, 15, 20], [9, 12, 15, 23], [9, 12, 15, 24], [3, 13, 16, 19], [3, 7, 19, 22], [1, 13, 17, 22], [4, 7, 15, 20], [1, 5, 14, 23], [6, 8, 9, 18], [5, 8, 9, 20], [5, 8, 9, 24], [2, 10, 15, 19], [2, 10, 15, 20], [2, 10, 15, 21], [2, 10, 15, 24], [3, 6, 8, 18], [1, 10, 13, 15], [1, 10, 13, 16], [1, 10, 13, 22], [4, 6, 18, 22], [3, 19, 21, 22], [3, 19, 21, 23], [1, 7, 17, 20], [2, 8, 10, 13], [2, 8, 10, 20], [2, 8, 10, 21], [2, 8, 10, 24], [4, 6, 19, 22], [5, 9, 15, 20], [5, 9, 15, 24], [2, 12, 17, 22], [4, 14, 15, 20], [5, 8, 18, 20], [5, 8, 18, 21], [5, 8, 18, 24], [4, 5, 14, 23], [2, 9, 11, 24], [11, 13, 14, 16], [5, 7, 17, 20], [5, 7, 17, 21], [5, 7, 17, 24], [8, 9, 12, 20], [8, 9, 12, 24], [3, 16, 19, 21], [1, 13, 16, 17], [1, 13, 16, 18], [1, 13, 16, 19], [1, 13, 16, 23], [1, 8, 13, 17], [1, 8, 13, 18], [1, 8, 13, 23], [4, 7, 16, 20], [1, 2, 19, 22], [3, 5, 21, 23], [3, 6, 18, 21], [3, 6, 18, 22], [3, 6, 18, 24], [6, 9, 18, 21], [6, 9, 18, 22], [6, 9, 18, 24], [2, 11, 13, 16], [9, 12, 14, 23], [9, 12, 14, 24], [7, 10, 12, 15], [7, 10, 12, 22], [1, 13, 18, 22], [1, 10, 12, 15], [2, 10, 14, 23], [5, 6, 16, 18], [5, 6, 16, 23], [5, 8, 19, 22], [4, 5, 15, 20], [4, 5, 15, 24], [2, 5, 9, 24], [7, 15, 17, 19], [3, 12, 18, 21], [3, 18, 19, 21], [4, 6, 20, 22], [7, 11, 13, 16], [7, 11, 13, 17], [1, 7, 19, 22], [5, 9, 14, 23], [5, 9, 14, 24], [5, 14, 16, 18], [5, 14, 16, 23], [4, 14, 16, 20], [7, 12, 13, 17], [1, 13, 15, 17], [1, 13, 15, 18], [1, 13, 15, 23], [2, 9, 10, 21], [2, 9, 10, 24], [3, 5, 10, 21], [4, 8, 14, 20], [4, 7, 8, 20], [1, 11, 21, 22], [7, 9, 12, 24], [3, 12, 21, 23], [2, 4, 19, 22], [1, 9, 20, 21], [4, 12, 15, 17], [4, 12, 15, 18], [4, 12, 15, 20], [4, 12, 15, 23], [4, 12, 15, 24], [2, 17, 19, 22], [2, 10, 13, 15], [2, 10, 13, 16], [2, 10, 13, 22], [3, 11, 13, 16], [3, 11, 13, 22], [5, 6, 9, 24], [1, 12, 15, 17], [1, 12, 15, 18], [1, 12, 15, 23], [2, 3, 18, 21], [2, 3, 18, 24], [4, 7, 13, 17], [4, 7, 13, 23], [3, 5, 18, 21], [6, 9, 11, 24], [7, 17, 19, 20], [7, 17, 19, 21], [7, 17, 19, 22], [7, 17, 19, 24], [6, 11, 13, 16], [8, 11, 12, 22], [2, 15, 17, 19], [11, 12, 15, 16], [1, 11, 13, 16], [1, 11, 13, 22], [5, 8, 17, 20], [5, 8, 17, 21], [5, 8, 17, 24], [4, 10, 12, 15], [3, 11, 21, 22], [3, 11, 21, 23], [5, 8, 10, 13], [5, 8, 10, 20], [5, 8, 10, 21], [5, 8, 10, 24], [4, 12, 14, 23], [2, 10, 12, 15], [2, 10, 12, 22], [3, 11, 14, 23], [2, 3, 19, 22], [2, 10, 19, 22], [1, 6, 19, 22], [6, 9, 12, 24], [5, 7, 9, 24], [3, 6, 19, 22], [6, 9, 19, 22], [6, 9, 19, 24], [5, 8, 23, 24], [2, 4, 8, 20], [4, 14, 19, 22], [4, 14, 19, 23], [5, 8, 14, 18], [5, 8, 14, 23], [7, 9, 19, 22], [7, 9, 19, 24], [3, 12, 14, 23], [7, 11, 17, 20], [7, 11, 17, 21], [7, 11, 17, 24], [1, 11, 14, 23], [1, 9, 13, 24], [1, 14, 19, 22], [1, 14, 19, 23], [4, 7, 20, 22], [4, 7, 20, 23], [5, 15, 16, 19], [3, 10, 11, 21], [4, 11, 14, 23], [2, 10, 20, 22], [1, 6, 18, 22], [2, 11, 16, 20], [2, 11, 16, 21], [2, 11, 16, 24], [5, 8, 13, 17], [5, 8, 13, 18], [5, 8, 13, 23], [9, 11, 14, 23], [9, 11, 14, 24], [1, 7, 13, 17], [1, 7, 13, 23], [2, 4, 16, 20], [3, 12, 15, 17], [3, 12, 15, 18], [3, 12, 15, 23], [7, 11, 16, 20], [7, 11, 16, 21], [7, 11, 16, 24], [1, 19, 21, 22], [7, 9, 11, 24], [4, 14, 20, 22], [4, 14, 20, 23], [1, 14, 20, 23], [7, 12, 17, 20], [7, 12, 17, 21], [7, 12, 17, 22], [7, 12, 17, 24], [4, 5, 8, 20], [4, 5, 8, 24], [3, 5, 14, 23], [8, 11, 14, 18], [8, 11, 14, 23], [2, 10, 21, 22], [3, 5, 17, 21], [3, 10, 19, 21], [4, 7, 19, 22], [9, 14, 19, 22], [9, 14, 19, 23], [9, 14, 19, 24], [3, 10, 12, 15], [3, 10, 12, 21], [1, 13, 22, 23], [7, 10, 19, 22], [3, 4, 20, 21], [2, 3, 10, 21], [2, 3, 10, 24], [3, 11, 16, 21], [3, 4, 13, 24]]

nops(%);

300

#
# Remove a specific subset of 7 edges (all edges adjacent to vertex 1), and prove that the
# domination number is <= 7:
#
MBS:-RemoveEdges(`{}`~(1, {2,3,4,5,7,9,11}));
MBS:-CheckDS();

true

#
# That means that none of g's original 300 minimum dominating sets is still dominating;
# thus the domination number must have increased; thus the bondage number is <= 7.
#
# Prove that the bondage number is > 5 by exhaustive multi-threaded search:
#
CodeTools:-Usage(MBS(g, no_setup, set_sizes= ..5));

Time to check 2-subsets of edges:       0.6 s; expected time to check 3-subsets:      15.9 s.

Time to check 3-subsets of edges:       1.6 s; expected time to check 4-subsets:      32.8 s.

Time to check 4-subsets of edges:      29.2 s; expected time to check 5-subsets:     467.9 s.

Time to check 5-subsets of edges:     537.7 s; expected time to check 6-subsets:    7079.2 s.

memory used=182.78GiB, alloc change=267.31MiB, cpu time=70.33m, real time=9.50m, gc time=5.44m

# time per edge subset checked:
(0.6 + 1.6 + 29.2 + 537.7)/add(binomial(84,k), k= 1..5);

0.1729767728e-4

60/%;

3468673.801

# So, it's using about 16 microseconds per edge subset checked.
# I'm using an Intel Core i7-7700HQ with 4 cores @ 2.8 GHz. There are 2 hyperthreads
# per core, so a total of 8 threads in the parallel process.

 

I also ran MinBondageSet on the 6-subsets of edges, finding no bondage sets. This takes about 2 hours on my computer. Memory usage is trivial. This confirms that the bondage number is 7.

 

Download BondageNumber.mw

Suggestions:

The circles for r = 1/3 and r = 2/3 serve no didactic purpose, and thus I think that they're detrimental to the pedagogy.

You need rays for theta = Pi/4, 3*Pi/4, etc.

The vertical lines should not extend beyond the circle. If they go outside the circle, it's easy to mistake them as stray marks. Their color should be more visible.

Your series has no free variables. The concept of radius of convergence doesn't make sense without a free variable such that the convergence of the series depends on that free variable being within a certain "radius" of some point. The concept of power series requires a free variable which is raised to "powers".  

In your first expression, TPP, you have square brackets used algebraically; in other words, they're used as a substitute for parentheses. While that is indeed standard in mathematical typesetting, and I agree that it improves readibility, it's not alllowed in Maple (nor in any other computer language that I'm aware of). The reason is that with the severe limitation of the number of special characters available on a standard keyboard, they need to all have their own meanings.

If I replace those square brackets with paremtheses, the error goes away.

In relatively recent versions of Maple, and only using 1-D input, a for-do loop (or, indeed, any do loop) can be used as an embedded expression whose output is an expression sequence:

A:= select(isprime, {$3..101});
    A := {3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 
      59, 61, 67, 71, 73, 79, 83, 89, 97, 101}

B:= {for a in A do if a mod 3 = 1 then a fi od};
    B := {7, 13, 19, 31, 37, 43, 61, 67, 73, 79, 97}

This is not just a syntactic nicety; it's often the most efficient way to solve set-building problems. However, in this case, acer's select works efficiently also, and it's what I would use.

The difference between what you perceive as the correct and incorrect results is only the constant 3/4. Being different by a constant is not incorrect for an indefinite integral.

Here's a solution that allows a decision to be made based on the number of arguments and avoids any awkwardness that may come from having arguments that don't match named parameters due to there not being any named parameters. An overload is a list of (usually anonymous) procedures all assigned to a single procedure name such that for any call to the procedure, Maple will choose the first member of the list whose declared parameters match the arguments in the call.

The purpose of the (called the end-of-parameters marker) in the following example is to force those procedures to balk at (rather than the default, to ignore) extra arguments. To advance to the next procedure in the list, it's necessary that the arguments not match the declared parameters; I think that no other error will cause it to advance.

There seemed to be no good reason to limit this to real constants (type realcons), so I used type algebraic. But it would work just as well if you changed those to realcons..

P:= overload([
    proc(a::algebraic, b::algebraic, $) option overload; 
        a/b 
    end proc,

    proc(a::algebraic, b::algebraic, c::algebraic, $) option overload;
        a + b*c
    end proc,
    
    #Fall-through case: You can choose to return an error, to return unevaluated (as shown here), 
    #or to leave off this case entirely:
    ()-> 'procname'(args)
]):

P(3,5);
                               3/5
P(7,1,1,1);
                         P(7, 1, 1, 1)
P(3,5,7);
                               38

 

It's just an undocumented feature. There are many commands in Maple that work on a wider range of types of input than they are documented to work on. If they documented it, they'd never be able to change it in the future. On the other hand, it's often convenient to treat a listlist as a Matrix.

Just about any procedure can be made into an operator-form procedure by giving it a name beginning with (see ?&). This is most natural with procedures of 2 arguments, but it's not limited to them. For example,

`&<--`:= (a, b::{list,set}(`=`))-> eval['recurse'](a,b):
(x+3) &<-- [x= 4];

                               
7

&-operators have a very high precedence among infix operators (see ?operators,precedence), so you need to be wary of correct usage of parentheses and other grouping symbols.

Regarding a comparison of eval['recurse'] and MmaTranslator:-Mma:-ReplaceRepeated: The code for both of these is short and easy to read. The actual procedure name for eval[recurse] is `simpl/eval` (it's actually an appliable module rather than a procedure, but that's an insignificant technicality here). So,

showstat(`simpl/eval`);
showstat(MmaTranslator:-Mma:-ReplaceRepeated);
 

The concept is weirdly named. I'd call it the UNbinding number. (I think some mathematician had an over-sexualized imagination when naming it the bondage number.) Anyway, for your example 7-regular graph with 48 automorphisms, I can very easily find a set of 6 edges whose removal increases the domination number from 4. It's more difficult to prove that no set of 5 edges suffice (binomial(84,5) ~ 31 million). By brute-force all-subsets search, I've proved that no 4-subset of edges will work. Thus, the "bondage number" is 5 or 6.

There are only 300 (exactly) minimal dominating sets. If you go back to the thread on those, I've posted new code that returns the set of 300. For each candidate set of edges, it's much easier computationally to check whether any of these 300 is still a dominating set after the edges are removed than it is to recompute the domination number from scratch. I'll post some code here along those lines.

Regarding your comment on symmetry (primarily from your linked StackExchange thread): My intuition is that the symmetry will have a profound effect on the computational effort required by various algorithms to compute the bondage number. In my new Answer in the domination-number thread, I've shown how to partition the 300 minimal dominating sets into 12 equivalence classes under automorphism (two sets being considered equivalent if there's an automorphism mapping one to the other). This partitioning takes less than one second, including the time required to find the 48 automorphisms and convert them to vertex permutations. My intuition is that these equivalence classes could somehow be used to reduce the computation needed to get the bondage number, but I haven't been able to make any further developments on that idea. And it may be an average-case reduction rather than a worst-case reduction.

From your example, it looks like perhaps by "similar" you mean "identical".  If that is the case, then Maple already recognizes identical subexpressions and makes use of that in its internal storage. It's only the displayed form of expressions that don't show this. 

Here's a procedure that will show you the common subexpressions that Maple has recognized:

CommonSubExprs:= e->
    select(se-> numboccur(expr, se) > 1, indets(e, {`+`, `*`, `^`, 'function'}))
:

The idea can be easily extended to more types than I've used above. I was just guessing that  `+`, `*`, `^`, function would cover what you need.

Any of the expressions returned by the procedure can be substituted by a variable with the ordinary subs command.

You just need to use the given ordering as an index of the vertex list:

R:= IsChordal(s, eliminationordering):
if [R][1] then op(3,s)[R[2]] fi;

If by Gamma you mean the generalized factorial function, then you need to spell it GAMMA (all uppercase). The cause of the error is that it doesn't know what Gamma means,

First 11 12 13 14 15 16 17 Last Page 13 of 382