File: Tropical.m2

package info (click to toggle)
macaulay2 1.21%2Bds-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 133,096 kB
  • sloc: cpp: 110,377; ansic: 16,306; javascript: 4,193; makefile: 3,821; sh: 3,580; lisp: 764; yacc: 590; xml: 177; python: 140; perl: 114; lex: 65; awk: 3
file content (2013 lines) | stat: -rw-r--r-- 59,562 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
newPackage(
    	"Tropical",
	Version => "1.0",
	Date => "July 2019",
	Authors => {
	    	{Name => "Carlos Amendola", Email => "carlos.amendola@tum.de", HomePage=>""},
	    	{Name => "Kathlen Kohn", Email => "kathlen.korn@gmail.com", HomePage=>""},
  		{Name => "Sara Lamboglia", Email => "lamboglia@math.uni-frankfurt.de", HomePage=>""},
	    	{Name => "Diane Maclagan", Email => "D.Maclagan@warwick.ac.uk", HomePage=>"http://homepages.warwick.ac.uk/staff/D.Maclagan/"},
   		{Name => "Ben Smith", Email => "benjamin.smith-3@manchester.ac.uk", HomePage=>""},
   		{Name => "Jeff Sommars", Email => "sommars1@uic.edu", HomePage=>"http://homepages.math.uic.edu/~sommars"},
    		{Name => "Paolo Tripoli", Email => "paolo.tripoli@nottingham.ac.uk", HomePage=>"https://sites.google.com/view/paolotripoli/home"},
   		{Name => "Magdalena Zajaczkowska", Email => "Magdalena.A.Zajaczkowska@gmail.com", HomePage=>""}
		},
	Headline => "A package for doing computations in tropical geometry",
	Configuration => {
		"path" => "",
		"fig2devpath" => "",
--		"keepfiles" => true,
"keepfiles" => false,
		"cachePolyhedralOutput" => true,
		"tropicalMax" => false,
		"polymakeCommand" =>""
	},
    	OptionalComponentsPresent => true,
        PackageExports => {"gfanInterface","EliminationMatrices","Matroids","Polyhedra"},
	AuxiliaryFiles => true,
--	AuxiliaryFiles => false,
	CacheExampleOutput => true
)


export{
  "TropicalCycle",
  "tropicalCycle",
  "isBalanced",
  "tropicalPrevariety",
  "ComputeMultiplicities",
  "Prime",
  "stableIntersection",
  "tropicalVariety",
  "isTropicalBasis",
  "multiplicities",
  "IsHomogeneous",
  "Symmetry",
  "visualizeHypersurface",
  "Valuation",
  "BergmanFan"
  }


polymakeCommand = (options Tropical)#Configuration#"polymakeCommand"
polymakeOK = polymakeCommand != ""

--Do we want to keep this?
verboseLog = if debugLevel > 0 then printerr else identity
if polymakeOK then verboseLog "polymake is installed" else verboseLog "polymake not present";


------------------------------------------------------------------------------
-- CODE
------------------------------------------------------------------------------


--Polymake visualization for tropical hypersurfaces

--inputs: p prime, x rational number
--outputs: p-adic valuation of x
pAdicVal = (p,x) -> (
    num := numerator(x);
    denom := denominator(x);
    temp := p;
    if num%p===0 then (while (num%temp===0) do (temp=temp*p); return round(log(p,temp)-1));
    if denom%p===0 then (while (denom%temp===0) do (temp=temp*p); return -round(log(p,temp)-1));
    return 0;
)

--inputs: p prime, polyn polynomial with p-adic coefficients
--outputs: polynomial whose coefficients are valuations of coefficients of polyn
pAdicCoeffs := (p,polyn) -> (
    (M,C):=coefficients polyn;
    valuations := transpose matrix{apply(flatten entries C,i->pAdicVal(p,sub(i,QQ)))};
    return (M,valuations);
)

--inputs: parameter specifies the coefficient ring for polyn, polyn polynomial over coefficient ring
--outputss: polynomial whose coefficients are valuations of coefficients of polyn

polynomialCoeffs := (parameter,polyn) -> (
    (M,C):=coefficients(Variables=>delete(parameter,gens class polyn),polyn);
    return (M,transpose matrix{apply(flatten entries C, i->min apply(exponents(polyn),sum))});
)

--inputs: var power of a monomial
--outputs: term with power as coefficient
expToCoeff = (var) -> (
    temp := separate("^",toString(var));
    if (length temp === 1) then return var else return concatenate(temp_1,temp_0);
)

--inputs: polyn macaulay 2 polynomial
--outputs: min of linear polynomials for polymake
toTropPoly = method(TypicalValue=>String)

toTropPoly (RingElement) := (polyn) ->(
    termList := apply(apply(terms polyn,toString),term->separate("*",term));
    tropTerms := apply(apply(apply(termList, term->apply(term,expToCoeff)),term->between("+",term)),concatenate);
    return "min("|concatenate(between(",",tropTerms))|")";
)

--inputs: (termList,coeffs)=coefficients polynomial
--outputs: min of linear polynomials for polymake
toTropPoly (Matrix,Matrix) := (termList,coeffs) ->(
    noCoeffs := sum flatten entries termList;
    termString := apply(apply(terms noCoeffs,toString),term->separate("*",term));
    tropTerms := apply(apply(apply(termString, term->apply(term,expToCoeff)),term->between("+",term)),concatenate);
    withCoeffs := for i when i<numColumns termList list toString((flatten entries coeffs)_i)|"+"|tropTerms_i;
    return "min("|concatenate(between(",",withCoeffs))|")";
)

