text:
nLab PrCat

• /

• /

Applications

Compact objects

objects $d \in C$ such that $C(d,-)$ commutes with certain

• ,

Contents

Idea

When working with locally presentable categories, one is typically interested only in the colimit-preserving functors between them, hence (by the adjoint functor theorem) equivalently the left adjoint functors.

One hence considers the very large category $PrCat$ whose objects are locally presentable categories, and whose morphisms are left adjoint functors.

The analog of this

Locally presentable categories: possibly- generated under by under . Equivalently, of . Accessible categories omit the cocompleteness requirement; toposes add the requirement of a localization.

$\phantom{A}$$\phantom{A}$$\phantom{A}$$\phantom{A}$locally presentableloc finitely preslocalization theoremaccessible
Porst’s theorem


text:
List *all* the tuples!

Write a program, given an input n, will generate all possible n-tuples using natural numbers.

n=1
(1),(2),(3),(4),(5),(6)...

n=2
(1,1),(1,2),(2,1),(2,2),(1,3),(3,1),(2,3),(3,2),(3,3)...

n=6
(1,1,1,1,1,1) (1,1,1,1,2,1) (1,1,1,2,1,1)...

• The output may be in any order that does not break any other rules.
• The program must be written to run forever and list all applicable tuples exactly once, in theory.
• In reality, your program will reach your integer type's limit and crash. This is acceptable as long the program would run infinitely long if only your integer type was unlimited.
• Each valid tuple must be listed within finite time, if only the program were allowed to run that long.
• The output may, at your option, include zeroes in addition to the natural numbers.
• You may choose your program's output format for your convenience, as long as the separation between tuples and numbers inside each tuple is clear and consistent. (For example, one tuple per line.)
• The input (n) is an integer from one to six. Required behavior is undefined for inputs outside of this range.
• Code-golf rules apply, shortest program wins.

Thanks to "Artemis Fowl" for feedback during the sandbox phase.

• I assume it is valid if when the program crashes it produces some extraneous output in addition to the tuples printed so far, right? – Luis Mendo Apr 15 at 16:32
• Must we output as we go or would a function which yields an infinite list at the end of time sufficient? – Jonathan Allan Apr 15 at 17:15
• "You may choose your program's output format for your convenience, as long as the separation between tuples and numbers inside each tuple is clear and consistent" - may we output differing (albeit consistently differing) separation (e.g. like this)? – Jonathan Allan Apr 15 at 18:04
• @JonathanAllan I would have to include the output of that object's infinite contents as part of the program. – billpg Apr 15 at 19:18
• Related (integers instead of natural numbers) – Esolanging Fruit Apr 16 at 5:16

Husk, 2 bytes

πN

Try it online!

Explanation

N is the infinite list of natural numbers [1,2,3,4,... π is Cartesian power. Result is an infinite list of lists. Each list of the desired length occurs exactly once because π is cool like that. Input and output are implicit.

• Wow, and this doesn't do [1,1,n] either. Is there a pattern to the order it outputs? – billpg Apr 15 at 20:04
• @billpg It builds the tuples recursively: n- tuples are obtained by taking the Cartesian product of the original list and the list of n-1-tuples, in ascending order of sum of indices. – Zgarb Apr 16 at 4:30
• "ascending order of sum of indices" -- Can you clarify this? I'm having trouble seeing why, eg, 2,2,2 comes after 4,1,2 and 5,1,1. – Jonah Apr 16 at 12:52
• @Jonah The recursion works like this. You start with 1-tuples over N. For 2-tuples you take Cartesian product with N ordered by sum of indices. In both lists, each number n is at index n so for length 2 the result happens to be ordered by sum. To get 3-tuples you take Cartesian product of N and the list of 2-tuples, ordered by sum of the elements' indices in these lists. It doesn't look at the tuple's sum, it looks at its position in the list of tuples. – Zgarb Apr 16 at 14:29
• "Figure out the different dimensions of infinity in this task and find a pattern that reduces it to countable infinity, then write a program that iterates over this pattern." - "Hey, I have a builtin for that!" – Fabian Röling Apr 17 at 11:00

([1..]>>=).(!)
0!s=[[]|s<1]
n!s=[a:p|a<-[1..s],p<-(n-1)!(s-a)]

Try it online!

n!s generates all the n-tuples that sum to s.

Then the answer is ([1..]>>=).(!), i.e. \n -> [t | s<-[1..], t<-n!s].

This is a function mapping an integer n to an infinite lazy list of tuples (lists of integers).

f n=[l|k<-[0..],l<-mapM([0..k]<$f)[0..n],sum l==k]  Try it online! Lists n-tuples sorted by sum. mapM does the heavy lifting to generate all n-tuples of numbers from 0 to k. The <$f trick is explained here.

f 1=pure<$>[0..] f n=[a-k:k:t|a:t<-f$n-1,k<-[0..a]]

Try it online!

Recursively stretches all n-1-tuples into all n-tuples by splitting the first number a of each n-1-tuple into two numbers a-k,k that sum to it, in every possible way.

Pyth - 9 bytes

Thanks to @FryAmTheEggman for the golf

Loops through all x, and takes [1..x]^n. This makes duplicates, so only keeps ones that are new to that x, aka contain x in them. The formatting is a little weird, but it can be made standard with one more byte, .V1j}#b^Sb

.V1}#b^Sb

• f}bT -> }#b Also, your byte count seems to be incorrect at the moment? – FryAmTheEggman Apr 16 at 4:33
• @FryAmTheEggman wait, why is it incorrect? If you're talking about the TIO link, that includes formatting with j(b). Also, thanks for the golf. – Maltysen Apr 17 at 19:11
• Ah, that's what confused me, sorry! – FryAmTheEggman Apr 17 at 20:48

Brachylog (v2), 9 bytes

~l.ℕᵐ+≜∧≜

Try it online!