--outputs: return Min or Max depending on the state of tropcailMax
minmax = () -> (if (Tropical#Options#Configuration#"tropicalMax") then return "Max" else return "Min";)

visualizeHypersurface = method(Options=>{
	Valuation=>null
	})

visualizeHypersurface (RingElement) := o-> (polyn)->(
    polynomial := toTropPoly(polyn);
    if (instance(o.Valuation,Number)) then polynomial = toTropPoly(pAdicCoeffs(o.Valuation,polyn));
    if (instance(o.Valuation,RingElement)) then polynomial = toTropPoly(polynomialCoeffs(o.Valuation,polyn));
    if (instance(o.Valuation,String) and o.Valuation == "constant") then polynomial = toTropPoly(sum flatten entries (coefficients polyn)_0);
    print polynomial;
    filename := temporaryFileName();
    filename << "use application 'tropical';" << endl << "visualize_in_surface(new Hypersurface<"|minmax()|">(POLYNOMIAL=>toTropicalPolynomial(\""|polynomial|"\")));" << close;
    runstring := polymakeCommand | " " |filename | " > "|filename|".out  2> "|filename|".err";
    run runstring;
    removeFile (filename|".err");
    removeFile (filename|".out");
    removeFile (filename);
)


--Example hypersurface
--visualizeHypersurface("min(12+3*x0,-131+2*x0+x1,-67+2*x0+x2,-9+2*x0+x3,-131+x0+2*x1,-129+x0+x1+x2,-131+x0+x1+x3,-116+x0+2*x2,-76+x0+x2+x3,-24+x0+2*x3,-95+3*x1,-108+2*x1+x2,-92+2*x1+x3,-115+x1+2*x2,-117+x1+x2+x3,-83+x1+2*x3,-119+3*x2,-119+2*x2+x3,-82+x2+2*x3,-36+3*x3)")
--opens in browser



--Setting up the data type TropicalCycle

TropicalCycle = new Type of MutableHashTable
TropicalCycle.synonym = "tropical cycle"
TropicalCycle.GlobalAssignHook = globalAssignFunction
TropicalCycle.GlobalReleaseHook = globalReleaseFunction


--basic operations on a tropical cycle

tropicalCycle = method(TypicalValue => TropicalCycle)

tropicalCycle (Fan, List) := (F,mult)->(
    if #maxCones(F) != #mult then error("The multiplicity list has the wrong length");
    T := new TropicalCycle;
    T#"Multiplicities" = mult;
    T#"Fan" = F;
    return T
)


--functions to switch to min-convention

minmaxSwitch = method ()

minmaxSwitch (Fan) := F ->
      fanFromGfan({- rays F, linSpace F, maxCones F ,dim F,Polyhedra$isPure F,isSimplicial F,Polyhedra$fVector F});

minmaxSwitch (TropicalCycle) := T ->(
    tropicalCycle( minmaxSwitch fan T, multiplicitiesReorder({rays (minmaxSwitch fan T),
	    maxCones (minmaxSwitch fan T),-rays  T,maxCones  T,multiplicities T})))



--Decide if a one-dimensional tropical cycle is balanced.
--input: TropicalCycle T, which we assume is 1-dimensional
isBalancedCurves = T ->(
    -- find first integer lattice points on each vector (get list of points)
    -- check whether sum * multiplicity is 0
	-- assuming already have lattice points V = {...}
	m := multiplicities T;
	r := entries transpose rays T;
	(first unique sum(#r, i->(m_i * r_i))) == 0
)

--computes the star of the codimension-one polyhedron P in the tropical cycle Sigma
star (TropicalCycle, Polyhedron) := (Sigma, P) -> (
    	--Create the linear space parallel to P
	--and quotient by it
	--Version for cones
	d:=dim P;
	V:= gens  kernel transpose (rays(P)|linealitySpace(P));
	B:=inverse(rays(P) | linealitySpace(P) | V);
    	--version for polyhedral complex
--    	adjacentCells=select(maxPolyhedra(fan Sigma),sigma->(contains(sigma,P)));
    	--version for fans, as currently implemented
	maxConesSigma:=facesAsCones(0, fan Sigma);
	adjacentCellsPos:=positions(maxConesSigma,sigma->(contains(sigma,P)));
	adjacentCells:=apply(adjacentCellsPos,i->(maxConesSigma_i));
	raysStar:=apply(adjacentCells,sigma->(
    		--Create vector pointing from P into sigma
		--version for Polyhedral complexes
--    		w:=interiorPoint(sigma)-interiorPoint(P);
    	        --version for fans
		w:=sum(rank source rays sigma, i->(rays sigma)_{i}) -
		     sum(rank source rays P, i->(rays P)_{i});
		--Project it onto ker(P)
		w=entries(B*w);
		w=posHull matrix apply(#w-d,i->(w_(i+d)))
	));
    	multsSigma:=multiplicities Sigma;
	multStar:=apply(adjacentCellsPos,i->(multsSigma_i));
	return(tropicalCycle(fan raysStar,multStar));
);


isBalanced = method(TypicalValue => Boolean)

isBalanced (TropicalCycle):= T->(
    if polymakeOK then (
--in polymake, the lineality span (1,...,1) is default.  we embed the
--fans in a higher dimensional fan in case our lineality span does not
--contain (1,...,1)
	C := tropicalCycle(embedFan fan T, multiplicities T);
-- parse object into a polymake script, run polymake and get result back from the same file (which got overwritten by polymake)
	filename := temporaryFileName();
       filename << "use application 'tropical';" << endl << "my $c = "|convertToPolymake(C) <<
	endl << "print is_balanced($c);" << endl;
	filename<<close;
--	filename << "use strict;" << endl << "my $filename = '" << filename << "';" << endl << "open(my $fh, '>', $filename);" << endl;
--	filename << "print $fh is_balanced($c);" << endl << "close $fh;" << endl << close;
	runstring := polymakeCommand | " "|filename | " > "|filename|".out  2> "|filename|".err";
	run runstring;
	removeFile (filename|".err");
	result := get (filename|".out");
	removeFile (filename|".out");
	removeFile (filename);
	if (substring(-4,result)=="true") then return true
	else if  (substring(-5,result)=="false")  then return false
	else if (substring(-1,result)=="1") then return true
	else if (substring(0,result)=="") then return false
	else return "Polymake throws an error";
    )
    else (
	if dim T == 1 then return (isBalancedCurves T) else (
	--loop over all co-dimension 1 faces F of T (use faces(ZZ, PolyhedralObject))
	--for each F, compute star F / lineality space F (can use linSpace, write star of polyhedral complex)
	--use isBalancedCurves to check if balanced for all F
	d:=dim T;
	balanced:=true;
	F:= Polyhedra$faces(1, fan T);
	i:=0;
	while balanced and i<#F do (
--change next line when PolyhedralComplex change is made
	    balanced = isBalancedCurves(star(T,polyhedronFromFace(fan T,F_i)));
	    i=i+1;
	);
    	return balanced;
       );
    );
);

--F is a fan and f is a list describing a face of F
polyhedronFromFace = (F, f) -> (
	L := linealitySpace F;
	R := rays F;
	ambientDim := numgens target rays F;
	origin := transpose matrix{apply(ambientDim, i -> 0)};
	convexHull(origin, R_f, L)
);


--Computing a tropical prevariety

tropicalPrevariety = method(TypicalValue => Fan,  Options => {
--in the future, more strategies not dependent on "gfan" will be available
	Strategy=> "gfan"
	})

tropicalPrevariety (List) := o -> L -> (
	gfanopt:=(new OptionTable) ++ {"tropicalbasistest" => false,"tplane" => false,"symmetryPrinting" => false,
	"symmetryExploit" => false,"restrict" => false,"stable" => false};

--using strategy gfan
    if (o.Strategy=="gfan") then (
    	F:= gfanTropicalIntersection(L, gfanopt);
--gives only the fan and not the fan plus multiplicities which are wrongly computed in gfan
	if (Tropical#Options#Configuration#"tropicalMax" == true) then return F_0 else return minmaxSwitch (F_0))
    else error "options not valid"
)

tropicalPrevariety (List, List) := o -> (L, symmetryList) -> (
	gfanopt:=(new OptionTable) ++ {"tropicalbasistest" => false,"tplane" => false,"symmetryPrinting" => false,
	"symmetryExploit" => true,"restrict" => false,"stable" => false};
--using strategy gfan
    if (o.Strategy=="gfan") then (
    	F:= gfanTropicalIntersection(L, symmetryList, gfanopt);
--gives only the fan and not the fan plus multiplicities which are wrongly computed in gfan
	if (Tropical#Options#Configuration#"tropicalMax" == true) then return F_0 else return minmaxSwitch (F_0))
    else error "options not valid"
)

--Computing a tropical variety
--The input is a matrix R, consisting of the rays of the variety,
--a list of lists M, being the list of maximal cones, and a matrix L giving generators
--for the lineality space.  R has the first lattice point on rays as columns, while L has generators
--for the lineality space as columns.
--output:list of matrices whose rows span the span of each cone.
-- note that ConesOfVariety is a local variable also in findMultiplicities
computeCones=(R,M,L)->(
      ConesOfVariety:={};
      i:=0;
      ConeOfVariety:={};
      if M!={{}} then(
     --this i is going through the maximal cones
      while(i<#M) do(
	  ConeOfVariety={};
	  j:=0;
     --this j is going through the rays inside the maximal cone you are in
	  while(j<#M_i) do(
	      --creates a list of rays
	      ConeOfVariety=append(ConeOfVariety, R_(M_i_j));
	  j=j+1);
      -- creates a matrix whose rows are the rays of the cone
     ConeOfVariety= L|matrix ConeOfVariety;
     -- each cone has to contain also the lineality space since we are not quotienting by it
     -- ConeOfVariety = matrix ConeOfVariety ;
      --add the cone to the list of cones
      	  ConesOfVariety=append(ConesOfVariety,ConeOfVariety);
	  i=i+1;
	);
    )
    else
    (ConesOfVariety={L};
	) ;
    ConesOfVariety
    )


--Compute the multiplicity of the cone spanned by the columns of the matrix M in trop(V(I))
findMultiplicity=(M,I)->(
    --compute vector w in relative interior in order to get the initial ideal in_w(I) with w in the maximal cone M
    w:=flatten entries(sum(numColumns M, j->M_{j}));
    --weight the ring according to this w , we are using leadTerm and max
    --convention since the input fan has not been changed to min
    --convention yet
    S:=ring I;
    R:=newRing(S, MonomialOrder=>{Weights=>w},Global=>false);
    J:=sub(I,R);
    K:=ideal(leadTerm(1,J));
    --you saturate since you don't want the components outside the torus
    initialIdeal:= saturate(sub(K,S), product gens S);
    --this is the basis of the lattice associated to the toric ideal we are going to compute
--    Basis:= (maxCol( generators kernel transpose M))_0;
      toricIdeal:= ideal apply(entries transpose gens kernel transpose M, u->(
	      mon1:=1_R;
		  mon2:=1_R;
		  scan(numgens ring I,i->(if u_i>0 then mon1=mon1*R_i^(u_i) else mon2=mon2*R_i^(-u_i)));
		  mon1-mon2
         ));
    --this is where we used to use Binomials package
--    toricIdeal:=saturate(latticeBasisIdeal(ring InitialIdeal,Basis),ideal product gens ring I);
    toricIdeal = saturate(toricIdeal,product gens R);
    m:=(degree(initialIdeal)/degree (toricIdeal));
    --return multiplicity m as integer, since it lives currently in QQ
    --if m is an integer (as it should be), then the following command parses it to ZZ
    --otherwise, an errow will be returned "rational number is not an integer"
    lift(m,ZZ)
    )

--input Matrix whose columns are the generators of the cone and the ideal of the variety
--output a list of one number that is the multiplicity
--maths behind it look at exercise 34 chapter 3 Tropical book and [Stu96]
--(Grobner basis and Convex Polytopes )




--input: the ideal of the variety and the fan computed by gfanbruteforce
--output: list with the multiplicities to add to the tropicalCycle
findMultiplicities=(I,T)->(
	ConesOfVariety:=computeCones( rays T,maxCones T, linSpace T);
      --creates a list with matrices that correspond to the maximal cones
	M:= apply(ConesOfVariety, linearSpan->(
       --for each cone computes the multiplicity and adds this to a list of multiplicities
	    findMultiplicity(linearSpan,I))
	    );
	M
)


tropicalVariety = method(TypicalValue => TropicalCycle,  Options => {
	ComputeMultiplicities => true,
	Prime => true,
	IsHomogeneous=>false,
	Symmetry => {}
	})



--Main function to call for tropicalVariety.  Makes no assumption on ideal
tropicalVariety (Ideal) := o -> (I) ->(
    local F;
    local T;
    newSymmetry:= o.Symmetry; --In case of homogenization we adjust the user given symmetries, recorded in the var newSymmetry.

    --If Symmetry present, check user has input permutations with the right length. If newSymmetry is {}, any always returns false.
    M := #(gens ring I);
    if any(newSymmetry, listPermutation ->  #listPermutation != M) then
	error ("Length of permutations should be " | M);

    if o.IsHomogeneous==false then
    (

	--First homogenize, append variable AA to the beginning
    	R := ring I;
    	AA := symbol AA;

	--Extend to a new coefficient ring. The added variable is at the beginning.
	S := first flattenRing(R[AA, Join =>false]);

	J:=substitute(I,S);
	J=homogenize(J,S_0);
	J=saturate(J,S_0);
	--we transform I in J so that the procedure continues as in the homogeneous case
	I=J;

	--If Symmetry present, adjust the symmetry vectors to the right length and shift the values up by one. If not present, this operates on an empty list.
    	--Increase the values of these lists by 1.
	newSymmetry = for listPermutation in newSymmetry list --make a list with the following values
	             apply(listPermutation, j -> j + 1);
        --Prepend a 0.
        newSymmetry = apply(newSymmetry, listPermutation -> prepend(0, listPermutation));
    );
    if (o.Prime== true) then (
	    cone := gfanTropicalStartingCone I;
	    --check if resulting fan would be empty
	    if instance(cone, String) then return cone;
		if(newSymmetry == {}) then
			F= gfanTropicalTraverse cone
		else
			F= gfanTropicalTraverse (cone, "symmetry" => newSymmetry);

	    --check if resulting fan would be empty
	    if (instance(F,String)) then return F;
	    T=tropicalCycle(F_0,F_1))
    else
	--If ideal not prime, use gfanTropicalBruteForce to ensure disconnected parts are not missed at expense of multiplicities
	    (if o.ComputeMultiplicities==false
	     then (
		   F= gfanTropicalBruteForce gfanBuchberger I;
		   --check if resulting fan is empty
		   if (instance(F,String)) then return F;
		   mult := {};
		   i:=0;
		   while(i<#maxCones (F))do(
		       mult=append(mult,{});
		       i=i+1);
		   T=tropicalCycle(F,mult)
		   --note that the output of gfanTropicalBruteForce is a fan and an empty list of multiplicities this is why we have to add the right number of empty multiplicities
    	    	   )
	     else (
		 F= gfanTropicalBruteForce gfanBuchberger I;
		 --check if resulting fan is empty
		 if (instance(F,String)) then return F;
			--call the function tropicalCycle to create a new tropical variety with multiplicities
		 T=tropicalCycle(F,findMultiplicities(I,F))
	 );  );
--Need to fix the paragraph below - why arewe doing all these checks when the
--tropical variety is computed?
    if   o.IsHomogeneous==false  then
	(
	    newRays:=dehomogenise(rays T);
     	    newLinSpace:=gens gb dehomogenise(linealitySpace T);
	    TProperties := {newRays,
			newLinSpace,
			maxCones T,
			dim(T)-1,
			Polyhedra$isPure fan T,
			isSimplicial T,
			drop(fVector T,1)};
	UFan:=fanFromGfan(TProperties);
	U:= tropicalCycle(UFan,multiplicitiesReorder({rays UFan,maxCones UFan,newRays,maxCones T,multiplicities(T)}));
	-- we always want the output to be called T so we change U to T
	T=U;
	);
	if (Tropical#Options#Configuration#"tropicalMax" == true) then return  T  else return minmaxSwitch T
)



--auxiliary function to quotient out the lineality space (1,1,...1) introduced by the homogenisation
--input= matrix whose columns are either the rays or the generators of the lineality space of a fan
--output= matrix whose columns are either the rays or the generators of the lineality space of the fan quotiented by (1,...,1)
dehomogenise=(M) -> (
	vectorList:= entries transpose M;
	dehomog:= new List;
	for L in vectorList do (
		newL := apply(#L-1,i->(L#(i+1)-L#0));
		gcdL := gcd(newL);
		if gcdL==0 then continue;
		newL = newL/gcdL;
		newL = apply(newL,i->(lift(i,ZZ)));
		dehomog = append(dehomog,newL);
	);
	if dehomog=={} then map(ZZ^(#entries(M)-1),ZZ^0,0)
	else transpose matrix dehomog
)

--Check if a list of polynomials is a tropical basis for the ideal they generate

--Current Strategy is using 'gfan'
isTropicalBasis = method(TypicalValue => Boolean,  Options => {
	Strategy=> "gfan"
	})

isTropicalBasis (List) := o -> L -> (
	if (o.Strategy=="gfan") then (
	    gfanopt:=(new OptionTable) ++ {"tropicalbasistest" => true,"tplane" => false,"symmetryPrinting" => false,"symmetryExploit" => false,"restrict" => false,"stable" => false};

if not all(L, a-> isHomogeneous a) then error "Not implemented for non homogeneous polynomials yet";
 	    return gfanTropicalIntersection(L, gfanopt)
	)
	)


stableIntersection = method(TypicalValue =>
TropicalCycle, Options => {Strategy=> if polymakeOK then "atint" else "gfan"})

stableIntersection (TropicalCycle, TropicalCycle) := o -> (T1,T2) -> (
--TODOS:
--4) gfan strategy outputs only a fan, not a tropical cycle
--5) test cases
--6) make tropical an immutable hash table
    if (o.Strategy=="atint") then (
	--in polymake, the lineality span (1,...,1) is default.
	--we embed the fans in a higher dimensional fan in case our lineality span does not contain (1,...,1)
	C1 := tropicalCycle(embedFan fan T1, multiplicities T1);
	C2 := tropicalCycle(embedFan fan T2, multiplicities T2);

	filename := temporaryFileName();
	--ugly declaration of helping strings
	openingStr := "\"_type SymmetricFan\\n\\nAMBIENT_DIM\\n\";";
	dimStr := "\"\\n\\nDIM\\n\";";
	linDimStr := "\"\\n\\nLINEALITY_DIM\\n\";";
	raysStr := "\"\\n\\nRAYS\\n\";";
	nRaysStr := "\"\\nN_RAYS\\n\";";
	linSpaceStr := "\"\\n\\nLINEALITY_SPACE\\n\";";
	orthLinStr := "\"\\n\\nORTH_LINEALITY_SPACE\\n\";";
	fStr := "\"\\n\\nF_VECTOR\\n\";";
	simpStr := "\"\\n\\nSIMPLICIAL\\n\";";
	pureStr := "\"\\n\\nPURE\\n\";";
	coneStr := "\"\\n\\nCONES\\n\";";
	maxConeStr := "\"MAXIMAL_CONES\\n\";";
	weightStr := "\"\\nMULTIPLICITIES\\n\";";
	filename << "use application 'tropical';" << "my $c = "|convertToPolymake(C1) << "my $d = "|convertToPolymake(C2) << "my $i = intersect($c,$d);" << "use strict;" << "my $filename = '" << filename << "';" << "open(my $fh, '>', $filename);" << "print $fh " << openingStr << "print $fh $i->AMBIENT_DIM;" << "print $fh " << dimStr << "print $fh $i->DIM;" << "print $fh " << linDimStr << "print $fh $i->LINEALITY_DIM;" << "print $fh " << raysStr << "print $fh $i->RAYS;" << "print $fh " << nRaysStr << "print $fh $i->N_RAYS;" << "print $fh " << linSpaceStr << "print $fh $i->LINEALITY_SPACE;" << "print $fh " << orthLinStr << "print $fh $i->ORTH_LINEALITY_SPACE;" << "print $fh " << fStr << "print $fh $i->F_VECTOR;" << "print $fh " << simpStr << "print $fh $i->SIMPLICIAL;" << "print $fh " << pureStr << "print $fh $i->PURE;" << "print $fh " << coneStr << "my $cones = $i->CONES;" << "$cones =~ s/['\\>','\\<']//g;" << "print $fh $cones;" << "print $fh " << maxConeStr << "print $fh $i->MAXIMAL_CONES;" << "print $fh " << weightStr << "print $fh $i->WEIGHTS;" << "close $fh;" << close;

	runstring := polymakeCommand | " "|filename | " > "|filename|".out  2> "|filename|".err";
	run runstring;
	result := get filename;
	removeFile (filename|".out");
	removeFile (filename|".err");
	removeFile (filename);
	parsedResult := gfanParsePolyhedralFan(result);
	if instance(parsedResult, String) then return parsedResult;
	(polyfan, mult) := parsedResult;
--now we still need to transform things back to our format:
--1) adjust the rays
	R := rays polyfan;
	row := (entries R)#0;
	ind := -1;
	scan(#row, i -> if ((row#i)==1) then ind = i);
	R = submatrix'(R, {0} , {ind});
--2)adjust the maximal cones
	C := maxCones polyfan;
	C = apply(C, c -> delete(ind, c));
	C = apply(C, c -> apply(c, n -> if (n > ind) then (n-1) else (n) ));
--3)adjust lineality space
	L := linSpace polyfan;
	L = submatrix'(L, {0} , );
--	L = L|(transpose matrix {apply(numgens target L , i -> 1)});
--4)inverse of our function embedFan
	F := unembedFan fan(R,L,C);
	return tropicalCycle (F,mult);
    )
    else if (o.Strategy=="gfan") then (
	F1 := fan(T1);
	m1 := multiplicities(T1);
	F2 := fan(T2);
	m2 := multiplicities(T2);
	return gfanStableIntersection(F1,m1,F2,m2);
    )
    else (
	return "Strategy unknown: Choose 'atint' or 'gfan'";
    );
)

embedFan = F -> (
--embeds a fan into a fan of one dimension higher
--and DOES NOT add the lineality space (1,...,1)
	--1) adjust rays
	rs := rays F;
	numberOfEntries := (numgens target rs)+1;
	rs = entries transpose rs;
	if (#rs != 0) then (
--		rs = apply(rs, s -> s|{-sum s});
		rs = apply(rs, s -> s|{0});
--		numberOfEntries = #first(rs);
		rs = transpose matrix rs;
	) else (
		rs = matrix apply(numberOfEntries, i -> {})
	);
	--2) adjust lineality space
 	ls := entries transpose linSpace F;
	if (#ls != 0) then(
--		ls = apply(ls, s -> s|{-sum s});
		ls = apply(ls, s -> s|{0});
--		ad := ambDim F;
--		ls = ls|{apply(ad+1, i -> 1)};
		ls = transpose matrix ls;
	) else (
		ls = matrix apply(numberOfEntries, i -> {});
	);
	return fan(rs,ls,maxCones F);
)

unembedFan = F -> (
--inverse function to embedFan
	--1) adjust rays
	rs := entries transpose rays F;
	if (#rs != 0) then (
--		rs = apply(rs, s -> apply(s, i -> i-sum(s)/(#s)));
		rs = apply(rs, s -> apply(s, i -> i-last(s)));
		rs = apply(rs, s -> drop(s,-1));
--		rs = apply(rs, s -> apply(s, i -> i*(#s+1)));
		rs = transpose matrix rs;
	) else (
		rs = matrix apply(numgens(target rays F)-1, i -> {});
	);
	--2) adjust lineality space
	ls := entries transpose linSpace F;
	if (#ls != 0) then (
--		ls = apply(ls, s -> apply(s, i -> i-sum(s)/(#s)));
		ls = apply(ls, s -> apply(s, i -> i-last(s)));
		ls = apply(ls, s -> drop(s,-1));
--		ls = apply(ls, s -> apply(s, i -> i*(#s+1)));
		ls = transpose matrix ls;
	) else (
		ls = matrix apply(numgens(target rays F)-1, i -> {});
	);
	return fan(rs,ls,maxCones F);
)

convertToPolymake = (T) ->(
-- converts a tropical cycle into a string, which is a constructor of a tropical cycle in polymake
--
	F := fan(T);
--check if given cycle is empty
	if (dim(F) < 0) then (return "new Cycle<Min>(PROJECTIVE_VERTICES=>[],MAXIMAL_POLYTOPES=>[],WEIGHTS=>[]);";) else (
--if not empty, check if min- or max-convention is used
	str := "new Cycle<";
	if Tropical#Options#Configuration#"tropicalMax" then str=str|"Max" else str=str|"Min";
	rs := entries transpose rays T;
	numberOfRays := #rs;
	ambientDim := ambDim F;
--convert to polymake convention of rays: 1) add origin of the form (1,0,...,0)
	str = str|">(PROJECTIVE_VERTICES=>[[1";
	local ray;
	scan (ambientDim,i -> str = str|",0");
	str = str|"]";
--2) add every ray with a leading 0
	scan (numberOfRays,i -> (
		ray = rs#i;
		str = str|",[0";
		scan (ambientDim,j -> str = str|","|ray#j);
		str = str|"]";
	));
--every cone must now also be spanned by the origin
	str = str|"],MAXIMAL_POLYTOPES=>[";
	maxCs := maxCones(F);
	numberOfMaxCones := #maxCs;
	local cone;
	scan (numberOfMaxCones,i -> (
		cone = maxCs#i;
		str = str|"[0";
		scan (#cone,j -> str = str|","|(cone#j+1));
		str = str|"],";
	));
--delete last comma
	str = substring(0,#str-1,str);
	ls := entries transpose linSpace F;
	if (#ls != 0) then (
		str = str|"],LINEALITY_SPACE=>[";
--add lineality space
		scan (#ls, i -> (
			ray = ls#i;
			str = str|"[0";
			scan(#ray, j -> str = str|","|(ray#j));
			str = str|"],";
		));
--delete last comma
		str = substring(0,#str-1,str);
	);
	str = str|"],WEIGHTS=>[";
--the multiplicities stay unchanged
	mult := multiplicities(T);
	scan (numberOfMaxCones,i -> str = str|mult#i|",");
	str = substring(0,#str-1,str);
	str = str | "]);";
	return str;
	)
)





--functions to get stuff from fans and tropical cycles

rays TropicalCycle:= T->( rays fan T)

cones (ZZ,TropicalCycle):= (i,T)->( cones(i,fan T))

dim TropicalCycle:= T->( dim fan T)

ambDim TropicalCycle:= T->( ambDim fan T)

fVector (TropicalCycle) := T->(Polyhedra$fVector fan T)

fan TropicalCycle := T -> (T#"Fan")

linealitySpace (TropicalCycle):= T->( linSpace fan T)

maxCones (TropicalCycle):= T->( maxCones fan T)

multiplicities = method(TypicalValue => List)

multiplicities (TropicalCycle) := T -> (T#"Multiplicities")

isPure TropicalCycle := Boolean => T->( Polyhedra$isPure(fan(T)))

isSimplicial TropicalCycle:= Boolean => T->( isSimplicial(fan(T)))



--------------------
--Bergman fan code
--------------------


-- BergmanconeC returns the matrix of generators of the cones
-- corresponding to the chain of flats C. It does not check whether C
-- is a chain of flats or not.

BergmanconeC  = (M, C) -> (
    groundSetM:=#M.groundSet;
    L := {};
    for F in C do(
    	  vect:={};
    	  scan(groundSetM, i->(
	    if member(i,F) then vect =  append(vect,1) else vect = append(vect,0);
	  ));
	L = append(L, vect)
	);
   transpose  matrix L
    )

-- BergmanFan returns the fan of a loopless well-defined matroid
-- ground set must be [n]
-- depends on functions above
BergmanFan = (M) -> (
    if ( loops(M) != {} ) then
	    error("The current method only works for loopless matroids");
    E := toList M.groundSet;
    L := {};
    LM := latticeOfFlats M;
    redLM := dropElements(LM, {{}, E});
    redOrdcplx := maximalChains redLM;
    allOnes := apply(E,i->1);
    for C in redOrdcplx do(
	L = append(L, coneFromVData(BergmanconeC(M,C),transpose matrix {allOnes}));
	);
    F:= fan L;
    mults:=apply(#(maxCones F),i->1);
    tropicalCycle(F,mults)    
    )


----------------------------------------------------------------------------

------------------------------------------------------------------------------
-- DOCUMENTATION
------------------------------------------------------------------------------
beginDocumentation()
doc ///
    Key
    	Tropical
    Headline
    	the main M2 package for tropical computations
    Description
    	Text
	    This is the main M2 package for all tropical computations.
	    This uses Anders Jensen's package gfan, Michael Joswig's
	    package Polymake, and also internal M2 computations.

    	    The package defaults to using the min convention for tropical geometry.
	    To switch to the max convention, reload the package using the command
            loadPackage("Tropical",Configuration=>{"tropicalMax"=>true});

	    The main command is @TO tropicalVariety@.

	    To use the Polymake commands see the @TO "Polymake interface instructions"@.

        Text
            @SUBSECTION "Contributors"@
        Text
	    The following people have also contributed to the package:
	Text
	     @UL {
	       {HREF("https://users.math.yale.edu/~km995/","Kalina Mincheva")},
	       {HREF("http://www.math.unibe.ch/ueber_uns/personen/vargas_de_leon_alejandro/index_ger.html","Alejandro Vargas de Leon")},
	       {HREF("http://www.math.harvard.edu/~cmwang/","Charles Wang")},
	       {HREF("https://math.berkeley.edu/~yelena/", "Yelena Mandelshtam")},
	       {HREF("https://alessioborzi.github.io/", "Alessio Borzì")},
	       {HREF("https://www.linkedin.com/in/timothyxu/", "Timothy Xu")},
	       {HREF{"https://publish.uwo.ca/~aashra9/","Ahmed Umer Ashraf"}}
    	     }@
///


doc ///
	Key
		visualizeHypersurface
		(visualizeHypersurface,RingElement)
		Valuation
	Headline
		visualize the tropical hypersurface of the given polynomial
	Usage
		visualizeHypersurface(polyn)
		visualizeHypersurface(Valuation=>p,polyn)
		visualizeHypersurface(Valuation=>t,polyn)
	Inputs
		polyn: RingElement
		    polynomial
		Valuation=>Number
		    use p-adic coefficients with given p
		Valuation=>RingElement
		    use coefficients in R[t] with given t
	Description
	    Text
	        This function wraps the Polymake visualization for a
		tropical hypersurface given an input polynomial. The input
		should be entered as a homogeneous polynomial. Running
		this method opens an image in a new browser window. The
		coefficients can be interpreted as p-adic coefficients or as
		polynomials via the option @TO Valuation@. Examples are
		commented out because they open a new browser window.
	    Example
	    	--Examples are commented because they open in browser. Uncomment to run.
    	        R=ZZ[x,y,z]
		f=2*x*y+x*z+y*z+z^2
		--visualizeHypersurface(Valuation=>2,f)

		f=2*x^2+x*y+2*y^2+x*z+y*z+2*z^2
		--visualizeHypersurface(f)

		R=ZZ[w,x,y,z]
		f=8*x^2+8*y^2+8*z^2+8*w^2+2*x*y+2*x*z+2*y*z+2*x*w+2*y*w+2*z*w
		--visualizeHypersurface(f)
///


doc ///
    Key
    	TropicalCycle
    Headline
    	a Type for working with tropical cycles
    Description
		Text
			This is the main type for tropical cycles. A TropicalCycle
			consists of a Fan with an extra HashKey Multiplicities,
			which is the list of multiplicities on the maximal cones
			listed in the order that the maximal cones appear in the
			MaxCones list. A TropicalCycle
			is saved as a hash table which contains the Fan and the
			Multiplicities.

///






doc ///
    Key
	tropicalCycle
	(tropicalCycle, Fan, List)
    Headline
    	constructs a TropicalCycle from a Fan and a list with multiplicities
    Usage
    	tropicalCycle(F,mult)
    Inputs
    	F:Fan
		mult:List
    Outputs
    	T:TropicalCycle
    Description
		Text
			This function creates a tropical cycle from a fan and a list of multiplicities.
			The multiplicities must be given in the same order as the maximal cones
			appear in the MaximalCones list.
		Example
			F = fan {posHull matrix {{1},{0},{0}}, posHull matrix {{0},{1},{0}}, posHull matrix {{0},{0},{1}}, posHull matrix {{-1},{-1},{-1}}}
			mult = {1,2,-3,1}
			tropicalCycle(F, mult)
///


doc///
    Key
	isBalanced
	(isBalanced, TropicalCycle)
    Headline
		checks whether a tropical cycle is balanced
    Usage
    	isBalanced T
    Inputs
		T:TropicalCycle
    Outputs
    	B:Boolean
    Description
		Text
			This function checks if a tropical cycle is balanced.
		Example
			QQ[x,y,z]
			V = tropicalVariety(ideal(x+y+z))
			isBalanced V
			F = fan {posHull matrix {{1},{0},{0}}, posHull matrix {{0},{1},{0}}, posHull matrix {{0},{0},{1}}, posHull matrix {{-1},{-1},{-1}}}
			mult = {1,2,-3,1}
			isBalanced (tropicalCycle(F, mult))
///


doc///
	Key
		tropicalPrevariety
		(tropicalPrevariety, List)
		(tropicalPrevariety, List, List)
		[tropicalPrevariety, Strategy]
	Headline
		the intersection of the tropical hypersurfaces
	Usage
		tropicalPrevariety(L)
		tropicalPrevariaty(L,LS)
		tropicalPrevariety(L,Strategy=>S)
		tropicalPrevariety(L,LS,Strategy=>S)
	Inputs
		L:List
		  of polynomials
		LS: List
		  of Symmetries (optional)
		Strategy=>String
		  Strategy (currently only "gfan")
	Outputs
		F:Fan
		  the intersection of the tropical hypersurfaces of polynomials in L
	Description
		Text
			This method intersects the tropical hypersurfaces
			coming from the tropicalizations of the polynomials in the list L.
			If there are symmetries that leave the specified polynomials fixed,
			they can  be specified by passing a list with the symmetries
			as second argument, with the same format as the option  @TO Symmetry@.
		Example
			QQ[x_1,x_2,x_3,x_4]
			L={x_1+x_2+x_3+x_4,x_1*x_2+x_2*x_3+x_3*x_4+x_4*x_1,x_1*x_2*x_3+x_2*x_3*x_4+x_3*x_4*x_1+x_4*x_1*x_2,x_1*x_2*x_3*x_4-1}
			tropicalPrevariety L
			QQ[x_0,x_1]
			tropicalPrevariety({x_0+x_1+1}, {{1,0}})
			QQ[x_0,x_1]
			tropicalPrevariety({x_0+x_1+1,x_0+x_1},Strategy => "gfan")
///



doc///
    Key
      tropicalVariety
      (tropicalVariety, Ideal)
      [tropicalVariety, ComputeMultiplicities]
      [tropicalVariety, Prime]
      [tropicalVariety, IsHomogeneous]
      [tropicalVariety, Symmetry]

    Headline
      the tropical variety associated to an ideal
    Usage
      tropicalVariety(I)
      tropicalVariety(I,ComputeMultiplicities=>true)
      tropicalVariety(I,Prime=>true)
      tropicalVariety(I,IsHomogeneous=>false)
      tropicalVariety(I,Symmetry=>{{...},{...}})
    Inputs
      I:Ideal
        of polynomials
      IsHomogeneous=>Boolean
        that ensures whether the ideal is already homogeneous
      ComputeMultiplicities=>Boolean
        that confirms whether the multiplicities will be computed
      Prime=>Boolean
        that ensures whether the ideal is already prime
      Symmetry=>List
        that records the symmetries of the ideal
    Outputs
        F:TropicalCycle
    Description
       Text
         This method takes an ideal and computes the tropical variety
         associated to it.  By default the ideal is assumed to be
         prime.  If this is not the case the default answer will not
         necessarily give the correct answer.  In this case use the
         optional argument Prime=>false.  By default the
         tropicalVariety command computes multiplicities but setting
         computeMultiplicities=>false turns this off.  This only saves
         time if Prime is set to false.  The ideal I is not assumed to
         be homogeneous.  The optional argument IsHomogeneous=>true
         allows the user to assert that the ideal is homogeneous. If there
	 are symmetries of the ring corresponding to I that leave I fixed,
	 they can be specified with the option @TO Symmetry@.
      Example
       QQ[x,y];
       I=ideal(x+y+1);
       T=tropicalVariety(I);
       rays(T)
       maxCones(T)
       linealitySpace T
       Polyhedra$fVector fan T
       multiplicities(T)
       QQ[x,y,z,w];
       I = ideal(w+x+y+z)
       T = tropicalVariety(I, IsHomogeneous=>true, Symmetry=>{{1,0,2,3},{2,1,0,3},{3,1,2,0}})
       rays(T)
       maxCones(T)
       I=intersect(ideal(x+y+z+w),ideal(x-y,y-z));
       T= tropicalVariety(I,Prime=>false);
       rays(T)
       maxCones(T)
       multiplicities(T)
       linealitySpace T
       QQ[x,y,z,w];
       I=intersect(ideal(x+y+z+1),ideal(x^2-y*z));
       T= tropicalVariety(I,Prime=>false,ComputeMultiplicities=>false);
       rays(T)
       maxCones(T)
       linealitySpace T
       multiplicities(T)

///



doc///
    Key
	stableIntersection
	(stableIntersection,TropicalCycle,TropicalCycle)
	[stableIntersection, Strategy]
    Headline
    	computes the stable intersection of two tropical varieties
    Usage
	stableIntersection(F,G)
	stableIntersection(L,Strategy=>S)
    Inputs
	F:TropicalCycle
	  a tropical cycle
  	G:TropicalCycle
  	  another tropical cycle
	Strategy=>String
	  Strategy ("atint" (polymake) or "gfan")
    Outputs
        T:TropicalCycle
		  a tropical cycle
    Description
    	Text
	    This computes the stable intersection of two tropical
	    cycles.  For details on the definition of stable
	    intersection, see, for example, Section 3.6 of TROPICALBOOK.
	    If a recent enough version of polymake is installed,
	    the Strategy "atint" is default. Otherwise "gfan" will be used,
	    which only computes the fan of the stable intersection
	    without multiplicities.
	Example
	    QQ[x,y,z];
	    I = ideal(x^2+y^2+z^2-1);
	    T1 = tropicalVariety(I);
	    J = ideal(x*y+y*z+x*z+1);
	    T2 = tropicalVariety(J);
	    V = tropicalVariety(I+J);
	    -- W1 =  stableIntersection(T1,T2,Strategy=>"atint");
	    W2 =  stableIntersection(T1,T2,Strategy=>"gfan");
	    -- V#"Fan" == W1#"Fan"
	    -- V#"Multiplicities" == W1#"Multiplicities"
	    V#"Fan" == W2

///


doc///
    Key
	isTropicalBasis
	(isTropicalBasis, List)
	[isTropicalBasis, Strategy]
    Headline
	checks if a list of polynomials is a tropical basis for the ideal they generate
    Usage
	isTropicalBasis(L)
	isTropicalBasis(L,Strategy=>S)
    Inputs
	L:List
	  of polynomials
	Strategy=>String
	    Strategy (currently only "gfan")
    Outputs
	F:Boolean
	    whether the list of polynomials is a tropical basis for the ideal it generates
    Description
	Text
	    This method checks if the intersection of the tropical hypersurfaces associated to the polynomials in the list equals the tropicalization of the variety corresponding to the ideal they generate.
        Example
	    QQ[x,y,z]
	    isTropicalBasis({x+y+z,2*x+3*y-z})
	    isTropicalBasis(flatten entries gens Grassmannian (1,4,QQ[a..l]))
///


doc///
    Key
	multiplicities
	(multiplicities, TropicalCycle)
    Headline
		returns the list of multiplicities on maximal cones in a tropical cycle
    Usage
    	multiplicities(T)
    Inputs
		T:TropicalCycle
    Outputs
    	L:List
    Description
		Text
			This method returns the list of multiplicities on maximal cones in a tropical cycle.
		Example
			QQ[x,y,z]
			V = tropicalVariety(ideal(x+y+z));
			multiplicities V
///

doc///
    Key
	ComputeMultiplicities
    Headline
		option to compute the multiplicities in case they ideal is not prime
    Usage
    	tropicalVariety(I,ComputeMultiplicities=>true)
    Description
		Text
			This option allows to compute the multiplicities in case the ideal I is not prime. In fact the output of gfan
			does not include them and hence they are computed separately by this package. By default the ideal is assumed to be prime.
		Example
			QQ[x,y,z];
			I=ideal(x^2-y^2);
			isPrime I
			T=tropicalVariety(I,Prime=>false,ComputeMultiplicities=>true);
			rays T
			maxCones T
			multiplicities T
///

doc///
    Key
	Prime
    Headline
		option to declare if the input ideal is prime
    Usage
    	tropicalVariety(I,Prime=>false)

    Description
		Text
			By default the ideal is assumed to be prime. If the ideal is not prime then the internal  procedure to compute the tropicalization is different.
			It is used gfan_tropicalbrute force instead of gfan_tropicaltraverse.
		Example
			QQ[x,y,z];
			I=ideal(x^2+y^2-2*x*y);
			isPrime I
			T=tropicalVariety(I,Prime=>false)
///


doc///
    Key
	IsHomogeneous
    Headline
		option to declare if the input ideal is homogeneous
    Usage
    	tropicalVariety(I,IsHomogeneous=>true)

    Description
		Text
			If the option is used than homogeneity of the
			ideal is not tested. By default the ideal is
			always assumed not homogeneous and a test is
			performed before applying the function
			tropicalVariety.
		Example
		          QQ[x,y];
			  I=ideal(x+y+1);
			  T=tropicalVariety (I,IsHomogeneous=>false)
///


doc///
    Key
	Symmetry
    Headline
		option to declare if the input ideal has symmetries
    Usage
    	tropicalVariety(I,Symmetry=>{{..},{..}})

    Description
		Text
			If the option is used, the specified
			symmetries are used in the calculation of the
			tropical variety. For an ideal I of a
			polynomial ring R = KK[x_0 .. x_N], each
			symmetry is a permutation encoded in a list
			\{s_0, s_1, ..., s_N\} of numbers from 0 to N
			which records that swapping the variable x_j
			with the variable x_{s_j} in R leaves the
			ideal I fixed. Exploiting symmetries reduces
			the number of computations needed. The length
			of each symmetry equals the number of
			generators of R, otherwise an error is raised.
		Example
		          QQ[x_0,x_1,x_2];
			  I=ideal(x_0+x_1+x_2+1);
			  T=tropicalVariety (I,Symmetry=>{{1,0,2}, {2,1,0} })
///


doc///
    Key
	(fan,TropicalCycle)
    Headline
	    outputs the fan associated to the tropical cycle
    Usage
    	fan(T)
    Inputs
	T:TropicalCycle

    Outputs
	F:Fan
	    the fan associated to the tropical cycle T

    Description
		Text
		        This function outputs the fan associated to the tropical cycle T.
		Example
			QQ[x,y,z]
			T=tropicalVariety (ideal(x+3*y+3));
			fan T
			peek o3#cache


///
doc///
    Key
	(maxCones,TropicalCycle)
    Headline
	computes the maximal cone of a tropical cycle
    Usage
    	maxCones(T)
    Inputs
	T:TropicalCycle

    Outputs
        L:List


    Description
		Text
		        This function computes the maximal cones of the fan associated to the tropical cycle.

		Example
			QQ[x,y,z,w]
			I=ideal(x^2-y*z+w^2,w^3-x*y^3+z^3);
			T=tropicalVariety I;
			maxCones T

///
doc///
    Key
	(isPure,TropicalCycle)
    Headline
	checks whether  a tropical cycle is pure
    Usage
    	isPure(T)
    Inputs
	T:TropicalCycle

    Outputs
	B:Boolean


    Description
		Text
		        This function checks whether the fan associated to the tropical cycle is pure, i.e. if the maximal cones have all the same dimension.
		Example
		        F=fan ({posHull(matrix{{1,2,3},{0,2,0}}),posHull(matrix{{0},{1}})});
			T=tropicalCycle (F,{1,2});
			isPure T

///
doc///
    Key
	(isSimplicial,TropicalCycle)
    Headline
		checks whether a tropical cycle is simplicial
    Usage
    	isSimplicial(T)
    Inputs
	T:TropicalCycle

    Outputs
	B:Boolean


    Description
		Text
		       This function checks if the fan associated to the tropical cycle T is simplicial, i.e. if for each cone the rays generating  it are linearly independent.
		Example
		       F=fan ({posHull(matrix{{1,2,3},{0,2,0}}),posHull(matrix{{0},{1}})});
		       T=tropicalCycle (F,{1,2});
		       isSimplicial T


///
doc///
    Key
	(rays,TropicalCycle)
    Headline
	computes the rays of a tropical cycle
    Usage
    	rays(T)
    Inputs
	T:TropicalCycle

    Outputs
	M:Matrix


    Description
		Text
		        This function computes the rays of the fan associated to the tropical cycle. These are the columns of
		        the output matrix.
		Example
		        QQ[x,y,z,w]
			I=ideal(x^2-y*z+w^2,w^3-x*y^3+z^3);
			T=tropicalVariety I;
			rays T

///
doc///
    Key
	(dim,TropicalCycle)
    Headline
		computes the dimension of a tropical cycle
    Usage
    	dim(T)
    Inputs
	T:TropicalCycle

    Outputs
	k:ZZ
	    the dimension of the tropical cycle T

    Description
		Text
	                This function computes the dimension of the fan associated to the tropical cycle T.
		Example
			QQ[x,y,z,w]
			I=ideal(x^2-y*z+w^2,w^3-y^3*x+z^3);
			T=tropicalVariety I;
			dim T

///

doc///
    Key
	(fVector,TropicalCycle)
    Headline
		computes the fVector of  a  tropical cycle
    Usage
    	fVector(T)
    Inputs
	T:TropicalCycle

    Outputs
	L:List
	    the fVector of the fan associated to the  tropical cycle T

    Description
		Text
		       This function computes the fVector of the fan associated to the tropical cycle T.
		Example
			QQ[x,y,z]
			T=tropicalVariety (ideal(x+3*y+3));
			fVector T

///

doc///
    Key
	(ambDim,TropicalCycle)
    Headline
		computes the dimension of the ambient space of a tropical cycle
    Usage
    	ambDim(T)
    Inputs
	T:TropicalCycle

    Outputs
	n:ZZ
	    the dimension of the tropicalCycle T

    Description
		Text
		        This function computes the dimension of the space where the tropical cycle is contained.
		Example
			QQ[x,y,z]
			T=tropicalVariety(ideal(x+y+z));
			ambDim T

///
doc///
    Key
	(cones,ZZ,TropicalCycle)
    Headline
		computes the cones of a tropical cycle
    Usage
    	cones(k,T)
    Inputs
	k:ZZ
	T:TropicalCycle

    Outputs
	L:List
	    the cones of codimension k in T

    Description
		Text
		        This function computes the cone of codimension k of the fan associated to the tropical cycle T.
		Example
			QQ[x,y,z,w,t]
			I=ideal(x^2-y*z+w^2,w^3-y^3*x+z^3,t-w+x);
			T=tropicalVariety I;
			cones(2,T)

///

doc///
    Key
	(linealitySpace,TropicalCycle)
    Headline
	computes the lineality space of a  tropical cycle
    Usage
    	linealitySpace(T)
    Inputs
	T:TropicalCycle

    Outputs
	M:Matrix


    Description
		Text
		        This function computes the lineality space of the fan associated to the tropical cycle T. The generators of the lineality space are the columns of the
		        output  matrix
		Example
		        QQ[x,y,z];
			I=ideal(x-y);
			T=tropicalVariety I;
			L=linealitySpace T

///


doc///
   Key
       "Polymake interface instructions"
   Headline
       instructions for loading Polymake with this package.
   Description
       Text
       	   The software program Polymake is not distributed with
       	   Macaulay2, so to use the Polymake commands the user needs
       	   to install Polymake on their own machine, and tell
       	   Macaulay2 where to find it.  This is done with the
       	   Configuration option "polymakeCommand".  The default is
       	   that this is empty, which means that Polymake options will
       	   not be used.  To tell the package where your copy of Polymake is installed, use either
	   loadPackage("Tropical",Configuration=>\{"polymakeCommand"=>"YOUR COMMAND"\}), or
	   edit the init-Tropical.m2 file (created after you install the package)
	   by changing "polymakeCommand" => "", into "polymakeCommand" => "YOUR COMMAND"

	   On a Mac, the default value for YOUR COMMAND is
	   /Applications/polymake.app/Contents/MacOS/polymake.start
	   and the init-Tropical.m2 file is usually in ~/Library/Application Support/Macaulay2.

	   On Unix, the default value for YOUR COMMAND is
           /usr/bin/polymake
	   and the init-Tropical.m2 file is usually in ~/.Macaulay2.
	   If polymake is installed in a nonstandard location, you can
	   find YOUR COMMAND with the terminal command "which polymake".

	   This package should work with Polymake versions > 3.2, and has been tested up to 4.2.
///

doc///
        Key
	  BergmanFan
	Headline
	    the Bergman fan of a matroid
	Usage
	    BergmanFan(M)
	Inputs
	    M:Matroid
	Outputs
	    T:TropicalCycle
	Description
	    Text
	    	Computes the Bergman fan of a matroid, with the fine
	    	fan structure.  This uses the Matroids package; the
	    	input should be a matroid in the sense of that
	    	package.  The output is a tropical cycle T whose
	    	underlying fan is the fine fan structure in the sense
	    	of Ardila-Klivans on the Bergman fan of the matroid.
	    	This has underlying simplicial complex the order
	    	complex of the lattice of flats of the matroid M.
		
    	    	If the ground set of the matroid has size n, then the
    	    	fan given is in R^n, so there is always a lineality
    	    	space of dimension at least one.
	    Example
	        M=uniformMatroid(2,3);
		T=BergmanFan(M);
		rays T
		maxCones T
		linealitySpace T
///

	      

----- TESTS -----

-----------------------
--tropicalCycle
-----------------------
TEST ///

F:=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0,1},{0,2},{1,2}})
assert((tropicalCycle(F,{1,1,1}))#"Fan"== F)
assert((tropicalCycle(F,{1,1,1}))#"Multiplicities"== {1,1,1})

///

-----------------------
--isTropicalBasis
-----------------------

TEST ///
assert(isTropicalBasis (flatten entries gens Grassmannian(1,4,QQ[a..l]))==true)
R:=QQ[x,y,z]
assert( not isTropicalBasis({x+y+z,2*x+3*y-z}))
///


-----------------------
--getters
-----------------------

--rays


TEST///
T:=new TropicalCycle
F:=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0,1},{0,2},{1,2}})
T#"Multiplicities" ={1,1,1};
T#"Fan" = F;
assert((rays T)==( matrix{{0,0,0},{1,-1,0},{0,-1,1}}))
F:=fan(map(ZZ^3,ZZ^0,0),matrix{{1},{1},{1}},{{}})
T#"Multiplicities" ={1};
T#"Fan" = F;
assert((rays(T))==(matrix {{}, {}, {}}))
///

--maxCones
TEST///
T:=new TropicalCycle
F:=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0,1},{0,2},{1,2}})
T#"Multiplicities" ={1,1,1};
T#"Fan" = F;
assert(sort(maxCones T)==( sort({{0,1},{0,2},{1,2}})))
F:=fan(map(ZZ^3,ZZ^0,0),matrix{{1},{1},{1}},{{}})
T#"Multiplicities" ={1};
T#"Fan" = F;
assert((maxCones(T))==({{}}))
///



--dim
TEST///
T:=new TropicalCycle
F:=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0,1},{0,2},{1,2}})
T#"Multiplicities" ={1,1,1};
T#"Fan" = F;
assert((dim T)==( 3))
F:=fan(map(ZZ^3,ZZ^0,0),matrix{{1},{1},{1}},{{}})
T#"Multiplicities" ={1};
T#"Fan" = F;
assert((dim T)==(1))
///

--ambDim

TEST///
T:=new TropicalCycle
F:=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0,1},{0,2},{1,2}})
T#"Multiplicities" ={1,1,1};
T#"Fan" = F;
assert((ambDim T)==( 3))
F:=fan(map(ZZ^3,ZZ^0,0),matrix{{1},{1},{1}},{{}})
T#"Multiplicities" ={1};
T#"Fan" = F;
assert((ambDim T)==(3))
///


--fVector
TEST///
T1:=new TropicalCycle
G:=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0,1},{0,2},{1,2}})
T1#"Multiplicities" ={1,1,1};
T1#"Fan" = G;
assert((fVector T1)==( {0, 1, 3, 3}))
G=fan(map(ZZ^3,ZZ^0,0),matrix{{1},{1},{1}},{{}})
T1#"Multiplicities" ={1};
T1#"Fan" = G;
assert((fVector T1)==({0,1}))
///



--linealitySpace
TEST///
T:=new TropicalCycle
F:=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0,1},{0,2},{1,2}})
T#"Multiplicities" ={1,1,1};
T#"Fan" = F;
assert((linealitySpace T)==( matrix{{1},{1},{1}}))
F=fan(matrix{{1,0,-1},{0,1,-1}},map(ZZ^2,ZZ^0,0),{{0,1},{0,2},{1,2}})
T#"Multiplicities" ={1,1,1};
T#"Fan" = F;
assert((linealitySpace T)==(0))
///

--multiplicities
TEST///
T:=new TropicalCycle
F:=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0,1},{0,2},{1,2}})
T#"Multiplicities" ={1,1,1};
T#"Fan" = F;
assert((multiplicities T)==( {1,1,1}))
F:=fan(map(ZZ^3,ZZ^0,0),matrix{{1},{1},{1}},{{}})
T#"Multiplicities" ={1};
T#"Fan" = F;
assert((multiplicities T)==({1}))
///


--fan
TEST///
T=new TropicalCycle
F=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0,1},{0,2},{1,2}})
T#"Multiplicities" ={1,1,1};
T#"Fan" = F;
assert((fan T)==(F))
F:=fan(map(ZZ^3,ZZ^0,0),matrix{{1},{1},{1}},{{}})
T#"Multiplicities" ={1};
T#"Fan" = F;
assert((fan T)==(F))
///

--cones
TEST///
T:=new TropicalCycle
F:=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0,1},{0,2},{1,2}})
T#"Multiplicities" ={1,1,1};
T#"Fan" = F;
assert((cones(1,T))==({{}}))
assert((cones(2,T))==({{0},{1},{2}}))
assert((cones(3,T))==({{0,1},{0,2},{1,2}}))
F:=fan(map(ZZ^3,ZZ^0,0),matrix{{1},{1},{1}},{{}})
T#"Multiplicities" ={1};
T#"Fan" = F;
assert((cones(1,T))==({{}}))
///







-----------------------
--isBalanced
-----------------------

TEST///

F=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0,1},{0,2},{1,2}});
T= tropicalCycle(F,{1,1,1});
assert(isBalanced T)

T2 = tropicalCycle(F,{1,2,3});
assert(not isBalanced T2);

///

TEST///

R=QQ[x,y,z];
V = tropicalVariety(ideal(x+y+z))
assert(isBalanced V)