This is an infinite generator that generates all possible tuples. The TIO link has a header that uses the generator to generate 1000 elements and prints them (but the generator could continue indefinitely if I asked for that instead; Brachylog's integers are unbounded).

It feels like there should be a terser way, but there are a lot of constraints and this is the tersest I can fit them into a single program.

Explanation

~l.ℕᵐ+≜∧≜
.        Generate
≜  all explicit
~l         lists whose length is {the input}
ᵐ      for which every element
ℕ       is non-negative
+     and whose sum
≜    is used to order the lists (closest to zero first)
∧   [remove unwanted implicit constraint]

Incidentally, it strikes me as interesting just how different my explanations of the two ≜ are, despite them doing the exact same thing from Brachylog's point of view. The first ≜ is the first nondeterministic predicate in the program, so it sets the order of results; in this case, it calculates all possible explicit values for the sum of the list in the order 0, 1, 2, 3…, and is being used to ensure that the lists are output in order of their sum (this ensures that each possible list appears after a finite amount of output). The second ≜ is used to calculate all the explicit possibilities for the list (rather than outputting a formula specifying how the elements of the list relate to each other).

• ↰₁ẉ⊥ is also a good header, for printing infinitely. – Unrelated String Apr 15 at 20:32
• Although I do feel like this may not actually be a full answer, since any single independent invocation of this predicate will just generate zeroes, with the "generate all" part being done by the ᶠ or the ⊥ in the header. – Unrelated String Apr 15 at 20:38
• @UnrelatedString Your code doesn't use the predicate as a generator, though. We have explicit rules allowing list output using a generator. What you're doing in your TIO link is calling the predicate in a loop to get 1000 different generators, then taking the first output from each of them; that's a really unnatural operation to do on generators, and it won't let you see the other elements that they can generate. – ais523 Apr 15 at 23:40
• Ah, so I've just been misinterpreting the semantics of what a Brachylog predicate is this whole time--my idea of "generator" is stuck on Python. Now that that's straight in my head I guess I'll go shave three bytes off of some of my old answers. – Unrelated String Apr 16 at 1:41

Perl 6, 37 bytes

{$++.polymod(1+$++ xx $_-1).say xx *}  Try it online! Essentially runs polymod with as many entries as needed, where the modulo is always greater than the input, i.e. 0.polymod( 1,1,1 ), 1.polymod( 2,2,2 ) etc. That way the digit is always within the range. Perl6 won't let me modulo infinity... • This doesn't list every tuple exactly once (for instance, (0, 1, 0, 0) is not listed). – bb94 Apr 15 at 20:03 Wolfram Language (Mathematica), 62 bytes Do[Print/@Permutations@#&/@n~IntegerPartitions~{#},{n,#,∞}]&  Try it online! -3 bytes with inconsistent separation (delete @#&) Try it online! C# (Visual C# Interactive Compiler), 148 bytes n=>{var a=new int[n];int j=0;void g(int k){if(k<n)for(int i=0;i++<j;g(k+1))a[k]=i;else if(a.Sum()==j)WriteLine(string.Join(' ',a));}for(;;j++)g(0);}  Try it online! -3 bytes thanks to @ASCIIOnly! // n: size of tuples to generate n=>{ // a: current tuple workspace var a=new int[n]; // j: target sum value int j=0; // recursive function that works on slot k void g(int k){ // tuple is not fully generated, if(k<n) // try all values from (0,j] for(int i=0;i++<j; // recursive call - generates all // values from (0,j] in the next slot g(k+1) ) // update the kth slot a[k]=i; // tuple is fully generated, however // we should only display if the sum // is equal to the target sum. tuples // are generated many times, this // let's us enforce that they are only // displayed once. else if(a.Sum()==j) WriteLine(string.Join(' ',a)); } // increment the high value forever // while continually starting the // recursive function at slot 0 for(;;j++) g(0); }  • how even did you do this – Stackstuck Apr 18 at 3:11 • straight-up porting this to .NET Core would probably still save me a lot of bytes. – Stackstuck Apr 18 at 3:14 • The biggest trick here is recursion. Most of the techniques I've seen to generate "permutations" use it. I plan on adding an explanation. – dana Apr 18 at 3:23 • Write with e.g. '<literal tab>' or | is the same length, and takes up a lot fewer lines :P – ASCII-only Apr 18 at 10:52 • – ASCII-only Apr 18 at 11:01 Jelly, 10 (9?) bytes 9 if we may output using non-consistent separation (which I have enquired about) -- removal of the €. ‘ɼṗ³ċƇ®Ṅ€ß  Try it online! How? ‘ɼṗ³ċƇ®Ṅ€ß - Main Link: some argument, x (initially equal to n, but unused) ɼ - recall v from the register (initially 0), then set register to, and yield, f(v) ‘ - f = increment - (i.e. v=v+1) ³ - program's third command line argument (1st program argument) = n ṗ - (implicit range of [1..v]) Cartesian power (n) - (i.e. all tuples of length n with items in [1..v]) Ƈ - filter keep those for which: ċ - count ® - recall from register - (i.e. keep only those containing v) Ṅ€ - print €ach ß - call this Link with the same arity - (i.e. call Main(theFilteredList), again the argument is not actually used)  • Based on "as long as the separation between tuples and numbers inside each tuple is clear and consistent. (For example, one tuple per line.)" I assumed it wasn't allowed and the € is required, but let's wait what OP has to say. – Kevin Cruijssen Apr 15 at 18:55 05AB1E, 15 11 bytes [¼¾LIãvy¾å—  -4 bytes by creating a port of @Maltysen's Pyth answer. Try it online. Explanation: [ # Start an infinite loop: ¼ # Increase the counter_variable by 1 (0 by default) ¾L # Create a list in the range [1, counter_variable] Iã # Take the cartesian power of this list with the input v # Loop over each list y in this list of lists: y¾å # If list y contains the counter_variable: — # Print list y with trailing newline  • When will the program get to [1,2,1]? Remember it has to be within finite time. – billpg Apr 15 at 13:39 • @billpg Should be fixed now. – Kevin Cruijssen Apr 15 at 15:24 MATL, 16 bytes @:GZ^t!Xs@=Y)DT  Tuples are ordered by increasing sum, and within a given sum they are ordered lexicographically. Try it online! Python 2, 126112106101100 83 bytes n=input() i=1 while 1: b=map(len,bin(i)[3:].split('0'));i+=1 if len(b)==n:print b  Try it online! 5 bytes thx to mypetlion; 1 byte from the eagle eye of ArBo; 17 bytes from xnor! Construct the ordered partitions of m into n bins, for m = 0,1,2,3,... by selecting for binary numbers with n-1 0s and m 1s. • if i==p:i=0;p*=2 can become i%=p;p<<=i<1 to save 5 bytes. – mypetlion Apr 15 at 22:21 • I'm pretty sure the space after print b is not needed :D – ArBo Apr 16 at 9:01 • It looks like the i+p is just counting up 1, 2, 3... in a convoluted way and so can just be a single variable. – xnor Apr 16 at 16:36 • @xnor: D'oh! Got so wrapped up in the concept, couldn't see the forest for the trees. – Chas Brown Apr 16 at 19:22 C# (.NET Core), 608 570 567 bytes using C=System.Console;using L=System.Collections.Generic.List<int[]>;class A{static void Main(){L x=new L(),y=new L(),z=new L();int i=int.Parse(C.ReadLine()),j=0,k,l,m;x.Add(new int[i]);while(i>0){j++;for(m=0;m++<i;){foreach(var a in y)x.Add(a);y=new L();foreach(var a in x){for(k=0;k<i;){int[] t=new int[i];System.Array.Copy(a,t,i);t[k++]=j;var b=true;z.AddRange(x);z.AddRange(y);foreach(var c in z){for(l=0;l<i;l++)if(c[l]!=t[l])break;if(l==i)b=false;}if(b)y.Add(t);}}}}for(k=0;k<x.Count;k++){C.Write("[ ");for(l=0;l<i;l++)C.Write(x[k][l]+" ");C.WriteLine("]");}}}  Try it online! my god what have I done (so many loops, that's what I've done) It should work, though! If you move the print loop back one bracket, it will show you the list as it's built, every time it loops. (I recommend adding a newline or something to distinguish each loop if you do.) Honestly, a lot of my time was spent fighting with the language...no pretty-printing arrays, assorted behaviors of ==... Hopefully this version is easier to read. using C=System.Console; using L=System.Collections.Generic.List<int[]>; class A{ static void Main(){ L x=new L(),y=new L(),z=new L(); int i=int.Parse(C.ReadLine()),j=0,k,l,m; x.Add(new int[i]); while(i>0){ j++; for(m=0;m++<i;){ foreach(var a in y) x.Add(a); y=new L(); foreach(var a in x){ for(k=0;k<i;){ int[] t=new int[i]; System.Array.Copy(a,t,i); t[k++]=j; var b=true; z.AddRange(x); z.AddRange(y); foreach(var c in z){ for(l=0;l<i;l++) if(c[l]!=t[l])break; if(l==i)b=false; } if(b)y.Add(t); } } } } for(k=0;k<x.Count;k++){ C.Write("[ "); for(l=0;l<i;l++)C.Write(x[k][l]+" "); C.WriteLine("]"); } } }  • I just realized I can stick the print loop in the if statement so it prints as it goes. facepalm one moment. – Stackstuck Apr 17 at 17:54 • wait nope can't do that – Stackstuck Apr 17 at 17:58 • ...oh dear, I'm not sure this code works anymore. – Stackstuck Apr 17 at 17:59 • aaaaand it doesn't. – Stackstuck Apr 17 at 18:00 • Good luck with this :) I started coding a solution in C# and realized it was quite a bit trickier than I was hoping. Why not use the "Visual C# Interactive" interpreter? That would save a bunch by simply not having to include the class definition. Anyways, +1 from me :) – dana Apr 17 at 21:44 Perl 6, 50 bytes {grep$_,{S/.//.split(0)>>.chars}($++.base(2))xx*}  Try it online! Anonymous code block that returns a lazy infinite list. This uses the same strategy as Chas Brown's answer. Explanation: {grep$_,{S/.//.split(0)>>.chars}($++.base(2))xx*} { } # Anonymous code block xx* # Repeat indefinitely ($++        )     # From the current index
.base(2)      # Get the binary form
{S/.//                 }   # Remove the first digit
.split(0)            # And split by zeroes
>>.chars    # And get the length of each section
grep   ,   # From this infinite list, filter:
$_ # The groups with length the same as the input  VDM-SL, 51 bytes g(i)==if i=0then{}else{[x]^y|x:nat,y in set g(i-1)}  Recursive set comprehension with sequence concatenation.. Not on TIO, you could run in a program (if you turn on limits for nat type or it wont terminate): functions g:nat->set of ? g(i)==if i=0then{}else{[x]^y|x:nat,y in set g(i-1)}  Includes the optional 0s in answer otherwise it would be 52 bytes binding on nat1 Wolfram Language (Mathematica), 131 bytes While[0<1,If[a~FreeQ~#,Print@#]&/@(b=Table[Select[Range@t~Tuples~{s},Tr@#==k&],{k,t,t(s=#)}]~Flatten~1);a={a}~Join~b;t++]& t=1 a={}  Try it online! perl -M5.010 122 bytes $n=shift;
$s.="for$$\x_(1..\$$m){"for 1..$n;
$t.="$$\x_ "for 1..n; u.='}'xn; eval"{\m++;s\_=qq' t';/ \$$m /&&say$u;redo}"

Added some newlines for readabilities sake (not counted in the byte count)

Python 2, 120 bytes

from random import*
m=n=input()
a=()
while 1:
m+=len(a)==m**n;t=[randint(1,m)for _ in[1]*n]
if(t in a)<1:a+=t,;print t

Try it online!

A bit longer than most other answers, but I liked the idea behind it.

Stax, 6 bytes

£ƒ\$↔┬ï

Run and debug it

For input n the procedure is roughly

for i in [0..infinity]:
get all the distinct n length arrays of positive integers that sum to i
for each
join with spaces
implicitly output

JavaScript (V8), 98 bytes

n=>{for(a=[],b=[j=1];;b.push(++j))(g=k=>k<n?b.map(i=>(a[k]=i)|g(k+1)):a.includes(j)&&print(a))(0)}

Try it online!

Hooray! Finally got it under 100 :) Basically a port of my C# answer.

// n: length of tuples to generate
n=>{
// a: workspace for current tuple
// b: range of numbers that grows
//     - iteration 1: [1]
//     - iteration 2: [1,2]
//     - iteration 3: [1,2,3]
// j: largest number in b
for(a=[],b=[j=1];;b.push(++j))
// g: recursive function to build tuples
// k: index of slot for current recursive call
(g=k=>
// current slot less than the tuple size?
k<n?
// tuple generation not complete
// try all values in current slot and
// recurse to the next slot
b.map(i=>(a[k]=i)|g(k+1)):
// tuple generation complete
// print tuple if it contains the
// current high value
a.includes(j)&&print(a)
// start recursive function at slot 0
)(0)
}

Python3 (58 characters)

This runs, but never outputs/returns any values, because the permutations function keeps pulling numbers from count. But in theory, this would return the requested permutations.

from itertools import*
lambda n:product(count(1),repeat=n)

Proof that this works for limited integer range:

from itertools import*
l = lambda n: product(range(1, 10), repeat=n)
print(list(l(3)))  # returns all permutations of (1, 2, 3, ..., 10) of length 3

• This is not a solution :-( The last element of the tuple will increase forever, so the other elements will never be reached. ("After infinity" does not count.) Also you never visit (1,1,1), etc., even in the demo case. – alexis Apr 15 at 20:49
• My mistake. I should have used product and not permutations`. This will return all tuples in the order that it will iterate the last element until infinity first and after that the element after that, etc. As I see it, all rules are obliged. I just chose another order... – agtoever Apr 16 at 5:44
• I do not think "Proof that this works for..." means what you think it means - Inigo Montoya – Chas Brown Apr 16 at 7:21
• @agtoever, you do not satisfy the rules. "Each valid tuple must be reached in finite time" translates into you cannot "run to infinity" on the last element and then come back for the rest. This is the whole point of this challenge. – alexis Apr 16 at 8:03

format: plain


text:
# What kind of camera was used to produce this Apollo-era footage of the Earth?

In the video Brian Eno on Apollo at 08:20 there is Apollo-era movie footage of the Earth seen through the window of a spacecraft.

In addition to the primary, large and overexposed half-full Earth image there is a second, smaller (~1/3x) and dimmer but otherwise similar looking and similar color image of the Earth which moves more slowly than the primary as the hand-held camera moves.

It then asks about "the likely cause of this second image/artifact, consistent with all of these characteristics and with the (likely high) quality of the photographic equipment sent to the Moon".

So far, one answer states that this is video, and another that it is 16 mm film. Is it possible to know

1. Video or film?
2. What specific camera and especially what specific lens was used?
3. If possible; Which mission and/or the ID of the archived footage?

• From the fringing I'm reasonably confident it's video rather than film, but I'm not an expert. Jul 29 '19 at 2:15
• If it's not film, it's from one of the Apollo TV cameras. In my answer to the other question I had assumed these were B/W but I'm wrong: there were colour ones. These were 'video' in the sense that their output was sent back to Earth & decoded there, there was no video stored on the spacecraft.
– user21103
Jul 29 '19 at 8:44
• @tfb that's right. There were many live transmissions to Earth and at least some were in color, even the robotic ones! but they weren't recorded locally. Were the Apollo broadcasts recorded locally on the LM?
– uhoh
Jul 29 '19 at 8:51

This is not a complete answer, because I haven't identified the video directly, but it has some information which I think should help someone interested in finding it.

## Camera

I am now pretty sure (despite my original answer in the photography SE) that this is footage from one of the Apollo TV cameras. The 16mm film footage is simply higher quality than this is.

## When was it taken?

There are two parts to this question:

• which flight was it taken on?
• in which phase of the flight was it taken?

I don't have an answer to the first part, except I think it probably is not Apollo 11, as I've looked through all the TV from that and there's only one candidate which I think it's not in fact. But it is possible to say something quite detailed about the second part, which should help prune any search for the answer to the first part.

So, when in a flight was it taken? Well, to answer that you need to know that the Apollo flights landed on the Moon during the lunar morning. For instance Apollo 11 landed on the 20th of July 1969 which was 5 days after the new Moon.

Well, this tells us what the phase of the Earth was as seen by the spacecraft once they had left Earth orbit, and how it changed over the flight. Note: I am assuming that this was not taken from Earth orbit: it would be bizarre if it was I think, as it would need to have been with a very wide lens, and probably the edge of the window would have been in the frame.

And the answer to this is that they were looking at evening on Earth (so in this footage north is up), and that as the flight went on the Earth waned: the illuminated part got smaller. This is pretty obvious if you think about the geometry a bit.

Well, I then had a look through the Apollo 11 flight journal, and it's very clear from that that the Earth has not waned enough on the outward flight, or I think while they were in lunar orbit. There is a candidate from day 8, towards the very end of the TV transmission that day, but I am not sure that this is right: note that the Earth is 'upside down' in the footage: north is down, so we'd have to assume that whoever took it for the Eno footage knew that and turned it around; I am also just not sure the weather patterns are the same.

## How to search for it

I think that the information that the Earth was waning gives someone with enough time on their hands enough information to find the footage:

• you're looking for a flight during which the Earth was about half full;
• this means that the Moon was half full as seen from the Earth;
• so you can use information about the phase of the Moon during the flights to work out which flights are candidates (but see below);


text:
# What is the slope of the line given by the equation 4x-3y=6?

Sep 5, 2016

$m = \frac{4}{3}$

#### Explanation:

Change equation into the form $y = m x + c$

$4 x - 3 y = 6$

$4 x - 6 = 3 y$

$y = \frac{4}{3} x - 2$

$m = \frac{4}{3}$


text:
# Polymode with python and latex-mode

The polymode manual suggests that creating new polymodes should be very easy:

Creating new polymodes typically takes a few lines of code.

I wanted to set it up to make emacs to switch to python mode inside of pythontex commands and environments. For the object oriented approach seems to be more complex to modify than just adding some delimiters to a list in my .emacs file. So I don't even see how to start and where to save apply my modifications.

So how would the equivalent setup for polymode look like as that given by JeanPierre for mmm-mode: https://emacs.stackexchange.com/a/20150/2323

• Note that the package author is in the midst (as of February 2016) of a complete rewrite of polymode. It may be a little unstable until this transition is complete. It sounds like that may be finished shortly, but beware (and patient) in the meantime. – Tyler Feb 20 '16 at 16:43

Following the example at https://github.com/vspinu/polymode/tree/master/modes:

  (require 'polymode)

(defcustom pm-inner/python
(pm-hbtchunkmode "python"
:mode 'python-mode
:tail-reg  "\\\\end{pycode}")
"python typical chunk."
:group 'innermodes
:type 'object)

(defcustom pm-poly/latex-python
(pm-polymode-one "latex-python"
:hostmode 'pm-host/latex
:innermode 'pm-inner/python)
"latex-python typical polymode."
:group 'polymodes
:type 'object)

(define-polymode poly-latex+python-mode pm-poly/latex-python)

It appears to work, though I only tested it briefly. This snippet can go in your .emacs, ~/.emacs.d/init.el or wherever you put your personal emacs configuration.
• It mostly works as expected for me. Syntax highlighting is as it is in a .py buffer, indenting with tab works correctly. I have emacs 24.5.1, python 3.5.1. – Ista Feb 20 '16 at 16:28


text:
Polygons and paths

For drawing shapes, Luxor provides polygons and paths.

A polygon is an ordered collection of Points stored in an array.

A path is a sequence of one or more straight and curved (circular arc or Bézier curve) segments. Paths can consist of subpaths. Luxor maintains a 'current path', to which you can add lines and curves until you finish with a stroke or fill instruction.

You can store a path in a Path type, which contains path elements.

Luxor also provides a BezierPath type, which is an array of four-point tuples, each of which is a Bézier cubic curve section.

createconvertdrawinfoedit
polygons
ngonpolysmoothpolyisinsidesimplify
ngonsidepolytopathprettypolypolyperimeterpolysplit
starpolysmoothpolyareapolyportion
polycrosspolycentroidpolyremainder
offsetpolyBoundingBoxpolysortbyangle
hypotrochoidispolyclockwisepolysortbydistance
epitrochoidispolyconvexpolyclip
polyrotate!ispointonpolypolymove!
polyfitpolyscale!
polyhull
polyreflect!
polysample
polytriangulate
insertvertices!
polymorph
paths
storepath
getpathpathtopolydrawpathpathlengthpathsample
getpathflat
Bezier paths
makebezierpathpathtobezierpathsdrawbezierpathtrimbezier
pathtobezierpathsbezierpathtopolybrushsplitbezier
BezierPathbezierpathtopathbezigon
BezierPathSegment
beziersegmentangles

Regular polygons ("ngons")

A polygon is an array of points. The points can be joined with straight lines.

You can make regular polygons — from triangles, pentagons, hexagons, septagons, heptagons, octagons, nonagons, decagons, and on-and-on-agons — with ngon.

cols = distinguishable_colors(10)
setline(2)
fontsize(12)
tiles = Tiler(700, 600, 3, 3)

for (pos, n) in tiles
@layer begin
translate(pos)

p = ngon(Point(0, 0), 80, n, vertices=true)

sethue(cols[n])

poly(p, action = :fill, close=true)
sethue("black")
poly(p, action = :stroke, close=true)

circle(Point(0, 0), 4, action = :fill)

label.([string(i) for i in 1:n], slope.(O, p), p, offset=5)
end
end

The initial orientation of the polygon defaults to 0.

If you want to specify the side length rather than the circumradius, use ngonside.

for i in 20:-1:3
sethue(i/20, 0.5, 0.7)
ngonside(Point(0, 0), 75, i, 0, action = :fill)
sethue("black")
ngonside(Point(0, 0), 75, i, 0, action = :stroke)
end

The functions return the vertices, or you can use the vertices=true option.

ngon(Point(0, 0), 10, 5)
 Point(3.0901699437494745, 9.510565162951535)
Point(-8.090169943749473, 5.877852522924733)
Point(-8.090169943749475, -5.87785252292473)
Point(3.0901699437494723, -9.510565162951536)
Point(10.0, -2.4492935982947065e-15)

Polygons

Use poly to draw lines connecting the points and/or just fill the area:

tiles = Tiler(600, 250, 1, 2, margin=20)
tile1, tile2 = collect(tiles)

randompoints = [Point(rand(-100:100), rand(-100:100)) for i in 1:10]

gsave()
translate(tile1[1])
poly(randompoints, action = :stroke)
grestore()

gsave()
translate(tile2[1])
poly(randompoints, action = :fill)
grestore()

Holes

To form a hole in a polygon, you reverse the direction of the hole compared to the outer shape. When converted to paths (which happens as part of the drawing process), the reversed polygon forms a hole when drawn.

In this example, the first nut is made by reversing the list of points, the second by using the keyword argument when constructing the shape, and the third when drawing the polygon as a path.

# nut 1

translate(-100, 0)

nut = ngon(O, 120, 6, vertices=true)
hole = reverse(ngon(O, 70, 6, vertices=true))

poly.((nut, hole), action = :path)
fillpath()

# nut 2

translate(100, 0)

sethue("purple")
nut = ngon(O, 120, 6, vertices=true)
hole = ngon(O, 70, 6, reversepath=true, vertices=true)

poly(nut, action = :path)
poly(hole, action = :path)
fillpath()

# nut 3

translate(100, 0)

sethue("orange")
nut = ngon(O, 120, 6, vertices=true)
hole = ngon(O, 70, 6, vertices=true)

poly(nut, action = :path)
newsubpath()
poly(hole, reversepath=true, action = :path)
fillpath()

Pretty polygons

The prettypoly function can place graphics at each vertex of a polygon. After the polygon action, the supplied vertexfunction function is evaluated at each vertex. For example, to mark each vertex of a polygon with a randomly-colored circle:

apoly = star(O, 70, 7, 0.6, 0, vertices=true)
prettypoly(apoly, action=:fill, () ->
begin
randomhue()
circle(O, 10, action=:fill)
end,
close=true)

An optional keyword argument vertexlabels lets you pass a function that can number each vertex. The function can use two arguments, the current vertex number, and the total number of points in the polygon:

apoly = star(O, 80, 5, 0.6, 0, vertices=true)
prettypoly(apoly,
:stroke,
vertexlabels = (n, l) -> (text(string(n, " of ", l), halign=:center)),
close=true)

Recursive decoration is possible:

decorate(pos, p, level) = begin
if level < 4
randomhue()
scale(0.25, 0.25)
prettypoly(p, action = :fill, () -> decorate(pos, p, level+1), close=true)
end
end

apoly = star(O, 100, 7, 0.6, 0, vertices=true)
prettypoly(apoly, action = :fill, () -> decorate(O, apoly, 1), close=true)

Polygons can be simplified using the Douglas-Peucker algorithm (non-recursive version), via simplify.

sincurve = [Point(6x, 80sin(x)) for x in -5π:π/20:5π]
prettypoly(collect(sincurve), action = :stroke,
() -> begin
sethue("red")
circle(O, 3, action = :fill)
end)
text(string("number of points: ", length(collect(sincurve))), 0, 100)
translate(0, 200)
simplercurve = simplify(collect(sincurve), 0.5)
prettypoly(simplercurve, action = :stroke,
() -> begin
sethue("red")
circle(O, 3, action = :fill)
end)
text(string("number of points: ", length(simplercurve)), 0, 100)

The isinside function returns true if a point is inside a polygon.

apolygon = star(O, 200, 8, 0.5, 0, vertices=true)
for pt in collect(first.(Table(30, 30, 15, 15)))
sethue(noise(pt.x/600, pt.y/600), noise(pt.x/300, pt.y/300), noise(pt.x/250, pt.y/250))
isinside(pt, apolygon, allowonedge=true) ? circle(pt, 8, action = :fill) : circle(pt, 3, action = :fill)
end

Quickly changing polygons

If you want to quickly and permanently modify a polygon, there's polymove!, polyscale!, polyreflect!, and polyrotate!.

shape = star(O, 10, 5, 0.5, 0, vertices=true)

circle(O, 3, action = :stroke)

polymove!(shape, O, O + (0, 50))

poly(shape, action = :stroke, close=true)

for i in 1:20
poly(polyrotate!(shape, π/5), action = :fill, close=true)
polyscale!(shape, 19//18)
end

The polygon is continually modified (notice the ! in the function names).

pgon = randompointarray(BoundingBox()/2 ..., 10)
polymove!(pgon, O, Point(-80, 0))
poly(pgon, action = :fill, close=true)
# reflect in y axis:
polyreflect!(pgon, Point(0, 0), Point(0, 100))
sethue("blue")
poly(pgon, action = :fill, close=true)

Other functions

There are a number of experimental polygon functions. These won't work well for polygons that aren't simple or where the sides intersect each other, but they sometimes do a reasonable job. For example, here's polysplit:

s = squircle(O, 60, 60, vertices=true)
pt1 = Point(0, -120)
pt2 = Point(0, 120)
line(pt1, pt2, action = :stroke)
poly1, poly2 = polysplit(s, pt1, pt2)
randomhue()
poly(poly1, action = :fill)
randomhue()
poly(poly2, action = :fill)

Smoothing polygons

Because polygons can have sharp corners, the experimental polysmooth function attempts to insert arcs at the corners and draw the result.

The original polygon is shown in red; the smoothed polygon is shown on top:

tiles = Tiler(600, 250, 1, 5, margin=10)
for (pos, n) in tiles
p = star(pos, tiles.tilewidth/2 - 2, 5, 0.3, 0, vertices=true)
sethue("red")
poly(p, close=true, action = :stroke)
sethue("black")
polysmooth(p, n * 2, action = :fill)
end

The final polygon shows that you can get unexpected results if you attempt to smooth corners by more than the possible amount. The debug=true option draws the circles if you want to find out what's going wrong, or if you want to explore the effect in more detail.

p = star(O, 60, 5, 0.35, 0, vertices=true)
setdash("dot")
sethue("red")
prettypoly(p, close=true, action = :stroke)
setdash("solid")
sethue("black")
polysmooth(p, 40, action = :fill, debug=true)

Offsetting polygons

There are three methods for offsetpoly, a function which constructs a new polygon that's offset from an existing one.

• offsetpoly(plist, d) treats the plist of points as a polygon with n vertices joined by n lines with offset d on both sides.

• offsetpoly(plist, startoffset=d1, endoffset=d2) treats the plist of points as a polyline with n vertices joined by n-1 lines, where the offset varies from startoffset to endoffset.

• offsetpoly(plist, f::function) applies a function f at each vertex of the polyline to determine the width of the offset polygon at that point.

The first method is good for making closed shapes larger or smaller. The other methods are useful for building shapes around an open linear spine.

1: n vertices joined by n lines

The offsetpoly(plist, d) method constructs a closed polygon outside or inside an existing polygon, at distance d. The last vertex in plist as assumed to be be connected to the first.

In the following example, the dotted red polygon is the original, the black polygons have positive offsets and surround the original, the cyan polygons have negative offsets and run inside the original. Use poly to draw the result.

p = star(O, 45, 5, 0.5, 0, vertices=true)
sethue("red")
setdash("dot")
poly(p, action = :stroke, close=true)
setdash("solid")
sethue("black")

poly(offsetpoly(p, 20), action = :stroke, close=true)
poly(offsetpoly(p, 25), action = :stroke, close=true)
poly(offsetpoly(p, 30), action = :stroke, close=true)
poly(offsetpoly(p, 35), action = :stroke, close=true)

sethue("darkcyan")

poly(offsetpoly(p, -10), action = :stroke, close=true)
poly(offsetpoly(p, -15), action = :stroke, close=true)
poly(offsetpoly(p, -20), action = :stroke, close=true)

The function is intended for simple cases, and it can go wrong if pushed too far. Sometimes the offset distances can be larger than the polygon segments, and things will start to go wrong. In this example, the offset goes so far negative that the polygon overshoots the origin, becomes inverted and starts getting larger again.

2 n vertices joined by n-1 lines

The offsetpoly(plist) method constructs a polygon around a line joining the lines in plist. At the start of the line, the polygon will be startoffset units on each side; by the end of the line, the polygon will be endoffset units on each side. The last vertex isn't joined to the first, hence n-1.

In the following example, the original spine is drawn in orange, on top of the black polygon that's constructed to be offset 2 units on each side at the start and 30 units on each side at the end.

spine = [Point(20 + 40x, 15sin(2x)) for x in 0:.1:4π]

for θ in range(0, 2π, step=π/12)
@layer begin
sethue("black")
rotate(θ)
poly(offsetpoly(spine, startoffset=1, endoffset=30), action = :fill)
sethue("orange")
poly(spine, action = :stroke)
end
end

Using an offset-control function

This method accepts a keyword argument that allows you to control the way the offsets are applied, using the easing functionality built in to Luxor (see Animation helper functions).

By default the function is lineartween, so the offset changes linearly between the startoffset and the endoffset values. With other easing functions, this change is modulated. For example, the easeinoutquad function moves between start and end values using a quadratic motion.

spine = between.(O - (200, 0), O + (200, 0), 0:0.025:1)

sethue("red")
prettypoly(spine, action = :stroke)

sethue("black")
pg = offsetpoly(spine, startoffset=0, endoffset=200, easingfunction=easeinoutquad)
prettypoly(pg, action = :stroke, close=true)

But in the next example, the function f(t, b, c, d) (the Luxor standard four-argument easing function) is defined to run from 0 to 2 and back again as t goes from 0 to 1, so the initial and final offsets are 'eased' to 0, and at the middle of the polygon the offsets at that location are 'eased' to 2 × the offset value at that point.

spine = [Point(20x, 15sin(x)) for x in -4π:pi/24:4pi]

f(t, b, c, d) = 2sin(t * π)

pg = offsetpoly(spine, startoffset=1, endoffset=10, easingfunction=f)
sethue("black")
poly(pg, action = :fill)

sethue("white")
poly(spine, action = :stroke)

3: Applying a function

This method generates offset widths using the supplied function. The value of the supplied function f at f(0, θ) determines the start offset on each side, and f(1, θ) determines the finishing offset on each side. The width at the middle vertex will be f(0.5, θ) (on each side). θ is provided as the current slope of the polyline at that point.

This example uses a simple sine curve in f() to vary the width of the spiral from beginning to end.

using Luxor, Colors

f(x, θ) =  10 + 40sin(x * π)

@drawsvg begin

spine = spiral(30, 1.3, vertices=true)
ps = polysample(spine, 250, include_first=true, closed=false)
pgon = offsetpoly(ps, f)
poly(pgon, action = :stroke)

setmesh(mesh(box(BoundingBox(pgon)),
[
RGB(Luxor.julia_red...),
RGB(Luxor.julia_blue...),
RGB(Luxor.julia_green...),
RGB(Luxor.julia_purple...),
]))
poly(pgon, action = :fill)

end

Fitting splines

The experimental polyfit function constructs a B-spline that follows the points approximately.

pts = [Point(x, rand(-100:100)) for x in -280:30:280]
setopacity(0.7)
sethue("red")
prettypoly(pts, () -> circle(O, 5, action = :fill))
sethue("darkmagenta")
poly(polyfit(pts, 200), action = :stroke)

Converting paths to polygons

You can convert the current path to an array of polygons, using pathtopoly.

In the next example, the path consists of a number of paths, some of which are subpaths, which form the holes.

textpath("get polygons from paths")
plist = pathtopoly()
for (n, pgon) in enumerate(plist)
randomhue()
prettypoly(pgon, action = :stroke, close=true)
gsave()
translate(0, 100)
poly(polysortbyangle(pgon, polycentroid(pgon)), action = :stroke, close=true)
grestore()
end

The pathtopoly function calls getpathflat to convert the current path to an array of polygons, with each curved section flattened to line segments.

The getpath function gets the current path as an array of elements, lines, and unflattened curves.

Bezigons

A bezigon is like a polygon, but the sides can be Bézier paths instead of straight lines. Supply the corners and sides to the bezigon function.

corners = [Point(10, 0), Point(200, 0)]
sides = [
[Point(70, -40), Point(150, -50)],
[Point(150, 50), Point(70, 40)],
]
for i in 1:10
sethue(HSV(36i, .7, .7))
rotate(2π / 10)
bezigon(corners, sides, :fill)
end
sethue("white")
circle.([corners..., sides[1]..., sides[2]...], 7, :fill)

Polygons to Bézier paths and back again

Use the makebezierpath and drawbezierpath functions to make and draw Bézier paths, and pathtobezierpaths to convert the current path to an array of Bézier paths.

A BezierPath type contains a sequence of BezierPathSegments; each curve segment is defined by four points: two end points and their control points.

    (Point(-129.904, 75.0),        # start point
Point(-162.38, 18.75),        # ^ control point
Point(-64.9519, -150.0),      # v control point
Point(-2.75546e-14, -150.0)), # end point
(Point(-2.75546e-14, -150.0),
Point(64.9519, -150.0),
Point(162.38, 18.75),
Point(129.904, 75.0)),
(Point(129.904, 75.0),
Point(97.4279, 131.25),
Point(-97.4279, 131.25),
Point(-129.904, 75.0)
),
...

Bézier paths are different from ordinary paths in that they don't usually contain straight line segments. However, by setting the two control points to be the same as their matching start/end points, you create straight line sections.

makebezierpath takes the points in a polygon and converts each line segment into one Bézier curve. drawbezierpath draws the resulting sequence.

pts = ngon(O, 150, 3, pi/6, vertices=true)
bezpath = makebezierpath(pts)
poly(pts, action = :stroke)
for (p1, c1, c2, p2) in bezpath[1:end-1]
circle.([p1, p2], 4, action = :stroke)
circle.([c1, c2], 2, action = :fill)
line(p1, c1, action = :stroke)
line(p2, c2, action = :stroke)
end
sethue("black")
setline(3)
drawbezierpath(bezpath, action = :stroke, close=false)

tiles = Tiler(600, 300, 1, 4, margin=20)
for (pos, n) in tiles
@layer begin
translate(pos)
pts = polysortbyangle(
randompointarray(
Point(-tiles.tilewidth/2, -tiles.tilewidth/2),
Point(tiles.tilewidth/2, tiles.tilewidth/2),
4))
setopacity(0.7)
sethue("black")
prettypoly(pts, action = :stroke, close=true)
randomhue()
drawbezierpath(makebezierpath(pts), action = :fill)
end
end

You can convert a Bézier path to a polygon (an array of points), using the bezierpathtopoly function. This chops up the curves into a series of straight line segments. An optional steps keyword lets you specify how many line segments are used to approximate each Bézier segment.

In this example, the original star is drawn in a dotted gray line, then converted to a Bézier path (drawn in orange), then the Bézier path is converted (with low resolution) to a polygon but offset by 20 units before being drawn (in blue).

pgon = star(O, 250, 5, 0.6, 0, vertices=true)

@layer begin
setgrey(0.5)
setdash("dot")
poly(pgon, action = :stroke, close=true)
setline(5)
end

setline(4)

sethue("orangered")

np = makebezierpath(pgon)
drawbezierpath(np, action = :stroke)

sethue("steelblue")
p = bezierpathtopoly(np, steps=3)

q1 = offsetpoly(p, 20)
prettypoly(q1, action = :stroke, close=true)

You can convert the current path to an array of BezierPaths using the pathtobezierpaths function.

In the next example, the letter "a" is placed at the current position (set by move) and then converted to an array of Bézier paths. Each Bézier path is drawn first of all in gray, then the control points of segment are drawn (in orange) showing how they affect the curvature.

st = "a"
thefontsize = 500
fontsize(thefontsize)
sethue("red")
tex = textextents(st)
move(-tex[3]/2, tex[4]/2)
textpath(st)
nbps = pathtobezierpaths()
setline(1.5)
for nbp in nbps
sethue("grey80")
drawbezierpath(nbp, action = :stroke)
for p in nbp
sethue("darkorange")
circle(p[2], 2.0, action = :fill)
circle(p[3], 2.0, action = :fill)
line(p[2], p[1], action = :stroke)
line(p[3], p[4], action = :stroke)
if p[1] != p[4]
sethue("black")
circle(p[1], 2.0, action = :fill)
circle(p[4], 2.0, action = :fill)
end
end
end

beziersegmentangles lets you define a Bézier path segment by specifying the angles the control handles make with the base line.

setline(.5)

@layer begin
rule.(O, (0, (π/2)))
end

P = O
Q = O + (200, 0)
sethue("black")

pts = beziersegmentangles(P, Q,

@layer begin
setline(2)
sethue("purple")
drawbezierpath(pts, action = :stroke)
end

sethue("grey50")
line(O, pts[2], action = :stroke)
line(Q, pts[3], action = :stroke)
fontsize(15)
circle.((P, pts[2], pts[3], Q), 5, action = :fill)
label.(("P", "Q"), :ne, (P, Q))
text("60°", P + (40, 20))
text("135°", Q + (10, 20))

There are some functions that can modify Bezier path segments. For example, trimbezier chops portions off each end:

setline(2)

bez  = BezierPathSegment(ngon(O, 150, 4, vertices=true)...)
drawbezierpath(bez, action = :stroke)

setopacity(0.4)
sethue("red")
setline(20)
trimbez = trimbezier(bez, 0.2, 0.8)
drawbezierpath(trimbez, action = :stroke)

setline(40)
sethue("purple")
trimbez = trimbezier(trimbez, 0.2, 0.8)
drawbezierpath(trimbez, action = :stroke)

When working with Bézier curves it's usual to consider the curve in terms of a parameter t going from 0.0 to 1.0.

splitbezier can split a segment into two shorter segments.

Brush strokes

The brush function builds Bezier paths in a quasi-random fashion, that could look like brush strokes. The optional keyword arguments allow a range of different effects.

You can pass a function that can adjust various drawing settings before the shapes are drawn.

brushα(nbpb) = begin
setline(1)
setopacity(0.3)
drawbezierpath(nbpb, action = :stroke)
sethue(0.2, 0.3, rand(0.3:0.01:0.65))
return nbpb
end

function numberit(pos, n)
@layer begin
sethue("black")
text(string(n), pos)
end
end

t  = Tiler(800, 700, 5, 1)
sethue("orange3")
fontsize(20)
for (pos, n) in t
start, finish = pos - (200, 0), pos + (200, 0)
if n == 1
# five brush strokes
brush(start, finish, 1)
numberit(pos, n)
elseif n == 2
# minwidth and maxwidth control the, er, width
brush(start, finish, 5, minwidth = -5, maxwidth = 2)
numberit(pos, n)
elseif n == 3
# dont have to have transparent strokes
brush(start, finish, 20, minwidth = .2, randomopacity = false)
numberit(pos, n)
elseif n == 4
# twist and adjust handles to taste
brush(start, finish, minwidth = -.1, maxwidth = .2,
twist = 2, highhandle = 2, tidystart=false)
numberit(pos, n)
elseif n == 5
# call a function to modify each stroke
brush(start, finish, 1, minwidth = -2.2, maxwidth = .8,
lowhandle = -.4, highhandle = 1.5, twist = .5,
strokefunction = brushα)
numberit(pos, n)
end
end

For more information (and more than you probably wanted to know) about Luxor's Bézier paths, visit https://cormullion.github.io/pages/2018-06-20-bezier/.

Polygon information

polyperimeter calculates the length of a polygon's perimeter.

p = box(O, 50, 50, vertices=true)
poly(p, action = :stroke)
text(string(round(polyperimeter(p, closed=false))), O.x, O.y + 60)

translate(200, 0)

poly(p, action = :stroke, close=true)
text(string(round(polyperimeter(p, closed=true))), O.x, O.y + 60)

To find the "left-most" point, ie the point with the lowest x coordinate, you can use built-in extrema() function, to return the left-most and right-most points. (This is because, when you compare points, the x coordinate is tested first.) To find the "lowest" points, ie the points with the lowest y value, you could find the y extrema and use it to find the index:

findfirst(pt -> isequal(pt.y, first(extrema(pt -> pt.y, pts))), pts)
# 13

Convex hull

A convex hull of a polygon is the subset of points such that, when connected with straight lines, the resulting shape contains every point of the polygon.

Use polyhull to find the convex hull of an array of points.

setline(4)

juliacircles(130) # draw in color

# get points
juliacircles(130, action=:path)
points  = simplify(pathtopoly()[1], 2)

hull = polyhull(points)

sethue("gold2")

poly(hull, close=true, action = :stroke)

In this example, the points forming the Julia logo (converted from a path to a polygon) are contained inside the convex hull.

Polygon selection and modification

There are Luxor functions to return the first part or last part of a polygon. You can also ask for a resampling of a polygon, choosing either to increase the number of points (which places new points to the "lines" joining the vertices) or decrease them (which changes the shape of the polygon). It's also possible to insert vertices automatically.

polyportion and polyremainder return part of a polygon depending on the fraction you supply. For example, polyportion(p, 0.5) returns the first half of polygon p, polyremainder(p, .75) returns the last quarter of it.

p = ngon(O, 100, 7, 0, vertices=true)
poly(p, action = :stroke, close=true)
setopacity(0.75)

setline(20)
sethue("red")
poly(polyportion(p, 0.25), action = :stroke)

setline(10)
sethue("green")
poly(polyportion(p, 0.5), action = :stroke)

setline(5)
sethue("blue")
poly(polyportion(p, 0.75), action = :stroke)

setline(1)
circle(polyremainder(p, 0.75)[1], 5, action = :stroke) # first point

You can insert vertices in the edges of a polygon with insertvertices!. For example, this code inserts a new vertex into each side of a polygon five times. The polygon ends up with 128 vertices.

pts = box(O, 500, 200, vertices=true)
prettypoly(pts, action = :stroke, close=true)

for i in 1:5
insertvertices!(pts)
prettypoly(pts, action = :stroke, close=true)
fontsize(16)
label(string(length(pts)), :ne, pts[1], offset=10)
scale(0.8)
end

To resample a polygon, use polysample. In this example, the same four-sided polygon is resampled at multiples of 4, with different circle radii at each multiple. This adds more points to the new copy of the original polygon.

pts = ngon(O, 100, 4, vertices=true)
for (n, npoints) in enumerate(reverse([4, 8, 16, 32, 48]))
prettypoly(polysample(pts, npoints),
:stroke, close=true,
() -> begin
circle(O, 2n, action = :stroke)
end)
end

There is a closed option, which determines whether or not the final edge (the one that would join the final vertex to the first), is included in the sampling. In the following example, the original polygon is drawn in black, then sampled as a closed polygon (in blue), then as a non-closed one (magenta).

# original polygon

numbervertices(l, n) = label(string(l), :N, O)
drawvertices() = ngon(O, 3, 4, 0, action = :fill)

pts = [Point(30x, 20sin(x)) for x in -2π:π/6:2π]

# 1: drawn as defined

prettypoly(pts, action = :stroke, drawvertices, vertexlabels = numbervertices)

translate(0, 50)

# 2: resampled as closed

npoints = 40

sethue("cornflowerblue")
prettypoly(polysample(pts, npoints, closed=true), action = :stroke, drawvertices,
vertexlabels = numbervertices)

translate(0, 50)

# 3: resampled as open

sethue("magenta")
prettypoly(polysample(pts, npoints, closed=false), action = :stroke, drawvertices,
vertexlabels = numbervertices)

Note

In Luxor, you'll meet close and closed options. close is an instruction to path-drawing functions, that says "join the most recent point to the first point". Whereas, closed is an indication that the polygons or paths should be treated as being closed rather than open, ie whether that last segment joining the end point to the first is used for calculations.

Polygon side lengths

polydistances returns an array of the accumulated side lengths of a polygon.

julia> p = ngon(O, 100, 7, 0, vertices=true);
julia> polydistances(p)
8-element Array{Real,1}:
0.0000
86.7767
173.553
260.33
347.107
433.884
520.66
607.437

It's used by polyportion and polyremainder, and you can pre-calculate and pass them to these functions via keyword arguments for performance. By default the result includes the final closing segment (closed=true).

These functions also make use of the nearestindex, which returns a tuple of: the index of the nearest value in an array of distances to a given value; and the excess value.

In this example, we want to find a point halfway round the perimeter of a triangle. Use nearestindex to find the index of the nearest vertex (nidx, 2), and the surplus length, (over, 100).

p = ngonside(O, 200, 3, vertices=true)
prettypoly(p, action = :stroke, close=true, vertexlabels = (n, l) -> label(string(n), :NW, offset=10))

# distances array
da = polydistances(p)

nidx, over = nearestindex(da, polyperimeter(p)/2)

sethue("red")
circle(p[nidx], 5, action = :stroke)

arrow(p[nidx],
between(p[nidx], p[nidx+1], over/distance(p[nidx], p[nidx+1])),
linewidth=2)

Of course, it's much easier to do polyportion(p, 0.5).

Area of polygon

Use polyarea to find the area of a polygon. Of course, this only works for simple polygons; polygons that intersect themselves or have holes are not correctly processed.

This code draws some regular polygons and calculates their area, perimeter, and shows how near the ratio of perimeter over radius approaches 2π.

fontface("Georgia")
sethue("black")
setline(0.25)
outerframe = Table([500], [400, 200])
total = 30
properties = Table(fill(15, total), [20, 85, 85], outerframe[1, 2])
sethue("grey20")
for i in 3:total
text(string(i), properties[i, 1], halign=:right)
p = ngon(outerframe[1], radius, i, 0, vertices=true)
prettypoly(p, action = :stroke, close=true, () -> (sethue("red"); circle(O, 2, action = :fill)))
pa = polyarea(p)
pp = polyperimeter(p)
text(string(Int(round(pa, digits=0))), properties[i, 2], halign=:left)
end

fontsize(10)
for (pt, n) in Table([20], [20, 85, 85], outerframe[2] - (0, 220))]

Morphing polygons

"morph" means to make one thing turn into another. The experimental polymorph function can gradually turn one polygon into another.

You supply two polygons and a value k between 0 and 1. For example, if the value of k is 0.5, the shape is about halfway between the two polygons.

polymorph() always returns an array of polygons.

By default, the polygons are assumed to be closed, suitable for filling.

But in this example, each of the two wavy-line polygons are open rather than closed, so you can pass false values to the closed argument, and the polygons won't be treated as closed shapes.

rotate(π/2)
fromshape  = [Point(90x, -230 + 50sin(3x)) for x in range(-π, π, length=250)]
toshape  = [Point(90x, 230 + 50sin(-3x)) for x in range(-π, π, length=250)]
for i in 0:0.03:1
sethue(1 - i, i/4 + 0.2, 1 - i/4)
morph = polymorph(fromshape, toshape, i,
easingfunction=easeinoutcubic,
closed=(false, false))
poly(first(morph), action = :stroke)
end

Sometimes polygons consist of two or more loops - this is how holes work. So polymorph() accepts both simple polygons and arrays of polygons, but always returns an array of polygons.

In the next example, fromshape, the circle, is an array holding a single vector of Points (pathtopoly() returns an array of polygons), and toshape, the line, is a simple vector of points (the minimum of three points). In this case, with just simple polygons, only the first element of the result of the polymorph() function is needed.

circlepath(O, 200, action = :path)
fromshape = pathtopoly()
toshape = [Point(0, -250), O, Point(0, 250)] # minimum of 3
for i in 0:0.015:1
sethue(i, 1 - i, i/2 + 0.5)
morph = polymorph(fromshape, toshape, i, easingfunction=easeinoutsine)
poly(first(morph), action = :stroke, close=true)
end

In the next example, a square morphs into a hexagon.

pgon1 = ngon(O, 80, 4,  vertices = true)
pgon2 = ngon(O, 270, 6, vertices = true)
sethue("cyan")
setline(1)
for i in 0:0.05:1.0
sethue(i, 1 - i, 0.5)
poly(first(polymorph(pgon1, pgon2, i)),
action = :stroke,
close = true)
end

In the next example, an octagon with a square hole morphs into a square with an octagonal hole.

# build first polygon
ngon(O + (-350, 0), 40, 8, π, action = :path)
newsubpath()
box(O + (-350, 0), 30, 30, reversepath=true, action = :path)
pgon1 = pathtopoly()

# build second polygon
newpath()
box(O + (350, 0), 60, 60, action = :path)
newsubpath()
ngon(O + (350, 0), 20, 8, π, reversepath=true, action = :path)
pgon2 = pathtopoly()

# draw morphs
sethue("cyan")
setline(1)
for i in 0:0.1:1.0
sethue(i, 1 - i, 0.5)
poly.(polymorph(pgon1, pgon2, i),
action=:path,
close=true)
fillpath()
end

Because both polygons have reversed subpaths (holes), the polygons should be drawn using :path and fillpath().

The next example animates a morph between two programming languages.

using Luxor, Colors

background("black")

fontface("JuliaMono")
fontsize(120)

textoutlines("", O + (0, 0), halign=:center, valign=:middle)
python_logo = pathtopoly()

textoutlines("", O + (0, 0), halign=:center, valign=:middle)
julia_logo = pathtopoly()

fontface("WorkSans-Black")
fontsize(130)
textoutlines("Python", O + (0, -100), halign=:center, valign=:middle, action = :path)
fromtext = pathtopoly()

textoutlines("Julia", O + (0, 100), halign=:center, valign=:middle, action = :path)
totext   = pathtopoly()

newpath()
sethue("cyan")

0, 1, scene.framerange.stop - scene.framerange.start)

i = sin(eased_n * π)
poly.(polymorph(fromtext, totext, i, easingfunction=easingflat, samples=200),
action=:path,
close=true)
strokepath()

pm = polymorph(python_logo, julia_logo, i)
for p in pm
poly(p, action = :path)
end
fillpath()
end

amovie = Movie(600, 400, "p to j")
animate(amovie,
Scene(amovie, frame, 1:200,
easingfunction = easeinoutsine),
creategif = true,
pathname = "/tmp/python-julia.gif")

The "Python" path has 9 loops, whereas "Julia" has 8. The polymorph() function tries to work around this - notice how the ninth loop, "n", morphs down to nothing. If you don't want this to happen, set the kludge keyword to false. In this particular case, you could increase the number of loops in totext to match by using a lower-case "j".

Other polygon operations

These functions are still in development. Expect varying degrees of success when using them.

polyclip() returns the region of a source polygon that lies inside a clipping polygon. In this example, each intersecting piece is created by clipping one of the "circles" with another (each circle is an 80-sided polygon).

using Luxor, Colors
@drawsvg begin
background("black")

npoints = 80
D = 140
pts = ngon(O, 110, 3, π / 6, vertices=true)

circle1 = ngon(pts[1], D, npoints, vertices=true)
circle2 = ngon(pts[2], D, npoints, vertices=true)
circle3 = ngon(pts[3], D, npoints, vertices=true)

sethue("cyan"); poly(circle1, :fill)
sethue("magenta"); poly(circle2, :fill)
sethue("yellow"); poly(circle3, :fill)

sethue("blue")
pc1 = polyclip(circle1, circle2)
poly(pc1, :fill, close=true)

sethue("red")
pc2 = polyclip(circle1, circle3)
poly(pc2, :fill, close=true)

sethue("green")
pc3 = polyclip(circle2, circle3)
poly(pc3, :fill, close=true)

pc4 = polyclip(pc1, pc2) # or polyclip(pc1, pc3) ...

sethue("white")
poly(pc4, :fill, close=true)
end

Intersections

intersectlinepoly(pt1, pt2, polygon) returns an array containing the points where a line from pt1 to pt2 crosses the perimeter of the polygon.

setline(0.3)
sethue("thistle")
c = star(O, 120, 7, 0.2, vertices=true)
poly(c, action = :fillstroke, close=true)
for n in 1:15
pt1 = Point(rand(-250:250, 2)...)
pt2 = Point(rand(-250:250, 2)...)
ips = intersectlinepoly(pt1, pt2, c)
if !isempty(ips)
sethue("grey20")
line(pt1, pt2, action = :stroke)
randomhue()
circle.(ips, 2, action = :fill)
else
sethue("grey80")
line(pt1, pt2, action = :stroke)
end
end

Triangulation

Use polytriangulate to join the vertices of a polygon to form triangles. It returns an array of triangular polygons.

pts = ngon(O, 200, 7, vertices=true)
triangles = polytriangulate(pts)

for (n, tri) in enumerate(triangles)
sethue([Luxor.julia_purple,
Luxor.julia_blue,
Luxor.julia_red,
Luxor.julia_green
][mod1(n, end)])
poly(offsetpoly(tri, -2), action = :fill, close = true)
sethue("white")
text(string(n), polycentroid(tri), halign=:center)
end

sethue("red")
setline(3)
poly(pts, action = :stroke, close=true)


text:
Department of

# Mathematics

Seminar Calendar
for events the day of Thursday, October 31, 2019.

.
events for the
events containing

Questions regarding events or the calendar should be directed to Tori Corkery.
    September 2019          October 2019          November 2019
Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa
1  2  3  4  5  6  7          1  2  3  4  5                   1  2
8  9 10 11 12 13 14    6  7  8  9 10 11 12    3  4  5  6  7  8  9
15 16 17 18 19 20 21   13 14 15 16 17 18 19   10 11 12 13 14 15 16
22 23 24 25 26 27 28   20 21 22 23 24 25 26   17 18 19 20 21 22 23
29 30                  27 28 29 30 31         24 25 26 27 28 29 30

Thursday, October 31, 2019

11:00 am in 241 Altgeld Hall,Thursday, October 31, 2019

#### Eisenstein ideal with squarefree level

###### Carl Wang-Erickson (University of Pittsburgh)

Abstract: In his landmark paper "Modular forms and the Eisenstein ideal," Mazur studied congruences modulo a prime p between the Hecke eigenvalues of an Eisenstein series and the Hecke eigenvalues of cusp forms, assuming these modular forms have weight 2 and prime level N. He asked about generalizations to squarefree levels N. I will present some work on such generalizations, which is joint with Preston Wake and Catherine Hsu.

12:00 pm in 243 Altgeld Hall,Thursday, October 31, 2019

#### Monopole Floer homology and spectral geometry of hyperbolic three-manifolds

###### Francesco Lin (Columbia University)

Abstract: By studying the Seiberg-Witten equations, Kronheimer and Mrowka defined a package of invariants of three-manifolds called monopole Floer homology. In this talk, we discuss some interactions between this topological invariant and the spectral geometry of the Laplacian on the underlying Riemannian manifold, with the goal of understanding concrete examples of hyperbolic manifolds. This is joint work with Mike Lipnowski.

1:00 pm in 464 Loomis Laboratory,Thursday, October 31, 2019

#### Multitrace excited states and perturbative entropy divergences

###### Antony Speranza (Perimeter Institute)

Abstract: Perturbative calculations of entanglement entropy have found a number of recent applications in understanding field theory, holography, and quantum gravity. In this talk, I will discuss a class of excited states of a CFT formed from a Euclidean path integral with nonlocal multitrace insertions, with an eye toward understanding their entanglement structure holographically. Such states are argued to have good semiclassical holographic duals, but can possess nontrivial bulk entanglement structure at order N^0. A surprising feature of these states is that divergences occur quite generically in the perturbative expansion of their entanglement entropy. These divergences signal a nonanalyticity in the expansion, and must be resummed in computing the full expression for the entropy. This resummation is challenging in general, but I will describe some simplified examples in which it may be tractable. In the process, I will also give some general techniques for diagnosing when such nonanalyticities occur, and point to some indications that they may in general be calculable. This talk is based on arXiv:1904.01584 and ongoing work.

2:00 pm in 243 Altgeld Hall,Thursday, October 31, 2019

#### Matrix Convex Sets, Tensor Products, and Noncommutative Choquet Boundaries

###### Roy Araiza (Purdue )

Abstract: I will discuss tensor products in the category of matrix convex sets and discuss how we may relate the study of their Choquet theory to questions about tensor product nuclearity. Based on joint work with Adam Dor-On and Thomas Sinclair.

3:00 pm in 347 Altgeld Hall,Thursday, October 31, 2019

#### The combinatorics of spherical Schubert varieties

###### Reuven Hodges   [email] (University of Illinois at Urbana-Champaign )

Abstract: Over the last several years, in joint work with V. Lakshmibai and M. B. Can, I have been studying Levi subgroup actions on Schubert varieties. I plan to discuss some of the combinatorial questions that have arisen from this work. I will introduce skew Schur functions and their decomposition in the basis of Schur functions, as well as when these decompositions are multiplicity free. Then we will discuss several problems involving these multiplicities. To conclude, I will illustrate how the answer to these multiplicity problems allows us to classify all Schubert varieties in the Grassmannian and Levi subgroups such that the Levi acts spherically on the Schubert variety.


text:
Can we have modulo a negative number?

• I

Main Question or Discussion Point

Why can't we have modulo negative number? I have never seen this.

PeroK
Homework Helper
Gold Member
Why can't we have modulo negative number? I have never seen this.
You would simply have to define what you mean by it.

In terms of factorisation and remainders, everything can be seen with a positive divisor, so I wouldn't expect any new insights.

The same goes for allowing negative numbers to be prime.

fresh_42
Mentor
Why can't we have modulo negative number? I have never seen this.
Because a negative number $-n=(-1)\cdot n$ differs from its positive counterpart only by a unit, $\varepsilon=-1$. So the ideals $n\mathbb{Z}$ and $\varepsilon n\mathbb{Z}$ are the same. This implies that the factor rings $\mathbb{Z}[x]/n\mathbb{Z} = \mathbb{Z}_n = \mathbb{Z}[x]/\varepsilon n\mathbb{Z}$ are equal, too. And as it makes no difference, it is a matter of convenience to choose the positive version. Otherwise the calculations were full of unnecessary signs.

FactChecker
Gold Member
I don't see any conceptual difference between modulo of a positive versus negative integer. I am not sure if all computer languages would implement it. Perl does:

Integers 0..9 mod -3:
0 mod -3 = 0
1 mod -3 = -2
2 mod -3 = -1
3 mod -3 = 0
4 mod -3 = -2
5 mod -3 = -1
6 mod -3 = 0
7 mod -3 = -2
8 mod -3 = -1
9 mod -3 = 0

fresh_42
Mentor
I don't see any conceptual difference between modulo of a positive versus negative integer. I am not sure if all computer languages would implement it. Perl does:

Integers 0..9 mod -3:
0 mod -3 = 0
1 mod -3 = -2
2 mod -3 = -1
3 mod -3 = 0
4 mod -3 = -2
5 mod -3 = -1
6 mod -3 = 0
7 mod -3 = -2
8 mod -3 = -1
9 mod -3 = 0
I had been impressed, if it would have calculated the results in the standard representation, i.e. $[0],[1],[2]$. This way its more an incidental result.

The essential point is really, that "up to units" is often dropped in the definitions, be it as sloppiness or because it is self-evident. As @PeroK mentioned
The same goes for allowing negative numbers to be prime.
the situation with primes is the same: "up to units", because $-3$ is as prime as $3$ is. And that $1$ isn't a prime, is only because the definition starts with "A number is prime, if it is no unit and ..." It makes absolute sense to exclude units. E.g. nobody ever asked, whether the fundamental theorem of arithmetic is wrong, since we can always add units as many as we want to: $6=2\cdot 3= 1\cdot 2\cdot 3= (-1)\cdot (-1)\cdot 2 \cdot 3 = 1\cdot 1\cdot 3\cdot 2\cdot 1 =\ldots$ Units simply don't change the game, so why bother them?

FactChecker
Gold Member
Modular arithmetic sets up equivalences between negative numbers (the additive inverse) and positive numbers. -3 mod 3 = 0; -2 mod 3 = 1; -1 mod 3 = 2; etc. Modulo 3 and modulo -3 works out to be consistant:

-4 mod 3 = 2
-3 mod 3 = 0
-2 mod 3 = 1
-1 mod 3 = 2
0 mod 3 = 0
1 mod 3 = 1
2 mod 3 = 2
3 mod 3 = 0
4 mod 3 = 1

-4 mod -3 = -1
-3 mod -3 = 0
-2 mod -3 = -2
-1 mod -3 = -1
0 mod -3 = 0
1 mod -3 = -2
2 mod -3 = -1
3 mod -3 = 0
4 mod -3 = -2

Last edited:
fresh_42
Mentor
Sure. But this isn't evidence for a smart programming of Perl as you implicitly suggested, but simply a logic outcome of ordinary arithmetic. An automated conversion into standard results would have been smart. The above is more or less an unintended result of a correct division.

FactChecker
Gold Member
Sure. But this isn't evidence for a smart programming of Perl as you implicitly suggested, but simply a logic outcome of ordinary arithmetic. An automated conversion into standard results would have been smart. The above is more or less an unintended result of a correct division.
there is no reason for them to apologize for a "happy coincidence" that turns out to be mathematically correct.

fresh_42
Mentor
there is no reason for them to apologize for a "happy coincidence" that turns out to be mathematically correct.
Yes, but that's not the point. The point is, that similar to what led to the OP's question, the programmers completely ignored the role of units. In this sense, it is rather off-topic here than a support for the equation $n\mathbb{Z}=-n\mathbb{Z}$. The example brought you no millimeter closer to the answer of the question. It only shows that you can do calculate with negative numbers, not why they are usually ignored in books.

FactChecker
Gold Member
IMO, in any algebra, -x is the additive inverse of x. x + (-x) = 0. I see no issue with units.

lavinia
Gold Member
Why can't we have modulo negative number? I have never seen this.
You can do arithmetic using negative bases for instance arithmetic base -2.

fresh_42
Mentor
IMO, in any algebra, -x is the additive inverse of x. x + (-x) = 0. I see no issue with units.
Because you confuse addition with multiplication. We are talking about multiplication here, since the module is $z \,\,\cdot\,\, \mathbb{Z}\,$.
No ring, no question.

PeroK
Homework Helper
Gold Member
Given that it's the 21st century, perhaps mathematicians should be thinking about equal rights for negative numbers! Why should $-5$, for example, be denied the right to be called a prime number, just because it was born on the wrong side of the number line?

FactChecker
Gold Member
I guess I don't see the problem. It seems natural and uncomplicated to extend the equivalence classes in the non-negative integers defined by mod 3 ({0,3,6,9,...}, {1,4,7,10,...},{2,5,8,11,...}) to include the negative integers ({...,-9,-6,-3,0,3,6,9,...}, {...,-8,-5,-2,1,4,7,10,...},{...,-7,-4,-1,2,5,8,11,...}). Does this cause a problem when multiplication is introduced? Off-hand, I don't see it.

fresh_42
Mentor
The female version of many professions is obtained by a suffix "in" in German, e.g. a female carpenter would be a carpenterin. This lead to thousandths of texts which are written with constructions like "... we are looking for a carpenter/in with at least five years of experience ..."

I see me writing: Let $p/-p$ be a prime. ...

However, in rings which have more than these two units, things will become quite disturbing: Let $p/\varepsilon\cdot p$ be a prime, where $\varepsilon$ is a unit, ...

fresh_42
Mentor
I guess I don't see the problem. It seems natural and uncomplicated to extend the equivalence classes in the non-negative integers defined by mod 3 ({0,3,6,9,...}, {1,4,7,10,...},{2,5,8,11,...}) to include the negative integers ({...,-9,-6,-3,0,3,6,9,...}, {...,-8,-5,-2,1,4,7,10,...},{...,-7,-4,-1,2,5,8,11,...}). Does this cause a problem when multiplication is introduced? Off-hand, I don't see it.
No, it does not. It simply doesn't contribute anything to the answer of the question: Why are negative numbers ignored? It only shows, that the question has a justification, but nothing as to why this is the case.

I had the same problem as the OP when I saw -1(MOD 10) on the OEIS site.
Centred 10-gonal numbers
A062786
no idea why the server cannot now find the site

FactChecker
Gold Member
No, it does not. It simply doesn't contribute anything to the answer of the question: Why are negative numbers ignored? It only shows, that the question has a justification, but nothing as to why this is the case.
The original OP question was "Why can't we have modulo negative numbers?". The answer is that we can. It is a natural extension of the concept to include negative integers. Then the OP asks why he has never seen it. The answer to that is that there is not much benefit.

mathwonk


text:
Due to a planned intervention the CERN Document Server website will be unavailable from Tuesday, June 29th at 13:30 CEST to Wednesday, June 30th at 9:30 CEST.

# Published Articles

Последно добавени:
2021-06-23
06:01
 Investigation of $\pi^+\pi^-, K^+\pi^-$ and $\pi^+K^-$ atoms for pion-pion and pion-kaon scattering length measurements / Yazkov, Valeriy (SINP, Moscow) /DIRAC Collaboration Theory, using Low Energy QCD, calculated with high precision the $\pi\pi$ and $\pi K$ scattering length. Lifetime of $\pi^+\pi^−$ atoms are related with a difference of pion-pion s-wave scattering lengths with isospin 0 and 2: $|a_0 − a_2|$ [...] DIRAC-CONF-2015-01.- 2015 - 6 p. External link: Fulltext In : The XXII International Workshop High Energy Physics and Quantum Field Theory, Samara, Russia, 24 Jun - 1 Jul 2015

2021-06-23
06:01
 Experimental facilities in Latin America / Dib, C O (CCTVal, Valparaiso ; Valparaiso Ctr. Sci. Tech.) These lecture notes briefly describe the current and planned experimental facilities for high-energy physics research in Latin America. The list is not exhaustive nor the descriptions are complete, but I tried to select some of the most representative facilities and large international experiments at the time. [...] 2021 - 27 p. - Published in : 10.23730/CYRSP-2021-002.193 Fulltext: PDF; In : 2019 CERN-Latin-American School of High-Energy Physics, Villa General Belgrano, Argentina, 13 - 26 March, 2019, pp.193-219 (CERN-2021-002)

2021-06-23
06:01
 HPS@L1 algorithm for the upgraded CMS level-1 hadronic tau trigger for the HL-LHC / Bhowmik, Sandeep (NICPB, Tallinn) /CMS Collaboration The High-Luminosity LHC will open an unprecedented window on the weak-scale nature of the universe, providing high-precision measurements of the standard model as well as searches for new physics beyond the standard model. The Compact Muon Solenoid (CMS) experiment is planning to replace entirely its trigger and data acquisition system to achieve this ambitious physics program. [...] SISSA, 2020 - 5 p. - Published in : PoS LHCP2020 (2021) 211 In : 8th Conference of Large Hadron Collider Physics (LHCP), Online, 25 - 30 May 2020, pp.211

2021-06-23
06:01
 Beam-test evaluation of the precision timing capabilities of a CMS HGCAL prototype / Buchot Perraguin, Axel (Ecole Polytechnique) /CMS Collaboration The existing CMS endcap calorimeters will be replaced by a High Granularity Calorimeter (HGCAL) for operation at the High Luminosity (HL) LHC which will start in 2027. Radiation hardness and excellent physics performance will be achieved by utilising silicon pad sensors and SiPM-on-scintillator tiles with high transverse and longitudinal segmentation. [...] SISSA, 2020 - 5 p. - Published in : PoS LHCP2020 (2021) 209 In : 8th Conference of Large Hadron Collider Physics (LHCP), Online, 25 - 30 May 2020, pp.209

2021-06-23
06:01
 Probe $p_T$-dependent flow vector fluctuations with ALICE / Nielsen, Emil Gorm (Bohr Inst.) /ALICE Collaboration One of the main goals of ultra-relativistic nuclear collisions is to create a new state of matter called the quark-gluon plasma (QGP) and study its properties. One of the experimental observables is the anisotropic flow $v_n$, defined as the correlation of the azimuthal angle of each particle with respect to a common symmetry plane $\Psi_n$. [...] SISSA, 2020 - 5 p. - Published in : PoS LHCP2020 (2021) 207 In : 8th Conference of Large Hadron Collider Physics (LHCP), Online, 25 - 30 May 2020, pp.207

2021-06-23
06:01
 Report on outreach activities at LHC / Hatzifotiadou, Despina (Bologna U. ; INFN, Bologna) /ALICE Collaboration ; ATLAS Collaboration ; CMS Collaboration ; LHCb Collaboration Outreach is undoubtedly an integral part of the scientific process. Reaching out to the public, explaining our results and sharing our enthusiasm, we try to motivate the youth, to clarify misconceptions about science and to ensure continued funding – to name but a few of our goals. [...] SISSA, 2020 - 7 p. - Published in : PoS LHCP2020 (2021) 203 In : 8th Conference of Large Hadron Collider Physics (LHCP), Online, 25 - 30 May 2020, pp.203

2021-06-23
06:01
 Activity on the Sextupole Round Coil Superferric Magnet Prototype at LASA / Mariotto, Samuele ; Leone, Augusto ; Paccalini, Antonio ; Pasini, Alessandro ; Pedrini, Danilo ; Quadrio, Mauro ; Sorbi, Massimo ; Statera, Marco ; Todero, Maurizio ; Valente, Riccardo The LASA Laboratory (INFN, Milan, Italy) is developing an unconventional type of superferric magnets suitable to arbitrary multipole order, which we refer to as round coil superferric magnets. This type of magnet is suitable for strain-sensitive superconductors because it uses round coils with large bending radius to create the magnetic field, while the round yoke with arbitrary multipoles is able to create the desired harmonic component for the magnet. [...] 2019 - 5 p. - Published in : IEEE Trans. Appl. Supercond. 29 (2019) 4004505

2021-06-23
06:01
 Assembly and Tests of SQ02, a Nb$_{3}$Sn Racetrack Quadrupole Magnet for LARP / Ferracin, P (LBNL, Berkeley) ; Ambrosio, G (Fermilab) ; Barzi, E (Fermilab) ; Caspi, S (LBNL, Berkeley) ; Dietderich, D R (LBNL, Berkeley) ; Feher, S (Fermilab) ; Gourlay, S A (LBNL, Berkeley) ; Hafalia, A R (LBNL, Berkeley) ; Hannaford, C R (LBNL, Berkeley) ; Lizarazo, J (LBNL, Berkeley) et al. The US LHC Accelerator Research Program (LARP) is developing Nb$_{3}$Sn accelerator magnets for a possible LHC luminosity upgrade. As part of the LARP supporting R&D;, a subscale racetrack quadrupole magnet (SQ) has been developed in order to provide a cost effective tool for technology development studies. [...] 2007 - 4 p. - Published in : IEEE Trans. Appl. Supercond. 17 (2007) 1019-1022 In : Applied Superconductivity Conference, Seattle, WA, USA, 27 Aug - 1 Sep 2006, pp.1019-1022

2021-06-23
06:01
 Test and Analysis of Technology Quadrupole Shell (TQS) Magnet Models for LARP / Caspi, S (LBNL, Berkeley) ; Ambrosio, G (fermilab) ; Andreev, A N (Fermilab) ; Barzi, E (Fermilab) ; Bossert, R (Fermilab) ; Dietderich, D R (LBNL, Berkeley) ; Ferracin, P (LBNL, Berkeley) ; Ghosh, A (Brookhaven Natl. Lab.) ; Hafalia, A R (LBNL, Berkeley) ; Kashikhin, V V (Fermilab) et al. Test results are reported on four quadrupole magnet model tests (TQS01a, TQS01b, TQS01c, TQS02) in support of the development of a large-aperture Nb$_3$Sn superconducting quadrupole for the US LHC Accelerator Research Program (LARP). All four magnet assemblies used key and bladder technology to compress and support the coils within an iron yoke and an aluminum shell. [...] 2008 - 5 p. - Published in : IEEE Trans. Appl. Supercond. 18 (2008) 179-183 In : 20th International Conference on Magnet Technology, Philadelphia, PA, USA, 27 - 31 Aug 2007, pp.179-183

2021-06-23
06:01
 Assembly and Test of a Support Structure for 3.6 m Long Nb$_3$Sn Racetrack Coils / Ferracin, P ; Ambrosio, G ; Anerella, M ; Caspi, S ; Cheng, D W ; Felice, H ; Hafalia, A R ; Hannaford, C R ; Lietzke, A F ; Lizarazo, J et al. The LHC accelerator research program (LARP) is currently developing 4 m long Nb$_3$Sn quadrupole magnets for a possible upgrade of the LHC Interaction Regions (IR). In order to provide a reliable test bed for the fabrication and test of long Nb$_3$Sn coils, LARP has started the development of the long racetrack magnet LRS01. [...] 2008 - 4 p. - Published in : IEEE Trans. Appl. Supercond. 18 (2008) 167-170 In : 20th International Conference on Magnet Technology, Philadelphia, PA, USA, 27 - 31 Aug 2007, pp.167-170

Търси също:


text:
# THESELEC - Editorial

Practice

Contest

Author: Sibasish Ghosh

Tester: Pritish Nayak

Editorialist: Sibasish Ghosh

Simple

# PREREQUISITES:

Basic Maths, Sorting, Greedy

# PROBLEM:

You are given N integers A_1,A_2,...,A_N. You are also given Q queries. Each query i (1\leq i\leq Q) is of the type L_i R_i X_i: meaning, add the value X_i to all the integers in the array whose indices lie in the range [L_i,R_i].

Your task is to tell the maximum possible sum of all the elements of the array if you are allowed to choose at most K (\leq Q) queries among the given queries.

# QUICK EXPLANATION:

The answer is (sum of all the array elements) + (largest positive val_i's (maximum K val_i's)), where val_i = X_i*(R_i-L_i+1).

# EXPLANATION:

Notice that the answer cannot be less than the sum of all the elements of the array. It is because we can decide not to choose any queries. So the answer is always greater than or equal to \sum_{i=1}^{N} A_i.

Now, let val_i = X_i*(R_i-L_i+1) represent the value of the i^{th} query. val_i represents the amount query i will add to the array. Why so? Because X_i is added (R_i-L_i+1) number of times to the array. It is now obvious that we will only choose those queries that have a positive value, because if we choose a query having a negative value, it will reduce our sum.

So our answer now becomes (sum of all the array elements) + (largest positive val_i's (maximum K val_i's)).

Now try to implement the approach on your own. Refer to the solutions below for implementation details if you are facing difficulties.

# SOLUTIONS:

Setter's/Editorialist's Solution
#include<bits/stdc++.h>
#define mod 1000000007
#define F first
#define S second
#define pb push_back
#define all(v) v.begin(),v.end()
#define rall(v) v.rbegin(),v.rend()

using namespace std;
typedef long long int ll;

int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
// freopen("input5.txt","r",stdin);
// freopen("output5.txt","w",stdout);
ll t=1;
cin>>t;
while(t--)
{
ll n,q,k,ans=0,i;
cin>>n>>q>>k;
ll a[n+10];
for(i=1;i<=n;i++)
{
cin>>a[i];
ans+=a[i];
}
vector<ll> v;
while(q--)
{
ll l,r,x;
cin>>l>>r>>x;
ll val=x*(r-l+1);
v.pb(val);
}
sort(rall(v));
for(i=0;i<k;i++)
{
if(v[i] > 0)
ans+=v[i];
else break;
}
cout<<ans<<"\n";
}
return 0;
}

Tester's Solution
#include<bits/stdc++.h>
using namespace std;

int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);

int t;
cin>>t;

while(t--)
{
int n,q,k;
cin>>n>>q>>k;

long long a[n],tot=0;

for(int i=0;i<n;i++){
cin>>a[i];
tot+=a[i];
}

vector<long long> vals;
while(q--)
{
long long l,r,x;
cin>>l>>r>>x;

if((r-l+1)*x>0)
vals.push_back((r-l+1)*x);
}

sort(vals.begin(), vals.end());
reverse(vals.begin(), vals.end());

int cnt=0;
for(auto x:vals)
{
if(cnt>=k)break;
cnt++;
tot+=x;
}

cout<<tot<<"\n";
}
return 0;
}


text:
Article Contents
Article Contents

# On a nonlinear age-structured model of semelparous species

• We study a nonlinear age-structured model of a population such that individuals may give birth only at a given age. Properties of measure-valued periodic solutions of this system are investigated. We show that in some cases the age profile of the population tends to a Dirac measure, which means that the population asymptotically consists of individuals at the same age. This phenomenon is observed in nature in some insects populations.
Mathematics Subject Classification: Primary: 92D25; Secondary: 35F20, 45G10.

 Citation:

•  [1] M. G. Bulmer, Periodical insects, The American Naturalist, 111 (1977), 1099-1117.doi: 10.1086/283240. [2] J. A. Carrillo, R. M. Colombo, P. Gwiazda and A. Ulikowska, Structured populations, cell growth and measure valued balance laws, J. Differential Equations, 252 (2012), 3245-3277.doi: 10.1016/j.jde.2011.11.003. [3] P. Cull and A. Vogt, The periodic limit for the Leslie model, Math. Biosci., 21 (1974), 39-54.doi: 10.1016/0025-5564(74)90103-5. [4] J. M. Cushing, Three stage semelparous Leslie models, J. Math. Biol., 59 (2009), 75-104. [5] O. Diekmann, N. Davydova and S. van Gils, On a boom and bust year class cycle, J. Difference Equ. Appl., 11 (2005), 327-335.doi: 10.1080/10236190412331335409. [6] R. Dilão and A. Lakmeche, On the weak solutions of the McKendrick equation: Existence of demography cycles, Math. Model. Nat. Phenom., 1 (2006), 1-32.doi: 10.1051/mmnp:2006001. [7] J. Z. Farkas, Stability conditions for the non-linear McKendrick equations, Appl. Math. Comput., 156 (2004), 771-777.doi: 10.1016/j.amc.2003.06.019. [8] J. E. Franke and A.-A. Yakubu, Globally attracting attenuant versus resonant cycles in periodic compensatory Leslie models, Math. Biosci., 204 (2006), 1-20.doi: 10.1016/j.mbs.2006.08.016. [9] G. Gripenberg, S. O. Londen and O. Staffans, Volterra Integral and Functional Equations, Cambridge University Press, New York, 1990.doi: 10.1017/CBO9780511662805. [10] M. E. Gurtin and R. C. MacCamy, Non-linear age-dependent populations dynamics, Arch. Rational Mech. Anal., 54 (1974), 281-300. [11] P. Gwiazda and A. Marciniak-Czochra, Structured population equations in metric spaces, J. Hyperbolic Differ. Equ., 7 (2010), 733-773.doi: 10.1142/S021989161000227X. [12] P. E. Jabin, Large time concentration for solutions to kinetic equations with energy dissipation, Comm. Partial Differential Equations, 25 (2000), 541-557.doi: 10.1080/03605300008821523. [13] P. Michel, A singular asymptotic behavior of a transport equation, C. R. Math. Acad. Sci. Paris, 346 (2008), 155-159.doi: 10.1016/j.crma.2007.12.010. [14] B. Perthame, Transport Equations in Biology, Frontiers in Mathematics, Birkhäuser, Basel 2007. [15] S. I. Rubinow, A maturity time representation for cell populations, Biophy. J., 8 (1968), 1055-1073.doi: 10.1016/S0006-3495(68)86539-7. [16] R. Rudnicki and R. Wieczorek, Asymptotic analysis of a semelparous species model, Fund. Inform., 103 (2010), 219-233. [17] S. K. Tumuluri, Steady state analysis of a nonlinear renewal equation, Math. Comput. Modelling, 53 (2011), 1420-1435.doi: 10.1016/j.mcm.2010.02.050.


text:
# Determine whether the set have a subset relationship. Are the two sets disjoint or equivalent? Do the set intersect? R={right triangles}, O={obtuse triangles}

Right triangles and trigonometry
Determine whether the set have a subset relationship. Are the two sets disjoint or equivalent? Do the set intersect?
R={right triangles},
O={obtuse triangles}


text:
Chess Game of Life

A bishop and a rook, of opposing colors, start on opposite corners on the same side of a chessboard, oriented as in the following picture:

They then proceed to play a game of cat-and-mouse.

Rules

• The pieces make a move based on the rules of chess, meaning that the bishop travels along the diagonal while the rook travels along the parallels.
• When a square is moved across, it becomes uninhabitable and can no longer be moved across.
• The bishop always goes first.
• If a piece is either a) captured, or b) does not move on its turn, whether by choice or because there are no valid moves left, that piece loses.

Based on these rules and assuming optimal play, which piece is crowned the victor?

Bonus Question 1: The same rules apply, except now a tile only becomes uninhabitable when a piece finishes its move on that tile. Still assuming optimal play, which piece wins this variation?

Bonus Question 2: If the bishop starts in the top lefthand corner instead of the bottom lefthand corner, and the rook is now allowed to go first, which piece is crowned the victor? (Answer this question for both variations of uninhabitable squares.)

Note: The open-ended tag is included because there is ambiguity associated with the restriction of "optimal play". A perfect answer will not only detail the victory condition of the winning piece, but also detail why the plays made can be considered "optimal" for each piece.

• Which is the cat? – warspyking Aug 24 '15 at 17:59
• @warspyking er...both? I guess it's more accurately "cat-and-cat" or something, but that's not as catchy. – Bailey M Aug 24 '15 at 18:00
• "Doctor Venture and I have been engaged in a deadly game of cat and also-cat for years!" -- The Monarch – dennisdeems Aug 24 '15 at 19:08
• Why did you put the bishop in black if it always goes first? – Pierre Arlaud Aug 24 '15 at 21:26
• @PierreArlaud cuz I'm stupid lol – Bailey M Aug 25 '15 at 0:17

General thoughts

The rook has obviously an advantage here, because it can use black as well as white squares, while the bishop can only use black squares. Apart from that several squares are dead ends for the bishop like for example h8. If the rook can fence in the bishop in about a half of the board ("Tron-Principle™") it is almost always a guaranteed win.

Base Question

Complete winning strategy (in all cases the rook has more moves left than the number specified for the bishop):

1. ... Bg7 2. Rh5 (Bishop has 11 moves left)

1. ... Bf6 2. Rh7
2. ... Bg5 3. Rh8 (Bishop has 6 moves left)
2. ... Bd8 3. Rg7 (Bishop has 8 moves left)

1. ... Be5 2. Rh6
2. ... Bf4 3. Re6 (Bishop has 5 moves left)
2. ... Bg3 3. Re6 (Bishop has 4 moves left)
2. ... Bg7 3. Rg6 (Bishop has 11 moves left)
2. ... Bc7 3. Rh8 (Bishop has 4 moves left)
2. ... Bb8 3. Rh7 (Bishop has 5 moves left)

1. ... Bd4 2. Rh5
2. ... Be3 3. Rd5 (Bishop has 5 moves left)
2. ... Bf2 3. Rd5 (Bishop has 2 moves left)
2. ... Bg1 3. Rd5 (Bishop has 0 moves left)
2. ... Bf6 3. Rh7 (2nd case above)
2. ... Bg7 3. Rg5 (Bishop has 11 moves left)
2. ... Bb6 3. Rh7
3. ... Bd8 4. Rd7 (Bishop has 0 moves left)
3. ... Ba5 4. Rh8 (Bishop has 2 moves left)
2. ... Ba7 3. Rh8 (Bishop has 0 moves left)

1. ... Bc3 2. Rh5
2. ... Bd2 3. Ra5 (Bishop has 6 moves left)
2. ... Bf1 3. Ra5 (Bishop has 5 moves left)
2. ... Bd4 3. Ra5 (Bishop has 6 moves left)
2. ... Bf6 3. Rh7 (2nd case above)
2. ... Bg7 3. Rg5 (Bishop has 11 moves left)
2. ... Bb4 3. Rb5 (Bishop has 1 move left)

1. ... Bb2 2. Rh3
2. ... Bc1 3. Rb3 (Bishop has 4 moves left)
2. ... Bd4 3. Rh5 (4th case above)
2. ... Be5 3. Rh6 (3rd case above)
2. ... Bf6 3. Rh7 (2nd case above)
2. ... Bg7 3. Rh5 (1st case above)

Bonus Question 1

I don't have a complete winning strategy here. But it seems even more obvious that the rook has an advantage here as well. My general strategy would be:
1. Block the black centre squares.
2. Block the path of the bishop on the sides (if the black centre squares are blocked, ideally only 1 more black square is needed for that).
3. Create dead ends for the bishop if possible.

Bonus Question 2

Complete winning strategy:

1. Re1 (as suggested by JonTheMon)

1. ... Bb7/Bc6/Bd5 2. Re8 (Bishop has 13/9/9 moves left)

1. ... Bf3 2. Re3 (Bishop has 12 moves left)

1. ... Bg2 2. Re2 (Bishop has 11 moves left)

• So to be clear about what I'm looking at, the rook basically just stall out the bishop until it gets stuck in each of these scenarios, correct? – Bailey M Aug 24 '15 at 20:29
• Yes, to be more specific, divide the board in 2 areas using the uninhabitable squares so that both pieces can't affect each other anymore. In each case the rook has more room to breathe. – Sleafar Aug 24 '15 at 20:35
• Why would the bishop move to G7 on the first move? Surely the best strategy for the bishop is to leave as many moves available as possible by moving to B2. – Gordon K Aug 24 '15 at 21:10
• @GordonK That is only one of the 6 possible moves of the bishop in the first turn. The other possible moves are listed in the variants below. Of course I ignored Bh8. – Sleafar Aug 24 '15 at 21:13
• @Sleafar it isn't clear to me what you mean when you use the word "field". I haven't come across that term in my chess reading. – dennisdeems Sep 1 '15 at 13:31

Base Question

the Rook wins

Strategy:

In general a good winning strategy for the Rook is to cut the chess board horizontally above the Bishop, leaving him trapped in an area with few moves.

To be more specific: to win the Rook should try to reach H7 as soon as possible, if the Bishop is already in G7 the Rook should move to H5.

Proof:

If the Rook manages to reach row 7 before the Bishop, it automatically wins. Refer to the image below (I will mark in black the squares already moved across):

When the Rook is in H7 the most convenient position for the Bishop is to be in F6 and to have the next move. The possible movement for the Bishop are marked in yellow (the red marks indicate where he can't go to avoid being caught by the Rook on the Rook's next move), but both "yellow moves" leads to a situation where the Bishop is left with less moves than the rook.

1. going to the upper yellow mark leads to 7 moves left for the Bishop and 24 moves left for the Rook
2. going to the lower yellow mark leads to 6 moves left for the Bishop and 28 moves left for the Rook

To avoid the Rook going in H7, the Bishop should go in G7 on the first move, refer to the image below:

in this case the optimal move for the Rook is to go on H5, (he should not go in H7 to avoid being trapped with 0 moves left). Now the Bishop can only move in the yellow mark, this leads to 9 moves left for the Bishop and 20 moves left for the Rook.

Edit: In 2nd scenario the optimal move for the Rook is in H2, it leaves more moves than H5 (23 moves instead of 20). Thanks @Jason.

• In the 2nd scenario, why should the rook move to H5? H2 would be just as effective, while leaving more inhabitable squares, hence more optimal. If the bishop has already cut off half the board in the first move, so long as the rook stays on H the only valid move for the bishop is F8, and never the twain shall meet. The rook can putter around at 1 square a move the entire game. – Jason Aug 31 '15 at 20:12
• @Jason you're right! I'll add it as a comment – Simone Sep 1 '15 at 12:29

I think the Rook has the advantage in the first and third cases due to 2 reasons: the bishop is limited to a single color and the rook overall has more moves.

If the bishop starts with G7, then the rook could go H5, and then the bishop has to go F8 (H6 is deadly, as is H8). The bishop then has 10 moves left, while the rook has 23.

In general, for the first case, the rook wants to split the board so that bishop has minimal spaces, then just outlast it. Try to stay above the bishop, or if the bishop has a long diagonal, go to it to split the board.

For the third case, the same strategy as first case could work. If the rook goes E1, then the bishop moving 1-3 spaces means the rook can go E8 (E7 if dangerous), cutting the board in half. Anything other than that, E3, again cutting the board in half.

I don't really have a good idea for the second case, except that I would favor the Rook as it has more moves available to it. In fact, the Rook could use the "split the board" tactic, but only need to hit 4 squares.

• Yeah it looks like the Bishop can never win because it can't use the split the board tactic for any advantage, and both pieces limit its options twice as much as the rook. Any strategy, no matter how aggressive, never works in the favor of the Bishop. – Kingrames Aug 25 '15 at 13:19


text:
## Category Archives: algebra

### Automorphism groups of groups

After last week’s GAGA tutorials, I wrote some notes related to sheet 5.

A quadratic form is essentially the same thing as a symmetric bilinear form, at least over a field of characteristic different from 2. A while ago, I wrote a brief note on quadratic forms dealing with diagonalization and geometry. I hope it’s useful for HT2013, sheet 4, problem 8, in particular.

### Orthogonal bases

I was a bit confused during tutorials today about orthogonal bases, so I wrote up a short note on how to find them. This method is illustrated with problem 5 on sheet 4 for Linear Algebra II.

### Group theory tutorial, TT week 1 (=HT week 9)

I got quite confused with one of the problems in tutorial today. I had a glimmer of the right answer, but then misled myself into saying something quite silly. Anyways, here is a short note on this.

### Symmetries

I have written some notes on symmetries following the Group Theory tutorials this week.

### Collections, Hilary Term, 2012

I’ve marked the scripts for the algebra portion of the Merton collections for Mods Pure Maths, Part A AC1 and Part A AC2.
I am including here brief remarks on the questions. Later, if I have the energy, I will also upload comments on the Banach Spaces paper for Part B students.

### POSTECH notes, algebra.

Here are some notes on

Automorphisms of algebraic number fields

to accompany the lecture on 5 December, 2011.

### Norms of elements and principality

Dear Professor Kim,

Sorry to bombard you with these questions. I have come across a problem on your note ‘some principle ideals’. When we factorize $m(x)=x^3 + x - 1$ modulo 3 we get $(x+1)(x^2-x-1)$ we then associate these factors with the ideals $P_3$ and $P_9$ respectively. When we compute the norm of $x^2-x-1$ we do so by calculating the determinant of the matrix $L_{a^2-a-1}$ and find that the norm is in fact 9, so $P_9$ is a principle ideal. However, we could just have easily used $x^2+2x-1$ or $x^2+2x+2$ and in each case I get a different answer for the determinant. Have I made an error or is there a canonical form of sort that I should be aware of?

First of all, I presume your $x^2-x-1$ etc. are $a^2-a-1$ etc. All the elements you mention do indeed belong to the ideal and can be used as generators *when used together with the element 3*. Indeed they are all all evaluations at $a$ of polynomials that are congruent to $x^2-x-1$ mod $3$. However, this does not mean they are generators on their own. Of course different elements in an ideal $I$ will have different norms in general. However, an element $b\in I$ is a generator *by itself* (making $I$ into a principal ideal), exactly when $|N(b)|=N(I)$. Of course such a $b$ need not exist. I haven’t calculated the norms of the elements you mention, but if their norms come out larger than 9, it merely says they are not generators (again, by themselves), while $a^2-a-1$ is.
A thorny point that comes out of this discussion is that if you had initially presented the ideal as $(3, a^2+2a-1)$, for example, then it might have been harder to see that it is principal.