G = V;
G#"Multiplicities" = {1,2,1}
assert(not isBalanced G)

///

TEST///

S = QQ[x,y];
V = tropicalVariety(ideal(x+y+1))
assert(isBalanced V)
///

TEST///

F = fan {posHull matrix {{1},{0},{0}}, posHull matrix {{0},{1},{0}}, posHull matrix {{0},{0},{1}}, posHull matrix {{-1},{-1},{-1}}}
mult = {1,2,-3,1}
assert(not isBalanced (tropicalCycle(F, mult)))

///



-----------------------
--tropicalPrevariety
-----------------------

TEST///
QQ[x,y,z,w]
F=tropicalPrevariety({x+y+z+w,x^2+y*z})
assert((rays F) == matrix {{1,1,-1},{5,-3,-1},{-3,5,-1},{-3,-3,3}})
///

TEST///
QQ[x,y,z,w]
F=tropicalPrevariety({x+y+z+w,x^2+y*z}, {{0,2,1,3}})
assert((rays F) == matrix {{1,1,-1},{5,-3,-1},{-3,5,-1},{-3,-3,3}})
///


TEST///
QQ[x,y]
F=tropicalPrevariety({x+y+1}, {{1,0}})
assert((rays F) == matrix {{1,-1,0},{0,-1,1}})
///

-----------------------
--stableIntersection
-----------------------

TEST///

F=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0,1},{0,2},{1,2}});
T= tropicalCycle(F,{1,1,1});
T2= stableIntersection(T,T,Strategy=>"gfan")
assert(dim T2 == 3)
assert(maxCones T2 == {{1, 2}, {0, 2}, {0, 1}})

///


if polymakeOK then (
TEST///

F1:=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0,1},{0,2},{1,2}});
T1:= tropicalCycle(F1,{1,1,1});
R1:= stableIntersection(T1,T1,Strategy=>"atint");
R2:= stableIntersection(T1,T1,Strategy=>"gfan");
assert(R1#"Fan" == R2)
assert(dim R2 == 3)
assert(maxCones R2 == {{1, 2}, {0, 2}, {0, 1}})

R =QQ[x,y,z,t];
I=ideal(x+y+z+t);
J=ideal(4*x+y-2*z+5*t);
T1 = stableIntersection(tropicalVariety(I),tropicalVariety(J));
T2 = tropicalVariety(I+J);
assert(T1#"Fan" == T2#"Fan")
assert(T1#"Multiplicities" == T2#"Multiplicities")

R = QQ[x,y,z];
I = ideal(x^2+y^2+z^2-1);
T1 = tropicalVariety(I);
J = ideal(x*y+y*z+x*z+1);
T2 = tropicalVariety(J);
V = tropicalVariety(I+J);
W1 =  stableIntersection(T1,T2,Strategy=>"gfan");
W2 =  stableIntersection(T1,T2,Strategy=>"atint");
assert(V#"Fan" == W1)
assert(V#"Fan" == W2#"Fan")
assert(V#"Multiplicities" == W2#"Multiplicities")

///
)

-----------------------
--tropicalVariety
-----------------------


TEST///
QQ[x,y,z,w]
--homogeneous
I=ideal(x^2+y^2+z^2)
T:=tropicalVariety(I)
assert ((rays T)==(matrix {{2, -1, -1},{-1, 2, -1}, {-1, -1, 2}, {0, 0, 0}}))
assert((linealitySpace T)==( matrix {{1, 0}, {1, 0}, {1, 0}, {0, 1}}))
assert((multiplicities T)==( {2,2,2}))
assert((maxCones T)==( {{0},{1},{2}}))
--homogeneous and binomial
I=ideal(x^2+x*z)
T=tropicalVariety (I,Prime=>false)
assert ((rays T)==(0 ))
assert((linealitySpace T)==( matrix {{0, 1, 0}, {1, 0, 0}, {0, 1, 0}, {0, 0, 1}}))
assert((maxCones T)==( {{}}))
assert((multiplicities T)==( {1}))
T=tropicalVariety (I,Prime=>false,ComputeMultiplicities=>false)
assert ((rays T)==(0))
assert((linealitySpace T)==( matrix {{0, 1, 0}, {1, 0, 0}, {0, 1, 0}, {0, 0, 1}}))
assert((maxCones T)==( {{}}))
assert((multiplicities T)==( {{}}))
--non homogeneous
I=ideal(x^2-y*z+w^2,w^3-y^3*x+z^3)
T=tropicalVariety(I)
assert((rays T)== (matrix {{-6, -3, 0, 1, 3, 6}, {-5, -2, -1, 1, 2, 5}, {-7, -3, -1, 1, 4, 7}, {-6, -3, -1, 1, 3, 7}}))
assert((linealitySpace T)==(0))
assert((maxCones T)==( {{0, 1}, {0, 2}, {0, 5}, {1, 3}, {2, 3}, {1, 4}, {2, 4}, {3, 5}, {4, 5}}))
assert((multiplicities T)==( {2, 1, 1, 6, 3, 2, 1, 3, 1}))
QQ[x,y,z]
--non homogeneous
I=ideal(x*y-y+1)
T=tropicalVariety(I)
assert ((rays T)== (matrix {{-1, 0, 3}, {1, -3, 0}, {0, -1, 1}}))
assert((linealitySpace T)==( matrix {{0}, {0}, {1}} ))
assert((maxCones T)==( {{1}, {0}, {2}}))
assert((multiplicities T)==( {1, 1, 1}))
--symmetry and homogeneous
QQ[x,y, z]
I=ideal(x^2+y^2+z^2)
G=tropicalVariety(I, Symmetry=>{{1, 0, 2}, {1, 2, 0}, {2, 0, 1}})
assert ((rays G)==(matrix {{2, -1, -1},{-1, 2, -1}, {-1, -1, 2}}))
--symmetry and non-homogeneous
QQ[x,y]
G=tropicalVariety(ideal(x+y+1), Symmetry=>{{1,0}})
assert((rays G) == matrix {{1,-1,0},{0,-1,1}})

///








-----------------------
--findMultiplicities
--findMultiplicity
--computeCones
-----------------------





-----------------------
--isPure
-----------------------
TEST///
T:=new TropicalCycle
F:=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0,1},{0,2},{1,2}})
T#"Multiplicities" ={1,1,1};
T#"Fan" = F;
assert(isPure(T)==(true))
F:=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0},{1,2}})
T#"Multiplicities" ={1,1};
T#"Fan" = F;
assert(isPure(T)==(false))
///



-----------------------
--isSimplicial
-----------------------
TEST///
T:=new TropicalCycle
F:=fan(matrix{{0,0,0},{1,0,-1},{0,1,-1}},matrix{{1},{1},{1}},{{0,1},{0,2},{1,2}})
T#"Multiplicities" ={1,1,1};
T#"Fan" = F;
assert(isSimplicial(T)==(true))
F:=fan(matrix{{0,0,0,0},{1,0,-1,2},{0,1,-1,1}},matrix{{1},{1},{1}},{{0,1,2},{0,1,3},{0,2,3},{1,2,3}});
T#"Multiplicities" ={1,1,1,1};
T#"Fan" = F;
assert(isSimplicial(T)==(false))
///


-----------------------
--BergmanFan
-----------------------
TEST///
U24 = uniformMatroid(2,4)
F = BergmanFan U24
ray = rays F
mC = maxCones F
l = sort(flatten(mC))
assert(ray*transpose(matrix({{1,1,1,1}})) == 0)
assert(l == toList(0..3))
assert(isBalanced(F)==(true))
///

TEST///
A=transpose matrix{{1,0,0},{1,1,0},{1,2,0},{1,0,1},{1,2,1},{1,0,2}};
M=matroid(A);
T=BergmanFan M;
R=rays T;
assert(rank source R ==17)
assert(dim(T)==rank(A))
///


-----------------------
--convertToPolymake
-----------------------


-----------------------
--star
-----------------------

TEST ///
R=QQ[x,y,z];
I=ideal(x+y+z+1);
T=tropicalVariety(I);
P=convexHull(matrix{{0},{0},{0}}, matrix{{1},{0},{0}});
starT=star(T,P);
R=rays starT;
assert(rank source R == 3);
assert(dim starT== 1);
R=QQ[x,y,z,w];
I=ideal(x+y+z+w);
T=tropicalVariety(I);
P=convexHull(matrix{{0},{0},{0},{0}}, matrix{{1},{0},{0},{0}}, matrix{{1},{1},{1},{1}});
starT=star(T,P);
assert(dim starT== 1);
///




end


restart
uninstallPackage "Tropical"

installPackage "Tropical"
check "Tropical"